From b544661e81bfe4358e41b001aef79579e1bbd324 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 11 Nov 2022 10:32:54 +0000 Subject: [PATCH 001/398] Experimental skin fix, inspired by craftycodie's Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 5 + .../pages/instance/InstanceSettingsPage.cpp | 7 + .../ui/pages/instance/InstanceSettingsPage.ui | 10 + libraries/launcher/CMakeLists.txt | 4 + .../org/prismlauncher/EntryPoint.java | 3 + .../launcher/org/prismlauncher/fix/Fix.java | 48 ++ .../launcher/org/prismlauncher/fix/Fixes.java | 56 +++ .../org/prismlauncher/fix/skins/SkinFix.java | 107 +++++ .../fix/skins/SkinFixUrlStreamHandler.java | 182 ++++++++ .../org/prismlauncher/utils/JsonParser.java | 433 ++++++++++++++++++ 10 files changed, 855 insertions(+) create mode 100644 libraries/launcher/org/prismlauncher/fix/Fix.java create mode 100644 libraries/launcher/org/prismlauncher/fix/Fixes.java create mode 100644 libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java create mode 100644 libraries/launcher/org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java create mode 100644 libraries/launcher/org/prismlauncher/utils/JsonParser.java diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 1d37224aa..91de955ad 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -192,6 +192,8 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerSetting("JoinServerOnLaunch", false); m_settings->registerSetting("JoinServerOnLaunchAddress", ""); + m_settings->registerSetting("LegacySkinFix", true); + qDebug() << "Instance-type specific settings were loaded!"; setSpecificSettingsLoaded(true); @@ -661,6 +663,9 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS launchScript += "traits " + trait + "\n"; } + if (profile->getTraits().contains("legacySkins") && settings()->get("LegacySkinFix").toBool()) + launchScript += "fixes legacySkinFix\n"; + launchScript += "launcher " + getLauncher() + "\n"; // qDebug() << "Generated launch script:" << launchScript; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index af2ba7c80..537271a2c 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -3,6 +3,7 @@ * PolyMC - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2022 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -275,6 +276,9 @@ void InstanceSettingsPage::applySettings() m_settings->reset("JoinServerOnLaunchAddress"); } + bool legacySkinFix = ui->legacySkinFix->isChecked(); + m_settings->set("LegacySkinFix", legacySkinFix); + // FIXME: This should probably be called by a signal instead m_instance->updateRuntimeContext(); } @@ -372,6 +376,9 @@ void InstanceSettingsPage::loadSettings() ui->serverJoinGroupBox->setChecked(m_settings->get("JoinServerOnLaunch").toBool()); ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString()); + + ui->legacySkinFix->setChecked(m_settings->get("LegacySkinFix").toBool()); + ui->legacySkinFix->setVisible(m_instance->traits().contains("legacySkins")); } void InstanceSettingsPage::on_javaDetectBtn_clicked() diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index b064367d1..ca49cbbe5 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -608,6 +608,16 @@ + + + + Enables support for modern skins on old versions. + + + Enable legacy skin fix + + + diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index 55ed58756..1ad398ff5 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -15,6 +15,10 @@ set(SRC org/prismlauncher/launcher/impl/legacy/LegacyFrame.java org/prismlauncher/exception/ParameterNotFoundException.java org/prismlauncher/exception/ParseException.java + org/prismlauncher/fix/Fix.java + org/prismlauncher/fix/Fixes.java + org/prismlauncher/fix/skins/SkinFix.java + org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java org/prismlauncher/utils/Parameters.java org/prismlauncher/utils/ReflectionUtils.java org/prismlauncher/utils/logging/Level.java diff --git a/libraries/launcher/org/prismlauncher/EntryPoint.java b/libraries/launcher/org/prismlauncher/EntryPoint.java index 78804b3e8..88ecb48ce 100644 --- a/libraries/launcher/org/prismlauncher/EntryPoint.java +++ b/libraries/launcher/org/prismlauncher/EntryPoint.java @@ -59,6 +59,7 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import org.prismlauncher.exception.ParseException; +import org.prismlauncher.fix.Fixes; import org.prismlauncher.launcher.Launcher; import org.prismlauncher.launcher.impl.StandardLauncher; import org.prismlauncher.launcher.impl.legacy.LegacyLauncher; @@ -107,6 +108,8 @@ public final class EntryPoint { } try { + Fixes.apply(params); + Launcher launcher; String type = params.getString("launcher"); diff --git a/libraries/launcher/org/prismlauncher/fix/Fix.java b/libraries/launcher/org/prismlauncher/fix/Fix.java new file mode 100644 index 000000000..da578c24f --- /dev/null +++ b/libraries/launcher/org/prismlauncher/fix/Fix.java @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.fix; + +import org.prismlauncher.utils.Parameters; + +public interface Fix { + + String getName(); + + boolean isApplicable(Parameters parameters); + + void apply(); + +} diff --git a/libraries/launcher/org/prismlauncher/fix/Fixes.java b/libraries/launcher/org/prismlauncher/fix/Fixes.java new file mode 100644 index 000000000..ad472fea5 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/fix/Fixes.java @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.fix; + +import java.util.Collections; +import java.util.List; + +import org.prismlauncher.fix.skins.SkinFix; +import org.prismlauncher.utils.Parameters; + +public final class Fixes { + + private static final Fix[] FIXES = { new SkinFix() }; + + public static void apply(Parameters parameters) { + List fixes = parameters.getList("fixes", Collections.emptyList()); + + for (Fix fix : FIXES) + if (fixes.contains(fix.getName()) && fix.isApplicable(parameters)) + fix.apply(); + } + +} diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java new file mode 100644 index 000000000..8d0969a6d --- /dev/null +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.fix.skins; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; + +import org.prismlauncher.fix.Fix; +import org.prismlauncher.utils.Parameters; +import org.prismlauncher.utils.logging.Log; + +public final class SkinFix implements Fix, URLStreamHandlerFactory { + + private static URLStreamHandler http; + private static MethodHandle openConnection; + private static MethodHandle openConnection2; + + static { + try { + Method getURLStreamHandler = URL.class.getDeclaredMethod("getURLStreamHandler", String.class); + getURLStreamHandler.setAccessible(true); + http = (URLStreamHandler) getURLStreamHandler.invoke(null, "http"); + + Method openConnectionReflect = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class); + openConnectionReflect.setAccessible(true); + openConnection = MethodHandles.lookup().unreflect(openConnectionReflect); + + Method openConnectionReflect2 = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, + Proxy.class); + openConnectionReflect2.setAccessible(true); + openConnection2 = MethodHandles.lookup().unreflect(openConnectionReflect2); + } catch (Throwable e) { + Log.error("Could not perform URL reflection; skin fix will not be availble", e); + } + } + + static URLConnection openConnection(URL url) throws Throwable { + return (URLConnection) openConnection.invokeExact(http, url); + } + + static URLConnection openConnection(URL url, Proxy proxy) throws Throwable { + return (URLConnection) openConnection2.invokeExact(http, url, proxy); + } + + @Override + public String getName() { + return "legacySkinFix"; + } + + @Override + public boolean isApplicable(Parameters parameters) { + return http != null && openConnection != null; + } + + @Override + public void apply() { + URL.setURLStreamHandlerFactory(this); + } + + @Override + public URLStreamHandler createURLStreamHandler(String protocol) { + if ("http".equals(protocol)) + return new SkinFixUrlStreamHandler(); + + return null; + } + +} diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java new file mode 100644 index 000000000..71af341c5 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.fix.skins; + +import java.io.IOException; +import java.io.InputStream; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.Map; + +import javax.xml.bind.DatatypeConverter; + +import org.prismlauncher.utils.JsonParser; + +@SuppressWarnings("unchecked") +final class SkinFixUrlStreamHandler extends URLStreamHandler { + + private URL redirect(URL address) throws IOException { + String skinOwner = findSkinOwner(address); + + if (skinOwner != null) + return convertSkin(address, skinOwner); + + String capeOwner = findCapeOwner(address); + + if (capeOwner != null) + return convertCape(address, capeOwner); + + return address; + } + + @Override + protected URLConnection openConnection(URL address) throws IOException { + address = redirect(address); + + try { + return SkinFix.openConnection(address); + } catch (RuntimeException | Error e) { + throw e; + } catch (Throwable e) { + throw new IllegalStateException(e); + } + } + + @Override + protected URLConnection openConnection(URL address, Proxy proxy) throws IOException { + address = redirect(address); + + try { + return SkinFix.openConnection(address, proxy); + } catch (RuntimeException | Error e) { + throw e; + } catch (Throwable e) { + throw new IllegalStateException(e); + } + } + + private URL convertSkin(URL defaultUrl, String owner) throws IOException { + Map textures = getTextures(owner); + + if (textures != null) { + textures = (Map) textures.get("SKIN"); + return new URL((String) textures.get("url")); + } + + return defaultUrl; + } + + private URL convertCape(URL defaultUrl, String owner) throws IOException { + Map textures = getTextures(owner); + + if (textures != null) { + textures = (Map) textures.get("CAPE"); + + if (textures == null) + return defaultUrl; + + return new URL((String) textures.get("url")); + } + + return defaultUrl; + } + + private static Map getTextures(String owner) throws IOException { + try (InputStream in = new URL("https://api.mojang.com/users/profiles/minecraft/" + owner).openStream()) { + Map map = (Map) JsonParser.parse(in); + String id = (String) map.get("id"); + + try (InputStream profileIn = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + id) + .openStream()) { + Map profile = (Map) JsonParser.parse(profileIn); + + for (Map property : (Iterable>) profile.get("properties")) { + if (property.get("name").equals("textures")) { + Map result = (Map) JsonParser + .parse(new String(DatatypeConverter.parseBase64Binary((String) property.get("value")))); + result = (Map) result.get("textures"); + return result; + } + } + + return null; + } + } + } + + private static String findSkinOwner(URL address) { + switch (address.getHost()) { + case "www.minecraft.net": + return stripPng(strip(address.getPath(), "/skin/")); + + case "s3.amazonaws.com": + case "skins.minecraft.net": + return stripPng(strip(address.getPath(), "/MinecraftSkins/")); + } + + return null; + } + + private static String findCapeOwner(URL address) { + switch (address.getHost()) { + case "www.minecraft.net": + return stripPng(strip(address.getQuery(), "user=")); + + case "s3.amazonaws.com": + case "skins.minecraft.net": + return stripPng(strip(address.getPath(), "/MinecraftCloaks/")); + } + + return null; + } + + private static String stripPng(String string) { + if (string != null && string.endsWith(".png")) + return string.substring(0, string.lastIndexOf('.')); + + return string; + } + + private static String strip(String string, String prefix) { + if (string != null && string.startsWith(prefix)) + return string.substring(prefix.length()); + + return null; + } + +} diff --git a/libraries/launcher/org/prismlauncher/utils/JsonParser.java b/libraries/launcher/org/prismlauncher/utils/JsonParser.java new file mode 100644 index 000000000..e1703972b --- /dev/null +++ b/libraries/launcher/org/prismlauncher/utils/JsonParser.java @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * MIT License + * + * Copyright (c) 2022 TheKodeToad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.prismlauncher.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Single-file JSON parser to allow for usage in versions without GSON. + */ +public final class JsonParser { + + private final Reader in; + private char[] buffer; + private int pos, length; + + public static Object parse(String in) throws JsonParseException, IOException { + return parse(new StringReader(in)); + } + + public static Object parse(InputStream in) throws JsonParseException, IOException { + return parse(new InputStreamReader(in, StandardCharsets.UTF_8)); + } + + public static Object parse(Reader in) throws JsonParseException, IOException { + return new JsonParser(in).readSingleValue(); + } + + private JsonParser(Reader in) throws IOException { + this.in = in; + pos = length = 0; + read(); + } + + private int character() { + if (length == -1) + return -1; + + return buffer[pos]; + } + + private int read() throws IOException { + if (length == -1) + return -1; + + if (buffer == null || pos++ == length - 1) { + pos = 0; + buffer = new char[8192]; + length = in.read(buffer); + } + + return character(); + } + + private void assertCharacter(char character) throws JsonParseException { + if (character() != character) + throw new JsonParseException("Expected '" + character + "' but got " + + (character() != -1 ? ("'" + (char) character() + "'") : "EOF")); + } + + private void assertNoEOF(String expected) throws JsonParseException { + if (character() == -1) + throw new JsonParseException("Expected " + expected + " but got EOF"); + } + + private void skipWhitespace() throws IOException { + while (isWhitespace()) + read(); + } + + private boolean isWhitespace() { + return character() == ' ' || character() == '\n' || character() == '\r' || character() == '\t'; + } + + private Object readSingleValue() throws IOException { + skipWhitespace(); + Object result = readValue(); + + if (!(result instanceof Double)) + read(); + + skipWhitespace(); + + if (character() != -1) + throw new JsonParseException("Found trailing non-whitespace characters"); + + return result; + } + + private Object readValue() throws IOException { + assertNoEOF("a value"); + + int character = character(); + + switch (character) { + case '{': + return readObject(); + + case '[': + return readArray(); + + case '"': + return readString(); + + case 't': + case 'f': + // probably boolean + Boolean bool = readBoolean(); + if (bool != null) + return bool; + + break; + + case 'n': + // probably null + if (readNull()) + return null; + + break; + } + + if (character == '-' || isDigit()) + // probably a number + return readNumber(); + + throw new JsonParseException("Expected a JSON value but got '" + (char) character + "'"); + } + + private Map readObject() throws IOException { + assertCharacter('{'); + Map obj = new HashMap<>(); + boolean comma = false; + + read(); + skipWhitespace(); + + while (character() != '}') { + if (comma) { + assertCharacter(','); + read(); + skipWhitespace(); + } + + String key = readString(); + read(); + skipWhitespace(); + assertCharacter(':'); + read(); + skipWhitespace(); + + Object value = readValue(); + obj.put(key, value); + + if (!(value instanceof Double)) + read(); + + skipWhitespace(); + comma = true; + } + + return obj; + } + + private List readArray() throws IOException { + assertCharacter('['); + List array = new ArrayList<>(); + boolean comma = false; + + read(); + skipWhitespace(); + + while (character() != ']') { + if (comma) { + assertCharacter(','); + read(); + skipWhitespace(); + } + + Object value = readValue(); + array.add(value); + + if (!(value instanceof Double)) + read(); + + skipWhitespace(); + comma = true; + } + + return array; + } + + private String readString() throws IOException { + assertCharacter('"'); + + StringBuilder result = new StringBuilder(); + + while (read() != '"') { + int character = character(); + + if (character >= '\u0000' && character <= '\u001F') + throw new JsonParseException("Found unescaped control character within string"); + + switch (character) { + case -1: + throw new JsonParseException("Expected '\"' but got EOF"); + + case 0x7F: + if (read() == '"') { + return result.toString(); + } + continue; + + case '\\': + int seq = read(); + + switch (seq) { + case -1: + throw new JsonParseException("Expected an escape sequence but got EOF"); + + case '\\': + break; + + case '/': + case '\"': + character = seq; + break; + + case 'b': + character = '\b'; + break; + + case 'f': + character = '\f'; + break; + + case 'n': + character = '\n'; + break; + + case 'r': + character = '\r'; + break; + + case 't': + character = '\t'; + break; + + case 'u': + // char array to allow allocation in advance. + char[] digits = new char[4]; + + for (int index = 0; index < digits.length; index++) { + character = read(); + if (index == 0 && character() == '-') { + throw new JsonParseException("Hex sequence may not be negative"); + } else if (character() == -1) { + throw new JsonParseException("Expected a hex sequence but got EOF"); + } + digits[index] = (char) character; + } + + String digitsString = new String(digits); + + try { + character = Integer.parseInt(digitsString, 16); + } catch (NumberFormatException e) { + throw new JsonParseException("Could not parse hex sequence \"" + digitsString + "\""); + } + + break; + default: + throw new JsonParseException("Invalid escape sequence: \\" + (char) seq); + } + break; + } + + result.append((char) character); + } + + return result.toString(); + } + + private boolean isDigit() { + return character() >= '0' && character() <= '9'; + } + + private Double readNumber() throws IOException { + StringBuilder result = new StringBuilder(); + + if (character() == '-') { + result.append((char) character()); + read(); + } + + if (character() == '0') { + result.append((char) character()); + read(); + if (isDigit()) + throw new JsonParseException("Found superfluous leading zero"); + } else if (!isDigit()) + throw new JsonParseException("Expected digits"); + + while (character() != -1 && isDigit()) { + result.append((char) character()); + read(); + } + + if (character() == '.') { + result.append('.'); + + read(); + assertNoEOF("digits"); + + if (!isDigit()) + throw new JsonParseException("Expected digits after decimal point"); + + while (character() != -1 && isDigit()) { + result.append((char) character()); + read(); + } + } + + if (character() == 'e' || character() == 'E') { + result.append('E'); + + read(); + assertNoEOF("digits"); + + if (character() == '+' || character() == '-') { + result.append((char) character()); + read(); + } + + if (!(character() == '+' || character() == '-' || isDigit())) + throw new JsonParseException("Expected exponent digits"); + + while (character() != -1 && isDigit()) { + result.append((char) character()); + read(); + } + } + + String resultStr = result.toString(); + + try { + return Double.parseDouble(resultStr); + } catch (NumberFormatException e) { + throw new JsonParseException("Failed to parse number '" + resultStr + "'"); + } + } + + private Boolean readBoolean() throws IOException { + if (character() == 't') { + if (read() == 'r' && read() == 'u' && read() == 'e') { + return true; + } + } else if (character() == 'f') { + if (read() == 'a' && read() == 'l' && read() == 's' && read() == 'e') { + return false; + } + } + return null; + } + + private boolean readNull() throws IOException { + return character() == 'n' && read() == 'u' && read() == 'l' && read() == 'l'; + } + + public class JsonParseException extends IOException { + + private static final long serialVersionUID = 1L; + + public JsonParseException(String message) { + super(message); + } + + } + +} \ No newline at end of file From 8a81aaaa0a0ead0a5398b4f3b4e967a3e78b6792 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 12 Nov 2022 12:55:31 +0000 Subject: [PATCH 002/398] Add separate util class Signed-off-by: TheKodeToad --- libraries/launcher/CMakeLists.txt | 3 +- .../launcher/org/prismlauncher/fix/Fix.java | 17 ++- ...nFixUrlStreamHandler.java => Handler.java} | 21 +-- .../org/prismlauncher/fix/skins/SkinFix.java | 73 +++++------ .../org/prismlauncher/utils/UrlUtils.java | 121 ++++++++++++++++++ 5 files changed, 177 insertions(+), 58 deletions(-) rename libraries/launcher/org/prismlauncher/fix/skins/{SkinFixUrlStreamHandler.java => Handler.java} (91%) create mode 100644 libraries/launcher/org/prismlauncher/utils/UrlUtils.java diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index 1ad398ff5..d022d2532 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -18,9 +18,10 @@ set(SRC org/prismlauncher/fix/Fix.java org/prismlauncher/fix/Fixes.java org/prismlauncher/fix/skins/SkinFix.java - org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java + org/prismlauncher/fix/skins/Handler.java org/prismlauncher/utils/Parameters.java org/prismlauncher/utils/ReflectionUtils.java + org/prismlauncher/utils/UrlUtils.java org/prismlauncher/utils/logging/Level.java org/prismlauncher/utils/logging/Log.java net/minecraft/Launcher.java diff --git a/libraries/launcher/org/prismlauncher/fix/Fix.java b/libraries/launcher/org/prismlauncher/fix/Fix.java index da578c24f..3ecd2e90a 100644 --- a/libraries/launcher/org/prismlauncher/fix/Fix.java +++ b/libraries/launcher/org/prismlauncher/fix/Fix.java @@ -39,10 +39,25 @@ import org.prismlauncher.utils.Parameters; public interface Fix { + /** + * Gets the name of the fix. If the name isn't passed into the program, the fix + * won't run. + * + * @return The name + */ String getName(); - boolean isApplicable(Parameters parameters); + /** + * Determines whether the fix will be run. This is additional to the name check. + * + * @param params The parameters + * @return true to proceed to applying the fix + */ + boolean isApplicable(Parameters params); + /** + * Applies the fix. + */ void apply(); } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java similarity index 91% rename from libraries/launcher/org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java rename to libraries/launcher/org/prismlauncher/fix/skins/Handler.java index 71af341c5..26a3d205e 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFixUrlStreamHandler.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java @@ -46,9 +46,10 @@ import java.util.Map; import javax.xml.bind.DatatypeConverter; import org.prismlauncher.utils.JsonParser; +import org.prismlauncher.utils.UrlUtils; @SuppressWarnings("unchecked") -final class SkinFixUrlStreamHandler extends URLStreamHandler { +final class Handler extends URLStreamHandler { private URL redirect(URL address) throws IOException { String skinOwner = findSkinOwner(address); @@ -67,27 +68,13 @@ final class SkinFixUrlStreamHandler extends URLStreamHandler { @Override protected URLConnection openConnection(URL address) throws IOException { address = redirect(address); - - try { - return SkinFix.openConnection(address); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw new IllegalStateException(e); - } + return UrlUtils.openHttpConnection(address); } @Override protected URLConnection openConnection(URL address, Proxy proxy) throws IOException { address = redirect(address); - - try { - return SkinFix.openConnection(address, proxy); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw new IllegalStateException(e); - } + return UrlUtils.openHttpConnection(address, proxy); } private URL convertSkin(URL defaultUrl, String owner) throws IOException { diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index 8d0969a6d..80cf5323e 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -35,60 +35,55 @@ package org.prismlauncher.fix.skins; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Method; -import java.net.Proxy; import java.net.URL; -import java.net.URLConnection; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; import org.prismlauncher.fix.Fix; import org.prismlauncher.utils.Parameters; +import org.prismlauncher.utils.UrlUtils; import org.prismlauncher.utils.logging.Log; +/** + * Fixes skins by redirecting to other URLs. + * + * @see {@link Handler} + * @see {@link UrlUtils} + */ public final class SkinFix implements Fix, URLStreamHandlerFactory { - private static URLStreamHandler http; - private static MethodHandle openConnection; - private static MethodHandle openConnection2; - - static { - try { - Method getURLStreamHandler = URL.class.getDeclaredMethod("getURLStreamHandler", String.class); - getURLStreamHandler.setAccessible(true); - http = (URLStreamHandler) getURLStreamHandler.invoke(null, "http"); - - Method openConnectionReflect = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class); - openConnectionReflect.setAccessible(true); - openConnection = MethodHandles.lookup().unreflect(openConnectionReflect); - - Method openConnectionReflect2 = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, - Proxy.class); - openConnectionReflect2.setAccessible(true); - openConnection2 = MethodHandles.lookup().unreflect(openConnectionReflect2); - } catch (Throwable e) { - Log.error("Could not perform URL reflection; skin fix will not be availble", e); - } - } - - static URLConnection openConnection(URL url) throws Throwable { - return (URLConnection) openConnection.invokeExact(http, url); - } - - static URLConnection openConnection(URL url, Proxy proxy) throws Throwable { - return (URLConnection) openConnection2.invokeExact(http, url, proxy); - } - @Override public String getName() { return "legacySkinFix"; } @Override - public boolean isApplicable(Parameters parameters) { - return http != null && openConnection != null; + public boolean isApplicable(Parameters params) { + if (!isSupported()) { + Log.warning("Using Java 8 will probably fix this"); + Log.warning("Alternatively, turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); + return false; + } + + return true; + } + + private boolean isSupported() { + // check for DatatypeConverter first + // most users will just be annoyed by the big stacktrace + try { + Class.forName("javax.xml.bind.DatatypeConverter"); + } catch (ClassNotFoundException e) { + Log.warning("Cannot find DatatypeConverter - required for skin fix"); + return false; + } + + if (!UrlUtils.isSupported()) { + Log.warning("Cannot access the necessary Java internals for skin fix"); + return false; + } + + return true; } @Override @@ -99,7 +94,7 @@ public final class SkinFix implements Fix, URLStreamHandlerFactory { @Override public URLStreamHandler createURLStreamHandler(String protocol) { if ("http".equals(protocol)) - return new SkinFixUrlStreamHandler(); + return new Handler(); return null; } diff --git a/libraries/launcher/org/prismlauncher/utils/UrlUtils.java b/libraries/launcher/org/prismlauncher/utils/UrlUtils.java new file mode 100644 index 000000000..c73c7600b --- /dev/null +++ b/libraries/launcher/org/prismlauncher/utils/UrlUtils.java @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.utils; + +import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +import org.prismlauncher.utils.logging.Log; + +/** + * A utility class for URLs which uses reflection to access hidden methods. + * Unfortunately not supported on newer Java versions. + */ +public class UrlUtils { + + private static URLStreamHandler http; + private static MethodHandle openConnection; + private static MethodHandle openConnectionProxied; + + static { + try { + // invoke URL.getURLStreamHandler to obtain some of the default handlers before + // they are overridden + Method getURLStreamHandler = URL.class.getDeclaredMethod("getURLStreamHandler", String.class); + getURLStreamHandler.setAccessible(true); + http = (URLStreamHandler) getURLStreamHandler.invoke(null, "http"); + + // reflection is required due to not having access + // unreflect is used due to the potential frequency of calls + Method openConnectionReflect = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class); + openConnectionReflect.setAccessible(true); + openConnection = MethodHandles.lookup().unreflect(openConnectionReflect); + + // a second method which takes in a proxy is required for a fully-functional + // URLStreamHandler + Method openConnectionReflectProxied = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, + Proxy.class); + openConnectionReflectProxied.setAccessible(true); + openConnectionProxied = MethodHandles.lookup().unreflect(openConnectionReflectProxied); + } catch (Throwable e) { + Log.error("URL reflection failed - some features may not work", e); + } + } + + /** + * Determines whether all the features of this class are available. + * + * @return true if all features can be used + */ + public static boolean isSupported() { + return http != null && openConnection != null && openConnectionProxied != null; + } + + public static URLConnection openHttpConnection(URL url) throws IOException { + return openConnection(http, url); + } + + public static URLConnection openHttpConnection(URL url, Proxy proxy) throws IOException { + return openConnection(http, url, proxy); + } + + public static URLConnection openConnection(URLStreamHandler handler, URL url) throws IOException { + try { + return (URLConnection) openConnection.invokeExact(handler, url); + } catch (IOException | Error | RuntimeException e) { + throw e; // rethrow if possible + } catch (Throwable e) { + throw new Error(e); // otherwise, wrap in Error + } + } + + public static URLConnection openConnection(URLStreamHandler handler, URL url, Proxy proxy) throws IOException { + try { + return (URLConnection) openConnectionProxied.invokeExact(handler, url, proxy); + } catch (IOException | Error | RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new Error(e); + } + } + +} From 7534eaf006e030f2f446a3c793090d7640fb2361 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 12 Nov 2022 14:48:42 +0000 Subject: [PATCH 003/398] Only use DatatypeConverter as a fallback Signed-off-by: TheKodeToad --- libraries/launcher/CMakeLists.txt | 2 + .../org/prismlauncher/fix/skins/Handler.java | 5 +- .../org/prismlauncher/fix/skins/SkinFix.java | 21 +------ .../org/prismlauncher/utils/Base64.java | 59 +++++++++++++++++++ .../org/prismlauncher/utils/JsonParser.java | 2 +- .../org/prismlauncher/utils/UrlUtils.java | 2 +- 6 files changed, 67 insertions(+), 24 deletions(-) create mode 100644 libraries/launcher/org/prismlauncher/utils/Base64.java diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index d022d2532..acc276218 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -19,6 +19,8 @@ set(SRC org/prismlauncher/fix/Fixes.java org/prismlauncher/fix/skins/SkinFix.java org/prismlauncher/fix/skins/Handler.java + org/prismlauncher/utils/Base64.java + org/prismlauncher/utils/JsonParser.java org/prismlauncher/utils/Parameters.java org/prismlauncher/utils/ReflectionUtils.java org/prismlauncher/utils/UrlUtils.java diff --git a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java index 26a3d205e..2bffeae96 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java @@ -43,8 +43,7 @@ import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.Map; -import javax.xml.bind.DatatypeConverter; - +import org.prismlauncher.utils.Base64; import org.prismlauncher.utils.JsonParser; import org.prismlauncher.utils.UrlUtils; @@ -115,7 +114,7 @@ final class Handler extends URLStreamHandler { for (Map property : (Iterable>) profile.get("properties")) { if (property.get("name").equals("textures")) { Map result = (Map) JsonParser - .parse(new String(DatatypeConverter.parseBase64Binary((String) property.get("value")))); + .parse(new String(Base64.decode((String) property.get("value")))); result = (Map) result.get("textures"); return result; } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index 80cf5323e..f5a9e0df4 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -59,27 +59,10 @@ public final class SkinFix implements Fix, URLStreamHandlerFactory { @Override public boolean isApplicable(Parameters params) { - if (!isSupported()) { - Log.warning("Using Java 8 will probably fix this"); - Log.warning("Alternatively, turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); - return false; - } - - return true; - } - - private boolean isSupported() { - // check for DatatypeConverter first - // most users will just be annoyed by the big stacktrace - try { - Class.forName("javax.xml.bind.DatatypeConverter"); - } catch (ClassNotFoundException e) { - Log.warning("Cannot find DatatypeConverter - required for skin fix"); - return false; - } - if (!UrlUtils.isSupported()) { Log.warning("Cannot access the necessary Java internals for skin fix"); + Log.warning("Using an older Java version will probably fix this"); + Log.warning("Alternatively, turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); return false; } diff --git a/libraries/launcher/org/prismlauncher/utils/Base64.java b/libraries/launcher/org/prismlauncher/utils/Base64.java new file mode 100644 index 000000000..20a189f46 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/utils/Base64.java @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.utils; + +import java.nio.charset.StandardCharsets; + +import javax.xml.bind.DatatypeConverter; + +public final class Base64 { + + private static boolean legacy; + + public static byte[] decode(String input) { + if (!legacy) { + try { + return java.util.Base64.getDecoder().decode(input.getBytes(StandardCharsets.UTF_8)); + } catch (NoClassDefFoundError e) { + legacy = true; + } + } + + // support for Java versions < 8 + return DatatypeConverter.parseBase64Binary(input); + } + +} diff --git a/libraries/launcher/org/prismlauncher/utils/JsonParser.java b/libraries/launcher/org/prismlauncher/utils/JsonParser.java index e1703972b..d1803c896 100644 --- a/libraries/launcher/org/prismlauncher/utils/JsonParser.java +++ b/libraries/launcher/org/prismlauncher/utils/JsonParser.java @@ -420,7 +420,7 @@ public final class JsonParser { return character() == 'n' && read() == 'u' && read() == 'l' && read() == 'l'; } - public class JsonParseException extends IOException { + public static class JsonParseException extends IOException { private static final long serialVersionUID = 1L; diff --git a/libraries/launcher/org/prismlauncher/utils/UrlUtils.java b/libraries/launcher/org/prismlauncher/utils/UrlUtils.java index c73c7600b..362feb4e3 100644 --- a/libraries/launcher/org/prismlauncher/utils/UrlUtils.java +++ b/libraries/launcher/org/prismlauncher/utils/UrlUtils.java @@ -50,7 +50,7 @@ import org.prismlauncher.utils.logging.Log; * A utility class for URLs which uses reflection to access hidden methods. * Unfortunately not supported on newer Java versions. */ -public class UrlUtils { +public final class UrlUtils { private static URLStreamHandler http; private static MethodHandle openConnection; From cfeadf858edd05e11db67d7d3d217ed25a00537b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 12 Nov 2022 15:12:55 +0000 Subject: [PATCH 004/398] Add workaround to warning Signed-off-by: TheKodeToad --- libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index f5a9e0df4..927c10142 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -61,7 +61,7 @@ public final class SkinFix implements Fix, URLStreamHandlerFactory { public boolean isApplicable(Parameters params) { if (!UrlUtils.isSupported()) { Log.warning("Cannot access the necessary Java internals for skin fix"); - Log.warning("Using an older Java version will probably fix this"); + Log.warning("Try adding '--add-opens java.base/java.net=ALL-UNNAMED' to your Java arguments"); Log.warning("Alternatively, turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); return false; } From ead59c0246639837bbdbfcc6a0ca443a1ab06d6c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 20 Nov 2022 09:16:30 +0000 Subject: [PATCH 005/398] Improve the skin fix code - Spoof 404 instead of keeping original URL. - Move JsonParseException to the package. - Pass proxy as null to reduce code duplication. Signed-off-by: TheKodeToad --- libraries/launcher/CMakeLists.txt | 3 +- .../exception/JsonParseException.java | 48 ++++++++++++++ .../launcher/org/prismlauncher/fix/Fixes.java | 6 +- .../org/prismlauncher/fix/skins/Handler.java | 60 +++++++---------- .../org/prismlauncher/fix/skins/SkinFix.java | 2 +- .../org/prismlauncher/utils/JsonParser.java | 12 +--- .../utils/url/NullConnection.java | 66 +++++++++++++++++++ .../utils/{ => url}/UrlUtils.java | 35 ++-------- 8 files changed, 153 insertions(+), 79 deletions(-) create mode 100644 libraries/launcher/org/prismlauncher/exception/JsonParseException.java create mode 100644 libraries/launcher/org/prismlauncher/utils/url/NullConnection.java rename libraries/launcher/org/prismlauncher/utils/{ => url}/UrlUtils.java (74%) diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index acc276218..65a8241eb 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -23,7 +23,8 @@ set(SRC org/prismlauncher/utils/JsonParser.java org/prismlauncher/utils/Parameters.java org/prismlauncher/utils/ReflectionUtils.java - org/prismlauncher/utils/UrlUtils.java + org/prismlauncher/utils/url/NullConnection.java + org/prismlauncher/utils/url/UrlUtils.java org/prismlauncher/utils/logging/Level.java org/prismlauncher/utils/logging/Log.java net/minecraft/Launcher.java diff --git a/libraries/launcher/org/prismlauncher/exception/JsonParseException.java b/libraries/launcher/org/prismlauncher/exception/JsonParseException.java new file mode 100644 index 000000000..5983eb883 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/exception/JsonParseException.java @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.exception; + +import java.io.IOException; + +public class JsonParseException extends IOException { + + private static final long serialVersionUID = 1L; + + public JsonParseException(String message) { + super(message); + } + +} \ No newline at end of file diff --git a/libraries/launcher/org/prismlauncher/fix/Fixes.java b/libraries/launcher/org/prismlauncher/fix/Fixes.java index ad472fea5..e099b653c 100644 --- a/libraries/launcher/org/prismlauncher/fix/Fixes.java +++ b/libraries/launcher/org/prismlauncher/fix/Fixes.java @@ -45,11 +45,11 @@ public final class Fixes { private static final Fix[] FIXES = { new SkinFix() }; - public static void apply(Parameters parameters) { - List fixes = parameters.getList("fixes", Collections.emptyList()); + public static void apply(Parameters params) { + List fixes = params.getList("fixes", Collections.emptyList()); for (Fix fix : FIXES) - if (fixes.contains(fix.getName()) && fix.isApplicable(parameters)) + if (fixes.contains(fix.getName()) && fix.isApplicable(params)) fix.apply(); } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java index 2bffeae96..0f5b556f8 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java @@ -45,61 +45,51 @@ import java.util.Map; import org.prismlauncher.utils.Base64; import org.prismlauncher.utils.JsonParser; -import org.prismlauncher.utils.UrlUtils; +import org.prismlauncher.utils.url.NullConnection; +import org.prismlauncher.utils.url.UrlUtils; @SuppressWarnings("unchecked") final class Handler extends URLStreamHandler { private URL redirect(URL address) throws IOException { String skinOwner = findSkinOwner(address); - if (skinOwner != null) - return convertSkin(address, skinOwner); + return convert(skinOwner, "SKIN"); String capeOwner = findCapeOwner(address); - if (capeOwner != null) - return convertCape(address, capeOwner); + return convert(capeOwner, "CAPE"); return address; } @Override protected URLConnection openConnection(URL address) throws IOException { - address = redirect(address); - return UrlUtils.openHttpConnection(address); + return openConnection(address, null); } @Override protected URLConnection openConnection(URL address, Proxy proxy) throws IOException { address = redirect(address); + + if (address == null) + return NullConnection.INSTANCE; + return UrlUtils.openHttpConnection(address, proxy); } - private URL convertSkin(URL defaultUrl, String owner) throws IOException { + private URL convert(String owner, String name) throws IOException { Map textures = getTextures(owner); if (textures != null) { - textures = (Map) textures.get("SKIN"); - return new URL((String) textures.get("url")); - } - - return defaultUrl; - } - - private URL convertCape(URL defaultUrl, String owner) throws IOException { - Map textures = getTextures(owner); - - if (textures != null) { - textures = (Map) textures.get("CAPE"); - + textures = (Map) textures.get(name); if (textures == null) - return defaultUrl; + return null; return new URL((String) textures.get("url")); } - return defaultUrl; + return null; } private static Map getTextures(String owner) throws IOException { @@ -116,6 +106,7 @@ final class Handler extends URLStreamHandler { Map result = (Map) JsonParser .parse(new String(Base64.decode((String) property.get("value")))); result = (Map) result.get("textures"); + return result; } } @@ -128,11 +119,11 @@ final class Handler extends URLStreamHandler { private static String findSkinOwner(URL address) { switch (address.getHost()) { case "www.minecraft.net": - return stripPng(strip(address.getPath(), "/skin/")); + return stripIfPrefixed(address.getPath(), "/skin/"); case "s3.amazonaws.com": case "skins.minecraft.net": - return stripPng(strip(address.getPath(), "/MinecraftSkins/")); + return stripIfPrefixed(address.getPath(), "/MinecraftSkins/"); } return null; @@ -141,26 +132,25 @@ final class Handler extends URLStreamHandler { private static String findCapeOwner(URL address) { switch (address.getHost()) { case "www.minecraft.net": - return stripPng(strip(address.getQuery(), "user=")); + return stripIfPrefixed(address.getQuery(), "user="); case "s3.amazonaws.com": case "skins.minecraft.net": - return stripPng(strip(address.getPath(), "/MinecraftCloaks/")); + return stripIfPrefixed(address.getPath(), "/MinecraftCloaks/"); } return null; } - private static String stripPng(String string) { - if (string != null && string.endsWith(".png")) - return string.substring(0, string.lastIndexOf('.')); + private static String stripIfPrefixed(String string, String prefix) { + if (string != null && string.startsWith(prefix)) { + string = string.substring(prefix.length()); - return string; - } + if (string.endsWith(".png")) + string = string.substring(0, string.lastIndexOf('.')); - private static String strip(String string, String prefix) { - if (string != null && string.startsWith(prefix)) - return string.substring(prefix.length()); + return string; + } return null; } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index 927c10142..e26dfb6f1 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -41,8 +41,8 @@ import java.net.URLStreamHandlerFactory; import org.prismlauncher.fix.Fix; import org.prismlauncher.utils.Parameters; -import org.prismlauncher.utils.UrlUtils; import org.prismlauncher.utils.logging.Log; +import org.prismlauncher.utils.url.UrlUtils; /** * Fixes skins by redirecting to other URLs. diff --git a/libraries/launcher/org/prismlauncher/utils/JsonParser.java b/libraries/launcher/org/prismlauncher/utils/JsonParser.java index d1803c896..378e58235 100644 --- a/libraries/launcher/org/prismlauncher/utils/JsonParser.java +++ b/libraries/launcher/org/prismlauncher/utils/JsonParser.java @@ -59,6 +59,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.prismlauncher.exception.JsonParseException; + /** * Single-file JSON parser to allow for usage in versions without GSON. */ @@ -420,14 +422,4 @@ public final class JsonParser { return character() == 'n' && read() == 'u' && read() == 'l' && read() == 'l'; } - public static class JsonParseException extends IOException { - - private static final long serialVersionUID = 1L; - - public JsonParseException(String message) { - super(message); - } - - } - } \ No newline at end of file diff --git a/libraries/launcher/org/prismlauncher/utils/url/NullConnection.java b/libraries/launcher/org/prismlauncher/utils/url/NullConnection.java new file mode 100644 index 000000000..628488e8d --- /dev/null +++ b/libraries/launcher/org/prismlauncher/utils/url/NullConnection.java @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.utils.url; + +import java.io.IOException; +import java.net.HttpURLConnection; + +/** + * Spoof 404 response from server to avoid unnecessary requests. + */ +public final class NullConnection extends HttpURLConnection { + + public static final NullConnection INSTANCE = new NullConnection(); + + public NullConnection() { + super(null); + } + + @Override + public void connect() throws IOException { + responseCode = 404; + } + + @Override + public void disconnect() { + } + + @Override + public boolean usingProxy() { + return false; + } + +} diff --git a/libraries/launcher/org/prismlauncher/utils/UrlUtils.java b/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java similarity index 74% rename from libraries/launcher/org/prismlauncher/utils/UrlUtils.java rename to libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java index 362feb4e3..751f833fd 100644 --- a/libraries/launcher/org/prismlauncher/utils/UrlUtils.java +++ b/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils; +package org.prismlauncher.utils.url; import java.io.IOException; import java.lang.invoke.MethodHandle; @@ -54,7 +54,6 @@ public final class UrlUtils { private static URLStreamHandler http; private static MethodHandle openConnection; - private static MethodHandle openConnectionProxied; static { try { @@ -64,18 +63,10 @@ public final class UrlUtils { getURLStreamHandler.setAccessible(true); http = (URLStreamHandler) getURLStreamHandler.invoke(null, "http"); - // reflection is required due to not having access - // unreflect is used due to the potential frequency of calls - Method openConnectionReflect = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class); + Method openConnectionReflect = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, + Proxy.class); openConnectionReflect.setAccessible(true); openConnection = MethodHandles.lookup().unreflect(openConnectionReflect); - - // a second method which takes in a proxy is required for a fully-functional - // URLStreamHandler - Method openConnectionReflectProxied = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, - Proxy.class); - openConnectionReflectProxied.setAccessible(true); - openConnectionProxied = MethodHandles.lookup().unreflect(openConnectionReflectProxied); } catch (Throwable e) { Log.error("URL reflection failed - some features may not work", e); } @@ -87,20 +78,16 @@ public final class UrlUtils { * @return true if all features can be used */ public static boolean isSupported() { - return http != null && openConnection != null && openConnectionProxied != null; - } - - public static URLConnection openHttpConnection(URL url) throws IOException { - return openConnection(http, url); + return http != null && openConnection != null; } public static URLConnection openHttpConnection(URL url, Proxy proxy) throws IOException { return openConnection(http, url, proxy); } - public static URLConnection openConnection(URLStreamHandler handler, URL url) throws IOException { + public static URLConnection openConnection(URLStreamHandler handler, URL url, Proxy proxy) throws IOException { try { - return (URLConnection) openConnection.invokeExact(handler, url); + return (URLConnection) openConnection.invokeExact(handler, url, proxy); } catch (IOException | Error | RuntimeException e) { throw e; // rethrow if possible } catch (Throwable e) { @@ -108,14 +95,4 @@ public final class UrlUtils { } } - public static URLConnection openConnection(URLStreamHandler handler, URL url, Proxy proxy) throws IOException { - try { - return (URLConnection) openConnectionProxied.invokeExact(handler, url, proxy); - } catch (IOException | Error | RuntimeException e) { - throw e; - } catch (Throwable e) { - throw new Error(e); - } - } - } From bfa5fe1598a6a60045fe01e589cc5f67cfe35f5a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 20 Nov 2022 09:55:30 +0000 Subject: [PATCH 006/398] Better skin fix error handling Signed-off-by: TheKodeToad --- libraries/launcher/org/prismlauncher/fix/Fixes.java | 13 ++++++++++--- .../org/prismlauncher/fix/skins/SkinFix.java | 8 +++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libraries/launcher/org/prismlauncher/fix/Fixes.java b/libraries/launcher/org/prismlauncher/fix/Fixes.java index e099b653c..e85bcfd42 100644 --- a/libraries/launcher/org/prismlauncher/fix/Fixes.java +++ b/libraries/launcher/org/prismlauncher/fix/Fixes.java @@ -40,6 +40,7 @@ import java.util.List; import org.prismlauncher.fix.skins.SkinFix; import org.prismlauncher.utils.Parameters; +import org.prismlauncher.utils.logging.Log; public final class Fixes { @@ -48,9 +49,15 @@ public final class Fixes { public static void apply(Parameters params) { List fixes = params.getList("fixes", Collections.emptyList()); - for (Fix fix : FIXES) - if (fixes.contains(fix.getName()) && fix.isApplicable(params)) - fix.apply(); + for (Fix fix : FIXES) { + if (fixes.contains(fix.getName()) && fix.isApplicable(params)) { + try { + fix.apply(); + } catch (Throwable e) { + Log.error("Could not apply " + fix.getName(), e); + } + } + } } } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index e26dfb6f1..ab978dc58 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -71,7 +71,13 @@ public final class SkinFix implements Fix, URLStreamHandlerFactory { @Override public void apply() { - URL.setURLStreamHandlerFactory(this); + try { + URL.setURLStreamHandlerFactory(this); + } catch (Error e) { + Log.warning("Cannot apply skin fix"); + Log.warning("URLStreamHandlerFactory is already set"); + Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); + } } @Override From 8a6776731af94e768831440f27d3e9e8e81ab7bf Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 22 Nov 2022 16:56:58 +0000 Subject: [PATCH 007/398] Use reflection to access DatatypeConverter Signed-off-by: TheKodeToad --- .../org/prismlauncher/fix/skins/SkinFix.java | 3 +- .../org/prismlauncher/utils/Base64.java | 53 +++++++++++++++---- .../org/prismlauncher/utils/url/UrlUtils.java | 6 +++ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index ab978dc58..66b5fda62 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -40,6 +40,7 @@ import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; import org.prismlauncher.fix.Fix; +import org.prismlauncher.utils.Base64; import org.prismlauncher.utils.Parameters; import org.prismlauncher.utils.logging.Log; import org.prismlauncher.utils.url.UrlUtils; @@ -59,7 +60,7 @@ public final class SkinFix implements Fix, URLStreamHandlerFactory { @Override public boolean isApplicable(Parameters params) { - if (!UrlUtils.isSupported()) { + if (!UrlUtils.isSupported() || !Base64.isSupported()) { Log.warning("Cannot access the necessary Java internals for skin fix"); Log.warning("Try adding '--add-opens java.base/java.net=ALL-UNNAMED' to your Java arguments"); Log.warning("Alternatively, turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); diff --git a/libraries/launcher/org/prismlauncher/utils/Base64.java b/libraries/launcher/org/prismlauncher/utils/Base64.java index 20a189f46..508df872d 100644 --- a/libraries/launcher/org/prismlauncher/utils/Base64.java +++ b/libraries/launcher/org/prismlauncher/utils/Base64.java @@ -35,25 +35,60 @@ package org.prismlauncher.utils; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.nio.charset.StandardCharsets; -import javax.xml.bind.DatatypeConverter; +import org.prismlauncher.utils.logging.Log; +/** + * Uses Base64 with Java 8 or later, otherwise DatatypeConverter. In the latter + * case, reflection is used to allow using newer compilers. + */ public final class Base64 { - private static boolean legacy; + private static boolean supported = true; + private static MethodHandle legacy; - public static byte[] decode(String input) { - if (!legacy) { + static { + try { + Class.forName("java.util.Base64"); + } catch (ClassNotFoundException e) { try { - return java.util.Base64.getDecoder().decode(input.getBytes(StandardCharsets.UTF_8)); - } catch (NoClassDefFoundError e) { - legacy = true; + Class datatypeConverter = Class.forName("javax.xml.bind.DatatypeConverter"); + legacy = MethodHandles.lookup().findStatic(datatypeConverter, "parseBase64Binary", + MethodType.methodType(byte[].class, String.class)); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e1) { + Log.error("Base64 not supported", e1); + supported = false; } } + } - // support for Java versions < 8 - return DatatypeConverter.parseBase64Binary(input); + /** + * Determines whether base64 is supported. + * + * @return true if base64 can be parsed + */ + public static boolean isSupported() { + return supported; + } + + public static byte[] decode(String input) { + if (!isSupported()) + throw new UnsupportedOperationException(); + + if (legacy == null) + return java.util.Base64.getDecoder().decode(input.getBytes(StandardCharsets.UTF_8)); + + try { + return (byte[]) legacy.invokeExact(input); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new Error(e); + } } } diff --git a/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java b/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java index 751f833fd..05912d005 100644 --- a/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java +++ b/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java @@ -82,10 +82,16 @@ public final class UrlUtils { } public static URLConnection openHttpConnection(URL url, Proxy proxy) throws IOException { + if (http == null) + throw new UnsupportedOperationException(); + return openConnection(http, url, proxy); } public static URLConnection openConnection(URLStreamHandler handler, URL url, Proxy proxy) throws IOException { + if (openConnection == null) + throw new UnsupportedOperationException(); + try { return (URLConnection) openConnection.invokeExact(handler, url, proxy); } catch (IOException | Error | RuntimeException e) { From 87bcefd08ac5023a6b406bc6c909ddff7d6ca1bf Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 15 Dec 2022 15:28:17 +0000 Subject: [PATCH 008/398] Automatically add add-opens if Java version >= 9 Signed-off-by: TheKodeToad --- launcher/java/JavaVersion.cpp | 10 +++++----- launcher/java/JavaVersion.h | 2 ++ launcher/minecraft/MinecraftInstance.cpp | 10 +++++----- .../launcher/org/prismlauncher/fix/skins/SkinFix.java | 3 +-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp index 0e4fc1d3c..cfb12fbf3 100644 --- a/launcher/java/JavaVersion.cpp +++ b/launcher/java/JavaVersion.cpp @@ -50,11 +50,11 @@ QString JavaVersion::toString() bool JavaVersion::requiresPermGen() { - if(m_parseable) - { - return m_major < 8; - } - return true; + return !m_parseable || m_major < 8; +} + +bool JavaVersion::isModular() { + return m_parseable && m_major >= 9; } bool JavaVersion::operator<(const JavaVersion &rhs) diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h index 9bbf06425..0551214ad 100644 --- a/launcher/java/JavaVersion.h +++ b/launcher/java/JavaVersion.h @@ -25,6 +25,8 @@ public: bool requiresPermGen(); + bool isModular(); + QString toString(); int major() diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 91de955ad..4434936f0 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -440,15 +440,15 @@ QStringList MinecraftInstance::javaArguments() args << "-Duser.language=en"; + if (javaVersion.isModular() && traits().contains("legacySkins") && settings()->get("LegacySkinFix").toBool()) + args << "--add-opens" << "java.base/java.net=ALL-UNNAMED"; + return args; } -QString MinecraftInstance::getLauncher() -{ - auto profile = m_components->getProfile(); - +QString MinecraftInstance::getLauncher() { // use legacy launcher if the traits are set - if (profile->getTraits().contains("legacyLaunch") || profile->getTraits().contains("alphaLaunch")) + if (traits().contains("legacyLaunch") || traits().contains("alphaLaunch")) return "legacy"; return "standard"; diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index 66b5fda62..19b15605a 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -62,8 +62,7 @@ public final class SkinFix implements Fix, URLStreamHandlerFactory { public boolean isApplicable(Parameters params) { if (!UrlUtils.isSupported() || !Base64.isSupported()) { Log.warning("Cannot access the necessary Java internals for skin fix"); - Log.warning("Try adding '--add-opens java.base/java.net=ALL-UNNAMED' to your Java arguments"); - Log.warning("Alternatively, turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); + Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); return false; } From 94067f34cf8a42c735c264ca30740bfec6f5af3a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 21 Dec 2022 18:13:41 +0000 Subject: [PATCH 009/398] Try to make some of the suggested changes Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 6 +- libraries/launcher/CMakeLists.txt | 3 +- .../org/prismlauncher/fix/skins/Handler.java | 7 +- .../org/prismlauncher/fix/skins/SkinFix.java | 2 +- .../utils/{url => }/UrlUtils.java | 14 ++-- .../utils/url/NullConnection.java | 66 ------------------- 6 files changed, 14 insertions(+), 84 deletions(-) rename libraries/launcher/org/prismlauncher/utils/{url => }/UrlUtils.java (91%) delete mode 100644 libraries/launcher/org/prismlauncher/utils/url/NullConnection.java diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 4434936f0..378af0e10 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -192,7 +192,7 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerSetting("JoinServerOnLaunch", false); m_settings->registerSetting("JoinServerOnLaunchAddress", ""); - m_settings->registerSetting("LegacySkinFix", true); + m_settings->registerSetting("LegacySkinFix", true); qDebug() << "Instance-type specific settings were loaded!"; @@ -441,7 +441,9 @@ QStringList MinecraftInstance::javaArguments() args << "-Duser.language=en"; if (javaVersion.isModular() && traits().contains("legacySkins") && settings()->get("LegacySkinFix").toBool()) - args << "--add-opens" << "java.base/java.net=ALL-UNNAMED"; + // allow reflective access to java.net - required by the skin fix + args << "--add-opens" + << "java.base/java.net=ALL-UNNAMED"; return args; } diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index 65a8241eb..acc276218 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -23,8 +23,7 @@ set(SRC org/prismlauncher/utils/JsonParser.java org/prismlauncher/utils/Parameters.java org/prismlauncher/utils/ReflectionUtils.java - org/prismlauncher/utils/url/NullConnection.java - org/prismlauncher/utils/url/UrlUtils.java + org/prismlauncher/utils/UrlUtils.java org/prismlauncher/utils/logging/Level.java org/prismlauncher/utils/logging/Log.java net/minecraft/Launcher.java diff --git a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java index 0f5b556f8..fa306ed44 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/Handler.java @@ -45,8 +45,7 @@ import java.util.Map; import org.prismlauncher.utils.Base64; import org.prismlauncher.utils.JsonParser; -import org.prismlauncher.utils.url.NullConnection; -import org.prismlauncher.utils.url.UrlUtils; +import org.prismlauncher.utils.UrlUtils; @SuppressWarnings("unchecked") final class Handler extends URLStreamHandler { @@ -71,10 +70,6 @@ final class Handler extends URLStreamHandler { @Override protected URLConnection openConnection(URL address, Proxy proxy) throws IOException { address = redirect(address); - - if (address == null) - return NullConnection.INSTANCE; - return UrlUtils.openHttpConnection(address, proxy); } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java index 19b15605a..3dd747376 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java @@ -42,8 +42,8 @@ import java.net.URLStreamHandlerFactory; import org.prismlauncher.fix.Fix; import org.prismlauncher.utils.Base64; import org.prismlauncher.utils.Parameters; +import org.prismlauncher.utils.UrlUtils; import org.prismlauncher.utils.logging.Log; -import org.prismlauncher.utils.url.UrlUtils; /** * Fixes skins by redirecting to other URLs. diff --git a/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java b/libraries/launcher/org/prismlauncher/utils/UrlUtils.java similarity index 91% rename from libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java rename to libraries/launcher/org/prismlauncher/utils/UrlUtils.java index 05912d005..1ab0eb918 100644 --- a/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java +++ b/libraries/launcher/org/prismlauncher/utils/UrlUtils.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils.url; +package org.prismlauncher.utils; import java.io.IOException; import java.lang.invoke.MethodHandle; @@ -47,8 +47,8 @@ import java.net.URLStreamHandler; import org.prismlauncher.utils.logging.Log; /** - * A utility class for URLs which uses reflection to access hidden methods. - * Unfortunately not supported on newer Java versions. + * A utility class for URLs which uses reflection to access constructors for + * internal classes. */ public final class UrlUtils { @@ -57,12 +57,12 @@ public final class UrlUtils { static { try { - // invoke URL.getURLStreamHandler to obtain some of the default handlers before - // they are overridden + // we first obtain the stock URLStreamHandler for http as we overwrite it later Method getURLStreamHandler = URL.class.getDeclaredMethod("getURLStreamHandler", String.class); getURLStreamHandler.setAccessible(true); http = (URLStreamHandler) getURLStreamHandler.invoke(null, "http"); + // we next find the openConnection method Method openConnectionReflect = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, Proxy.class); openConnectionReflect.setAccessible(true); @@ -97,8 +97,8 @@ public final class UrlUtils { } catch (IOException | Error | RuntimeException e) { throw e; // rethrow if possible } catch (Throwable e) { - throw new Error(e); // otherwise, wrap in Error + throw new AssertionError(e); // oh dear! this isn't meant to happen } } -} +} \ No newline at end of file diff --git a/libraries/launcher/org/prismlauncher/utils/url/NullConnection.java b/libraries/launcher/org/prismlauncher/utils/url/NullConnection.java deleted file mode 100644 index 628488e8d..000000000 --- a/libraries/launcher/org/prismlauncher/utils/url/NullConnection.java +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 TheKodeToad - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Linking this library statically or dynamically with other modules is - * making a combined work based on this library. Thus, the terms and - * conditions of the GNU General Public License cover the whole - * combination. - * - * As a special exception, the copyright holders of this library give - * you permission to link this library with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also meet, - * for each linked independent module, the terms and conditions of the - * license of that module. An independent module is a module which is - * not derived from or based on this library. If you modify this - * library, you may extend this exception to your version of the - * library, but you are not obliged to do so. If you do not wish to do - * so, delete this exception statement from your version. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.prismlauncher.utils.url; - -import java.io.IOException; -import java.net.HttpURLConnection; - -/** - * Spoof 404 response from server to avoid unnecessary requests. - */ -public final class NullConnection extends HttpURLConnection { - - public static final NullConnection INSTANCE = new NullConnection(); - - public NullConnection() { - super(null); - } - - @Override - public void connect() throws IOException { - responseCode = 404; - } - - @Override - public void disconnect() { - } - - @Override - public boolean usingProxy() { - return false; - } - -} From 884bd8549537cb67a9e59c83ab4ca761491ff27b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 23 Dec 2022 09:35:29 +0000 Subject: [PATCH 010/398] Skin fix -> online fixes Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 8 +-- .../pages/instance/InstanceSettingsPage.cpp | 8 +-- .../ui/pages/instance/InstanceSettingsPage.ui | 6 +- libraries/launcher/CMakeLists.txt | 6 +- .../launcher/org/prismlauncher/fix/Fixes.java | 21 +------ .../fix/{Fix.java => online/Handler.java} | 38 ++++++------ .../SkinFix.java => online/OnlineFixes.java} | 26 ++------- .../Handler.java => online/SkinFix.java} | 58 ++----------------- 8 files changed, 44 insertions(+), 127 deletions(-) rename libraries/launcher/org/prismlauncher/fix/{Fix.java => online/Handler.java} (73%) rename libraries/launcher/org/prismlauncher/fix/{skins/SkinFix.java => online/OnlineFixes.java} (82%) rename libraries/launcher/org/prismlauncher/fix/{skins/Handler.java => online/SkinFix.java} (56%) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 378af0e10..ec916f26f 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -192,7 +192,7 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerSetting("JoinServerOnLaunch", false); m_settings->registerSetting("JoinServerOnLaunchAddress", ""); - m_settings->registerSetting("LegacySkinFix", true); + m_settings->registerSetting("OnlineFixes", true); qDebug() << "Instance-type specific settings were loaded!"; @@ -440,7 +440,7 @@ QStringList MinecraftInstance::javaArguments() args << "-Duser.language=en"; - if (javaVersion.isModular() && traits().contains("legacySkins") && settings()->get("LegacySkinFix").toBool()) + if (javaVersion.isModular() && traits().contains("legacyServices") && settings()->get("OnlineFixes").toBool()) // allow reflective access to java.net - required by the skin fix args << "--add-opens" << "java.base/java.net=ALL-UNNAMED"; @@ -665,8 +665,8 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS launchScript += "traits " + trait + "\n"; } - if (profile->getTraits().contains("legacySkins") && settings()->get("LegacySkinFix").toBool()) - launchScript += "fixes legacySkinFix\n"; + if (profile->getTraits().contains("legacyServices") && settings()->get("OnlineFixes").toBool()) + launchScript += "onlineFixes true\n"; launchScript += "launcher " + getLauncher() + "\n"; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 537271a2c..23299b1dc 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -276,8 +276,8 @@ void InstanceSettingsPage::applySettings() m_settings->reset("JoinServerOnLaunchAddress"); } - bool legacySkinFix = ui->legacySkinFix->isChecked(); - m_settings->set("LegacySkinFix", legacySkinFix); + bool onlineFixes = ui->onlineFixes->isChecked(); + m_settings->set("OnlineFixes", onlineFixes); // FIXME: This should probably be called by a signal instead m_instance->updateRuntimeContext(); @@ -377,8 +377,8 @@ void InstanceSettingsPage::loadSettings() ui->serverJoinGroupBox->setChecked(m_settings->get("JoinServerOnLaunch").toBool()); ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString()); - ui->legacySkinFix->setChecked(m_settings->get("LegacySkinFix").toBool()); - ui->legacySkinFix->setVisible(m_instance->traits().contains("legacySkins")); + ui->onlineFixes->setChecked(m_settings->get("OnlineFixes").toBool()); + ui->onlineFixes->setVisible(m_instance->traits().contains("legacyServices")); } void InstanceSettingsPage::on_javaDetectBtn_clicked() diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index ca49cbbe5..7b42b8397 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -609,12 +609,12 @@ - + - Enables support for modern skins on old versions. + <html><head/><body><p>Fixes usages of old online services which are no longer operating by emulating them or redirecting to their modern counterparts.</p><p>This currently only allows modern skins to be used.</p></body></html> - Enable legacy skin fix + Enable online fixes diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index acc276218..71996ae33 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -15,10 +15,10 @@ set(SRC org/prismlauncher/launcher/impl/legacy/LegacyFrame.java org/prismlauncher/exception/ParameterNotFoundException.java org/prismlauncher/exception/ParseException.java - org/prismlauncher/fix/Fix.java org/prismlauncher/fix/Fixes.java - org/prismlauncher/fix/skins/SkinFix.java - org/prismlauncher/fix/skins/Handler.java + org/prismlauncher/fix/online/OnlineFixes.java + org/prismlauncher/fix/online/SkinFix.java + org/prismlauncher/fix/online/Handler.java org/prismlauncher/utils/Base64.java org/prismlauncher/utils/JsonParser.java org/prismlauncher/utils/Parameters.java diff --git a/libraries/launcher/org/prismlauncher/fix/Fixes.java b/libraries/launcher/org/prismlauncher/fix/Fixes.java index e85bcfd42..429964ad9 100644 --- a/libraries/launcher/org/prismlauncher/fix/Fixes.java +++ b/libraries/launcher/org/prismlauncher/fix/Fixes.java @@ -35,29 +35,14 @@ package org.prismlauncher.fix; -import java.util.Collections; -import java.util.List; - -import org.prismlauncher.fix.skins.SkinFix; +import org.prismlauncher.fix.online.OnlineFixes; import org.prismlauncher.utils.Parameters; -import org.prismlauncher.utils.logging.Log; public final class Fixes { - private static final Fix[] FIXES = { new SkinFix() }; - public static void apply(Parameters params) { - List fixes = params.getList("fixes", Collections.emptyList()); - - for (Fix fix : FIXES) { - if (fixes.contains(fix.getName()) && fix.isApplicable(params)) { - try { - fix.apply(); - } catch (Throwable e) { - Log.error("Could not apply " + fix.getName(), e); - } - } - } + if ("true".equalsIgnoreCase(params.getString("onlineFixes", null))) + OnlineFixes.apply(); } } diff --git a/libraries/launcher/org/prismlauncher/fix/Fix.java b/libraries/launcher/org/prismlauncher/fix/online/Handler.java similarity index 73% rename from libraries/launcher/org/prismlauncher/fix/Fix.java rename to libraries/launcher/org/prismlauncher/fix/online/Handler.java index 3ecd2e90a..b5b4de28e 100644 --- a/libraries/launcher/org/prismlauncher/fix/Fix.java +++ b/libraries/launcher/org/prismlauncher/fix/online/Handler.java @@ -33,31 +33,27 @@ * along with this program. If not, see . */ -package org.prismlauncher.fix; +package org.prismlauncher.fix.online; -import org.prismlauncher.utils.Parameters; +import java.io.IOException; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; -public interface Fix { +import org.prismlauncher.utils.UrlUtils; - /** - * Gets the name of the fix. If the name isn't passed into the program, the fix - * won't run. - * - * @return The name - */ - String getName(); +final class Handler extends URLStreamHandler { - /** - * Determines whether the fix will be run. This is additional to the name check. - * - * @param params The parameters - * @return true to proceed to applying the fix - */ - boolean isApplicable(Parameters params); + @Override + protected URLConnection openConnection(URL address) throws IOException { + return openConnection(address, null); + } - /** - * Applies the fix. - */ - void apply(); + @Override + protected URLConnection openConnection(URL address, Proxy proxy) throws IOException { + address = SkinFix.redirect(address); + return UrlUtils.openHttpConnection(address, proxy); + } } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java similarity index 82% rename from libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java rename to libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java index 3dd747376..c344a8e73 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java @@ -33,15 +33,13 @@ * along with this program. If not, see . */ -package org.prismlauncher.fix.skins; +package org.prismlauncher.fix.online; import java.net.URL; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; -import org.prismlauncher.fix.Fix; import org.prismlauncher.utils.Base64; -import org.prismlauncher.utils.Parameters; import org.prismlauncher.utils.UrlUtils; import org.prismlauncher.utils.logging.Log; @@ -51,31 +49,19 @@ import org.prismlauncher.utils.logging.Log; * @see {@link Handler} * @see {@link UrlUtils} */ -public final class SkinFix implements Fix, URLStreamHandlerFactory { +public final class OnlineFixes implements URLStreamHandlerFactory { - @Override - public String getName() { - return "legacySkinFix"; - } - - @Override - public boolean isApplicable(Parameters params) { + public static void apply() { if (!UrlUtils.isSupported() || !Base64.isSupported()) { Log.warning("Cannot access the necessary Java internals for skin fix"); Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); - return false; + return; } - return true; - } - - @Override - public void apply() { try { - URL.setURLStreamHandlerFactory(this); + URL.setURLStreamHandlerFactory(new OnlineFixes()); } catch (Error e) { - Log.warning("Cannot apply skin fix"); - Log.warning("URLStreamHandlerFactory is already set"); + Log.warning("Cannot apply skin fix: URLStreamHandlerFactory is already set"); Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); } } diff --git a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java b/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java similarity index 56% rename from libraries/launcher/org/prismlauncher/fix/skins/Handler.java rename to libraries/launcher/org/prismlauncher/fix/online/SkinFix.java index fa306ed44..f1e480776 100644 --- a/libraries/launcher/org/prismlauncher/fix/skins/Handler.java +++ b/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java @@ -1,56 +1,17 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 TheKodeToad - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Linking this library statically or dynamically with other modules is - * making a combined work based on this library. Thus, the terms and - * conditions of the GNU General Public License cover the whole - * combination. - * - * As a special exception, the copyright holders of this library give - * you permission to link this library with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also meet, - * for each linked independent module, the terms and conditions of the - * license of that module. An independent module is a module which is - * not derived from or based on this library. If you modify this - * library, you may extend this exception to your version of the - * library, but you are not obliged to do so. If you do not wish to do - * so, delete this exception statement from your version. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.prismlauncher.fix.skins; +package org.prismlauncher.fix.online; import java.io.IOException; import java.io.InputStream; -import java.net.Proxy; import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; import java.util.Map; import org.prismlauncher.utils.Base64; import org.prismlauncher.utils.JsonParser; -import org.prismlauncher.utils.UrlUtils; @SuppressWarnings("unchecked") -final class Handler extends URLStreamHandler { +final class SkinFix { - private URL redirect(URL address) throws IOException { + static URL redirect(URL address) throws IOException { String skinOwner = findSkinOwner(address); if (skinOwner != null) return convert(skinOwner, "SKIN"); @@ -62,18 +23,7 @@ final class Handler extends URLStreamHandler { return address; } - @Override - protected URLConnection openConnection(URL address) throws IOException { - return openConnection(address, null); - } - - @Override - protected URLConnection openConnection(URL address, Proxy proxy) throws IOException { - address = redirect(address); - return UrlUtils.openHttpConnection(address, proxy); - } - - private URL convert(String owner, String name) throws IOException { + private static URL convert(String owner, String name) throws IOException { Map textures = getTextures(owner); if (textures != null) { From 5c96b1c6289d0f31b073153668140e84066e87f2 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Dec 2022 09:45:42 +0000 Subject: [PATCH 011/398] Remove MIT license from JsonParser I don't mind, and it's my code. Signed-off-by: TheKodeToad --- .../org/prismlauncher/utils/JsonParser.java | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/libraries/launcher/org/prismlauncher/utils/JsonParser.java b/libraries/launcher/org/prismlauncher/utils/JsonParser.java index 378e58235..5f10e9a7b 100644 --- a/libraries/launcher/org/prismlauncher/utils/JsonParser.java +++ b/libraries/launcher/org/prismlauncher/utils/JsonParser.java @@ -31,19 +31,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * MIT License - * - * Copyright (c) 2022 TheKodeToad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package org.prismlauncher.utils; @@ -422,4 +409,4 @@ public final class JsonParser { return character() == 'n' && read() == 'u' && read() == 'l' && read() == 'l'; } -} \ No newline at end of file +} From cb32711077af62b527abdc4af5aabce44f4e5d21 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Dec 2022 11:40:49 +0000 Subject: [PATCH 012/398] Slim skin fix - thanks to @craftycodie and @DelofJ ! Signed-off-by: TheKodeToad --- libraries/launcher/CMakeLists.txt | 5 +- .../org/prismlauncher/fix/online/Handler.java | 12 ++- .../prismlauncher/fix/online/OnlineFixes.java | 2 +- .../org/prismlauncher/fix/online/SkinFix.java | 94 +++++++++------- .../prismlauncher/utils/api/MojangApi.java | 101 ++++++++++++++++++ .../org/prismlauncher/utils/api/Texture.java | 61 +++++++++++ .../utils/url/CustomUrlConnection.java | 79 ++++++++++++++ .../utils/{ => url}/UrlUtils.java | 12 ++- 8 files changed, 322 insertions(+), 44 deletions(-) create mode 100644 libraries/launcher/org/prismlauncher/utils/api/MojangApi.java create mode 100644 libraries/launcher/org/prismlauncher/utils/api/Texture.java create mode 100644 libraries/launcher/org/prismlauncher/utils/url/CustomUrlConnection.java rename libraries/launcher/org/prismlauncher/utils/{ => url}/UrlUtils.java (89%) diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index 71996ae33..bf8f0baa2 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -23,9 +23,12 @@ set(SRC org/prismlauncher/utils/JsonParser.java org/prismlauncher/utils/Parameters.java org/prismlauncher/utils/ReflectionUtils.java - org/prismlauncher/utils/UrlUtils.java + org/prismlauncher/utils/api/MojangApi.java + org/prismlauncher/utils/api/Texture.java org/prismlauncher/utils/logging/Level.java org/prismlauncher/utils/logging/Log.java + org/prismlauncher/utils/url/UrlUtils.java + org/prismlauncher/utils/url/CustomUrlConnection.java net/minecraft/Launcher.java ) add_jar(NewLaunch ${SRC}) diff --git a/libraries/launcher/org/prismlauncher/fix/online/Handler.java b/libraries/launcher/org/prismlauncher/fix/online/Handler.java index b5b4de28e..618683119 100644 --- a/libraries/launcher/org/prismlauncher/fix/online/Handler.java +++ b/libraries/launcher/org/prismlauncher/fix/online/Handler.java @@ -41,7 +41,7 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; -import org.prismlauncher.utils.UrlUtils; +import org.prismlauncher.utils.url.UrlUtils; final class Handler extends URLStreamHandler { @@ -52,8 +52,14 @@ final class Handler extends URLStreamHandler { @Override protected URLConnection openConnection(URL address, Proxy proxy) throws IOException { - address = SkinFix.redirect(address); - return UrlUtils.openHttpConnection(address, proxy); + URLConnection result; + + // try skin fix + result = SkinFix.openConnection(address, proxy); + if (result != null) + return result; + + return UrlUtils.openConnection(address, proxy); } } diff --git a/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java b/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java index c344a8e73..5f9ff1014 100644 --- a/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java +++ b/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java @@ -40,8 +40,8 @@ import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; import org.prismlauncher.utils.Base64; -import org.prismlauncher.utils.UrlUtils; import org.prismlauncher.utils.logging.Log; +import org.prismlauncher.utils.url.UrlUtils; /** * Fixes skins by redirecting to other URLs. diff --git a/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java b/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java index f1e480776..b05e1f208 100644 --- a/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java +++ b/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java @@ -1,63 +1,85 @@ package org.prismlauncher.fix.online; +import java.awt.AlphaComposite; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.Proxy; import java.net.URL; -import java.util.Map; +import java.net.URLConnection; -import org.prismlauncher.utils.Base64; -import org.prismlauncher.utils.JsonParser; +import javax.imageio.ImageIO; + +import org.prismlauncher.utils.api.MojangApi; +import org.prismlauncher.utils.api.Texture; +import org.prismlauncher.utils.url.CustomUrlConnection; +import org.prismlauncher.utils.url.UrlUtils; -@SuppressWarnings("unchecked") final class SkinFix { - static URL redirect(URL address) throws IOException { + static URLConnection openConnection(URL address, Proxy proxy) throws IOException { String skinOwner = findSkinOwner(address); if (skinOwner != null) - return convert(skinOwner, "SKIN"); + // we need to correct the skin + return getSkinConnection(skinOwner, proxy); String capeOwner = findCapeOwner(address); - if (capeOwner != null) - return convert(capeOwner, "CAPE"); - - return address; - } - - private static URL convert(String owner, String name) throws IOException { - Map textures = getTextures(owner); - - if (textures != null) { - textures = (Map) textures.get(name); - if (textures == null) + if (capeOwner != null) { + // since we do not need to process the image, open a direct connection bypassing Handler + Texture texture = MojangApi.getTexture(MojangApi.getUuid(capeOwner), "CAPE"); + if (texture == null) return null; - return new URL((String) textures.get("url")); + return UrlUtils.openConnection(texture.getUrl(), proxy); } return null; } - private static Map getTextures(String owner) throws IOException { - try (InputStream in = new URL("https://api.mojang.com/users/profiles/minecraft/" + owner).openStream()) { - Map map = (Map) JsonParser.parse(in); - String id = (String) map.get("id"); + private static URLConnection getSkinConnection(String owner, Proxy proxy) throws IOException { + Texture texture = MojangApi.getTexture(MojangApi.getUuid(owner), "SKIN"); + if (texture == null) + return null; - try (InputStream profileIn = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + id) - .openStream()) { - Map profile = (Map) JsonParser.parse(profileIn); + URLConnection connection = UrlUtils.openConnection(texture.getUrl(), proxy); + try (InputStream in = connection.getInputStream()) { + // thank you craftycodie! + // this is heavily based on + // https://github.com/Mojang/LegacyLauncher/pull/33/files#diff-b61023785a9260651ca0a223573ea9acb5be5eec478bff626dafb7abe13ffebaR99 + BufferedImage image = ImageIO.read(in); + Graphics2D graphics = image.createGraphics(); + graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); - for (Map property : (Iterable>) profile.get("properties")) { - if (property.get("name").equals("textures")) { - Map result = (Map) JsonParser - .parse(new String(Base64.decode((String) property.get("value")))); - result = (Map) result.get("textures"); + BufferedImage subimage; - return result; - } - } - - return null; + if (image.getHeight() > 32) { + // flatten second layers + subimage = image.getSubimage(0, 32, 56, 16); + graphics.drawImage(subimage, 0, 16, null); } + + if (texture.isSlim()) { + // convert slim to wide + subimage = image.getSubimage(45, 16, 9, 16); + graphics.drawImage(subimage, 46, 16, null); + + subimage = image.getSubimage(49, 16, 2, 4); + graphics.drawImage(subimage, 50, 16, null); + + subimage = image.getSubimage(53, 20, 2, 12); + graphics.drawImage(subimage, 54, 20, null); + } + + graphics.dispose(); + + // crop the image + ByteArrayOutputStream out = new ByteArrayOutputStream(); + image = image.getSubimage(0, 0, 64, 32); + ImageIO.write(image, "png", out); + + return new CustomUrlConnection(out.toByteArray()); } } diff --git a/libraries/launcher/org/prismlauncher/utils/api/MojangApi.java b/libraries/launcher/org/prismlauncher/utils/api/MojangApi.java new file mode 100644 index 000000000..dc2794107 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/utils/api/MojangApi.java @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.utils.api; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Map; + +import org.prismlauncher.utils.Base64; +import org.prismlauncher.utils.JsonParser; + +/** + * Basic access to Mojang's Minecraft API. + */ +@SuppressWarnings("unchecked") +public final class MojangApi { + + public static String getUuid(String username) throws IOException { + try (InputStream in = new URL("https://api.mojang.com/users/profiles/minecraft/" + username).openStream()) { + Map map = (Map) JsonParser.parse(in); + return (String) map.get("id"); + } + } + + public static Texture getTexture(String player, String name) throws IOException { + Map map = getTextures(player); + + if (map != null) { + map = (Map) map.get(name); + if (map == null) + return null; + + URL url = new URL((String) map.get("url")); + boolean slim = false; + + if (name.equals("SKIN")) { + map = (Map) map.get("metadata"); + if (map != null && "slim".equals(map.get("model"))) + slim = true; + } + + return new Texture(url, slim); + } + + return null; + } + + public static Map getTextures(String player) throws IOException { + try (InputStream profileIn = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + player) + .openStream()) { + Map profile = (Map) JsonParser.parse(profileIn); + + for (Map property : (Iterable>) profile.get("properties")) { + if (property.get("name").equals("textures")) { + Map result = (Map) JsonParser + .parse(new String(Base64.decode((String) property.get("value")))); + result = (Map) result.get("textures"); + + return result; + } + } + + return null; + } + } + +} diff --git a/libraries/launcher/org/prismlauncher/utils/api/Texture.java b/libraries/launcher/org/prismlauncher/utils/api/Texture.java new file mode 100644 index 000000000..1b5c2204e --- /dev/null +++ b/libraries/launcher/org/prismlauncher/utils/api/Texture.java @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.utils.api; + +import java.net.URL; + +/** + * Represents a texture from the Mojang API. + */ +public final class Texture { + + private final URL url; + private final boolean slim; + + public Texture(URL url, boolean slim) { + this.url = url; + this.slim = slim; + } + + public URL getUrl() { + return url; + } + + public boolean isSlim() { + return slim; + } + +} diff --git a/libraries/launcher/org/prismlauncher/utils/url/CustomUrlConnection.java b/libraries/launcher/org/prismlauncher/utils/url/CustomUrlConnection.java new file mode 100644 index 000000000..8bc0cff11 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/utils/url/CustomUrlConnection.java @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.prismlauncher.utils.url; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + +public class CustomUrlConnection extends HttpURLConnection { + + private InputStream in; + + public CustomUrlConnection(byte[] data) { + this(new ByteArrayInputStream(data)); + } + + public CustomUrlConnection(InputStream in) { + super(null); + this.in = in; + } + + @Override + public void connect() throws IOException { + responseCode = 200; + } + + @Override + public void disconnect() { + try { + in.close(); + } catch (IOException e) { + } + } + + @Override + public InputStream getInputStream() throws IOException { + return in; + } + + @Override + public boolean usingProxy() { + return false; + } + +} diff --git a/libraries/launcher/org/prismlauncher/utils/UrlUtils.java b/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java similarity index 89% rename from libraries/launcher/org/prismlauncher/utils/UrlUtils.java rename to libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java index 1ab0eb918..69ebbd50b 100644 --- a/libraries/launcher/org/prismlauncher/utils/UrlUtils.java +++ b/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils; +package org.prismlauncher.utils.url; import java.io.IOException; import java.lang.invoke.MethodHandle; @@ -81,11 +81,17 @@ public final class UrlUtils { return http != null && openConnection != null; } - public static URLConnection openHttpConnection(URL url, Proxy proxy) throws IOException { + public static URLConnection openConnection(URL url, Proxy proxy) throws IOException { if (http == null) throw new UnsupportedOperationException(); - return openConnection(http, url, proxy); + if (url.getProtocol().equals("http")) + return openConnection(http, url, proxy); + + // fall back to Java's default method + // at this point, this should not cause a StackOverflowError unless we've missed + // a protocol out from the if statements + return url.openConnection(); } public static URLConnection openConnection(URLStreamHandler handler, URL url, Proxy proxy) throws IOException { From 17317ea308d3523a4ead9c926e8f2213d7ea53ea Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 6 Jan 2023 09:21:09 +0000 Subject: [PATCH 013/398] Move legacy support classes to another jar Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 12 +++- launcher/minecraft/MinecraftInstance.h | 1 + .../minecraft/launch/LauncherPartLaunch.cpp | 16 +++++ libraries/launcher/CMakeLists.txt | 34 +++++++---- .../{ => legacy}/net/minecraft/Launcher.java | 0 .../prismlauncher}/legacy/LegacyFrame.java | 4 +- .../prismlauncher}/legacy/LegacyLauncher.java | 49 ++++++++++++--- .../org/prismlauncher/legacy/LegacyProxy.java | 17 ++++++ .../legacy}/fix/online/Handler.java | 4 +- .../legacy}/fix/online/OnlineFixes.java | 12 ++-- .../legacy}/fix/online/SkinFix.java | 8 +-- .../prismlauncher/legacy}/utils/Base64.java | 2 +- .../legacy/utils}/JsonParseException.java | 2 +- .../legacy}/utils/JsonParser.java | 4 +- .../legacy}/utils/api/MojangApi.java | 5 +- .../legacy}/utils/api/Texture.java | 2 +- .../utils/url/CustomUrlConnection.java | 2 +- .../legacy}/utils/url/UrlUtils.java | 2 +- .../org/prismlauncher/EntryPoint.java | 7 +-- .../launcher/org/prismlauncher/fix/Fixes.java | 48 --------------- .../org/prismlauncher/legacy/LegacyProxy.java | 17 ++++++ .../prismlauncher/utils/ReflectionUtils.java | 61 ------------------- .../org/prismlauncher/utils/logging/Log.java | 2 +- 23 files changed, 150 insertions(+), 161 deletions(-) rename libraries/launcher/{ => legacy}/net/minecraft/Launcher.java (100%) rename libraries/launcher/{org/prismlauncher/launcher/impl => legacy/org/prismlauncher}/legacy/LegacyFrame.java (98%) rename libraries/launcher/{org/prismlauncher/launcher/impl => legacy/org/prismlauncher}/legacy/LegacyLauncher.java (76%) create mode 100644 libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/fix/online/Handler.java (96%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/fix/online/OnlineFixes.java (89%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/fix/online/SkinFix.java (94%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/utils/Base64.java (98%) rename libraries/launcher/{org/prismlauncher/exception => legacy/org/prismlauncher/legacy/utils}/JsonParseException.java (97%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/utils/JsonParser.java (99%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/utils/api/MojangApi.java (96%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/utils/api/Texture.java (97%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/utils/url/CustomUrlConnection.java (98%) rename libraries/launcher/{org/prismlauncher => legacy/org/prismlauncher/legacy}/utils/url/UrlUtils.java (98%) delete mode 100644 libraries/launcher/org/prismlauncher/fix/Fixes.java create mode 100644 libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index ec916f26f..9aa2db0be 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -440,7 +440,7 @@ QStringList MinecraftInstance::javaArguments() args << "-Duser.language=en"; - if (javaVersion.isModular() && traits().contains("legacyServices") && settings()->get("OnlineFixes").toBool()) + if (javaVersion.isModular() && shouldApplyOnlineFixes()) // allow reflective access to java.net - required by the skin fix args << "--add-opens" << "java.base/java.net=ALL-UNNAMED"; @@ -448,7 +448,8 @@ QStringList MinecraftInstance::javaArguments() return args; } -QString MinecraftInstance::getLauncher() { +QString MinecraftInstance::getLauncher() +{ // use legacy launcher if the traits are set if (traits().contains("legacyLaunch") || traits().contains("alphaLaunch")) return "legacy"; @@ -456,6 +457,11 @@ QString MinecraftInstance::getLauncher() { return "standard"; } +bool MinecraftInstance::shouldApplyOnlineFixes() +{ + return traits().contains("legacyServices") && settings()->get("OnlineFixes").toBool(); +} + QMap MinecraftInstance::getVariables() { QMap out; @@ -665,7 +671,7 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS launchScript += "traits " + trait + "\n"; } - if (profile->getTraits().contains("legacyServices") && settings()->get("OnlineFixes").toBool()) + if (shouldApplyOnlineFixes()) launchScript += "onlineFixes true\n"; launchScript += "launcher " + getLauncher() + "\n"; diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 1bbd7b832..9826bfd9e 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -132,6 +132,7 @@ public: /// get arguments passed to java QStringList javaArguments(); QString getLauncher(); + bool shouldApplyOnlineFixes(); /// get variables for launch command variable substitution/environment QMap getVariables() override; diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index 1d8d70833..71280cb8d 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -107,6 +107,19 @@ void LauncherPartLaunch::executeTask() auto instance = m_parent->instance(); std::shared_ptr minecraftInstance = std::dynamic_pointer_cast(instance); + QString legacyJarPath; + if (minecraftInstance->getLauncher() == "legacy" || minecraftInstance->shouldApplyOnlineFixes()) + { + legacyJarPath = APPLICATION->getJarPath("NewLaunchLegacy.jar"); + if (legacyJarPath.isEmpty()) + { + const char *reason = QT_TR_NOOP("Legacy launcher library could not be found. Please check your installation."); + emit logLine(tr(reason), MessageLevel::Fatal); + emitFailed(tr(reason)); + return; + } + } + m_launchScript = minecraftInstance->createLaunchScript(m_session, m_serverToJoin); QStringList args = minecraftInstance->javaArguments(); QString allArgs = args.join(", "); @@ -122,6 +135,9 @@ void LauncherPartLaunch::executeTask() auto classPath = minecraftInstance->getClassPath(); classPath.prepend(jarPath); + if (!legacyJarPath.isEmpty()) + classPath.prepend(legacyJarPath); + auto natPath = minecraftInstance->getNativePath(); #ifdef Q_OS_WIN if (!fitsInLocal8bit(natPath)) diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index bf8f0baa2..d835dc9a3 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -11,25 +11,33 @@ set(SRC org/prismlauncher/launcher/Launcher.java org/prismlauncher/launcher/impl/AbstractLauncher.java org/prismlauncher/launcher/impl/StandardLauncher.java - org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java - org/prismlauncher/launcher/impl/legacy/LegacyFrame.java org/prismlauncher/exception/ParameterNotFoundException.java org/prismlauncher/exception/ParseException.java - org/prismlauncher/fix/Fixes.java - org/prismlauncher/fix/online/OnlineFixes.java - org/prismlauncher/fix/online/SkinFix.java - org/prismlauncher/fix/online/Handler.java - org/prismlauncher/utils/Base64.java - org/prismlauncher/utils/JsonParser.java org/prismlauncher/utils/Parameters.java org/prismlauncher/utils/ReflectionUtils.java - org/prismlauncher/utils/api/MojangApi.java - org/prismlauncher/utils/api/Texture.java org/prismlauncher/utils/logging/Level.java org/prismlauncher/utils/logging/Log.java - org/prismlauncher/utils/url/UrlUtils.java - org/prismlauncher/utils/url/CustomUrlConnection.java - net/minecraft/Launcher.java + org/prismlauncher/legacy/LegacyProxy.java ) + +set(LEGACY_SRC + legacy/org/prismlauncher/legacy/LegacyFrame.java + legacy/org/prismlauncher/legacy/LegacyLauncher.java + legacy/org/prismlauncher/legacy/fix/online/Handler.java + legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java + legacy/org/prismlauncher/legacy/fix/online/SkinFix.java + legacy/org/prismlauncher/legacy/utils/Base64.java + legacy/org/prismlauncher/legacy/utils/JsonParseException.java + legacy/org/prismlauncher/legacy/utils/JsonParser.java + legacy/org/prismlauncher/legacy/utils/api/MojangApi.java + legacy/org/prismlauncher/legacy/utils/api/Texture.java + legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java + legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java + legacy/net/minecraft/Launcher.java + legacy/org/prismlauncher/legacy/LegacyProxy.java +) + add_jar(NewLaunch ${SRC}) +add_jar(NewLaunchLegacy ${LEGACY_SRC} INCLUDE_JARS NewLaunch) install_jar(NewLaunch "${JARS_DEST_DIR}") +install_jar(NewLaunchLegacy "${JARS_DEST_DIR}") diff --git a/libraries/launcher/net/minecraft/Launcher.java b/libraries/launcher/legacy/net/minecraft/Launcher.java similarity index 100% rename from libraries/launcher/net/minecraft/Launcher.java rename to libraries/launcher/legacy/net/minecraft/Launcher.java diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyFrame.java similarity index 98% rename from libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/LegacyFrame.java index c215e7fe0..553b07eb1 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyFrame.java @@ -52,7 +52,7 @@ * limitations under the License. */ -package org.prismlauncher.launcher.impl.legacy; +package org.prismlauncher.legacy; import java.applet.Applet; import java.awt.Dimension; @@ -74,7 +74,7 @@ import org.prismlauncher.utils.logging.Log; import net.minecraft.Launcher; -public final class LegacyFrame extends JFrame { +final class LegacyFrame extends JFrame { private static final long serialVersionUID = 1L; diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java similarity index 76% rename from libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java index d349177b2..dae737224 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java @@ -53,11 +53,15 @@ * limitations under the License. */ -package org.prismlauncher.launcher.impl.legacy; +package org.prismlauncher.legacy; +import java.applet.Applet; import java.io.File; import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.Collections; import java.util.List; @@ -69,7 +73,7 @@ import org.prismlauncher.utils.logging.Log; /** * Used to launch old versions that support applets. */ -public final class LegacyLauncher extends AbstractLauncher { +final class LegacyLauncher extends AbstractLauncher { private final String user, session; private final String title; @@ -94,11 +98,9 @@ public final class LegacyLauncher extends AbstractLauncher { @Override public void launch() throws Throwable { Class main = ClassLoader.getSystemClassLoader().loadClass(mainClassName); - Field gameDirField = ReflectionUtils.findMinecraftGameDirField(main); + Field gameDirField = findMinecraftGameDirField(main); - if (gameDirField == null) - Log.warning("Could not find Minecraft folder field"); - else { + if (gameDirField != null) { gameDirField.setAccessible(true); gameDirField.set(null, new File(gameDir)); } @@ -107,7 +109,7 @@ public final class LegacyLauncher extends AbstractLauncher { System.setProperty("minecraft.applet.TargetDirectory", gameDir); try { - LegacyFrame window = new LegacyFrame(title, ReflectionUtils.createAppletClass(appletClass)); + LegacyFrame window = new LegacyFrame(title, createAppletClass(appletClass)); window.start(user, session, width, height, maximize, serverAddress, serverPort, gameArgs.contains("--demo")); @@ -123,4 +125,37 @@ public final class LegacyLauncher extends AbstractLauncher { method.invokeExact(gameArgs.toArray(new String[0])); } + private static Applet createAppletClass(String clazz) throws Throwable { + Class appletClass = ClassLoader.getSystemClassLoader().loadClass(clazz); + + MethodHandle appletConstructor = MethodHandles.lookup().findConstructor(appletClass, MethodType.methodType(void.class)); + return (Applet) appletConstructor.invoke(); + } + + private static Field findMinecraftGameDirField(Class clazz) { + Log.debug("Resolving minecraft game directory field"); + + // search for private static File + for (Field field : clazz.getDeclaredFields()) { + if (field.getType() != File.class) { + continue; + } + + int fieldModifiers = field.getModifiers(); + + if (!Modifier.isStatic(fieldModifiers)) + continue; + + if (!Modifier.isPrivate(fieldModifiers)) + continue; + + if (Modifier.isFinal(fieldModifiers)) + continue; + + return field; + } + + return null; + } + } diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java new file mode 100644 index 000000000..f2e65087f --- /dev/null +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java @@ -0,0 +1,17 @@ +package org.prismlauncher.legacy; + +import org.prismlauncher.launcher.Launcher; +import org.prismlauncher.legacy.fix.online.OnlineFixes; +import org.prismlauncher.utils.Parameters; + +public final class LegacyProxy { + + public static Launcher createLauncher(Parameters params) { + return new LegacyLauncher(params); + } + + public static void applyOnlineFixes(Parameters parameters) { + OnlineFixes.apply(parameters); + } + +} diff --git a/libraries/launcher/org/prismlauncher/fix/online/Handler.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/Handler.java similarity index 96% rename from libraries/launcher/org/prismlauncher/fix/online/Handler.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/Handler.java index 618683119..02a325e37 100644 --- a/libraries/launcher/org/prismlauncher/fix/online/Handler.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/Handler.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.fix.online; +package org.prismlauncher.legacy.fix.online; import java.io.IOException; import java.net.Proxy; @@ -41,7 +41,7 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; -import org.prismlauncher.utils.url.UrlUtils; +import org.prismlauncher.legacy.utils.url.UrlUtils; final class Handler extends URLStreamHandler { diff --git a/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java similarity index 89% rename from libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java index 5f9ff1014..d4e4c27d5 100644 --- a/libraries/launcher/org/prismlauncher/fix/online/OnlineFixes.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java @@ -33,15 +33,16 @@ * along with this program. If not, see . */ -package org.prismlauncher.fix.online; +package org.prismlauncher.legacy.fix.online; import java.net.URL; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; -import org.prismlauncher.utils.Base64; +import org.prismlauncher.legacy.utils.Base64; +import org.prismlauncher.legacy.utils.url.UrlUtils; +import org.prismlauncher.utils.Parameters; import org.prismlauncher.utils.logging.Log; -import org.prismlauncher.utils.url.UrlUtils; /** * Fixes skins by redirecting to other URLs. @@ -51,7 +52,10 @@ import org.prismlauncher.utils.url.UrlUtils; */ public final class OnlineFixes implements URLStreamHandlerFactory { - public static void apply() { + public static void apply(Parameters params) { + if (!"true".equals(params.getString("onlineFixes", null))) + return; + if (!UrlUtils.isSupported() || !Base64.isSupported()) { Log.warning("Cannot access the necessary Java internals for skin fix"); Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); diff --git a/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java similarity index 94% rename from libraries/launcher/org/prismlauncher/fix/online/SkinFix.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java index b05e1f208..1c4888312 100644 --- a/libraries/launcher/org/prismlauncher/fix/online/SkinFix.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java @@ -1,4 +1,4 @@ -package org.prismlauncher.fix.online; +package org.prismlauncher.legacy.fix.online; import java.awt.AlphaComposite; import java.awt.Graphics2D; @@ -12,10 +12,8 @@ import java.net.URLConnection; import javax.imageio.ImageIO; -import org.prismlauncher.utils.api.MojangApi; -import org.prismlauncher.utils.api.Texture; -import org.prismlauncher.utils.url.CustomUrlConnection; -import org.prismlauncher.utils.url.UrlUtils; +import org.prismlauncher.legacy.utils.api.*; +import org.prismlauncher.legacy.utils.url.*; final class SkinFix { diff --git a/libraries/launcher/org/prismlauncher/utils/Base64.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/Base64.java similarity index 98% rename from libraries/launcher/org/prismlauncher/utils/Base64.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/Base64.java index 508df872d..3f7852e74 100644 --- a/libraries/launcher/org/prismlauncher/utils/Base64.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/Base64.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils; +package org.prismlauncher.legacy.utils; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; diff --git a/libraries/launcher/org/prismlauncher/exception/JsonParseException.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParseException.java similarity index 97% rename from libraries/launcher/org/prismlauncher/exception/JsonParseException.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParseException.java index 5983eb883..6ba8d10b6 100644 --- a/libraries/launcher/org/prismlauncher/exception/JsonParseException.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParseException.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.exception; +package org.prismlauncher.legacy.utils; import java.io.IOException; diff --git a/libraries/launcher/org/prismlauncher/utils/JsonParser.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java similarity index 99% rename from libraries/launcher/org/prismlauncher/utils/JsonParser.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java index 5f10e9a7b..4339f98e6 100644 --- a/libraries/launcher/org/prismlauncher/utils/JsonParser.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils; +package org.prismlauncher.legacy.utils; import java.io.IOException; import java.io.InputStream; @@ -46,8 +46,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.prismlauncher.exception.JsonParseException; - /** * Single-file JSON parser to allow for usage in versions without GSON. */ diff --git a/libraries/launcher/org/prismlauncher/utils/api/MojangApi.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java similarity index 96% rename from libraries/launcher/org/prismlauncher/utils/api/MojangApi.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java index dc2794107..6159a4e72 100644 --- a/libraries/launcher/org/prismlauncher/utils/api/MojangApi.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java @@ -33,15 +33,14 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils.api; +package org.prismlauncher.legacy.utils.api; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Map; -import org.prismlauncher.utils.Base64; -import org.prismlauncher.utils.JsonParser; +import org.prismlauncher.legacy.utils.*; /** * Basic access to Mojang's Minecraft API. diff --git a/libraries/launcher/org/prismlauncher/utils/api/Texture.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/Texture.java similarity index 97% rename from libraries/launcher/org/prismlauncher/utils/api/Texture.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/Texture.java index 1b5c2204e..838a2758e 100644 --- a/libraries/launcher/org/prismlauncher/utils/api/Texture.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/Texture.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils.api; +package org.prismlauncher.legacy.utils.api; import java.net.URL; diff --git a/libraries/launcher/org/prismlauncher/utils/url/CustomUrlConnection.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java similarity index 98% rename from libraries/launcher/org/prismlauncher/utils/url/CustomUrlConnection.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java index 8bc0cff11..36ac235f3 100644 --- a/libraries/launcher/org/prismlauncher/utils/url/CustomUrlConnection.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils.url; +package org.prismlauncher.legacy.utils.url; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java similarity index 98% rename from libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java index 69ebbd50b..85c35eb17 100644 --- a/libraries/launcher/org/prismlauncher/utils/url/UrlUtils.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.utils.url; +package org.prismlauncher.legacy.utils.url; import java.io.IOException; import java.lang.invoke.MethodHandle; diff --git a/libraries/launcher/org/prismlauncher/EntryPoint.java b/libraries/launcher/org/prismlauncher/EntryPoint.java index 88ecb48ce..a2d9a5f78 100644 --- a/libraries/launcher/org/prismlauncher/EntryPoint.java +++ b/libraries/launcher/org/prismlauncher/EntryPoint.java @@ -59,10 +59,9 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import org.prismlauncher.exception.ParseException; -import org.prismlauncher.fix.Fixes; import org.prismlauncher.launcher.Launcher; import org.prismlauncher.launcher.impl.StandardLauncher; -import org.prismlauncher.launcher.impl.legacy.LegacyLauncher; +import org.prismlauncher.legacy.LegacyProxy; import org.prismlauncher.utils.Parameters; import org.prismlauncher.utils.logging.Log; @@ -108,7 +107,7 @@ public final class EntryPoint { } try { - Fixes.apply(params); + LegacyProxy.applyOnlineFixes(params); Launcher launcher; String type = params.getString("launcher"); @@ -119,7 +118,7 @@ public final class EntryPoint { break; case "legacy": - launcher = new LegacyLauncher(params); + launcher = LegacyProxy.createLauncher(params); break; default: diff --git a/libraries/launcher/org/prismlauncher/fix/Fixes.java b/libraries/launcher/org/prismlauncher/fix/Fixes.java deleted file mode 100644 index 429964ad9..000000000 --- a/libraries/launcher/org/prismlauncher/fix/Fixes.java +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 TheKodeToad - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Linking this library statically or dynamically with other modules is - * making a combined work based on this library. Thus, the terms and - * conditions of the GNU General Public License cover the whole - * combination. - * - * As a special exception, the copyright holders of this library give - * you permission to link this library with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also meet, - * for each linked independent module, the terms and conditions of the - * license of that module. An independent module is a module which is - * not derived from or based on this library. If you modify this - * library, you may extend this exception to your version of the - * library, but you are not obliged to do so. If you do not wish to do - * so, delete this exception statement from your version. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.prismlauncher.fix; - -import org.prismlauncher.fix.online.OnlineFixes; -import org.prismlauncher.utils.Parameters; - -public final class Fixes { - - public static void apply(Parameters params) { - if ("true".equalsIgnoreCase(params.getString("onlineFixes", null))) - OnlineFixes.apply(); - } - -} diff --git a/libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java b/libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java new file mode 100644 index 000000000..9b96d7179 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java @@ -0,0 +1,17 @@ +package org.prismlauncher.legacy; + +import org.prismlauncher.launcher.Launcher; +import org.prismlauncher.utils.Parameters; + +// used as a fallback if NewLaunchLegacy is not on the classpath +// if it is, this class will be replaced +public final class LegacyProxy { + + public static Launcher createLauncher(Parameters params) { + throw new AssertionError("NewLaunchLegacy is not loaded"); + } + + public static void applyOnlineFixes(Parameters params) { + } + +} diff --git a/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java b/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java index dd212ef93..1925bf049 100644 --- a/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java +++ b/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java @@ -54,76 +54,15 @@ package org.prismlauncher.utils; -import java.applet.Applet; -import java.io.File; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -import org.prismlauncher.utils.logging.Log; public final class ReflectionUtils { private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private static final ClassLoader LOADER = ClassLoader.getSystemClassLoader(); - /** - * Construct a Java applet by its class name. - * - * @param clazz The class name - * @return The applet instance - * @throws Throwable - */ - public static Applet createAppletClass(String clazz) throws Throwable { - Class appletClass = LOADER.loadClass(clazz); - - MethodHandle appletConstructor = LOOKUP.findConstructor(appletClass, MethodType.methodType(void.class)); - return (Applet) appletConstructor.invoke(); - } - - /** - * Best guess of the game directory field within net.minecraft.client.Minecraft. - * Designed for legacy versions - newer versions do not use a static field. - * - * @param clazz The class - * @return The first field matching criteria - */ - public static Field findMinecraftGameDirField(Class clazz) { - Log.debug("Resolving minecraft game directory field"); - - // search for private static File - for (Field field : clazz.getDeclaredFields()) { - if (field.getType() != File.class) { - continue; - } - - int fieldModifiers = field.getModifiers(); - - if (!Modifier.isStatic(fieldModifiers)) { - Log.debug("Rejecting field " + field.getName() + " because it is not static"); - continue; - } - - if (!Modifier.isPrivate(fieldModifiers)) { - Log.debug("Rejecting field " + field.getName() + " because it is not private"); - continue; - } - - if (Modifier.isFinal(fieldModifiers)) { - Log.debug("Rejecting field " + field.getName() + " because it is final"); - continue; - } - - Log.debug("Identified field " + field.getName() + " to match conditions for game directory field"); - - return field; - } - - return null; - } - /** * Gets the main method within a class. * diff --git a/libraries/launcher/org/prismlauncher/utils/logging/Log.java b/libraries/launcher/org/prismlauncher/utils/logging/Log.java index e3aa538b2..0c5dc3009 100644 --- a/libraries/launcher/org/prismlauncher/utils/logging/Log.java +++ b/libraries/launcher/org/prismlauncher/utils/logging/Log.java @@ -45,7 +45,7 @@ import java.io.PrintStream; public final class Log { // original before possibly overridden by MC - private static final PrintStream OUT = new PrintStream(System.out), ERR = new PrintStream(System.err); + private static final PrintStream OUT = new PrintStream(System.out), ERR = new PrintStream(System.err); private static final boolean DEBUG = Boolean.getBoolean("org.prismlauncher.debug"); public static void launcher(String message) { From be7f81421ab98b439a4b285dd47bd293b61dc860 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 6 Jan 2023 10:45:59 +0000 Subject: [PATCH 014/398] Finishing touches Signed-off-by: TheKodeToad --- .../launcher/legacy/net/minecraft/Launcher.java | 5 ++--- .../org/prismlauncher/legacy/LegacyFrame.java | 2 +- .../prismlauncher/legacy/LegacyLauncher.java | 14 ++++++-------- .../org/prismlauncher/legacy/LegacyProxy.java | 1 + .../legacy/fix/online/OnlineFixes.java | 8 ++++---- .../legacy/fix/online/SkinFix.java | 15 +++++++++------ .../prismlauncher/legacy/utils/JsonParser.java | 17 +++++++++-------- .../legacy/utils/api/MojangApi.java | 11 ++++++----- 8 files changed, 38 insertions(+), 35 deletions(-) diff --git a/libraries/launcher/legacy/net/minecraft/Launcher.java b/libraries/launcher/legacy/net/minecraft/Launcher.java index 646e2e3ea..4c7fcb6ee 100644 --- a/libraries/launcher/legacy/net/minecraft/Launcher.java +++ b/libraries/launcher/legacy/net/minecraft/Launcher.java @@ -93,12 +93,11 @@ public final class Launcher extends Applet implements AppletStub { try { if (documentBase == null) { - if (applet.getClass().getPackage().getName().startsWith("com.mojang.")) { + if (applet.getClass().getPackage().getName().startsWith("com.mojang")) // Special case only for Classic versions documentBase = new URL("http://www.minecraft.net:80/game/"); - } else { + else documentBase = new URL("http://www.minecraft.net/game/"); - } } } catch (MalformedURLException e) { throw new AssertionError(e); diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyFrame.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyFrame.java index 553b07eb1..49a126e7f 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyFrame.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyFrame.java @@ -131,7 +131,7 @@ final class LegacyFrame extends JFrame { launcher.setParameter("username", user); launcher.setParameter("sessionid", session); - launcher.setParameter("stand-alone", true); // Show the quit button. TODO: why won't this work? + launcher.setParameter("stand-alone", true); // Show the quit button. This often doesn't seem to work. launcher.setParameter("haspaid", true); // Some old versions need this for world saves to work. launcher.setParameter("demo", demo); launcher.setParameter("fullscreen", false); diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java index dae737224..f84b971cb 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java @@ -71,7 +71,7 @@ import org.prismlauncher.utils.ReflectionUtils; import org.prismlauncher.utils.logging.Log; /** - * Used to launch old versions that support applets. + * Used to launch old versions which support applets. */ final class LegacyLauncher extends AbstractLauncher { @@ -119,8 +119,8 @@ final class LegacyLauncher extends AbstractLauncher { } } - // find and invoke the main method, this time without size parameters - // in all versions that support applets, these are ignored + // find and invoke the main method, this time without size parameters - in all + // versions that support applets, these are ignored MethodHandle method = ReflectionUtils.findMainMethod(main); method.invokeExact(gameArgs.toArray(new String[0])); } @@ -128,18 +128,16 @@ final class LegacyLauncher extends AbstractLauncher { private static Applet createAppletClass(String clazz) throws Throwable { Class appletClass = ClassLoader.getSystemClassLoader().loadClass(clazz); - MethodHandle appletConstructor = MethodHandles.lookup().findConstructor(appletClass, MethodType.methodType(void.class)); + MethodHandle appletConstructor = MethodHandles.lookup().findConstructor(appletClass, + MethodType.methodType(void.class)); return (Applet) appletConstructor.invoke(); } private static Field findMinecraftGameDirField(Class clazz) { - Log.debug("Resolving minecraft game directory field"); - // search for private static File for (Field field : clazz.getDeclaredFields()) { - if (field.getType() != File.class) { + if (field.getType() != File.class) continue; - } int fieldModifiers = field.getModifiers(); diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java index f2e65087f..11c9d6692 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java @@ -4,6 +4,7 @@ import org.prismlauncher.launcher.Launcher; import org.prismlauncher.legacy.fix.online.OnlineFixes; import org.prismlauncher.utils.Parameters; +// implementation of LegacyProxy public final class LegacyProxy { public static Launcher createLauncher(Parameters params) { diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java index d4e4c27d5..56849cdd9 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java @@ -62,12 +62,12 @@ public final class OnlineFixes implements URLStreamHandlerFactory { return; } - try { + try { URL.setURLStreamHandlerFactory(new OnlineFixes()); - } catch (Error e) { + } catch (Error e) { Log.warning("Cannot apply skin fix: URLStreamHandlerFactory is already set"); - Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); - } + Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); + } } @Override diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java index 1c4888312..7cfd297aa 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java @@ -12,8 +12,10 @@ import java.net.URLConnection; import javax.imageio.ImageIO; -import org.prismlauncher.legacy.utils.api.*; -import org.prismlauncher.legacy.utils.url.*; +import org.prismlauncher.legacy.utils.api.MojangApi; +import org.prismlauncher.legacy.utils.api.Texture; +import org.prismlauncher.legacy.utils.url.CustomUrlConnection; +import org.prismlauncher.legacy.utils.url.UrlUtils; final class SkinFix { @@ -25,7 +27,8 @@ final class SkinFix { String capeOwner = findCapeOwner(address); if (capeOwner != null) { - // since we do not need to process the image, open a direct connection bypassing Handler + // since we do not need to process the image, open a direct connection bypassing + // Handler Texture texture = MojangApi.getTexture(MojangApi.getUuid(capeOwner), "CAPE"); if (texture == null) return null; @@ -45,7 +48,7 @@ final class SkinFix { try (InputStream in = connection.getInputStream()) { // thank you craftycodie! // this is heavily based on - // https://github.com/Mojang/LegacyLauncher/pull/33/files#diff-b61023785a9260651ca0a223573ea9acb5be5eec478bff626dafb7abe13ffebaR99 + // https://github.com/craftycodie/MineOnline/blob/4f4f86f9d051e0a6fd7ff0b95b2a05f7437683d7/src/main/java/gg/codie/mineonline/gui/textures/TextureHelper.java#L17 BufferedImage image = ImageIO.read(in); Graphics2D graphics = image.createGraphics(); graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); @@ -59,7 +62,7 @@ final class SkinFix { } if (texture.isSlim()) { - // convert slim to wide + // convert slim to classic subimage = image.getSubimage(45, 16, 9, 16); graphics.drawImage(subimage, 46, 16, null); @@ -72,7 +75,7 @@ final class SkinFix { graphics.dispose(); - // crop the image + // crop the image - old versions disregard all secondary layers besides the hat ByteArrayOutputStream out = new ByteArrayOutputStream(); image = image.getSubimage(0, 0, 64, 32); ImageIO.write(image, "png", out); diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java index 4339f98e6..73258fd09 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java @@ -47,7 +47,8 @@ import java.util.List; import java.util.Map; /** - * Single-file JSON parser to allow for usage in versions without GSON. + * A lightweight portable JSON parser used instead of GSON since it is not + * available in a lot of versions. */ public final class JsonParser { @@ -55,15 +56,15 @@ public final class JsonParser { private char[] buffer; private int pos, length; - public static Object parse(String in) throws JsonParseException, IOException { + public static Object parse(String in) throws IOException { return parse(new StringReader(in)); } - public static Object parse(InputStream in) throws JsonParseException, IOException { + public static Object parse(InputStream in) throws IOException { return parse(new InputStreamReader(in, StandardCharsets.UTF_8)); } - public static Object parse(Reader in) throws JsonParseException, IOException { + public static Object parse(Reader in) throws IOException { return new JsonParser(in).readSingleValue(); } @@ -336,6 +337,7 @@ public final class JsonParser { if (character() == '0') { result.append((char) character()); read(); + if (isDigit()) throw new JsonParseException("Found superfluous leading zero"); } else if (!isDigit()) @@ -395,11 +397,10 @@ public final class JsonParser { if (read() == 'r' && read() == 'u' && read() == 'e') { return true; } - } else if (character() == 'f') { - if (read() == 'a' && read() == 'l' && read() == 's' && read() == 'e') { - return false; - } + } else if (character() == 'f' && read() == 'a' && read() == 'l' && read() == 's' && read() == 'e') { + return false; } + return null; } diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java index 6159a4e72..e15ebe7f5 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java @@ -40,10 +40,11 @@ import java.io.InputStream; import java.net.URL; import java.util.Map; -import org.prismlauncher.legacy.utils.*; +import org.prismlauncher.legacy.utils.Base64; +import org.prismlauncher.legacy.utils.JsonParser; /** - * Basic access to Mojang's Minecraft API. + * Basic wrapper for Mojang's Minecraft API. */ @SuppressWarnings("unchecked") public final class MojangApi { @@ -55,18 +56,18 @@ public final class MojangApi { } } - public static Texture getTexture(String player, String name) throws IOException { + public static Texture getTexture(String player, String id) throws IOException { Map map = getTextures(player); if (map != null) { - map = (Map) map.get(name); + map = (Map) map.get(id); if (map == null) return null; URL url = new URL((String) map.get("url")); boolean slim = false; - if (name.equals("SKIN")) { + if (id.equals("SKIN")) { map = (Map) map.get("metadata"); if (map != null && "slim".equals(map.get("model"))) slim = true; From 52b3a54e4bdbe0be48429ae3744fa6a0cb2fa8f2 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 8 Jan 2023 15:36:36 +0000 Subject: [PATCH 015/398] Fix cloaks conflicting with join server endpoint Signed-off-by: TheKodeToad --- .../legacy/org/prismlauncher/legacy/fix/online/SkinFix.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java index 7cfd297aa..1d23c6d14 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java @@ -100,6 +100,9 @@ final class SkinFix { private static String findCapeOwner(URL address) { switch (address.getHost()) { case "www.minecraft.net": + if (!address.getPath().equals("/cloak/get.jsp")) + return null; + return stripIfPrefixed(address.getQuery(), "user="); case "s3.amazonaws.com": From d4b346b7ae7201af3c67d7450ac7144eb486638c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 9 Jan 2023 10:48:46 +0000 Subject: [PATCH 016/398] Fix oversights Signed-off-by: TheKodeToad --- libraries/launcher/CMakeLists.txt | 4 +- .../org/prismlauncher/legacy/LegacyProxy.java | 52 +++++++++++++++++++ .../legacy/fix/online/SkinFix.java | 52 +++++++++++++++++++ .../legacy/utils/api/MojangApi.java | 2 +- .../utils/{ => json}/JsonParseException.java | 4 +- .../legacy/utils/{ => json}/JsonParser.java | 2 +- .../legacy/utils/url/CustomUrlConnection.java | 4 +- .../org/prismlauncher/legacy/LegacyProxy.java | 52 +++++++++++++++++++ 8 files changed, 164 insertions(+), 8 deletions(-) rename libraries/launcher/legacy/org/prismlauncher/legacy/utils/{ => json}/JsonParseException.java (94%) rename libraries/launcher/legacy/org/prismlauncher/legacy/utils/{ => json}/JsonParser.java (99%) diff --git a/libraries/launcher/CMakeLists.txt b/libraries/launcher/CMakeLists.txt index d835dc9a3..7bf160760 100644 --- a/libraries/launcher/CMakeLists.txt +++ b/libraries/launcher/CMakeLists.txt @@ -27,10 +27,10 @@ set(LEGACY_SRC legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java legacy/org/prismlauncher/legacy/fix/online/SkinFix.java legacy/org/prismlauncher/legacy/utils/Base64.java - legacy/org/prismlauncher/legacy/utils/JsonParseException.java - legacy/org/prismlauncher/legacy/utils/JsonParser.java legacy/org/prismlauncher/legacy/utils/api/MojangApi.java legacy/org/prismlauncher/legacy/utils/api/Texture.java + legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java + legacy/org/prismlauncher/legacy/utils/json/JsonParser.java legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java legacy/net/minecraft/Launcher.java diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java index 11c9d6692..34460db10 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyProxy.java @@ -1,3 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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.prismlauncher.legacy; import org.prismlauncher.launcher.Launcher; diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java index 1d23c6d14..37dd125a5 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/SkinFix.java @@ -1,3 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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.prismlauncher.legacy.fix.online; import java.awt.AlphaComposite; diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java index e15ebe7f5..e774ee3e1 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/api/MojangApi.java @@ -41,7 +41,7 @@ import java.net.URL; import java.util.Map; import org.prismlauncher.legacy.utils.Base64; -import org.prismlauncher.legacy.utils.JsonParser; +import org.prismlauncher.legacy.utils.json.JsonParser; /** * Basic wrapper for Mojang's Minecraft API. diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParseException.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java similarity index 94% rename from libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParseException.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java index 6ba8d10b6..222427016 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParseException.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java @@ -33,11 +33,11 @@ * along with this program. If not, see . */ -package org.prismlauncher.legacy.utils; +package org.prismlauncher.legacy.utils.json; import java.io.IOException; -public class JsonParseException extends IOException { +public final class JsonParseException extends IOException { private static final long serialVersionUID = 1L; diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParser.java similarity index 99% rename from libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java rename to libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParser.java index 73258fd09..db2efc6cd 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/JsonParser.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParser.java @@ -33,7 +33,7 @@ * along with this program. If not, see . */ -package org.prismlauncher.legacy.utils; +package org.prismlauncher.legacy.utils.json; import java.io.IOException; import java.io.InputStream; diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java index 36ac235f3..8a8e3416c 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java @@ -40,9 +40,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; -public class CustomUrlConnection extends HttpURLConnection { +public final class CustomUrlConnection extends HttpURLConnection { - private InputStream in; + private final InputStream in; public CustomUrlConnection(byte[] data) { this(new ByteArrayInputStream(data)); diff --git a/libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java b/libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java index 9b96d7179..ec9a1fcc9 100644 --- a/libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java +++ b/libraries/launcher/org/prismlauncher/legacy/LegacyProxy.java @@ -1,3 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. An independent module is a module which is + * not derived from or based on this library. If you modify this + * library, you may extend this exception to your version of the + * library, but you are not obliged to do so. If you do not wish to do + * so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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.prismlauncher.legacy; import org.prismlauncher.launcher.Launcher; From bb62c62a03df0431cbc8cad983f0b176a5640264 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 19 Feb 2023 11:37:59 +0000 Subject: [PATCH 017/398] Fix cmark again :facepalm: Signed-off-by: TheKodeToad --- libraries/cmark | 1 + 1 file changed, 1 insertion(+) create mode 160000 libraries/cmark diff --git a/libraries/cmark b/libraries/cmark new file mode 160000 index 000000000..5ba25ff40 --- /dev/null +++ b/libraries/cmark @@ -0,0 +1 @@ +Subproject commit 5ba25ff40eba44c811f79ab6a792baf945b8307c From 6a5e9a59dff7601907f354ff7585dddf1c35206c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 19 Feb 2023 12:00:18 +0000 Subject: [PATCH 018/398] Fix screwed up ui file Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/InstanceSettingsPage.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 6a73a84c0..f16802c0a 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -648,6 +648,9 @@ + + + <html><head/><body><p>Fixes usages of old online services which are no longer operating by emulating them or redirecting to their modern counterparts.</p><p>This currently only allows modern skins to be used.</p></body></html> From 83c526459886f5d8a2498443cafe5b6823cea2eb Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 10 Mar 2023 11:04:09 +0000 Subject: [PATCH 019/398] Stupidly small skinfixfix as requested by DioEgizio Signed-off-by: TheKodeToad --- .../org/prismlauncher/legacy/utils/json/JsonParseException.java | 2 +- .../legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java index 222427016..bb35cb165 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/json/JsonParseException.java @@ -45,4 +45,4 @@ public final class JsonParseException extends IOException { super(message); } -} \ No newline at end of file +} diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java index 85c35eb17..de9358b16 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java @@ -107,4 +107,4 @@ public final class UrlUtils { } } -} \ No newline at end of file +} From dfc2b9c76ac0dfeae55759665033539df3f27c2f Mon Sep 17 00:00:00 2001 From: Kode Date: Fri, 21 Apr 2023 20:49:47 +0100 Subject: [PATCH 020/398] thanks flowln! :P Signed-off-by: Kode --- .../org/prismlauncher/legacy/fix/online/OnlineFixes.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java index 56849cdd9..cf35b75d7 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java @@ -58,7 +58,7 @@ public final class OnlineFixes implements URLStreamHandlerFactory { if (!UrlUtils.isSupported() || !Base64.isSupported()) { Log.warning("Cannot access the necessary Java internals for skin fix"); - Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); + Log.warning("Turning off online fixes in the settings will silence the warnings"); return; } @@ -66,7 +66,7 @@ public final class OnlineFixes implements URLStreamHandlerFactory { URL.setURLStreamHandlerFactory(new OnlineFixes()); } catch (Error e) { Log.warning("Cannot apply skin fix: URLStreamHandlerFactory is already set"); - Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings"); + Log.warning("Turning off online fixes in the settings will silence the warnings"); } } From 63c21c53af457673a836915ae7351111c980a4bf Mon Sep 17 00:00:00 2001 From: timoreo Date: Tue, 13 Sep 2022 12:00:22 +0200 Subject: [PATCH 021/398] Added url handler for curseforge Signed-off-by: timoreo --- cmake/MacOSXBundleInfo.plist.in | 11 ++++++ launcher/Application.cpp | 1 - launcher/InstanceImportTask.cpp | 69 +++++++++++++++++++++++++-------- launcher/InstanceImportTask.h | 1 + program_info/win_install.nsi.in | 4 ++ 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/cmake/MacOSXBundleInfo.plist.in b/cmake/MacOSXBundleInfo.plist.in index 400e482fe..d36ac3e8f 100644 --- a/cmake/MacOSXBundleInfo.plist.in +++ b/cmake/MacOSXBundleInfo.plist.in @@ -67,5 +67,16 @@ Alternate + CFBundleURLTypes + + + CFBundleURLName + Curseforge + CFBundleURLSchemes + + curseforge + + + diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 28c2a9ced..0b1ab16cb 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -240,7 +240,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); } - // error if --launch is missing with --server or --profile if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 8a48873ef..ef221bf97 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -47,6 +47,8 @@ #include "modplatform/technic/TechnicPackProcessor.h" #include "modplatform/modrinth/ModrinthInstanceCreationTask.h" #include "modplatform/flame/FlameInstanceCreationTask.h" +// FIXME : move this over to FlameInstanceCreationTask +#include "Json.h" #include "settings/INISettingsObject.h" @@ -87,25 +89,59 @@ void InstanceImportTask::executeTask() setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString())); m_downloadRequired = true; - const QString path(m_sourceUrl.host() + '/' + m_sourceUrl.path()); - - auto entry = APPLICATION->metacache()->resolveEntry("general", path); - entry->setStale(true); - m_archivePath = entry->getFullPath(); - - m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network())); - m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry)); - - connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded); - connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); - connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress); - connect(m_filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::downloadFailed); - connect(m_filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::downloadAborted); - - m_filesNetJob->start(); + if (m_sourceUrl.scheme() == "curseforge") { + // need to find the download link for the modpack + // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE + QUrlQuery query(m_sourceUrl); + auto addonId = query.allQueryItemValues("addonId")[0]; + auto fileId = query.allQueryItemValues("fileId")[0]; + auto array = new QByteArray(); + auto req = new NetJob("Curseforge Meta", APPLICATION->network()); + req->addNetAction( + Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), array)); + connect(req, &NetJob::finished, [array, req] { + req->deleteLater(); + delete array; + }); + connect(req, &NetJob::failed, this, &InstanceImportTask::downloadFailed); + connect(req, &NetJob::succeeded, [array, this] { + auto doc = Json::requireDocument(*array); + // Have to use ensureString then use QUrl to get proper url encoding + m_sourceUrl = QUrl( + Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); + if (!m_sourceUrl.isValid()) { + emitFailed(tr("The modpack is blocked ! Please download it manually")); + return; + } + downloadFromUrl(); + }); + connect(req, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); + connect(req, &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(req, &NetJob::aborted, this, &InstanceImportTask::downloadAborted); + req->start(); + } else { + downloadFromUrl(); + } } } +void InstanceImportTask::downloadFromUrl() +{ + const QString path = m_sourceUrl.host() + '/' + m_sourceUrl.path(); + auto entry = APPLICATION->metacache()->resolveEntry("general", path); + entry->setStale(true); + m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network())); + m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry)); + m_archivePath = entry->getFullPath(); + + connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded); + connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); + connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(m_filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::downloadFailed); + connect(m_filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::downloadAborted); + m_filesNetJob->start(); +} + void InstanceImportTask::downloadSucceeded() { processZipPack(); @@ -396,3 +432,4 @@ void InstanceImportTask::processModrinth() inst_creation_task->start(); } + diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h index 7fda439fc..9c1edc6d1 100644 --- a/launcher/InstanceImportTask.h +++ b/launcher/InstanceImportTask.h @@ -106,4 +106,5 @@ private: /* data */ //FIXME: nuke QWidget* m_parent; + void downloadFromUrl(); }; diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index a809c55dd..72ff4709a 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -294,6 +294,10 @@ Section "@Launcher_DisplayName@" ; Write the installation path into the registry WriteRegStr HKCU Software\@Launcher_CommonName@ "InstallDir" "$INSTDIR" + ; Write the URL Handler into registry for curseforge + WriteRegStr HKCU Software\Classes\curseforge "URL Protocol" "" + WriteRegStr HKCU Software\Classes\curseforge\shell\open\command "" '"$INSTDIR\@Launcher_APP_BINARY_NAME@.exe" "%1"' + ; Write the uninstall keys for Windows ${GetParameters} $R0 ${GetOptions} $R0 "/NoUninstaller" $R1 From 565202c99004a13f4d6b9bad6ec1e0634fb280fb Mon Sep 17 00:00:00 2001 From: timoreo Date: Tue, 13 Sep 2022 14:00:10 +0200 Subject: [PATCH 022/398] Added a protection against giving a mod url Signed-off-by: timoreo --- launcher/InstanceImportTask.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index ef221bf97..4d5193baa 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -106,14 +106,21 @@ void InstanceImportTask::executeTask() connect(req, &NetJob::failed, this, &InstanceImportTask::downloadFailed); connect(req, &NetJob::succeeded, [array, this] { auto doc = Json::requireDocument(*array); - // Have to use ensureString then use QUrl to get proper url encoding - m_sourceUrl = QUrl( - Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); - if (!m_sourceUrl.isValid()) { - emitFailed(tr("The modpack is blocked ! Please download it manually")); - return; + // No way to find out if it's a mod or a modpack before here + // And also we need to check if it ends with .zip, instead of any better way + auto fileName = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "fileName"); + if (fileName.endsWith(".zip")) { + // Have to use ensureString then use QUrl to get proper url encoding + m_sourceUrl = QUrl( + Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); + if (!m_sourceUrl.isValid()) { + emitFailed(tr("The modpack is blocked ! Please download it manually")); + return; + } + downloadFromUrl(); + } else { + emitFailed(tr("This url isn't a valid modpack !")); } - downloadFromUrl(); }); connect(req, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); connect(req, &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress); From 54fb799d95faa3d646cfc835937e5fbdb10afa4d Mon Sep 17 00:00:00 2001 From: timoreo Date: Wed, 16 Nov 2022 14:26:52 +0100 Subject: [PATCH 023/398] Fix command line args Signed-off-by: timoreo --- launcher/Application.cpp | 3 +++ program_info/org.prismlauncher.PrismLauncher.desktop.in | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 0b1ab16cb..6994d1ba6 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -219,6 +219,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}, {"show", "Opens the window for the specified instance (by instance ID)", "show"} }); + // Has to be positional for some OS to handle that properly + parser.addPositionalArgument("urls","import the resource at the given url(s) (URL to modpack Zip / local Zip / curseforge:// modpack link)","[urls...]"); + parser.addHelpOption(); parser.addVersionOption(); diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index f08f2ba43..675e1f1f1 100644 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -10,4 +10,4 @@ Icon=org.prismlauncher.PrismLauncher Categories=Game;ActionGame;AdventureGame;Simulation; Keywords=game;minecraft;launcher;mc;multimc;polymc; StartupWMClass=PrismLauncher -MimeType=application/zip;application/x-modrinth-modpack+zip +MimeType=application/zip;application/x-modrinth-modpack+zip;x-scheme-handler/curseforge; From a3173b53717fcea686f267f4eb8fd9788e6677db Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 7 Apr 2023 16:54:25 -0700 Subject: [PATCH 024/398] fix: ensure Application accepts URLs and local files form cmd args refactor: Move curseforge:// url scheme detection to Import Page feat: pass along extra CF pack info so pack metadata is established. Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 42 +++++++++----- launcher/Application.h | 4 +- launcher/InstanceImportTask.cpp | 40 +------------- launcher/ui/pages/modplatform/ImportPage.cpp | 58 ++++++++++++++++++++ launcher/ui/pages/modplatform/ImportPage.ui | 2 +- 5 files changed, 92 insertions(+), 54 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6994d1ba6..c97fdb0a6 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -216,11 +216,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) {{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"}, {{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"}, {"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"}, - {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}, + {{"I", "import"}, "Import instance or resource from specified local path or URL", "url"}, {"show", "Opens the window for the specified instance (by instance ID)", "show"} }); // Has to be positional for some OS to handle that properly - parser.addPositionalArgument("urls","import the resource at the given url(s) (URL to modpack Zip / local Zip / curseforge:// modpack link)","[urls...]"); + parser.addPositionalArgument("urls","import the resource at the given url(s) (same as -I / --import)","[urls...]"); parser.addHelpOption(); parser.addVersionOption(); @@ -234,13 +234,13 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_instanceIdToShowWindowOf = parser.value("show"); - for (auto zip_path : parser.values("import")){ - m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); + for (auto url : parser.values("import")){ + addImportUrl(url); } // treat unspecified positional arguments as import urls - for (auto zip_path : parser.positionalArguments()) { - m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); + for (auto url : parser.positionalArguments()) { + addImportUrl(url); } // error if --launch is missing with --server or --profile @@ -345,12 +345,12 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) activate.command = "activate"; m_peerInstance->sendMessage(activate.serialize(), timeout); - if(!m_zipsToImport.isEmpty()) + if(!m_urlsToImport.isEmpty()) { - for (auto zip_url : m_zipsToImport) { + for (auto url : m_urlsToImport) { ApplicationMessage import; import.command = "import"; - import.args.insert("path", zip_url.toString()); + import.args.insert("path", url.toString()); m_peerInstance->sendMessage(import.serialize(), timeout); } } @@ -1027,10 +1027,10 @@ void Application::performMainStartupAction() showMainWindow(false); qDebug() << "<> Main window shown."; } - if(!m_zipsToImport.isEmpty()) + if(!m_urlsToImport.isEmpty()) { - qDebug() << "<> Importing from zip:" << m_zipsToImport; - m_mainWindow->processURLs( m_zipsToImport ); + qDebug() << "<> Importing from url:" << m_urlsToImport; + m_mainWindow->processURLs( m_urlsToImport ); } } @@ -1083,7 +1083,12 @@ void Application::messageReceived(const QByteArray& message) qWarning() << "Received" << command << "message without a zip path/URL."; return; } - m_mainWindow->processURLs({ QUrl::fromLocalFile(QFileInfo(path).absoluteFilePath()) }); + auto local_file = QFileInfo(path); + if (local_file.exists()) { + m_mainWindow->processURLs({ QUrl::fromLocalFile(local_file.absoluteFilePath()) }); + } else { + m_mainWindow->processURLs({ QUrl::fromUserInput(path) }); + } } else if(command == "launch") { @@ -1735,3 +1740,14 @@ void Application::triggerUpdateCheck() qDebug() << "Updater not available."; } } + +void Application::addImportUrl(QString const& url) +{ + auto local_file = QFileInfo(url); + if (local_file.exists()){ + m_urlsToImport.append(QUrl::fromLocalFile(local_file.absoluteFilePath())); + } else { + m_urlsToImport.append(QUrl::fromUserInput(url)); + } +} + diff --git a/launcher/Application.h b/launcher/Application.h index ced0af17d..83bfa9efd 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -211,6 +211,8 @@ public: int suitableMaxMem(); + void addImportUrl(QString const& url); + signals: void updateAllowedChanged(bool status); void globalSettingsAboutToOpen(); @@ -314,7 +316,7 @@ public: QString m_serverToJoin; QString m_profileToUse; bool m_liveCheck = false; - QList m_zipsToImport; + QList m_urlsToImport; QString m_instanceIdToShowWindowOf; std::unique_ptr logFile; }; diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 4d5193baa..41b7898cb 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -51,6 +51,7 @@ #include "Json.h" #include "settings/INISettingsObject.h" +#include "tasks/Task.h" #include #include @@ -89,46 +90,7 @@ void InstanceImportTask::executeTask() setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString())); m_downloadRequired = true; - if (m_sourceUrl.scheme() == "curseforge") { - // need to find the download link for the modpack - // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE - QUrlQuery query(m_sourceUrl); - auto addonId = query.allQueryItemValues("addonId")[0]; - auto fileId = query.allQueryItemValues("fileId")[0]; - auto array = new QByteArray(); - auto req = new NetJob("Curseforge Meta", APPLICATION->network()); - req->addNetAction( - Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), array)); - connect(req, &NetJob::finished, [array, req] { - req->deleteLater(); - delete array; - }); - connect(req, &NetJob::failed, this, &InstanceImportTask::downloadFailed); - connect(req, &NetJob::succeeded, [array, this] { - auto doc = Json::requireDocument(*array); - // No way to find out if it's a mod or a modpack before here - // And also we need to check if it ends with .zip, instead of any better way - auto fileName = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "fileName"); - if (fileName.endsWith(".zip")) { - // Have to use ensureString then use QUrl to get proper url encoding - m_sourceUrl = QUrl( - Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); - if (!m_sourceUrl.isValid()) { - emitFailed(tr("The modpack is blocked ! Please download it manually")); - return; - } - downloadFromUrl(); - } else { - emitFailed(tr("This url isn't a valid modpack !")); - } - }); - connect(req, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); - connect(req, &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress); - connect(req, &NetJob::aborted, this, &InstanceImportTask::downloadAborted); - req->start(); - } else { downloadFromUrl(); - } } } diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 30196aad6..78b7d1d56 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -35,12 +35,16 @@ */ #include "ImportPage.h" +#include "ui/dialogs/ProgressDialog.h" #include "ui_ImportPage.h" #include #include #include "ui/dialogs/NewInstanceDialog.h" +#include "ui/dialogs/CustomMessageBox.h" + +#include "Json.h" #include "InstanceImportTask.h" @@ -123,8 +127,62 @@ void ImportPage::updateState() dialog->setSuggestedIcon("default"); } } + else if (url.scheme() == "curseforge") + { + // need to find the download link for the modpack + // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE + QUrlQuery query(url); + auto addonId = query.allQueryItemValues("addonId")[0]; + auto fileId = query.allQueryItemValues("fileId")[0]; + auto array = new QByteArray(); + auto req = unique_qobject_ptr(new NetJob("Curseforge Meta", APPLICATION->network())); + req->addNetAction( + Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), array)); + + connect(req.get(), &NetJob::finished, [array] { + delete array; + }); + connect(req.get(), &NetJob::failed, this, [this](QString reason){ + CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); + }); + connect(req.get(), &NetJob::succeeded, this, [this, array, addonId, fileId] { + qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); + auto doc = Json::requireDocument(*array); + // No way to find out if it's a mod or a modpack before here + // And also we need to check if it ends with .zip, instead of any better way + auto fileName = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "fileName"); + if (fileName.endsWith(".zip")) { + // Have to use ensureString then use QUrl to get proper url encoding + auto dl_url = QUrl( + Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); + if (!dl_url.isValid()) { + CustomMessageBox::selectable(this, tr("Error"), tr("The modpack is blocked ! Please download it manually"), QMessageBox::Critical)->show(); + return; + } + + QFileInfo dl_file(dl_url.fileName()); + QString pack_name = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "displayName", dl_file.completeBaseName(), "displayName"); + + QMap extra_info; + extra_info.insert("pack_id", addonId); + extra_info.insert("pack_version_id", fileId); + + dialog->setSuggestedPack(pack_name, new InstanceImportTask(dl_url, this, std::move(extra_info))); + dialog->setSuggestedIcon("default"); + + } else { + CustomMessageBox::selectable(this, tr("Error"), tr("This url isn't a valid modpack !"), QMessageBox::Critical)->show(); + } + }); + ProgressDialog dlUrlDialod(this); + dlUrlDialod.setSkipButton(true, tr("Abort")); + dlUrlDialod.execWithTask(req.get()); + return; + } else { + + if(input.endsWith("?client=y")) { input.chop(9); input.append("/file"); diff --git a/launcher/ui/pages/modplatform/ImportPage.ui b/launcher/ui/pages/modplatform/ImportPage.ui index 3583cf90a..9a9736b8a 100644 --- a/launcher/ui/pages/modplatform/ImportPage.ui +++ b/launcher/ui/pages/modplatform/ImportPage.ui @@ -40,7 +40,7 @@ - - CurseForge modpacks (ZIP) + - CurseForge modpacks (ZIP / curseforge:// URL) Qt::AlignCenter From 3e11d94829989986a460242fa55c0110772d00f3 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 12 May 2023 01:47:18 -0700 Subject: [PATCH 025/398] spelling suggestions from code review Co-authored-by: Sefa Eyeoglu Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 5694b82e7..5effc01be 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -220,7 +220,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) {"show", "Opens the window for the specified instance (by instance ID)", "show"} }); // Has to be positional for some OS to handle that properly - parser.addPositionalArgument("urls","import the resource at the given url(s) (same as -I / --import)","[urls...]"); + parser.addPositionalArgument("URL", "Import the resource(s) at the given URL(s) (same as -I / --import)", "[URL...]"); parser.addHelpOption(); parser.addVersionOption(); From b1ffc8ddab7d9aff10b6195a75e6e58c43b233ca Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 12 May 2023 16:37:45 -0700 Subject: [PATCH 026/398] refactor: normalize url fn & cleanup Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 45 ++++++------------ launcher/Application.h | 2 +- launcher/InstanceImportTask.cpp | 2 +- launcher/ui/pages/modplatform/ImportPage.cpp | 50 ++++++++------------ 4 files changed, 36 insertions(+), 63 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 5effc01be..edaccadf6 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -235,12 +235,12 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_instanceIdToShowWindowOf = parser.value("show"); for (auto url : parser.values("import")){ - addImportUrl(url); + m_urlsToImport.append(normalizeImportUrl(url)); } // treat unspecified positional arguments as import urls for (auto url : parser.positionalArguments()) { - addImportUrl(url); + m_urlsToImport.append(normalizeImportUrl(url)); } // error if --launch is missing with --server or --profile @@ -345,12 +345,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) activate.command = "activate"; m_peerInstance->sendMessage(activate.serialize(), timeout); - if(!m_urlsToImport.isEmpty()) - { + if (!m_urlsToImport.isEmpty()) { for (auto url : m_urlsToImport) { ApplicationMessage import; import.command = "import"; - import.args.insert("path", url.toString()); + import.args.insert("url", url.toString()); m_peerInstance->sendMessage(import.serialize(), timeout); } } @@ -1071,27 +1070,16 @@ void Application::messageReceived(const QByteArray& message) auto & command = received.command; - if(command == "activate") - { + if (command == "activate") { showMainWindow(); - } - else if(command == "import") - { - QString path = received.args["path"]; - if(path.isEmpty()) - { + } else if (command == "import") { + QString url = received.args["url"]; + if (url.isEmpty()) { qWarning() << "Received" << command << "message without a zip path/URL."; return; } - auto local_file = QFileInfo(path); - if (local_file.exists()) { - m_mainWindow->processURLs({ QUrl::fromLocalFile(local_file.absoluteFilePath()) }); - } else { - m_mainWindow->processURLs({ QUrl::fromUserInput(path) }); - } - } - else if(command == "launch") - { + m_mainWindow->processURLs({ normalizeImportUrl(url) }); + } else if (command == "launch") { QString id = received.args["id"]; QString server = received.args["server"]; QString profile = received.args["profile"]; @@ -1131,9 +1119,7 @@ void Application::messageReceived(const QByteArray& message) serverObject, accountObject ); - } - else - { + } else { qWarning() << "Received invalid message" << message; } } @@ -1741,13 +1727,12 @@ void Application::triggerUpdateCheck() } } -void Application::addImportUrl(QString const& url) +QUrl Application::normalizeImportUrl(QString const& url) { auto local_file = QFileInfo(url); - if (local_file.exists()){ - m_urlsToImport.append(QUrl::fromLocalFile(local_file.absoluteFilePath())); + if (local_file.exists()) { + return QUrl::fromLocalFile(local_file.absoluteFilePath()); } else { - m_urlsToImport.append(QUrl::fromUserInput(url)); + return QUrl::fromUserInput(url); } } - diff --git a/launcher/Application.h b/launcher/Application.h index 83bfa9efd..97d33830c 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -211,7 +211,7 @@ public: int suitableMaxMem(); - void addImportUrl(QString const& url); + QUrl normalizeImportUrl(QString const& url); signals: void updateAllowedChanged(bool status); diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 41b7898cb..badcf0a22 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -90,7 +90,7 @@ void InstanceImportTask::executeTask() setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString())); m_downloadRequired = true; - downloadFromUrl(); + downloadFromUrl(); } } diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 78b7d1d56..315f6555b 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -102,16 +102,13 @@ void ImportPage::openedImpl() void ImportPage::updateState() { - if(!isOpened) - { + if (!isOpened) { return; } - if(ui->modpackEdit->hasAcceptableInput()) - { + if (ui->modpackEdit->hasAcceptableInput()) { QString input = ui->modpackEdit->text(); auto url = QUrl::fromUserInput(input); - if(url.isLocalFile()) - { + if (url.isLocalFile()) { // FIXME: actually do some validation of what's inside here... this is fake AF QFileInfo fi(input); @@ -120,15 +117,12 @@ void ImportPage::updateState() // mrpack is a modrinth pack bool isMRPack = fi.suffix() == "mrpack"; - if(fi.exists() && (isZip || isMRPack)) - { + if (fi.exists() && (isZip || isMRPack)) { QFileInfo fi(url.fileName()); - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url,this)); + dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this)); dialog->setSuggestedIcon("default"); } - } - else if (url.scheme() == "curseforge") - { + } else if (url.scheme() == "curseforge") { // need to find the download link for the modpack // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE QUrlQuery query(url); @@ -139,12 +133,9 @@ void ImportPage::updateState() req->addNetAction( Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), array)); - connect(req.get(), &NetJob::finished, [array] { - delete array; - }); - connect(req.get(), &NetJob::failed, this, [this](QString reason){ - CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); - }); + connect(req.get(), &NetJob::finished, [array] { delete array; }); + connect(req.get(), &NetJob::failed, this, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); connect(req.get(), &NetJob::succeeded, this, [this, array, addonId, fileId] { qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); auto doc = Json::requireDocument(*array); @@ -156,12 +147,15 @@ void ImportPage::updateState() auto dl_url = QUrl( Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); if (!dl_url.isValid()) { - CustomMessageBox::selectable(this, tr("Error"), tr("The modpack is blocked ! Please download it manually"), QMessageBox::Critical)->show(); + CustomMessageBox::selectable(this, tr("Error"), tr("The modpack is blocked ! Please download it manually"), + QMessageBox::Critical) + ->show(); return; } QFileInfo dl_file(dl_url.fileName()); - QString pack_name = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "displayName", dl_file.completeBaseName(), "displayName"); + QString pack_name = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "displayName", + dl_file.completeBaseName(), "displayName"); QMap extra_info; extra_info.insert("pack_id", addonId); @@ -169,7 +163,7 @@ void ImportPage::updateState() dialog->setSuggestedPack(pack_name, new InstanceImportTask(dl_url, this, std::move(extra_info))); dialog->setSuggestedIcon("default"); - + } else { CustomMessageBox::selectable(this, tr("Error"), tr("This url isn't a valid modpack !"), QMessageBox::Critical)->show(); } @@ -178,24 +172,18 @@ void ImportPage::updateState() dlUrlDialod.setSkipButton(true, tr("Abort")); dlUrlDialod.execWithTask(req.get()); return; - } - else - { - - - if(input.endsWith("?client=y")) { + } else { + if (input.endsWith("?client=y")) { input.chop(9); input.append("/file"); url = QUrl::fromUserInput(input); } // hook, line and sinker. QFileInfo fi(url.fileName()); - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url,this)); + dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this)); dialog->setSuggestedIcon("default"); } - } - else - { + } else { dialog->setSuggestedPack(); } } From fc656b6927914d64077e23690859996447908c57 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 15 May 2023 16:34:33 -0700 Subject: [PATCH 027/398] fix: when given a remost resource, download and identify it before import. Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .../mod/tasks/LocalResourceParse.cpp | 8 +- launcher/modplatform/flame/FlameAPI.cpp | 12 ++ launcher/modplatform/flame/FlameAPI.h | 1 + launcher/ui/MainWindow.cpp | 104 ++++++++++++++++-- launcher/ui/MainWindow.h | 2 +- launcher/ui/dialogs/NewInstanceDialog.cpp | 8 +- launcher/ui/dialogs/NewInstanceDialog.h | 29 ++--- launcher/ui/pages/modplatform/ImportPage.cpp | 30 +++-- launcher/ui/pages/modplatform/ImportPage.h | 3 +- 9 files changed, 159 insertions(+), 38 deletions(-) diff --git a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp index 4d760df2b..ef052afc3 100644 --- a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp @@ -44,7 +44,10 @@ static const QMap s_packed_type_names = { namespace ResourceUtils { PackedResourceType identify(QFileInfo file){ if (file.exists() && file.isFile()) { - if (ResourcePackUtils::validate(file)) { + if (ModUtils::validate(file)) { + qDebug() << file.fileName() << "is a mod"; + return PackedResourceType::Mod; + } else if (ResourcePackUtils::validate(file)) { qDebug() << file.fileName() << "is a resource pack"; return PackedResourceType::ResourcePack; } else if (TexturePackUtils::validate(file)) { @@ -53,9 +56,6 @@ PackedResourceType identify(QFileInfo file){ } else if (DataPackUtils::validate(file)) { qDebug() << file.fileName() << "is a data pack"; return PackedResourceType::DataPack; - } else if (ModUtils::validate(file)) { - qDebug() << file.fileName() << "is a mod"; - return PackedResourceType::Mod; } else if (WorldSaveUtils::validate(file)) { qDebug() << file.fileName() << "is a world save"; return PackedResourceType::WorldSave; diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 5ef9a4090..674ea427e 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -217,6 +217,18 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) c return netJob; } +Task::Ptr FlameAPI::getFile(const QString& addonId, const QString& fileId, QByteArray* response) const +{ + auto netJob = makeShared(QString("Flame::GetFile"), APPLICATION->network()); + netJob->addNetAction( + Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), response)); + + QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); + QObject::connect(netJob.get(), &NetJob::failed, [addonId, fileId] { qDebug() << "Flame API file failure" << addonId << fileId; }); + + return netJob; +} + // https://docs.curseforge.com/?python#tocS_ModsSearchSortField static QList s_sorts = { { 1, "Featured", QObject::tr("Sort by Featured") }, { 2, "Popularity", QObject::tr("Sort by Popularity") }, diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 5811d7175..f3b328a6f 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -17,6 +17,7 @@ class FlameAPI : public NetworkResourceAPI { Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; Task::Ptr matchFingerprints(const QList& fingerprints, QByteArray* response); Task::Ptr getFiles(const QStringList& fileIds, QByteArray* response) const; + Task::Ptr getFile(const QString& addonId, const QString& fileId, QByteArray* response) const; [[nodiscard]] auto getSortingMethods() const -> QList override; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 72b7db641..7e46cc412 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include @@ -116,11 +117,15 @@ #include "minecraft/mod/ShaderPackFolderModel.h" #include "minecraft/WorldList.h" +#include "modplatform/flame/FlameAPI.h" + #include "KonamiCode.h" #include "InstanceImportTask.h" #include "InstanceCopyTask.h" +#include "Json.h" + #include "MMCTime.h" namespace { @@ -981,7 +986,7 @@ void MainWindow::finalizeInstance(InstancePtr inst) } } -void MainWindow::addInstance(QString url) +void MainWindow::addInstance(const QString& url, const QMap& extra_info) { QString groupName; do @@ -1003,7 +1008,7 @@ void MainWindow::addInstance(QString url) groupName = APPLICATION->settings()->get("LastUsedGroupForNewInstance").toString(); } - NewInstanceDialog newInstDlg(groupName, url, this); + NewInstanceDialog newInstDlg(groupName, url, extra_info, this); if (!newInstDlg.exec()) return; @@ -1031,18 +1036,103 @@ void MainWindow::processURLs(QList urls) if (url.scheme().isEmpty()) url.setScheme("file"); - if (!url.isLocalFile()) { // probably instance/modpack - addInstance(url.toString()); - break; + QMap extra_info; + QUrl local_url; + if (!url.isLocalFile()) { // download the remote resource and identify + QUrl dl_url; + if(url.scheme() == "curseforge") { + // need to find the download link for the modpack / resource + // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE + QUrlQuery query(url); + + auto addonId = query.allQueryItemValues("addonId")[0]; + auto fileId = query.allQueryItemValues("fileId")[0]; + + extra_info.insert("pack_id", addonId); + extra_info.insert("pack_version_id", fileId); + + auto array = new QByteArray(); + + auto api = FlameAPI(); + auto job = api.getFile(addonId, fileId, array); + + QString resource_name; + + + connect(job.get(), &Task::failed, this, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); + connect(job.get(), &Task::succeeded, this, [this, array, addonId, fileId, &dl_url, &resource_name] { + qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); + auto doc = Json::requireDocument(*array); + // No way to find out if it's a mod or a modpack before here + // And also we need to check if it ends with .zip, instead of any better way + auto fileName = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "fileName"); + + // Have to use ensureString then use QUrl to get proper url encoding + dl_url = QUrl(Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", + "", "downloadUrl")); + if (!dl_url.isValid()) { + CustomMessageBox::selectable(this, tr("Error"), tr("The modpack, mod, or resource is blocked ! Please download it manually \n%1").arg(dl_url.toDisplayString()), + QMessageBox::Critical) + ->show(); + return; + } + + QFileInfo dl_file(dl_url.fileName()); + resource_name = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "displayName", + dl_file.completeBaseName(), "displayName"); + }); + + { // drop stack + ProgressDialog dlUrlDialod(this); + dlUrlDialod.setSkipButton(true, tr("Abort")); + dlUrlDialod.execWithTask(job.get()); + } + + // dialog->setSuggestedPack(pack_name, new InstanceImportTask(dl_url, this, std::move(extra_info))); + // dialog->setSuggestedIcon("default"); + + } else { + dl_url = url; + } + + if (!dl_url.isValid()) { + continue; // no valid url to download this resource + } + + const QString path = dl_url.host() + '/' + dl_url.path(); + auto entry = APPLICATION->metacache()->resolveEntry("general", path); + entry->setStale(true); + auto dl_job = unique_qobject_ptr(new NetJob(tr("Modpack download"), APPLICATION->network())); + dl_job->addNetAction(Net::Download::makeCached(dl_url, entry)); + auto archivePath = entry->getFullPath(); + + bool dl_success = false; + connect(dl_job.get(), &Task::failed, this, [this](QString reason){CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); + connect(dl_job.get(), &Task::succeeded, this, [&dl_success]{dl_success = true;}); + + { // drop stack + ProgressDialog dlUrlDialod(this); + dlUrlDialod.setSkipButton(true, tr("Abort")); + dlUrlDialod.execWithTask(dl_job.get()); + } + + if (!dl_success) { + continue; // no local file to identify + } + local_url = QUrl::fromLocalFile(archivePath); + + } else { + local_url = url; } - auto localFileName = QDir::toNativeSeparators(url.toLocalFile()) ; + auto localFileName = QDir::toNativeSeparators(local_url.toLocalFile()) ; QFileInfo localFileInfo(localFileName); auto type = ResourceUtils::identify(localFileInfo); if (ResourceUtils::ValidResourceTypes.count(type) == 0) { // probably instance/modpack - addInstance(localFileName); + addInstance(localFileName, extra_info); continue; } diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 3a42c34e1..1b8903194 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -210,7 +210,7 @@ private slots: private: void retranslateUi(); - void addInstance(QString url = QString()); + void addInstance(const QString& url = QString(), const QMap& extra_info = {}); void activateInstance(InstancePtr instance); void setCatBackground(bool enabled); void updateInstanceToolIcon(QString new_icon); diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 64ed76739..3f9e11c39 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -62,9 +62,10 @@ #include "ui/pages/modplatform/modrinth/ModrinthPage.h" #include "ui/pages/modplatform/technic/TechnicPage.h" - - -NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString & url, QWidget *parent) +NewInstanceDialog::NewInstanceDialog(const QString& initialGroup, + const QString& url, + const QMap& extra_info, + QWidget* parent) : QDialog(parent), ui(new Ui::NewInstanceDialog) { ui->setupUi(this); @@ -128,6 +129,7 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString QUrl actualUrl(url); m_container->selectPage("import"); importPage->setUrl(url); + importPage->setExtraInfo(extra_info); } updateDialogState(); diff --git a/launcher/ui/dialogs/NewInstanceDialog.h b/launcher/ui/dialogs/NewInstanceDialog.h index 961f512e2..368ad0dfc 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.h +++ b/launcher/ui/dialogs/NewInstanceDialog.h @@ -55,24 +55,27 @@ class NewInstanceDialog : public QDialog, public BasePageProvider Q_OBJECT public: - explicit NewInstanceDialog(const QString & initialGroup, const QString & url = QString(), QWidget *parent = 0); - ~NewInstanceDialog(); + explicit NewInstanceDialog(const QString& initialGroup, + const QString& url = QString(), + const QMap& extra_info = {}, + QWidget* parent = 0); + ~NewInstanceDialog(); - void updateDialogState(); + void updateDialogState(); - void setSuggestedPack(const QString& name = QString(), InstanceTask * task = nullptr); - void setSuggestedPack(const QString& name, QString version, InstanceTask * task = nullptr); - void setSuggestedIconFromFile(const QString &path, const QString &name); - void setSuggestedIcon(const QString &key); + void setSuggestedPack(const QString& name = QString(), InstanceTask* task = nullptr); + void setSuggestedPack(const QString& name, QString version, InstanceTask* task = nullptr); + void setSuggestedIconFromFile(const QString& path, const QString& name); + void setSuggestedIcon(const QString& key); - InstanceTask * extractTask(); + InstanceTask* extractTask(); - QString dialogTitle() override; - QList getPages() override; + QString dialogTitle() override; + QList getPages() override; - QString instName() const; - QString instGroup() const; - QString iconKey() const; + QString instName() const; + QString instGroup() const; + QString iconKey() const; public slots: void accept() override; diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 315f6555b..038b2a842 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -35,15 +35,20 @@ */ #include "ImportPage.h" +#include +#include #include "ui/dialogs/ProgressDialog.h" #include "ui_ImportPage.h" #include #include +#include #include "ui/dialogs/NewInstanceDialog.h" #include "ui/dialogs/CustomMessageBox.h" +#include "modplatform/flame/FlameAPI.h" + #include "Json.h" #include "InstanceImportTask.h" @@ -119,7 +124,9 @@ void ImportPage::updateState() if (fi.exists() && (isZip || isMRPack)) { QFileInfo fi(url.fileName()); - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this)); + auto extra_info = QMap(m_extra_info); + qDebug() << "Pack Extra Info" << extra_info << m_extra_info; + dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this, std::move(extra_info))); dialog->setSuggestedIcon("default"); } } else if (url.scheme() == "curseforge") { @@ -129,14 +136,13 @@ void ImportPage::updateState() auto addonId = query.allQueryItemValues("addonId")[0]; auto fileId = query.allQueryItemValues("fileId")[0]; auto array = new QByteArray(); - auto req = unique_qobject_ptr(new NetJob("Curseforge Meta", APPLICATION->network())); - req->addNetAction( - Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), array)); - connect(req.get(), &NetJob::finished, [array] { delete array; }); - connect(req.get(), &NetJob::failed, this, + auto api = FlameAPI(); + auto job = api.getFile(addonId, fileId, array); + + connect(job.get(), &NetJob::failed, this, [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(req.get(), &NetJob::succeeded, this, [this, array, addonId, fileId] { + connect(job.get(), &NetJob::succeeded, this, [this, array, addonId, fileId] { qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); auto doc = Json::requireDocument(*array); // No way to find out if it's a mod or a modpack before here @@ -170,7 +176,7 @@ void ImportPage::updateState() }); ProgressDialog dlUrlDialod(this); dlUrlDialod.setSkipButton(true, tr("Abort")); - dlUrlDialod.execWithTask(req.get()); + dlUrlDialod.execWithTask(job.get()); return; } else { if (input.endsWith("?client=y")) { @@ -180,7 +186,8 @@ void ImportPage::updateState() } // hook, line and sinker. QFileInfo fi(url.fileName()); - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this)); + auto extra_info = QMap(m_extra_info); + dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this, std::move(extra_info))); dialog->setSuggestedIcon("default"); } } else { @@ -194,6 +201,11 @@ void ImportPage::setUrl(const QString& url) updateState(); } +void ImportPage::setExtraInfo(const QMap& extra_info) { + m_extra_info = QMap(extra_info); // copy + updateState(); +} + void ImportPage::on_modpackBtn_clicked() { auto filter = QMimeDatabase().mimeTypeForName("application/zip").filterString(); diff --git a/launcher/ui/pages/modplatform/ImportPage.h b/launcher/ui/pages/modplatform/ImportPage.h index 8d13ac100..d35cb361e 100644 --- a/launcher/ui/pages/modplatform/ImportPage.h +++ b/launcher/ui/pages/modplatform/ImportPage.h @@ -76,7 +76,7 @@ public: void setUrl(const QString & url); void openedImpl() override; - + void setExtraInfo(const QMap& extra_info); private slots: void on_modpackBtn_clicked(); void updateState(); @@ -87,5 +87,6 @@ private: private: Ui::ImportPage *ui = nullptr; NewInstanceDialog* dialog = nullptr; + QMap m_extra_info = {}; }; From 649753e97e4609deee09a1c8beeba3027d66e4d0 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 15 May 2023 16:40:56 -0700 Subject: [PATCH 028/398] cleanup: remove unneeded headers Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .../mod/tasks/LocalResourceParse.cpp | 2 +- launcher/ui/MainWindow.cpp | 1 - launcher/ui/dialogs/NewInstanceDialog.h | 58 +++++++++---------- launcher/ui/pages/modplatform/ImportPage.cpp | 3 +- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp index ef052afc3..fa7d7f4ae 100644 --- a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp @@ -44,7 +44,7 @@ static const QMap s_packed_type_names = { namespace ResourceUtils { PackedResourceType identify(QFileInfo file){ if (file.exists() && file.isFile()) { - if (ModUtils::validate(file)) { + if (ModUtils::validate(file)) { // Mods can also contain resource and data packs qDebug() << file.fileName() << "is a mod"; return PackedResourceType::Mod; } else if (ResourcePackUtils::validate(file)) { diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 7e46cc412..31a75e5bf 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -86,7 +86,6 @@ #include #include #include -#include #include #include #include diff --git a/launcher/ui/dialogs/NewInstanceDialog.h b/launcher/ui/dialogs/NewInstanceDialog.h index 368ad0dfc..6a6ad89eb 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.h +++ b/launcher/ui/dialogs/NewInstanceDialog.h @@ -37,11 +37,10 @@ #include -#include "ui/pages/BasePageProvider.h" #include "InstanceTask.h" +#include "ui/pages/BasePageProvider.h" -namespace Ui -{ +namespace Ui { class NewInstanceDialog; } @@ -50,48 +49,47 @@ class QDialogButtonBox; class ImportPage; class FlamePage; -class NewInstanceDialog : public QDialog, public BasePageProvider -{ +class NewInstanceDialog : public QDialog, public BasePageProvider { Q_OBJECT -public: - explicit NewInstanceDialog(const QString& initialGroup, - const QString& url = QString(), - const QMap& extra_info = {}, - QWidget* parent = 0); - ~NewInstanceDialog(); + public: + explicit NewInstanceDialog(const QString& initialGroup, + const QString& url = QString(), + const QMap& extra_info = {}, + QWidget* parent = 0); + ~NewInstanceDialog(); - void updateDialogState(); + void updateDialogState(); - void setSuggestedPack(const QString& name = QString(), InstanceTask* task = nullptr); - void setSuggestedPack(const QString& name, QString version, InstanceTask* task = nullptr); - void setSuggestedIconFromFile(const QString& path, const QString& name); - void setSuggestedIcon(const QString& key); + void setSuggestedPack(const QString& name = QString(), InstanceTask* task = nullptr); + void setSuggestedPack(const QString& name, QString version, InstanceTask* task = nullptr); + void setSuggestedIconFromFile(const QString& path, const QString& name); + void setSuggestedIcon(const QString& key); - InstanceTask* extractTask(); + InstanceTask* extractTask(); - QString dialogTitle() override; - QList getPages() override; + QString dialogTitle() override; + QList getPages() override; - QString instName() const; - QString instGroup() const; - QString iconKey() const; + QString instName() const; + QString instGroup() const; + QString iconKey() const; -public slots: + public slots: void accept() override; void reject() override; -private slots: + private slots: void on_iconButton_clicked(); - void on_instNameTextBox_textChanged(const QString &arg1); + void on_instNameTextBox_textChanged(const QString& arg1); -private: - Ui::NewInstanceDialog *ui = nullptr; - PageContainer * m_container = nullptr; - QDialogButtonBox * m_buttons = nullptr; + private: + Ui::NewInstanceDialog* ui = nullptr; + PageContainer* m_container = nullptr; + QDialogButtonBox* m_buttons = nullptr; QString InstIconKey; - ImportPage *importPage = nullptr; + ImportPage* importPage = nullptr; std::unique_ptr creationTask; bool importIcon = false; diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 038b2a842..1e540cf21 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -35,8 +35,7 @@ */ #include "ImportPage.h" -#include -#include + #include "ui/dialogs/ProgressDialog.h" #include "ui_ImportPage.h" From bd1ea64d02828df7b24081e02ec162abb4b13e9f Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 16 May 2023 00:01:52 -0700 Subject: [PATCH 029/398] cleanup Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/MainWindow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 31a75e5bf..4546eb1e7 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1088,8 +1088,6 @@ void MainWindow::processURLs(QList urls) dlUrlDialod.execWithTask(job.get()); } - // dialog->setSuggestedPack(pack_name, new InstanceImportTask(dl_url, this, std::move(extra_info))); - // dialog->setSuggestedIcon("default"); } else { dl_url = url; From c15603406907383c58786cb1dc235ac79c7f9626 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 26 May 2023 13:50:22 -0700 Subject: [PATCH 030/398] feat: add verion_type / release_type to IndexedVersion Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/ModIndex.cpp | 50 +++++++++++++++++++ launcher/modplatform/ModIndex.h | 24 +++++++++ launcher/modplatform/flame/FlameAPI.cpp | 5 +- launcher/modplatform/flame/FlameModIndex.cpp | 8 ++- .../modrinth/ModrinthPackIndex.cpp | 9 +++- 5 files changed, 93 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 6a507caf4..7fdca3b37 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -24,6 +24,56 @@ namespace ModPlatform { +static const QMap s_indexed_version_type_names = { + {"release", IndexedVersionType::Enum::Release}, + {"beta", IndexedVersionType::Enum::Beta}, + {"alpha", IndexedVersionType::Enum::Alpha} +}; + +IndexedVersionType::IndexedVersionType(const QString& type): IndexedVersionType(enumFromString(type)) +{} + +IndexedVersionType::IndexedVersionType(int type) +{ + m_type = static_cast(type); +} + +IndexedVersionType::IndexedVersionType(const IndexedVersionType::Enum& type) +{ + m_type = type; +} + +IndexedVersionType::IndexedVersionType(const IndexedVersionType& other) +{ + m_type = other.m_type; +} + +const QString IndexedVersionType::toString (const IndexedVersionType::Enum& type) +{ + switch (type) { + case IndexedVersionType::Enum::Release: + return "release"; + case IndexedVersionType::Enum::Beta: + return "beta"; + case IndexedVersionType::Enum::Alpha: + return "alpha"; + case IndexedVersionType::Enum::UNKNOWN: + default: + return "unknown"; + + } +} + +const IndexedVersionType::Enum IndexedVersionType::enumFromString(const QString& type) +{ + auto found = s_indexed_version_type_names.constFind(type); + if (found != s_indexed_version_type_names.constEnd()) { + return *found; + } else { + return IndexedVersionType::Enum::UNKNOWN; + } +} + auto ProviderCapabilities::name(ResourceProvider p) -> const char* { switch (p) { diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 40f1efc4e..f15b296af 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -23,6 +23,7 @@ #include #include #include +#include class QIODevice; @@ -51,11 +52,34 @@ struct DonationData { QString url; }; +struct IndexedVersionType { + enum class Enum { + Release = 1, + Beta, + Alpha, + UNKNOWN + }; + IndexedVersionType(const QString& type); + IndexedVersionType(int type); + IndexedVersionType(const IndexedVersionType::Enum& type); + IndexedVersionType(const IndexedVersionType& type); + static const QString toString (const IndexedVersionType::Enum& type); + static const IndexedVersionType::Enum enumFromString(const QString& type); + bool isValid() const {return m_type != IndexedVersionType::Enum::UNKNOWN; } + bool operator==(const IndexedVersionType& other) const { return m_type == other.m_type; } + bool operator==(const IndexedVersionType::Enum& type) const { return m_type == type; } + bool operator<(const IndexedVersionType& other) const { return m_type < other.m_type; } + bool operator<(const IndexedVersionType::Enum& type) const { return m_type < type; } + + IndexedVersionType::Enum m_type; +}; + struct IndexedVersion { QVariant addonId; QVariant fileId; QString version; QString version_number = {}; + std::optional verison_type = {}; QStringList mcVersion; QString downloadUrl; QString date; diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 5ef9a4090..0f26efefe 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -144,7 +144,10 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - if(file_tmp.date > ver_tmp.date) { + bool better_release = true; + if (file_tmp.verison_type.has_value() && ver_tmp.verison_type.has_value()) + better_release = file_tmp.verison_type.value() < ver_tmp.verison_type.value(); + if(file_tmp.date > ver_tmp.date && better_release) { ver_tmp = file_tmp; latest_file_obj = file_obj; } diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 7498e8302..5866cfbd4 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -94,8 +94,11 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { + bool a_better_release = true; + if (a.verison_type.has_value() && b.verison_type.has_value()) + a_better_release = a.verison_type.value() < b.verison_type.value(); // dates are in RFC 3339 format - return a.date > b.date; + return a.date > b.date && a_better_release; }; std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); pack.versions = unsortedVersions; @@ -123,6 +126,9 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> file.version = Json::requireString(obj, "displayName"); file.downloadUrl = Json::ensureString(obj, "downloadUrl"); file.fileName = Json::requireString(obj, "fileName"); + auto version_type = ModPlatform::IndexedVersionType(Json::requireInteger(obj, "releaseType")); + if (version_type.isValid()) + file.verison_type = version_type; auto hash_list = Json::ensureArray(obj, "hashes"); for (auto h : hash_list) { diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 7ade131e4..c87fa3029 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -109,8 +109,11 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { + bool a_better_release = true; + if (a.verison_type.has_value() && b.verison_type.has_value()) + a_better_release = a.verison_type.value() < b.verison_type.value(); // dates are in RFC 3339 format - return a.date > b.date; + return a.date > b.date && a_better_release; }; std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); pack.versions = unsortedVersions; @@ -138,6 +141,10 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t } file.version = Json::requireString(obj, "name"); file.version_number = Json::requireString(obj, "version_number"); + auto verison_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type")); + if (verison_type.isValid()) + file.verison_type = verison_type; + file.changelog = Json::requireString(obj, "changelog"); auto files = Json::requireArray(obj, "files"); From cf4df19986fe53357ef04b2a4407f69a2f4fa196 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 26 May 2023 16:23:43 -0700 Subject: [PATCH 031/398] feat: display release type Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/CheckUpdateTask.h | 28 +++++++++++++++---- launcher/modplatform/ModIndex.cpp | 14 +++++++++- launcher/modplatform/ModIndex.h | 4 ++- launcher/modplatform/flame/FlameAPI.cpp | 4 +-- .../modplatform/flame/FlameCheckUpdate.cpp | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 8 ++---- launcher/modplatform/flame/FlamePackIndex.cpp | 1 + launcher/modplatform/flame/FlamePackIndex.h | 3 ++ .../modrinth/ModrinthCheckUpdate.cpp | 4 +-- .../modrinth/ModrinthPackIndex.cpp | 8 ++---- .../modrinth/ModrinthPackManifest.cpp | 4 ++- .../modrinth/ModrinthPackManifest.h | 3 ++ launcher/ui/dialogs/ModUpdateDialog.cpp | 5 ++++ launcher/ui/pages/modplatform/ModPage.cpp | 6 ++-- .../ui/pages/modplatform/ResourcePage.cpp | 4 +-- .../ui/pages/modplatform/flame/FlamePage.cpp | 3 +- .../modplatform/modrinth/ModrinthPage.cpp | 6 ++-- 17 files changed, 73 insertions(+), 34 deletions(-) diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index f7582b8f1..fbafedd77 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -1,8 +1,8 @@ #pragma once #include "minecraft/mod/Mod.h" -#include "modplatform/ResourceAPI.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "tasks/Task.h" class ResourceDownloadTask; @@ -12,21 +12,39 @@ class CheckUpdateTask : public Task { Q_OBJECT public: - CheckUpdateTask(QList& mods, std::list& mcVersions, std::optional loaders, std::shared_ptr mods_folder) - : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder) {}; + CheckUpdateTask(QList& mods, + std::list& mcVersions, + std::optional loaders, + std::shared_ptr mods_folder) + : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){}; struct UpdatableMod { QString name; QString old_hash; QString old_version; QString new_version; + std::optional new_verison_type; QString changelog; ModPlatform::ResourceProvider provider; shared_qobject_ptr download; public: - UpdatableMod(QString name, QString old_h, QString old_v, QString new_v, QString changelog, ModPlatform::ResourceProvider p, shared_qobject_ptr t) - : name(name), old_hash(old_h), old_version(old_v), new_version(new_v), changelog(changelog), provider(p), download(t) + UpdatableMod(QString name, + QString old_h, + QString old_v, + QString new_v, + std::optional new_v_type, + QString changelog, + ModPlatform::ResourceProvider p, + shared_qobject_ptr t) + : name(name) + , old_hash(old_h) + , old_version(old_v) + , new_version(new_v) + , new_verison_type(new_v_type) + , changelog(changelog) + , provider(p) + , download(t) {} }; diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 7fdca3b37..607c26e61 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -35,7 +35,19 @@ IndexedVersionType::IndexedVersionType(const QString& type): IndexedVersionType( IndexedVersionType::IndexedVersionType(int type) { - m_type = static_cast(type); + switch (type) { + case 1: + m_type = IndexedVersionType::Enum::Release; + break; + case 2: + m_type = IndexedVersionType::Enum::Beta; + break; + case 3: + m_type = IndexedVersionType::Enum::Alpha; + break; + default: + m_type = IndexedVersionType::Enum::UNKNOWN; + } } IndexedVersionType::IndexedVersionType(const IndexedVersionType::Enum& type) diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index f15b296af..10b61b167 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -63,6 +63,7 @@ struct IndexedVersionType { IndexedVersionType(int type); IndexedVersionType(const IndexedVersionType::Enum& type); IndexedVersionType(const IndexedVersionType& type); + IndexedVersionType() : IndexedVersionType(IndexedVersionType::Enum::UNKNOWN) {} static const QString toString (const IndexedVersionType::Enum& type); static const IndexedVersionType::Enum enumFromString(const QString& type); bool isValid() const {return m_type != IndexedVersionType::Enum::UNKNOWN; } @@ -70,6 +71,7 @@ struct IndexedVersionType { bool operator==(const IndexedVersionType::Enum& type) const { return m_type == type; } bool operator<(const IndexedVersionType& other) const { return m_type < other.m_type; } bool operator<(const IndexedVersionType::Enum& type) const { return m_type < type; } + QString toString() const { return toString(m_type); } IndexedVersionType::Enum m_type; }; @@ -79,7 +81,7 @@ struct IndexedVersion { QVariant fileId; QString version; QString version_number = {}; - std::optional verison_type = {}; + IndexedVersionType verison_type; QStringList mcVersion; QString downloadUrl; QString date; diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 0f26efefe..ad3ab16ac 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -144,9 +144,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - bool better_release = true; - if (file_tmp.verison_type.has_value() && ver_tmp.verison_type.has_value()) - better_release = file_tmp.verison_type.value() < ver_tmp.verison_type.value(); + bool better_release = file_tmp.verison_type < ver_tmp.verison_type; if(file_tmp.date > ver_tmp.date && better_release) { ver_tmp = file_tmp; latest_file_obj = file_obj; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 06a895027..1e8cc66d9 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -173,7 +173,7 @@ void FlameCheckUpdate::executeTask() } auto download_task = makeShared(pack, latest_ver, m_mods_folder); - m_updatable.emplace_back(pack.name, mod->metadata()->hash, old_version, latest_ver.version, + m_updatable.emplace_back(pack.name, mod->metadata()->hash, old_version, latest_ver.version, latest_ver.verison_type, api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), ModPlatform::ResourceProvider::FLAME, download_task); } diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 5866cfbd4..cb7177d2e 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -94,9 +94,7 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = true; - if (a.verison_type.has_value() && b.verison_type.has_value()) - a_better_release = a.verison_type.value() < b.verison_type.value(); + bool a_better_release = a.verison_type < b.verison_type; // dates are in RFC 3339 format return a.date > b.date && a_better_release; }; @@ -126,9 +124,7 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> file.version = Json::requireString(obj, "displayName"); file.downloadUrl = Json::ensureString(obj, "downloadUrl"); file.fileName = Json::requireString(obj, "fileName"); - auto version_type = ModPlatform::IndexedVersionType(Json::requireInteger(obj, "releaseType")); - if (version_type.isValid()) - file.verison_type = version_type; + file.verison_type = ModPlatform::IndexedVersionType(Json::requireInteger(obj, "releaseType")); auto hash_list = Json::ensureArray(obj, "hashes"); for (auto h : hash_list) { diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp index ad48b7b6a..e643c96b0 100644 --- a/launcher/modplatform/flame/FlamePackIndex.cpp +++ b/launcher/modplatform/flame/FlamePackIndex.cpp @@ -90,6 +90,7 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr) // pick the latest version supported file.mcVersion = versionArray[0].toString(); file.version = Json::requireString(version, "displayName"); + file.version_type = ModPlatform::IndexedVersionType(Json::requireInteger(version, "releaseType")); file.downloadUrl = Json::ensureString(version, "downloadUrl"); // only add if we have a download URL (third party distribution is enabled) diff --git a/launcher/modplatform/flame/FlamePackIndex.h b/launcher/modplatform/flame/FlamePackIndex.h index 1ca0fc0e5..0abcadb36 100644 --- a/launcher/modplatform/flame/FlamePackIndex.h +++ b/launcher/modplatform/flame/FlamePackIndex.h @@ -5,6 +5,8 @@ #include #include +#include "modplatform/ModIndex.h" + namespace Flame { struct ModpackAuthor { @@ -16,6 +18,7 @@ struct IndexedVersion { int addonId; int fileId; QString version; + ModPlatform::IndexedVersionType version_type; QString mcVersion; QString downloadUrl; }; diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index d1be72099..76ad70157 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -161,8 +161,8 @@ void ModrinthCheckUpdate::executeTask() auto download_task = makeShared(pack, project_ver, m_mods_folder); - m_updatable.emplace_back(pack.name, hash, mod->version(), project_ver.version_number, project_ver.changelog, - ModPlatform::ResourceProvider::MODRINTH, download_task); + m_updatable.emplace_back(pack.name, hash, mod->version(), project_ver.version_number, project_ver.verison_type, + project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task); } } } catch (Json::JsonException& e) { diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index c87fa3029..2e9d14575 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -109,9 +109,7 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = true; - if (a.verison_type.has_value() && b.verison_type.has_value()) - a_better_release = a.verison_type.value() < b.verison_type.value(); + bool a_better_release = a.verison_type < b.verison_type; // dates are in RFC 3339 format return a.date > b.date && a_better_release; }; @@ -141,9 +139,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t } file.version = Json::requireString(obj, "name"); file.version_number = Json::requireString(obj, "version_number"); - auto verison_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type")); - if (verison_type.isValid()) - file.verison_type = verison_type; + file.verison_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type")); file.changelog = Json::requireString(obj, "changelog"); diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index 4dca786f0..04ed4fa23 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -111,8 +111,9 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc) unsortedVersions.append(file); } auto orderSortPredicate = [](const ModpackVersion& a, const ModpackVersion& b) -> bool { + bool a_better_release = a.version_type < b.version_type; // dates are in RFC 3339 format - return a.date > b.date; + return a.date > b.date && a_better_release; }; std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); @@ -128,6 +129,7 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion file.name = Json::requireString(obj, "name"); file.version = Json::requireString(obj, "version_number"); + file.version_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type")); file.changelog = Json::ensureString(obj, "changelog"); file.id = Json::requireString(obj, "id"); diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.h b/launcher/modplatform/modrinth/ModrinthPackManifest.h index 2973dfba2..5f8c50a1a 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.h +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.h @@ -45,6 +45,8 @@ #include #include +#include "modplatform/ModIndex.h" + class MinecraftInstance; namespace Modrinth { @@ -80,6 +82,7 @@ struct ModpackExtra { struct ModpackVersion { QString name; QString version; + ModPlatform::IndexedVersionType version_type; QString changelog; QString id; diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 8618b9240..9e010444c 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -362,6 +362,11 @@ void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info) auto new_version_item = new QTreeWidgetItem(item_top); new_version_item->setText(0, tr("New version: %1").arg(info.new_version)); + if (info.new_verison_type.has_value()) { + auto new_version_type_itme = new QTreeWidgetItem(item_top); + new_version_type_itme->setText(0, tr("New Version Type: %1").arg(info.new_verison_type.value().toString())); + } + auto changelog_item = new QTreeWidgetItem(item_top); changelog_item->setText(0, tr("Changelog of the latest version")); diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 04be43ada..e156f5009 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -137,8 +137,10 @@ void ModPage::updateVersionList() } // Only add the version if it's valid or using the 'Any' filter, but never if the version is opted out - if ((valid || m_filter->versions.empty()) && !optedOut(version)) - m_ui->versionSelectionBox->addItem(version.version, QVariant(i)); + if ((valid || m_filter->versions.empty()) && !optedOut(version)) { + auto release_type = version.verison_type.isValid() ? QString(" : %1").arg(version.verison_type.toString()) : ""; + m_ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(i)); + } } if (m_ui->versionSelectionBox->count() == 0) { m_ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1)); diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index bbd465bc1..72565eccc 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -256,8 +256,8 @@ void ResourcePage::updateVersionList() auto& version = current_pack.versions[i]; if (optedOut(version)) continue; - - m_ui->versionSelectionBox->addItem(current_pack.versions[i].version, QVariant(i)); + auto release_type = current_pack.versions[i].verison_type.isValid() ? QString(" : %1").arg(current_pack.versions[i].verison_type.toString()) : ""; + m_ui->versionSelectionBox->addItem(QString("%1%2").arg(current_pack.versions[i].version, release_type), QVariant(i)); } if (m_ui->versionSelectionBox->count() == 0) { diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index f9ac4a789..95bb9d0f3 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -155,7 +155,8 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) } for (auto version : current.versions) { - ui->versionSelectionBox->addItem(version.version, QVariant(version.downloadUrl)); + auto release_type = version.version_type.isValid() ? QString(" : %1").arg(version.version_type.toString()) : ""; + ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(version.downloadUrl)); } QVariant current_updated; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 0bb11d834..725af9b0c 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -201,12 +201,12 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) qDebug() << *response; qWarning() << "Error while reading modrinth modpack version: " << e.cause(); } - for (auto version : current.versions) { + auto release_type = version.version_type.isValid() ? QString(" : %1").arg(version.version_type.toString()) : ""; if (!version.name.contains(version.version)) - ui->versionSelectionBox->addItem(QString("%1 — %2").arg(version.name, version.version), QVariant(version.id)); + ui->versionSelectionBox->addItem(QString("%1 — %2%3").arg(version.name, version.version, release_type), QVariant(version.id)); else - ui->versionSelectionBox->addItem(version.name, QVariant(version.id)); + ui->versionSelectionBox->addItem(QString("%1%2").arg(version.name, release_type), QVariant(version.id)); } QVariant current_updated; From 832a61f88674ee1ba01d7618e1021184cc851e3a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 26 May 2023 16:34:30 -0700 Subject: [PATCH 032/398] fix: make codeQl happy Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/ModIndex.cpp | 8 +++++++- launcher/modplatform/ModIndex.h | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 607c26e61..3e1f473e9 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -60,6 +60,12 @@ IndexedVersionType::IndexedVersionType(const IndexedVersionType& other) m_type = other.m_type; } +IndexedVersionType& IndexedVersionType::operator=(const IndexedVersionType& other) +{ + m_type = other.m_type; + return *this; +} + const QString IndexedVersionType::toString (const IndexedVersionType::Enum& type) { switch (type) { @@ -76,7 +82,7 @@ const QString IndexedVersionType::toString (const IndexedVersionType::Enum& type } } -const IndexedVersionType::Enum IndexedVersionType::enumFromString(const QString& type) +IndexedVersionType::Enum IndexedVersionType::enumFromString(const QString& type) { auto found = s_indexed_version_type_names.constFind(type); if (found != s_indexed_version_type_names.constEnd()) { diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 10b61b167..f317d29e8 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -65,8 +65,9 @@ struct IndexedVersionType { IndexedVersionType(const IndexedVersionType& type); IndexedVersionType() : IndexedVersionType(IndexedVersionType::Enum::UNKNOWN) {} static const QString toString (const IndexedVersionType::Enum& type); - static const IndexedVersionType::Enum enumFromString(const QString& type); + static IndexedVersionType::Enum enumFromString(const QString& type); bool isValid() const {return m_type != IndexedVersionType::Enum::UNKNOWN; } + IndexedVersionType& operator=(const IndexedVersionType& other); bool operator==(const IndexedVersionType& other) const { return m_type == other.m_type; } bool operator==(const IndexedVersionType::Enum& type) const { return m_type == type; } bool operator<(const IndexedVersionType& other) const { return m_type < other.m_type; } From 2680dba0aa74abefea58903dadad6578381101cb Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 26 May 2023 17:16:50 -0700 Subject: [PATCH 033/398] fix: use <= when compareing release types Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/ModIndex.h | 9 +++++++++ launcher/modplatform/flame/FlameAPI.cpp | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackIndex.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackManifest.cpp | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index f317d29e8..652e21ef0 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -70,8 +70,17 @@ struct IndexedVersionType { IndexedVersionType& operator=(const IndexedVersionType& other); bool operator==(const IndexedVersionType& other) const { return m_type == other.m_type; } bool operator==(const IndexedVersionType::Enum& type) const { return m_type == type; } + bool operator!=(const IndexedVersionType& other) const { return m_type != other.m_type; } + bool operator!=(const IndexedVersionType::Enum& type) const { return m_type != type; } bool operator<(const IndexedVersionType& other) const { return m_type < other.m_type; } bool operator<(const IndexedVersionType::Enum& type) const { return m_type < type; } + bool operator<=(const IndexedVersionType& other) const { return m_type <= other.m_type; } + bool operator<=(const IndexedVersionType::Enum& type) const { return m_type <= type; } + bool operator>(const IndexedVersionType& other) const { return m_type > other.m_type; } + bool operator>(const IndexedVersionType::Enum& type) const { return m_type > type; } + bool operator>=(const IndexedVersionType& other) const { return m_type >= other.m_type; } + bool operator>=(const IndexedVersionType::Enum& type) const { return m_type >= type; } + QString toString() const { return toString(m_type); } IndexedVersionType::Enum m_type; diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index ad3ab16ac..b5155dd8c 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -144,7 +144,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - bool better_release = file_tmp.verison_type < ver_tmp.verison_type; + bool better_release = file_tmp.verison_type <= ver_tmp.verison_type; if(file_tmp.date > ver_tmp.date && better_release) { ver_tmp = file_tmp; latest_file_obj = file_obj; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index cb7177d2e..389ee03b3 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -94,7 +94,7 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = a.verison_type < b.verison_type; + bool a_better_release = a.verison_type <= b.verison_type; // dates are in RFC 3339 format return a.date > b.date && a_better_release; }; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 2e9d14575..e643df677 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -109,7 +109,7 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = a.verison_type < b.verison_type; + bool a_better_release = a.verison_type <= b.verison_type; // dates are in RFC 3339 format return a.date > b.date && a_better_release; }; diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index 04ed4fa23..aff29fb8c 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -111,7 +111,7 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc) unsortedVersions.append(file); } auto orderSortPredicate = [](const ModpackVersion& a, const ModpackVersion& b) -> bool { - bool a_better_release = a.version_type < b.version_type; + bool a_better_release = a.version_type <= b.version_type; // dates are in RFC 3339 format return a.date > b.date && a_better_release; }; From eb079c80605f88cbd0aaff8285dafc459c6f42eb Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 28 May 2023 11:13:53 -0700 Subject: [PATCH 034/398] cleanup: msgbox msg editor Co-authored-by: flow Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 4546eb1e7..63209b9f5 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1071,7 +1071,7 @@ void MainWindow::processURLs(QList urls) dl_url = QUrl(Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); if (!dl_url.isValid()) { - CustomMessageBox::selectable(this, tr("Error"), tr("The modpack, mod, or resource is blocked ! Please download it manually \n%1").arg(dl_url.toDisplayString()), + CustomMessageBox::selectable(this, tr("Error"), tr("The modpack, mod, or resource is blocked for third-parties! Please download it manually at: \n%1").arg(dl_url.toDisplayString()), QMessageBox::Critical) ->show(); return; From 1c91d2f24255272a5526d70ff06f8907f65012a6 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 30 May 2023 23:03:44 -0700 Subject: [PATCH 035/398] feat: paliminary updater - can check for need to update - can select a version to update to - perform update: TODO Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 2 +- launcher/CMakeLists.txt | 59 +- launcher/Version.h | 1 + launcher/filelink/FileLink.cpp | 3 + launcher/filelink/FileLink.h | 11 + launcher/filelink/main.cpp | 14 +- launcher/updater/windows/GitHubRelease.h | 34 + .../updater/windows/SelectReleaseDialog.ui | 89 +++ launcher/updater/windows/UpdaterDialogs.cpp | 78 +++ launcher/updater/windows/UpdaterDialogs.h | 33 + launcher/updater/windows/WindowsUpdater.cpp | 647 ++++++++++++++++++ launcher/updater/windows/WindowsUpdater.h | 110 +++ launcher/updater/windows/windows_main.cpp | 44 ++ 13 files changed, 1122 insertions(+), 3 deletions(-) create mode 100644 launcher/updater/windows/GitHubRelease.h create mode 100644 launcher/updater/windows/SelectReleaseDialog.ui create mode 100644 launcher/updater/windows/UpdaterDialogs.cpp create mode 100644 launcher/updater/windows/UpdaterDialogs.h create mode 100644 launcher/updater/windows/WindowsUpdater.cpp create mode 100644 launcher/updater/windows/WindowsUpdater.h create mode 100644 launcher/updater/windows/windows_main.cpp diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1659eb445..4b0ba368b 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -469,7 +469,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) { - qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT; + qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); qDebug() << "Version : " << BuildConfig.printableVersionString(); qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 273b5449a..5a979b8d9 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -567,6 +567,25 @@ set(LINKEXE_SOURCES DesktopServices.cpp ) +set(WINDOWSUPDATEREXE_SOURCES + updater/windows/WindowsUpdater.h + updater/windows/WindowsUpdater.cpp + updater/windows/UpdaterDialogs.h + updater/windows/UpdaterDialogs.cpp + updater/windows/GitHubRelease.h + Json.h + Json.cpp + FileSystem.h + FileSystem.cpp + StringUtils.h + StringUtils.cpp + DesktopServices.h + DesktopServices.cpp + Version.h + Version.cpp + Markdown.h +) + ######## Logging categories ######## ecm_qt_declare_logging_category(CORE_SOURCES @@ -1075,6 +1094,10 @@ qt_add_resources(LAUNCHER_RESOURCES ../${Launcher_Branding_LogoQRC} ) +qt_wrap_ui(WINDOWSUPDATER_UI + updater/windows/SelectReleaseDialog.ui +) + ######## Windows resource files ######## if(WIN32) set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC}) @@ -1158,7 +1181,41 @@ install(TARGETS ${Launcher_Name} FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime ) -if(WIN32) +if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) + # Updater + add_library(windows_updater_logic STATIC ${WINDOWSUPDATEREXE_SOURCES} ${WINDOWSUPDATER_UI}) + target_include_directories(windows_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(windows_updater_logic + systeminfo + BuildConfig + ghcFilesystem::ghc_filesystem + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network + ${Launcher_QT_LIBS} + cmark::cmark + ) + + add_executable("${Launcher_Name}_updater" WIN32 updater/windows/windows_main.cpp) + target_link_libraries("${Launcher_Name}_updater" windows_updater_logic) + + if(DEFINED Launcher_APP_BINARY_NAME) + set_target_properties("${Launcher_Name}_updater" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_updater") + endif() + if(DEFINED Launcher_BINARY_RPATH) + SET_TARGET_PROPERTIES("${Launcher_Name}_updater" PROPERTIES INSTALL_RPATH "${Launcher_BINARY_RPATH}") + endif() + + install(TARGETS "${Launcher_Name}_updater" + BUNDLE DESTINATION "." COMPONENT Runtime + LIBRARY DESTINATION ${LIBRARY_DEST_DIR} COMPONENT Runtime + RUNTIME DESTINATION ${BINARY_DEST_DIR} COMPONENT Runtime + FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime + ) +endif() + +if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER)) + # File link add_library(filelink_logic STATIC ${LINKEXE_SOURCES}) target_include_directories(filelink_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(filelink_logic diff --git a/launcher/Version.h b/launcher/Version.h index 659f8e54e..1bba44126 100644 --- a/launcher/Version.h +++ b/launcher/Version.h @@ -56,6 +56,7 @@ class Version { bool operator!=(const Version &other) const; QString toString() const { return m_string; } + bool isEmpty() const { return m_string.isEmpty(); } friend QDebug operator<<(QDebug debug, const Version& v); diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index c9599b820..79b30c665 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -111,6 +111,7 @@ FileLinkApp::FileLinkApp(int& argc, char** argv) : QCoreApplication(argc, argv), joinServer(serverToJoin); } else { qDebug() << "no server to join"; + m_status = Failed; exit(); } } @@ -126,6 +127,7 @@ void FileLinkApp::joinServer(QString server) connect(&socket, &QLocalSocket::readyRead, this, &FileLinkApp::readPathPairs); connect(&socket, &QLocalSocket::errorOccurred, this, [&](QLocalSocket::LocalSocketError socketError) { + m_status = Failed; switch (socketError) { case QLocalSocket::ServerNotFoundError: qDebug() @@ -150,6 +152,7 @@ void FileLinkApp::joinServer(QString server) connect(&socket, &QLocalSocket::disconnected, this, [&]() { qDebug() << "disconnected from server, should exit"; + m_status = Succeeded; exit(); }); diff --git a/launcher/filelink/FileLink.h b/launcher/filelink/FileLink.h index 4c47d9bbb..ab3e9d360 100644 --- a/launcher/filelink/FileLink.h +++ b/launcher/filelink/FileLink.h @@ -41,8 +41,17 @@ class FileLinkApp : public QCoreApplication { // friends for the purpose of limiting access to deprecated stuff Q_OBJECT public: + enum Status { + Starting, + Failed, + Succeeded, + Initialized + }; FileLinkApp(int& argc, char** argv); virtual ~FileLinkApp(); + Status status() const { + return m_status; + } private: void joinServer(QString server); @@ -50,6 +59,8 @@ class FileLinkApp : public QCoreApplication { void runLink(); void sendResults(); + Status m_status = Status::Starting; + bool m_useHardLinks = false; QDateTime m_startTime; diff --git a/launcher/filelink/main.cpp b/launcher/filelink/main.cpp index 83566a3c6..a656a9c96 100644 --- a/launcher/filelink/main.cpp +++ b/launcher/filelink/main.cpp @@ -26,5 +26,17 @@ int main(int argc, char* argv[]) { FileLinkApp ldh(argc, argv); - return ldh.exec(); + switch(ldh.status()) { + case FileLinkApp::Starting: + case FileLinkApp::Initialized: + { + return ldh.exec(); + } + case FileLinkApp::Failed: + return 1; + case FileLinkApp::Succeeded: + return 0; + default: + return -1; + } } diff --git a/launcher/updater/windows/GitHubRelease.h b/launcher/updater/windows/GitHubRelease.h new file mode 100644 index 000000000..1326a69f1 --- /dev/null +++ b/launcher/updater/windows/GitHubRelease.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include +#include + +#include "Version.h" + +struct GitHubReleaseAsset { + int id = -1; + QString name; + QString label; + QString content_type; + int size; + QDateTime created_at; + QDateTime updated_at; + QString browser_download_url; + + bool isValid() { return id > 0; } +}; + +struct GitHubRelease { + int id = -1; + QString name; + QString tag_name; + QDateTime created_at; + QDateTime published_at; + bool prerelease; + bool draft; + QString body; + QList assets; + Version version; + + bool isValid() const { return id > 0; } +}; diff --git a/launcher/updater/windows/SelectReleaseDialog.ui b/launcher/updater/windows/SelectReleaseDialog.ui new file mode 100644 index 000000000..9d3613727 --- /dev/null +++ b/launcher/updater/windows/SelectReleaseDialog.ui @@ -0,0 +1,89 @@ + + + SelectReleaseDialog + + + + 0 + 0 + 478 + 517 + + + + Select Release to Install + + + true + + + + + + Please select the release you wish to update to. + + + + + + + true + + + + 1 + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + SelectReleaseDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SelectReleaseDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/launcher/updater/windows/UpdaterDialogs.cpp b/launcher/updater/windows/UpdaterDialogs.cpp new file mode 100644 index 000000000..5949194b2 --- /dev/null +++ b/launcher/updater/windows/UpdaterDialogs.cpp @@ -0,0 +1,78 @@ +#include "UpdaterDialogs.h" + +#include "ui_SelectReleaseDialog.h" + +#include +#include "Markdown.h" + +SelectReleaseDialog::SelectReleaseDialog(const Version& current_version, const QList& releases, QWidget* parent) + : QDialog(parent), m_releases(releases), m_currentVersion(current_version), ui(new Ui::SelectReleaseDialog) +{ + ui->setupUi(this); + + ui->changelogTextBrowser->setOpenExternalLinks(true); + ui->changelogTextBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth); + ui->changelogTextBrowser->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + + ui->versionsTree->setColumnCount(2); + + ui->versionsTree->header()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::Stretch); + ui->versionsTree->setHeaderLabels({tr("Verison"), tr("Published Date")}); + ui->versionsTree->header()->setStretchLastSection(false); + + ui->eplainLabel->setText(tr("Select a version to install.\n" + "\n" + "Currently installed version: %1") + .arg(m_currentVersion.toString())); + + loadReleases(); + + connect(ui->versionsTree, &QTreeWidget::currentItemChanged, this, &SelectReleaseDialog::selectionChanged); + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SelectReleaseDialog::accept); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &SelectReleaseDialog::reject); +} + +SelectReleaseDialog::~SelectReleaseDialog() +{ + delete ui; +} + +void SelectReleaseDialog::loadReleases() +{ + for (auto rls : m_releases) { + appendRelease(rls); + } +} + +void SelectReleaseDialog::appendRelease(GitHubRelease const& release) +{ + auto rls_item = new QTreeWidgetItem(ui->versionsTree); + rls_item->setText(0, release.tag_name); + rls_item->setExpanded(true); + rls_item->setText(1, release.published_at.toString()); + rls_item->setData(0, Qt::UserRole, QVariant(release.id)); + + ui->versionsTree->addTopLevelItem(rls_item); +} + +GitHubRelease SelectReleaseDialog::getRelease(QTreeWidgetItem* item) { + int id = item->data(0, Qt::UserRole).toInt(); + GitHubRelease release; + for (auto rls: m_releases) { + if (rls.id == id) + release = rls; + } + return release; +} + +void SelectReleaseDialog::selectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous) +{ + GitHubRelease release = getRelease(current); + QString body = markdownToHTML(release.body.toUtf8()); + m_selectedRelease = release; + + ui->changelogTextBrowser->setHtml(body); +} + diff --git a/launcher/updater/windows/UpdaterDialogs.h b/launcher/updater/windows/UpdaterDialogs.h new file mode 100644 index 000000000..7481e499a --- /dev/null +++ b/launcher/updater/windows/UpdaterDialogs.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include "Version.h" +#include "updater/windows/GitHubRelease.h" + +namespace Ui { +class SelectReleaseDialog; +} + +class SelectReleaseDialog : public QDialog { + Q_OBJECT + + public: + explicit SelectReleaseDialog(const Version& cur_version, const QList& releases, QWidget* parent = 0); + ~SelectReleaseDialog(); + + void loadReleases(); + void appendRelease(GitHubRelease const& release); + GitHubRelease selectedRelease() { return m_selectedRelease; } + private slots: + GitHubRelease getRelease(QTreeWidgetItem* item); + void selectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous); + + protected: + QList m_releases; + GitHubRelease m_selectedRelease; + Version m_currentVersion; + + Ui::SelectReleaseDialog* ui; +}; diff --git a/launcher/updater/windows/WindowsUpdater.cpp b/launcher/updater/windows/WindowsUpdater.cpp new file mode 100644 index 000000000..f0ea9998c --- /dev/null +++ b/launcher/updater/windows/WindowsUpdater.cpp @@ -0,0 +1,647 @@ +// SPDX-FileCopyrightText: 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "WindowsUpdater.h" +#include "BuildConfig.h" + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#if defined Q_OS_WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#endif + +// Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header + +#ifdef __APPLE__ +#include // for deployment target to support pre-catalina targets without std::fs +#endif // __APPLE__ + +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include) +#if __has_include() && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) +#define GHC_USE_STD_FS +#include +namespace fs = std::filesystem; +#endif // MacOS min version check +#endif // Other OSes version check + +#ifndef GHC_USE_STD_FS +#include +namespace fs = ghc::filesystem; +#endif + +#include + +#include "UpdaterDialogs.h" + +#include "FileSystem.h" +#include "Json.h" +#include "StringUtils.h" + +/** output to the log file */ +void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + static std::mutex loggerMutex; + const std::lock_guard lock(loggerMutex); // synchronized, QFile logFile is not thread-safe + + QString out = qFormatLogMessage(type, context, msg); + out += QChar::LineFeed; + + WindowsUpdaterApp* app = static_cast(QCoreApplication::instance()); + app->logFile->write(out.toUtf8()); + app->logFile->flush(); + if (app->logToConsole) { + QTextStream(stderr) << out.toLocal8Bit(); + fflush(stderr); + } +} + +WindowsUpdaterApp::WindowsUpdaterApp(int& argc, char** argv) : QApplication(argc, argv) +{ +#if defined Q_OS_WIN32 + // attach the parent console + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + // if attach succeeds, reopen and sync all the i/o + if (freopen("CON", "w", stdout)) { + std::cout.sync_with_stdio(); + } + if (freopen("CON", "w", stderr)) { + std::cerr.sync_with_stdio(); + } + if (freopen("CON", "r", stdin)) { + std::cin.sync_with_stdio(); + } + auto out = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD written; + const char* endline = "\n"; + WriteConsole(out, endline, strlen(endline), &written, NULL); + consoleAttached = true; + } +#endif + setOrganizationName(BuildConfig.LAUNCHER_NAME); + setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN); + setApplicationName(BuildConfig.LAUNCHER_NAME + "Updater"); + setApplicationVersion(BuildConfig.printableVersionString() + "\n" + BuildConfig.GIT_COMMIT); + + // Commandline parsing + QCommandLineParser parser; + parser.setApplicationDescription(QObject::tr("An auto-updater for Prism Launcher")); + + parser.addOptions({ { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory).", "directory" }, + { { "I", "install-version" }, "Install a spesfic version.", "version name" }, + { { "U", "update-url" }, "Update from the spesified repo.", "github repo url" }, + { { "e", "executable" }, "Path to the prismluancher executable.", "path" }, + { { "c", "check-only" }, + "Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error)." }, + { { "F", "force" }, "Force an update, even if one is not needed." }, + { { "l", "list" }, "List avalible releases." }, + { "debug", "Log debug to console." }, + { { "L", "latest" }, "Update to the latest avalible version." }, + { { "D", "allow-downgrade" }, "Allow the updater to downgrade to previous verisons." } }); + + parser.addHelpOption(); + parser.addVersionOption(); + parser.process(arguments()); + + logToConsole = parser.isSet("debug"); + + auto prism_executable = parser.value("executable"); + if (prism_executable.isEmpty()) { + prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME; +#if defined(Q_OS_WIN32) + prism_executable += ".exe"; +#endif + } + m_prismExecutable = prism_executable; + + auto prism_update_url = parser.value("update-url"); + if (prism_update_url.isEmpty()) + prism_update_url = "https://github.com/PrismLauncher/PrismLauncher"; + m_prismRepoUrl = QUrl::fromUserInput(prism_update_url); + + m_checkOnly = parser.isSet("check-only"); + m_forceUpdate = parser.isSet("force"); + m_printOnly = parser.isSet("list"); + auto user_version = parser.value("install-version"); + if (!user_version.isEmpty()) { + m_userSelectedVersion = Version(user_version); + } + m_updateLatest = parser.isSet("latest"); + m_allowDowngrade = parser.isSet("allow-downgrade"); + + QString origcwdPath = QDir::currentPath(); + QString binPath = applicationDirPath(); + + { // find data director + // Root path is used for updates and portable data +#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) + QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr + m_rootPath = foo.absolutePath(); +#elif defined(Q_OS_WIN32) + m_rootPath = binPath; +#elif defined(Q_OS_MAC) + QDir foo(FS::PathCombine(binPath, "../..")); + m_rootPath = foo.absolutePath(); + // on macOS, touch the root to force Finder to reload the .app metadata (and fix any icon change issues) + FS::updateTimestamp(m_rootPath); +#endif + } + + QString adjustedBy; + QString dataPath; + // change folder + QString dirParam = parser.value("dir"); + if (!dirParam.isEmpty()) { + // the dir param. it makes multimc data path point to whatever the user specified + // on command line + adjustedBy = "Command line"; + dataPath = dirParam; + } else { + QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); + dataPath = foo.absolutePath(); + adjustedBy = "Persistent data path"; + +#ifndef Q_OS_MACOS + if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) { + dataPath = m_rootPath; + adjustedBy = "Portable data path"; + m_portable = true; + } +#endif + } + m_network = new QNetworkAccessManager(); + + { // setup logging + static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; + auto moveFile = [](const QString& oldName, const QString& newName) { + QFile::remove(newName); + QFile::copy(oldName, newName); + QFile::remove(oldName); + }; + + moveFile(logBase.arg(3), logBase.arg(4)); + moveFile(logBase.arg(2), logBase.arg(3)); + moveFile(logBase.arg(1), logBase.arg(2)); + moveFile(logBase.arg(0), logBase.arg(1)); + + logFile = std::unique_ptr(new QFile(logBase.arg(0))); + if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { + showFatalErrorMessage("The launcher data folder is not writable!", + QString("The launcher couldn't create a log file - the data folder is not writable.\n" + "\n" + "Make sure you have write permissions to the data folder.\n" + "(%1)\n" + "\n" + "The launcher cannot continue until you fix this problem.") + .arg(dataPath)); + return; + } + qInstallMessageHandler(appDebugOutput); + + qSetMessagePattern( + "%{time process}" + " " + "%{if-debug}D%{endif}" + "%{if-info}I%{endif}" + "%{if-warning}W%{endif}" + "%{if-critical}C%{endif}" + "%{if-fatal}F%{endif}" + " " + "|" + " " + "%{if-category}[%{category}]: %{endif}" + "%{message}"); + + bool foundLoggingRules = false; + + auto logRulesFile = QStringLiteral("qtlogging.ini"); + auto logRulesPath = FS::PathCombine(dataPath, logRulesFile); + + qDebug() << "Testing" << logRulesPath << "..."; + foundLoggingRules = QFile::exists(logRulesPath); + + // search the dataPath() + // seach app data standard path + if (!foundLoggingRules && !isPortable() && dirParam.isEmpty()) { + logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, FS::PathCombine("..", logRulesFile)); + if (!logRulesPath.isEmpty()) { + qDebug() << "Found" << logRulesPath << "..."; + foundLoggingRules = true; + } + } + // seach root path + if (!foundLoggingRules) { + logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); + qDebug() << "Testing" << logRulesPath << "..."; + foundLoggingRules = QFile::exists(logRulesPath); + } + + if (foundLoggingRules) { + // load and set logging rules + qDebug() << "Loading logging rules from:" << logRulesPath; + QSettings loggingRules(logRulesPath, QSettings::IniFormat); + loggingRules.beginGroup("Rules"); + QStringList rule_names = loggingRules.childKeys(); + QStringList rules; + qDebug() << "Setting log rules:"; + for (auto rule_name : rule_names) { + auto rule = QString("%1=%2").arg(rule_name).arg(loggingRules.value(rule_name).toString()); + rules.append(rule); + qDebug() << " " << rule; + } + auto rules_str = rules.join("\n"); + QLoggingCategory::setFilterRules(rules_str); + } + + qDebug() << "<> Log initialized."; + } + + { // log debug program info + qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater" + << ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); + qDebug() << "Version : " << BuildConfig.printableVersionString(); + qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; + qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; + if (adjustedBy.size()) { + qDebug() << "Work dir before adjustment : " << origcwdPath; + qDebug() << "Work dir after adjustment : " << QDir::currentPath(); + qDebug() << "Adjusted by : " << adjustedBy; + } else { + qDebug() << "Work dir : " << QDir::currentPath(); + } + qDebug() << "Binary path : " << binPath; + qDebug() << "Application root path : " << m_rootPath; + qDebug() << "<> Paths set."; + } + + loadReleaseList(); +} + +WindowsUpdaterApp::~WindowsUpdaterApp() +{ + qDebug() << "updater shutting down"; + // Shut down logger by setting the logger function to nothing + qInstallMessageHandler(nullptr); + +#if defined Q_OS_WIN32 + // Detach from Windows console + if (consoleAttached) { + fclose(stdout); + fclose(stdin); + fclose(stderr); + FreeConsole(); + } +#endif + + m_network->deleteLater(); + if (m_reply) + m_reply->deleteLater(); +} + +void WindowsUpdaterApp::fail(const QString& reason) +{ + qCritical() << qPrintable(reason); + m_status = Failed; + exit(1); +} + +void WindowsUpdaterApp::abort(const QString& reason) +{ + qCritical() << qPrintable(reason); + m_status = Aborted; + exit(2); +} + +void WindowsUpdaterApp::showFatalErrorMessage(const QString& title, const QString& content) +{ + m_status = Failed; + auto msgBox = new QMessageBox(); + msgBox->setWindowTitle(title); + msgBox->setText(content); + msgBox->setStandardButtons(QMessageBox::Ok); + msgBox->setDefaultButton(QMessageBox::Ok); + msgBox->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction); + msgBox->setIcon(QMessageBox::Critical); + msgBox->exec(); + exit(1); +} + +void WindowsUpdaterApp::run() +{ + qDebug() << "found" << m_releases.length() << "releases on github"; + qDebug() << "loading exe at " << m_prismExecutable; + + if (m_printOnly) { + printReleases(); + m_status = Succeeded; + return exit(0); + } + + loadPrismVersionFromExe(m_prismExecutable); + m_status = Succeeded; + + qDebug() << "Executable reports as:" << m_prismBinaryName << "version:" << m_prismVerison; + qDebug() << "Version major:" << m_prismVersionMajor; + qDebug() << "Verison minor:" << m_prismVersionMinor; + qDebug() << "Verison channel:" << m_prsimVersionChannel; + qDebug() << "Git Commit:" << m_prismGitCommit; + + auto latest = getLatestRelease(); + qDebug() << "Latest release" << latest.version; + auto need_update = needUpdate(latest); + + if (m_checkOnly) { + if (need_update) + return exit(100); + else + return exit(0); + } + + if (need_update || m_forceUpdate || !m_userSelectedVersion.isEmpty()) { + GitHubRelease update_release = latest; + if (!m_userSelectedVersion.isEmpty()) { + bool found = false; + for (auto rls : m_releases) { + if (rls.version == m_userSelectedVersion) { + found = true; + update_release = rls; + break; + } + } + if (!found) { + showFatalErrorMessage( + "No release for version!", + QString("Can not find a github relase for user spesified verison %1").arg(m_userSelectedVersion.toString())); + return; + } + } else if (!m_updateLatest) { + update_release = selectRelease(); + if (!update_release.isValid()) { + showFatalErrorMessage("No version selected.", "No version was selected."); + return; + } + } + + performUpdate(update_release); + } + + exit(0); +} + +void WindowsUpdaterApp::printReleases() +{ + for (auto release : m_releases) { + std::cout << release.name.toStdString() << " Version: " << release.tag_name.toStdString() << std::endl; + } +} + +QList WindowsUpdaterApp::nonDraftReleases() +{ + QList nonDraft; + for (auto rls : m_releases) { + if (rls.isValid() && !rls.draft) + nonDraft.append(rls); + } + return nonDraft; +} + +QList WindowsUpdaterApp::newerReleases() +{ + QList newer; + for (auto rls : nonDraftReleases()) { + if (rls.version > m_prismVerison) + newer.append(rls); + } + return newer; +} + +GitHubRelease WindowsUpdaterApp::selectRelease() +{ + QList releases; + + if (m_allowDowngrade) { + releases = nonDraftReleases(); + } else { + releases = newerReleases(); + } + + if (releases.isEmpty()) + return {}; + + SelectReleaseDialog dlg(Version(m_prismVerison), releases); + auto result = dlg.exec(); + + GitHubRelease release = dlg.selectedRelease(); + if (result == QDialog::Rejected) { + return {}; + } + + return release; +} + +void WindowsUpdaterApp::performUpdate(const GitHubRelease& release) +{ + qDebug() << "Updating to" << release.tag_name; +} + +void WindowsUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) +{ + QProcess proc = QProcess(); + proc.start(exe_path, { "-v" }); + proc.waitForFinished(); + auto out = proc.readAll(); + auto lines = out.split('\n'); + if (lines.length() < 2) + return; + auto first = lines.takeFirst(); + auto first_parts = first.split(' '); + if (first_parts.length() < 2) + return; + m_prismBinaryName = first_parts.takeFirst(); + auto version = first_parts.takeFirst(); + m_prismVerison = version; + if (version.contains('-')) { + auto index = version.indexOf('-'); + m_prsimVersionChannel = version.mid(index + 1); + version = version.left(index); + } else { + m_prsimVersionChannel = "stable"; + } + auto version_parts = version.split('.'); + m_prismVersionMajor = version_parts.takeFirst().toInt(); + m_prismVersionMinor = version_parts.takeFirst().toInt(); + m_prismGitCommit = lines.takeFirst().simplified(); +} + +void WindowsUpdaterApp::loadReleaseList() +{ + auto github_repo = m_prismRepoUrl; + if (github_repo.host() != "github.com") + return fail("updating from a non github url is not supported"); + + auto path_parts = github_repo.path().split('/'); + path_parts.removeFirst(); // empty segment from leading / + auto repo_owner = path_parts.takeFirst(); + auto repo_name = path_parts.takeFirst(); + auto api_url = QString("https://api.github.com/repos/%1/%2/releases").arg(repo_owner, repo_name); + + qDebug() << "Fetching release list from" << api_url; + + downloadReleasePage(api_url, 1); +} + +void WindowsUpdaterApp::downloadReleasePage(const QString& api_url, int page) +{ + int per_page = 30; + auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page)); + QNetworkRequest request(page_url); + request.setRawHeader("Accept", "application/vnd.github+json"); + request.setRawHeader("X-GitHub-Api-Version", "2022-11-28"); + + QNetworkReply* rep = m_network->get(request); + m_reply = rep; + auto responce = new QByteArray(); + + connect(rep, &QNetworkReply::finished, this, [this, responce, per_page, api_url, page]() { + int num_found = parseReleasePage(responce); + delete responce; + + if (!(num_found < per_page)) { // there may be more, fetch next page + downloadReleasePage(api_url, page + 1); + } else { + run(); + } + }); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &WindowsUpdaterApp::downloadError); +#else + connect(rep, QOverload::of(&QNetworkReply::error), this, &WindowsUpdaterApp::downloadError); +#endif + connect(rep, &QNetworkReply::sslErrors, this, &WindowsUpdaterApp::sslErrors); + connect(rep, &QNetworkReply::readyRead, this, [this, responce]() { + auto data = m_reply->readAll(); + responce->append(data); + }); +} + +int WindowsUpdaterApp::parseReleasePage(const QByteArray* responce) +{ + if (responce->isEmpty()) // empty page + return 0; + int num_releases = 0; + try { + auto doc = Json::requireDocument(*responce); + auto release_list = Json::requireArray(doc); + for (auto release_json : release_list) { + auto release_obj = Json::requireObject(release_json); + + GitHubRelease release = {}; + release.id = Json::requireInteger(release_obj, "id"); + release.name = Json::ensureString(release_obj, "name"); + release.tag_name = Json::requireString(release_obj, "tag_name"); + release.created_at = QDateTime::fromString(Json::requireString(release_obj, "created_at"), Qt::ISODate); + release.published_at = QDateTime::fromString(Json::ensureString(release_obj, "published_at"), Qt::ISODate); + release.draft = Json::requireBoolean(release_obj, "draft"); + release.prerelease = Json::requireBoolean(release_obj, "prerelease"); + release.body = Json::ensureString(release_obj, "body"); + release.version = Version(release.tag_name); + + auto release_assets_obj = Json::requireArray(release_obj, "assets"); + for (auto asset_json : release_assets_obj) { + auto asset_obj = Json::requireObject(asset_json); + GitHubReleaseAsset asset = {}; + asset.id = Json::requireInteger(asset_obj, "id"); + asset.name = Json::requireString(asset_obj, "name"); + asset.label = Json::ensureString(asset_obj, "label"); + asset.content_type = Json::requireString(asset_obj, "content_type"); + asset.size = Json::requireInteger(asset_obj, "size"); + asset.created_at = QDateTime::fromString(Json::requireString(asset_obj, "created_at"), Qt::ISODate); + asset.updated_at = QDateTime::fromString(Json::requireString(asset_obj, "updated_at"), Qt::ISODate); + asset.browser_download_url = Json::requireString(asset_obj, "browser_download_url"); + release.assets.append(asset); + } + m_releases.append(release); + num_releases++; + } + } catch (Json::JsonException& e) { + auto err_msg = + QString("Failed to parse releases from github: %1\n%2").arg(e.what()).arg(QString::fromStdString(responce->toStdString())); + fail(err_msg); + } + return num_releases; +} + +GitHubRelease WindowsUpdaterApp::getLatestRelease() +{ + GitHubRelease latest; + for (auto release : m_releases) { + if (!latest.isValid() || (!release.draft && release.version > latest.version)) { + latest = release; + } + } + return latest; +} + +bool WindowsUpdaterApp::needUpdate(const GitHubRelease& release) +{ + auto current_ver = Version(QString("%1.%2").arg(QString::number(m_prismVersionMajor)).arg(QString::number(m_prismVersionMinor))); + return current_ver < release.version; +} + +void WindowsUpdaterApp::downloadError(QNetworkReply::NetworkError error) +{ + if (error == QNetworkReply::OperationCanceledError) { + abort(QString("Aborted %1").arg(m_reply->url().toString())); + } else { + fail(QString("Network request Failed: %1 with reason %2").arg(m_reply->url().toString()).arg(error)); + } +} + +void WindowsUpdaterApp::sslErrors(const QList& errors) +{ + int i = 1; + QString err_msg; + for (auto error : errors) { + err_msg.append(QString("Network request %1 SSL Error %2: %3\n").arg(m_reply->url().toString()).arg(i).arg(error.errorString())); + auto cert = error.certificate(); + err_msg.append(QString("Certificate in question:\n%1").arg(cert.toText())); + i++; + } + fail(err_msg); +} diff --git a/launcher/updater/windows/WindowsUpdater.h b/launcher/updater/windows/WindowsUpdater.h new file mode 100644 index 000000000..b79a86271 --- /dev/null +++ b/launcher/updater/windows/WindowsUpdater.h @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PRISM_EXTERNAL_EXE +#include "FileSystem.h" + +#include "updater/windows/GitHubRelease.h" + +class WindowsUpdaterApp : public QApplication { + // friends for the purpose of limiting access to deprecated stuff + Q_OBJECT + public: + enum Status { Starting, Failed, Succeeded, Initialized, Aborted }; + WindowsUpdaterApp(int& argc, char** argv); + virtual ~WindowsUpdaterApp(); + void loadReleaseList(); + void run(); + Status status() const { return m_status; } + + private: + void fail(const QString& reason); + void abort(const QString& reason); + void showFatalErrorMessage(const QString& title, const QString& content); + + void loadPrismVersionFromExe(const QString& exe_path); + + void downloadReleasePage(const QString& api_url, int page); + int parseReleasePage(const QByteArray* responce); + GitHubRelease getLatestRelease(); + bool needUpdate(const GitHubRelease& release); + GitHubRelease selectRelease(); + void performUpdate(const GitHubRelease& release); + void printReleases(); + QList newerReleases(); + QList nonDraftReleases(); + + void downloadError(QNetworkReply::NetworkError error); + void sslErrors(const QList& errors); + + const QString& root() { return m_rootPath; } + + bool isPortable() { return m_portable; } + + QString m_rootPath; + bool m_portable = false; + QString m_prismExecutable; + QUrl m_prismRepoUrl; + Version m_userSelectedVersion; + bool m_checkOnly; + bool m_forceUpdate; + bool m_printOnly; + bool m_updateLatest; + bool m_allowDowngrade; + + QString m_prismBinaryName; + QString m_prismVerison; + int m_prismVersionMajor; + int m_prismVersionMinor; + QString m_prsimVersionChannel; + QString m_prismGitCommit; + + Status m_status = Status::Starting; + QNetworkAccessManager* m_network; + QNetworkReply* m_reply; + QList m_releases; + + public: + std::unique_ptr logFile; + bool logToConsole = false; + +#if defined Q_OS_WIN32 + // used on Windows to attach the standard IO streams + bool consoleAttached = false; +#endif +}; diff --git a/launcher/updater/windows/windows_main.cpp b/launcher/updater/windows/windows_main.cpp new file mode 100644 index 000000000..31d7646b5 --- /dev/null +++ b/launcher/updater/windows/windows_main.cpp @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + + +#include "updater/windows/WindowsUpdater.h" +int main(int argc, char* argv[]) +{ + WindowsUpdaterApp wUpApp(argc, argv); + + switch(wUpApp.status()) { + case WindowsUpdaterApp::Starting: + case WindowsUpdaterApp::Initialized: + { + return wUpApp.exec(); + } + case WindowsUpdaterApp::Failed: + return 1; + case WindowsUpdaterApp::Succeeded: + return 0; + default: + return -1; + } + +} From 0b2044e9a434ba3d2724630399bc41ebb321b039 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 13:52:23 -0700 Subject: [PATCH 036/398] fix: typo - no space before comment Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/ComponentUpdateTask_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/minecraft/ComponentUpdateTask_p.h b/launcher/minecraft/ComponentUpdateTask_p.h index 5b02431b2..84f6f9a63 100644 --- a/launcher/minecraft/ComponentUpdateTask_p.h +++ b/launcher/minecraft/ComponentUpdateTask_p.h @@ -4,6 +4,7 @@ #include #include #include "net/Mode.h" +#include "ComponentUpdateTask.h" class PackProfile; From f5729d9a7c953d88ae60e106a787b1d7c35ede8b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 13:53:44 -0700 Subject: [PATCH 037/398] Revert "fix: typo - no space before comment" This reverts commit 0b2044e9a434ba3d2724630399bc41ebb321b039. --- launcher/minecraft/ComponentUpdateTask_p.h | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/minecraft/ComponentUpdateTask_p.h b/launcher/minecraft/ComponentUpdateTask_p.h index 84f6f9a63..5b02431b2 100644 --- a/launcher/minecraft/ComponentUpdateTask_p.h +++ b/launcher/minecraft/ComponentUpdateTask_p.h @@ -4,7 +4,6 @@ #include #include #include "net/Mode.h" -#include "ComponentUpdateTask.h" class PackProfile; From 2dce08caf16ac80452ccaebed5e4f24c0ec7418a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 13:54:13 -0700 Subject: [PATCH 038/398] fix: typo - space before comment Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- program_info/win_install.nsi.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index 27c400395..8389e2468 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -293,7 +293,7 @@ Function RunUninstall stringloop: ; get string length StrCpy $2 $1 1 $3 ; get next char IntOp $3 $3 + 1 ; index += 1 - StrCmp $2 "" +2 stringloop; if empty exit loop + StrCmp $2 "" +2 stringloop ; if empty exit loop IntOp $3 $3 - 1 ; index -= 1 Goto run quoteloop: ; get string length with quotes removed From 7c85462ff371f2400bd9cae8a80904aa6175ac73 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 14:31:38 -0700 Subject: [PATCH 039/398] packaging: include file manifest in portable install Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 691e257bf..838eddef0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -411,12 +411,14 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable + cat ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt - name: Package (Windows MSVC, portable) if: runner.os == 'Windows' && matrix.msystem == '' run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable + cat ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt - name: Package (Windows, installer) if: runner.os == 'Windows' From dbe14c6be5ff3ae015c783a406a0d13759475aa0 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 14:54:06 -0700 Subject: [PATCH 040/398] packaging: ensure all files are in manifest Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 838eddef0..f309a3d06 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -375,11 +375,13 @@ jobs: shell: msys2 {0} run: | cmake --install ${{ env.BUILD_DIR }} + Copy-Item ${{ env.BUILD_DIR }}/install_manifest.txt ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }} + Copy-Item ${{ env.BUILD_DIR }}/install_manifest.txt ${{ env.INSTALL_DIR }}/manifest.txt cd ${{ env.INSTALL_DIR }} if ("${{ matrix.qt_ver }}" -eq "5") @@ -418,7 +420,7 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - cat ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt + cat ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt - name: Package (Windows, installer) if: runner.os == 'Windows' From 68c28335520ca4a4a17d47f863dd92a0b9a00904 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 14:55:13 -0700 Subject: [PATCH 041/398] packaging: use powershell name Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f309a3d06..dcc891c62 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -413,14 +413,14 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - cat ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt - name: Package (Windows MSVC, portable) if: runner.os == 'Windows' && matrix.msystem == '' run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - cat ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt - name: Package (Windows, installer) if: runner.os == 'Windows' From 4cbae0a751f54aa77a5e49cce23a3e4b5bea9a37 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 15:36:25 -0700 Subject: [PATCH 042/398] packaging: trim manfest paths to be relative Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dcc891c62..338f71a05 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -375,13 +375,13 @@ jobs: shell: msys2 {0} run: | cmake --install ${{ env.BUILD_DIR }} - Copy-Item ${{ env.BUILD_DIR }}/install_manifest.txt ${{ env.INSTALL_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }} - Copy-Item ${{ env.BUILD_DIR }}/install_manifest.txt ${{ env.INSTALL_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt cd ${{ env.INSTALL_DIR }} if ("${{ matrix.qt_ver }}" -eq "5") @@ -413,14 +413,14 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC, portable) if: runner.os == 'Windows' && matrix.msystem == '' run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_PORTABLE_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows, installer) if: runner.os == 'Windows' From 9b1e0eb57d4e59421bb019b866688c4138b15d7e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 16:01:31 -0700 Subject: [PATCH 043/398] packaging: msys2 shell is bash Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 338f71a05..fa1081c5c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -375,7 +375,7 @@ jobs: shell: msys2 {0} run: | cmake --install ${{ env.BUILD_DIR }} - Get-Content ${{ env.BUILD_DIR }}/install_manifest.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' @@ -413,7 +413,7 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC, portable) if: runner.os == 'Windows' && matrix.msystem == '' From 4e0a08345d7049fe9785a88d66e8216d3bc573b7 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 16:07:29 -0700 Subject: [PATCH 044/398] packaging: add manifest.txt to linux tarballs Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fa1081c5c..ef4becc08 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -441,6 +441,7 @@ jobs: if: runner.os == 'Linux' run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }} + while read l; do l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt cd ${{ env.INSTALL_DIR }} tar --owner root --group root -czf ../PrismLauncher.tar.gz * @@ -450,6 +451,8 @@ jobs: run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable + while read l; do l=${l#${{ env.INSTALL_DIR_PORTABLE }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR_PORTABLE }}/manifest.txt + while read l; do l=${l#${{ env.INSTALL_DIR_PORTABLE }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR_PORTABLE }}/manifest.txt cd ${{ env.INSTALL_PORTABLE_DIR }} tar -czf ../PrismLauncher-portable.tar.gz * From b48540dc322ab9eb5f0f270598f2720b13599fae Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 16:27:53 -0700 Subject: [PATCH 045/398] packaging: trim leading working dir from manifest paths Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ef4becc08..2fde49226 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -375,13 +375,13 @@ jobs: shell: msys2 {0} run: | cmake --install ${{ env.BUILD_DIR }} - while read l; do l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }} - Get-Content ${{ env.BUILD_DIR }}/install_manifest.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest.txt | %{ $_.TrimStart("$pwd/") } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt cd ${{ env.INSTALL_DIR }} if ("${{ matrix.qt_ver }}" -eq "5") @@ -413,14 +413,14 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - while read l; do l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC, portable) if: runner.os == 'Windows' && matrix.msystem == '' run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt + Get-Content ${{ env.BUILD_DIR }}/install_manifest_portable.txt | %{ $_.TrimStart("$pwd/") } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows, installer) if: runner.os == 'Windows' @@ -441,7 +441,7 @@ jobs: if: runner.os == 'Linux' run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_DIR }} - while read l; do l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt cd ${{ env.INSTALL_DIR }} tar --owner root --group root -czf ../PrismLauncher.tar.gz * @@ -451,8 +451,8 @@ jobs: run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - while read l; do l=${l#${{ env.INSTALL_DIR_PORTABLE }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR_PORTABLE }}/manifest.txt - while read l; do l=${l#${{ env.INSTALL_DIR_PORTABLE }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR_PORTABLE }}/manifest.txt + while read l; do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR_PORTABLE }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR_PORTABLE }}/manifest.txt + while read l; do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR_PORTABLE }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR_PORTABLE }}/manifest.txt cd ${{ env.INSTALL_PORTABLE_DIR }} tar -czf ../PrismLauncher-portable.tar.gz * From 3bbe33132af3d979200d03a16d625ecf7e9cfc51 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 19:39:14 -0700 Subject: [PATCH 046/398] packaging: convert msys paths Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2fde49226..4f59354b5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -375,7 +375,7 @@ jobs: shell: msys2 {0} run: | cmake --install ${{ env.BUILD_DIR }} - while read l; do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l;=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' @@ -413,7 +413,7 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - while read l; do l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest_portable.txt >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC, portable) if: runner.os == 'Windows' && matrix.msystem == '' From 46a13c876771bf521dbaf1902623f080b4843bd1 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 31 May 2023 20:16:58 -0700 Subject: [PATCH 047/398] packaging: fix typo ; in middle of line Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f59354b5..f103ecc1e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -375,7 +375,7 @@ jobs: shell: msys2 {0} run: | cmake --install ${{ env.BUILD_DIR }} - while read l; do l;=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt + while read l; do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}}; l=${l#./}; echo $l; done < ${{ env.BUILD_DIR }}/install_manifest.txt >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' From 5627b4a9c555a6e2b3fe781500a4c103e9deee0b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 1 Jun 2023 13:45:36 -0700 Subject: [PATCH 048/398] refactor: rename updater files Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/{windows => prismupdater}/GitHubRelease.h | 0 .../{windows/WindowsUpdater.cpp => prismupdater/PrismUpdater.cpp} | 0 .../{windows/WindowsUpdater.h => prismupdater/PrismUpdater.h} | 0 launcher/updater/{windows => prismupdater}/SelectReleaseDialog.ui | 0 launcher/updater/{windows => prismupdater}/UpdaterDialogs.cpp | 0 launcher/updater/{windows => prismupdater}/UpdaterDialogs.h | 0 launcher/updater/{windows => prismupdater}/windows_main.cpp | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename launcher/updater/{windows => prismupdater}/GitHubRelease.h (100%) rename launcher/updater/{windows/WindowsUpdater.cpp => prismupdater/PrismUpdater.cpp} (100%) rename launcher/updater/{windows/WindowsUpdater.h => prismupdater/PrismUpdater.h} (100%) rename launcher/updater/{windows => prismupdater}/SelectReleaseDialog.ui (100%) rename launcher/updater/{windows => prismupdater}/UpdaterDialogs.cpp (100%) rename launcher/updater/{windows => prismupdater}/UpdaterDialogs.h (100%) rename launcher/updater/{windows => prismupdater}/windows_main.cpp (100%) diff --git a/launcher/updater/windows/GitHubRelease.h b/launcher/updater/prismupdater/GitHubRelease.h similarity index 100% rename from launcher/updater/windows/GitHubRelease.h rename to launcher/updater/prismupdater/GitHubRelease.h diff --git a/launcher/updater/windows/WindowsUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp similarity index 100% rename from launcher/updater/windows/WindowsUpdater.cpp rename to launcher/updater/prismupdater/PrismUpdater.cpp diff --git a/launcher/updater/windows/WindowsUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h similarity index 100% rename from launcher/updater/windows/WindowsUpdater.h rename to launcher/updater/prismupdater/PrismUpdater.h diff --git a/launcher/updater/windows/SelectReleaseDialog.ui b/launcher/updater/prismupdater/SelectReleaseDialog.ui similarity index 100% rename from launcher/updater/windows/SelectReleaseDialog.ui rename to launcher/updater/prismupdater/SelectReleaseDialog.ui diff --git a/launcher/updater/windows/UpdaterDialogs.cpp b/launcher/updater/prismupdater/UpdaterDialogs.cpp similarity index 100% rename from launcher/updater/windows/UpdaterDialogs.cpp rename to launcher/updater/prismupdater/UpdaterDialogs.cpp diff --git a/launcher/updater/windows/UpdaterDialogs.h b/launcher/updater/prismupdater/UpdaterDialogs.h similarity index 100% rename from launcher/updater/windows/UpdaterDialogs.h rename to launcher/updater/prismupdater/UpdaterDialogs.h diff --git a/launcher/updater/windows/windows_main.cpp b/launcher/updater/prismupdater/windows_main.cpp similarity index 100% rename from launcher/updater/windows/windows_main.cpp rename to launcher/updater/prismupdater/windows_main.cpp From f619a04fe7ce1e7649152e383f0415f59de55d5d Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 1 Jun 2023 14:55:20 -0700 Subject: [PATCH 049/398] refactor: rename app class Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 28 +++++------ .../filelink/{main.cpp => filelink_main.cpp} | 0 .../updater/prismupdater/PrismUpdater.cpp | 48 +++++++++---------- launcher/updater/prismupdater/PrismUpdater.h | 8 ++-- .../updater/prismupdater/UpdaterDialogs.h | 2 +- .../{windows_main.cpp => updater_main.cpp} | 12 ++--- 6 files changed, 49 insertions(+), 49 deletions(-) rename launcher/filelink/{main.cpp => filelink_main.cpp} (100%) rename launcher/updater/prismupdater/{windows_main.cpp => updater_main.cpp} (80%) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 5a979b8d9..89dea0d11 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -567,12 +567,12 @@ set(LINKEXE_SOURCES DesktopServices.cpp ) -set(WINDOWSUPDATEREXE_SOURCES - updater/windows/WindowsUpdater.h - updater/windows/WindowsUpdater.cpp - updater/windows/UpdaterDialogs.h - updater/windows/UpdaterDialogs.cpp - updater/windows/GitHubRelease.h +set(PRISMUPDATER_SOURCES + updater/prismupdater/PrismUpdater.h + updater/prismupdater/PrismUpdater.cpp + updater/prismupdater/UpdaterDialogs.h + updater/prismupdater/UpdaterDialogs.cpp + updater/prismupdater/GitHubRelease.h Json.h Json.cpp FileSystem.h @@ -1094,8 +1094,8 @@ qt_add_resources(LAUNCHER_RESOURCES ../${Launcher_Branding_LogoQRC} ) -qt_wrap_ui(WINDOWSUPDATER_UI - updater/windows/SelectReleaseDialog.ui +qt_wrap_ui(PRISMUPDATER_UI + updater/prismupdater/SelectReleaseDialog.ui ) ######## Windows resource files ######## @@ -1183,9 +1183,9 @@ install(TARGETS ${Launcher_Name} if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) # Updater - add_library(windows_updater_logic STATIC ${WINDOWSUPDATEREXE_SOURCES} ${WINDOWSUPDATER_UI}) - target_include_directories(windows_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(windows_updater_logic + add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${PRISMUPDATER_UI}) + target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(prism_updater_logic systeminfo BuildConfig ghcFilesystem::ghc_filesystem @@ -1196,8 +1196,8 @@ if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) cmark::cmark ) - add_executable("${Launcher_Name}_updater" WIN32 updater/windows/windows_main.cpp) - target_link_libraries("${Launcher_Name}_updater" windows_updater_logic) + add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp) + target_link_libraries("${Launcher_Name}_updater" prism_updater_logic) if(DEFINED Launcher_APP_BINARY_NAME) set_target_properties("${Launcher_Name}_updater" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_updater") @@ -1229,7 +1229,7 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER)) ${Launcher_QT_LIBS} ) - add_executable("${Launcher_Name}_filelink" WIN32 filelink/main.cpp) + add_executable("${Launcher_Name}_filelink" WIN32 filelink/filelink_main.cpp) target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest) diff --git a/launcher/filelink/main.cpp b/launcher/filelink/filelink_main.cpp similarity index 100% rename from launcher/filelink/main.cpp rename to launcher/filelink/filelink_main.cpp diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index f0ea9998c..923b891f9 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -20,7 +20,7 @@ * */ -#include "WindowsUpdater.h" +#include "PrismUpdater.h" #include "BuildConfig.h" #include @@ -68,7 +68,7 @@ namespace fs = ghc::filesystem; #include -#include "UpdaterDialogs.h" +#include "updater/prismupdater/UpdaterDialogs.h" #include "FileSystem.h" #include "Json.h" @@ -83,7 +83,7 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt QString out = qFormatLogMessage(type, context, msg); out += QChar::LineFeed; - WindowsUpdaterApp* app = static_cast(QCoreApplication::instance()); + PrismUpdaterApp* app = static_cast(QCoreApplication::instance()); app->logFile->write(out.toUtf8()); app->logFile->flush(); if (app->logToConsole) { @@ -92,7 +92,7 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt } } -WindowsUpdaterApp::WindowsUpdaterApp(int& argc, char** argv) : QApplication(argc, argv) +PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 // attach the parent console @@ -313,7 +313,7 @@ WindowsUpdaterApp::WindowsUpdaterApp(int& argc, char** argv) : QApplication(argc loadReleaseList(); } -WindowsUpdaterApp::~WindowsUpdaterApp() +PrismUpdaterApp::~PrismUpdaterApp() { qDebug() << "updater shutting down"; // Shut down logger by setting the logger function to nothing @@ -334,21 +334,21 @@ WindowsUpdaterApp::~WindowsUpdaterApp() m_reply->deleteLater(); } -void WindowsUpdaterApp::fail(const QString& reason) +void PrismUpdaterApp::fail(const QString& reason) { qCritical() << qPrintable(reason); m_status = Failed; exit(1); } -void WindowsUpdaterApp::abort(const QString& reason) +void PrismUpdaterApp::abort(const QString& reason) { qCritical() << qPrintable(reason); m_status = Aborted; exit(2); } -void WindowsUpdaterApp::showFatalErrorMessage(const QString& title, const QString& content) +void PrismUpdaterApp::showFatalErrorMessage(const QString& title, const QString& content) { m_status = Failed; auto msgBox = new QMessageBox(); @@ -362,7 +362,7 @@ void WindowsUpdaterApp::showFatalErrorMessage(const QString& title, const QStrin exit(1); } -void WindowsUpdaterApp::run() +void PrismUpdaterApp::run() { qDebug() << "found" << m_releases.length() << "releases on github"; qDebug() << "loading exe at " << m_prismExecutable; @@ -424,14 +424,14 @@ void WindowsUpdaterApp::run() exit(0); } -void WindowsUpdaterApp::printReleases() +void PrismUpdaterApp::printReleases() { for (auto release : m_releases) { std::cout << release.name.toStdString() << " Version: " << release.tag_name.toStdString() << std::endl; } } -QList WindowsUpdaterApp::nonDraftReleases() +QList PrismUpdaterApp::nonDraftReleases() { QList nonDraft; for (auto rls : m_releases) { @@ -441,7 +441,7 @@ QList WindowsUpdaterApp::nonDraftReleases() return nonDraft; } -QList WindowsUpdaterApp::newerReleases() +QList PrismUpdaterApp::newerReleases() { QList newer; for (auto rls : nonDraftReleases()) { @@ -451,7 +451,7 @@ QList WindowsUpdaterApp::newerReleases() return newer; } -GitHubRelease WindowsUpdaterApp::selectRelease() +GitHubRelease PrismUpdaterApp::selectRelease() { QList releases; @@ -475,12 +475,12 @@ GitHubRelease WindowsUpdaterApp::selectRelease() return release; } -void WindowsUpdaterApp::performUpdate(const GitHubRelease& release) +void PrismUpdaterApp::performUpdate(const GitHubRelease& release) { qDebug() << "Updating to" << release.tag_name; } -void WindowsUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) +void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) { QProcess proc = QProcess(); proc.start(exe_path, { "-v" }); @@ -509,7 +509,7 @@ void WindowsUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) m_prismGitCommit = lines.takeFirst().simplified(); } -void WindowsUpdaterApp::loadReleaseList() +void PrismUpdaterApp::loadReleaseList() { auto github_repo = m_prismRepoUrl; if (github_repo.host() != "github.com") @@ -526,7 +526,7 @@ void WindowsUpdaterApp::loadReleaseList() downloadReleasePage(api_url, 1); } -void WindowsUpdaterApp::downloadReleasePage(const QString& api_url, int page) +void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) { int per_page = 30; auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page)); @@ -549,18 +549,18 @@ void WindowsUpdaterApp::downloadReleasePage(const QString& api_url, int page) } }); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 - connect(rep, &QNetworkReply::errorOccurred, this, &WindowsUpdaterApp::downloadError); + connect(rep, &QNetworkReply::errorOccurred, this, &PrismUpdaterApp::downloadError); #else connect(rep, QOverload::of(&QNetworkReply::error), this, &WindowsUpdaterApp::downloadError); #endif - connect(rep, &QNetworkReply::sslErrors, this, &WindowsUpdaterApp::sslErrors); + connect(rep, &QNetworkReply::sslErrors, this, &PrismUpdaterApp::sslErrors); connect(rep, &QNetworkReply::readyRead, this, [this, responce]() { auto data = m_reply->readAll(); responce->append(data); }); } -int WindowsUpdaterApp::parseReleasePage(const QByteArray* responce) +int PrismUpdaterApp::parseReleasePage(const QByteArray* responce) { if (responce->isEmpty()) // empty page return 0; @@ -607,7 +607,7 @@ int WindowsUpdaterApp::parseReleasePage(const QByteArray* responce) return num_releases; } -GitHubRelease WindowsUpdaterApp::getLatestRelease() +GitHubRelease PrismUpdaterApp::getLatestRelease() { GitHubRelease latest; for (auto release : m_releases) { @@ -618,13 +618,13 @@ GitHubRelease WindowsUpdaterApp::getLatestRelease() return latest; } -bool WindowsUpdaterApp::needUpdate(const GitHubRelease& release) +bool PrismUpdaterApp::needUpdate(const GitHubRelease& release) { auto current_ver = Version(QString("%1.%2").arg(QString::number(m_prismVersionMajor)).arg(QString::number(m_prismVersionMinor))); return current_ver < release.version; } -void WindowsUpdaterApp::downloadError(QNetworkReply::NetworkError error) +void PrismUpdaterApp::downloadError(QNetworkReply::NetworkError error) { if (error == QNetworkReply::OperationCanceledError) { abort(QString("Aborted %1").arg(m_reply->url().toString())); @@ -633,7 +633,7 @@ void WindowsUpdaterApp::downloadError(QNetworkReply::NetworkError error) } } -void WindowsUpdaterApp::sslErrors(const QList& errors) +void PrismUpdaterApp::sslErrors(const QList& errors) { int i = 1; QString err_msg; diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index b79a86271..da6b4bf71 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -39,15 +39,15 @@ #define PRISM_EXTERNAL_EXE #include "FileSystem.h" -#include "updater/windows/GitHubRelease.h" +#include "updater/prismupdater/GitHubRelease.h" -class WindowsUpdaterApp : public QApplication { +class PrismUpdaterApp : public QApplication { // friends for the purpose of limiting access to deprecated stuff Q_OBJECT public: enum Status { Starting, Failed, Succeeded, Initialized, Aborted }; - WindowsUpdaterApp(int& argc, char** argv); - virtual ~WindowsUpdaterApp(); + PrismUpdaterApp(int& argc, char** argv); + virtual ~PrismUpdaterApp(); void loadReleaseList(); void run(); Status status() const { return m_status; } diff --git a/launcher/updater/prismupdater/UpdaterDialogs.h b/launcher/updater/prismupdater/UpdaterDialogs.h index 7481e499a..1449befbd 100644 --- a/launcher/updater/prismupdater/UpdaterDialogs.h +++ b/launcher/updater/prismupdater/UpdaterDialogs.h @@ -4,7 +4,7 @@ #include #include "Version.h" -#include "updater/windows/GitHubRelease.h" +#include "updater/prismupdater/GitHubRelease.h" namespace Ui { class SelectReleaseDialog; diff --git a/launcher/updater/prismupdater/windows_main.cpp b/launcher/updater/prismupdater/updater_main.cpp similarity index 80% rename from launcher/updater/prismupdater/windows_main.cpp rename to launcher/updater/prismupdater/updater_main.cpp index 31d7646b5..6bc7dd208 100644 --- a/launcher/updater/prismupdater/windows_main.cpp +++ b/launcher/updater/prismupdater/updater_main.cpp @@ -22,20 +22,20 @@ -#include "updater/windows/WindowsUpdater.h" +#include "updater/prismupdater/PrismUpdater.h" int main(int argc, char* argv[]) { - WindowsUpdaterApp wUpApp(argc, argv); + PrismUpdaterApp wUpApp(argc, argv); switch(wUpApp.status()) { - case WindowsUpdaterApp::Starting: - case WindowsUpdaterApp::Initialized: + case PrismUpdaterApp::Starting: + case PrismUpdaterApp::Initialized: { return wUpApp.exec(); } - case WindowsUpdaterApp::Failed: + case PrismUpdaterApp::Failed: return 1; - case WindowsUpdaterApp::Succeeded: + case PrismUpdaterApp::Succeeded: return 0; default: return -1; From 74d4a98864ba2deb2449e7e3ec7632054ece4823 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:39:04 -0700 Subject: [PATCH 050/398] refactor: split out setting api headers for downloads Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 4 ++ launcher/InstanceImportTask.cpp | 4 +- launcher/ResourceDownloadTask.cpp | 4 +- launcher/meta/BaseEntity.cpp | 4 +- launcher/minecraft/AssetsUtils.cpp | 4 +- launcher/minecraft/Library.cpp | 6 +-- launcher/minecraft/update/AssetUpdateTask.cpp | 4 +- .../minecraft/update/FMLLibrariesTask.cpp | 4 +- .../atlauncher/ATLPackInstallTask.cpp | 12 +++-- .../modplatform/flame/FileResolvingTask.cpp | 5 +- launcher/modplatform/flame/FlameAPI.cpp | 7 +-- .../modplatform/flame/FlameCheckUpdate.cpp | 6 ++- .../flame/FlameInstanceCreationTask.cpp | 4 +- .../helpers/NetworkResourceAPI.cpp | 8 +-- .../modplatform/legacy_ftb/PackFetchTask.cpp | 8 +-- .../legacy_ftb/PackInstallTask.cpp | 4 +- launcher/modplatform/modrinth/ModrinthAPI.cpp | 5 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 5 +- .../technic/SingleZipPackInstallTask.cpp | 4 +- .../technic/SolderPackInstallTask.cpp | 5 +- launcher/net/ApiDownload.h | 39 ++++++++++++++ launcher/net/ApiHeaderProxy.h | 51 +++++++++++++++++++ launcher/net/Download.cpp | 12 ++--- launcher/net/HeaderProxy.h | 49 ++++++++++++++++++ launcher/net/NetAction.h | 9 +++- launcher/net/RawHeaderProxy.h | 44 ++++++++++++++++ .../ui/pages/instance/ManagedPackPage.cpp | 6 ++- .../ui/pages/modplatform/ResourceModel.cpp | 4 +- .../modplatform/atlauncher/AtlListModel.cpp | 6 ++- .../atlauncher/AtlOptionalModDialog.cpp | 4 +- .../ui/pages/modplatform/flame/FlameModel.cpp | 6 ++- .../ui/pages/modplatform/flame/FlamePage.cpp | 4 +- .../modplatform/legacy_ftb/ListModel.cpp | 3 +- .../modplatform/modrinth/ModrinthModel.cpp | 6 ++- .../modplatform/modrinth/ModrinthPage.cpp | 6 ++- .../modplatform/technic/TechnicModel.cpp | 6 ++- .../pages/modplatform/technic/TechnicPage.cpp | 6 ++- .../ui/widgets/VariableSizedImageObject.cpp | 3 +- 38 files changed, 303 insertions(+), 68 deletions(-) create mode 100644 launcher/net/ApiDownload.h create mode 100644 launcher/net/ApiHeaderProxy.h create mode 100644 launcher/net/HeaderProxy.h create mode 100644 launcher/net/RawHeaderProxy.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 273b5449a..bce885ca8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -136,6 +136,10 @@ set(NET_SOURCES net/Validator.h net/Upload.cpp net/Upload.h + net/HeaderProxy.h + net/RawHeaderProxy.h + net/ApiHeaderProxy.h + net/ApiDownload.h ) # Game launch logic diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 352848f02..7332e917f 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -51,6 +51,8 @@ #include "settings/INISettingsObject.h" +#include "net/ApiDownload.h" + #include #include @@ -95,7 +97,7 @@ void InstanceImportTask::executeTask() m_archivePath = entry->getFullPath(); m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network())); - m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry)); + m_filesNetJob->addNetAction(Net::ApiDownload::makeCached(m_sourceUrl, entry)); connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp index 61b918aaf..03e103f13 100644 --- a/launcher/ResourceDownloadTask.cpp +++ b/launcher/ResourceDownloadTask.cpp @@ -24,6 +24,8 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourceFolderModel.h" +#include "net/ApiDownload.h" + ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, @@ -50,7 +52,7 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack, } } - m_filesNetJob->addNetAction(Net::Download::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename()))); + m_filesNetJob->addNetAction(Net::ApiDownload::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename()))); connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ResourceDownloadTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &ResourceDownloadTask::downloadProgressChanged); connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propogateStepProgress); diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 97815eba8..fd810a91b 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -15,7 +15,7 @@ #include "BaseEntity.h" -#include "net/Download.h" +#include "net/ApiDownload.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" #include "Json.h" @@ -130,7 +130,7 @@ void Meta::BaseEntity::load(Net::Mode loadType) auto url = this->url(); auto entry = APPLICATION->metacache()->resolveEntry("meta", localFilename()); entry->setStale(true); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); /* * The validator parses the file and loads it into the object. * If that fails, the file is not written to storage. diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp index 16fdfdb1c..65ad6da69 100644 --- a/launcher/minecraft/AssetsUtils.cpp +++ b/launcher/minecraft/AssetsUtils.cpp @@ -45,7 +45,7 @@ #include "AssetsUtils.h" #include "FileSystem.h" -#include "net/Download.h" +#include "net/ApiDownload.h" #include "net/ChecksumValidator.h" #include "BuildConfig.h" @@ -311,7 +311,7 @@ NetAction::Ptr AssetObject::getDownloadAction() QFileInfo objectFile(getLocalPath()); if ((!objectFile.isFile()) || (objectFile.size() != size)) { - auto objectDL = Net::Download::makeFile(getUrl(), objectFile.filePath()); + auto objectDL = Net::ApiDownload::makeFile(getUrl(), objectFile.filePath()); if(hash.size()) { auto rawHash = QByteArray::fromHex(hash.toLatin1()); diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index cb2b5254d..e0318ef22 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -36,7 +36,7 @@ #include "Library.h" #include "MinecraftInstance.h" -#include +#include #include #include #include @@ -129,14 +129,14 @@ QList Library::getDownloads( if(sha1.size()) { auto rawSha1 = QByteArray::fromHex(sha1.toLatin1()); - auto dl = Net::Download::makeCached(url, entry, options); + auto dl = Net::ApiDownload::makeCached(url, entry, options); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); qDebug() << "Checksummed Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; out.append(dl); } else { - out.append(Net::Download::makeCached(url, entry, options)); + out.append(Net::ApiDownload::makeCached(url, entry, options)); qDebug() << "Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; } return true; diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index 31fd5eb11..bafbe75f1 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -7,6 +7,8 @@ #include "Application.h" +#include "net/ApiDownload.h" + AssetUpdateTask::AssetUpdateTask(MinecraftInstance * inst) { m_inst = inst; @@ -34,7 +36,7 @@ void AssetUpdateTask::executeTask() entry->setStale(true); auto hexSha1 = assets->sha1.toLatin1(); qDebug() << "Asset index SHA1:" << hexSha1; - auto dl = Net::Download::makeCached(indexUrl, entry); + auto dl = Net::ApiDownload::makeCached(indexUrl, entry); auto rawSha1 = QByteArray::fromHex(assets->sha1.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); job->addNetAction(dl); diff --git a/launcher/minecraft/update/FMLLibrariesTask.cpp b/launcher/minecraft/update/FMLLibrariesTask.cpp index 75e5c5720..3651f4f40 100644 --- a/launcher/minecraft/update/FMLLibrariesTask.cpp +++ b/launcher/minecraft/update/FMLLibrariesTask.cpp @@ -8,6 +8,8 @@ #include "BuildConfig.h" #include "Application.h" +#include "net/ApiDownload.h" + FMLLibrariesTask::FMLLibrariesTask(MinecraftInstance * inst) { m_inst = inst; @@ -68,7 +70,7 @@ void FMLLibrariesTask::executeTask() { auto entry = metacache->resolveEntry("fmllibs", lib.filename); QString urlString = BuildConfig.FMLLIBS_BASE_URL + lib.filename; - dljob->addNetAction(Net::Download::makeCached(QUrl(urlString), entry, options)); + dljob->addNetAction(Net::ApiDownload::makeCached(QUrl(urlString), entry, options)); } connect(dljob.get(), &NetJob::succeeded, this, &FMLLibrariesTask::fmllibsFinished); diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 96cea7b7d..966e2665f 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -53,6 +53,8 @@ #include "meta/Version.h" #include "meta/VersionList.h" +#include "net/ApiDownload.h" + #include "BuildConfig.h" #include "Application.h" @@ -84,7 +86,7 @@ void PackInstallTask::executeTask() NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) }; auto searchUrl = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json") .arg(m_pack_safe_name).arg(m_version_name); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), &response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); @@ -658,7 +660,7 @@ void PackInstallTask::installConfigs() auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", path); entry->setStale(true); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!m_version.configs.sha1.isEmpty()) { auto rawSha1 = QByteArray::fromHex(m_version.configs.sha1.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); @@ -781,7 +783,7 @@ void PackInstallTask::downloadMods() entry->setStale(true); modsToExtract.insert(entry->getFullPath(), mod); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); @@ -793,7 +795,7 @@ void PackInstallTask::downloadMods() entry->setStale(true); modsToDecomp.insert(entry->getFullPath(), mod); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); @@ -807,7 +809,7 @@ void PackInstallTask::downloadMods() auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", cacheName); entry->setStale(true); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 83db642e7..011c4cdf2 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -2,6 +2,7 @@ #include "Json.h" #include "net/Upload.h" +#include "net/ApiDownload.h" #include "modplatform/modrinth/ModrinthPackIndex.h" @@ -94,7 +95,7 @@ void Flame::FileResolvingTask::netJobFinished() if(!hash.isEmpty()) { auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); auto output = std::make_shared(); - auto dl = Net::Download::makeByteArray(QUrl(url), output.get()); + auto dl = Net::ApiDownload::makeByteArray(QUrl(url), output.get()); QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; }); @@ -169,7 +170,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { auto projectId = mod->projectId; auto output = std::make_shared(); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); - auto dl = Net::Download::makeByteArray(url, output.get()); + auto dl = Net::ApiDownload::makeByteArray(url, output.get()); qDebug() << "Fetching url slug for file:" << mod->fileName; QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 92590a084..49ab06db2 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -9,6 +9,7 @@ #include "BuildConfig.h" #include "Json.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" #include "net/Upload.h" Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, QByteArray* response) @@ -40,7 +41,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString auto netJob = makeShared(QString("Flame::FileChangelog"), APPLICATION->network()); auto response = std::make_shared(); - netJob->addNetAction(Net::Download::makeByteArray( + netJob->addNetAction(Net::ApiDownload::makeByteArray( QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog") .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))), response.get())); @@ -75,7 +76,7 @@ auto FlameAPI::getModDescription(int modId) -> QString auto netJob = makeShared(QString("Flame::ModDescription"), APPLICATION->network()); auto response = std::make_shared(); - netJob->addNetAction(Net::Download::makeByteArray( + netJob->addNetAction(Net::ApiDownload::makeByteArray( QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get())); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { @@ -115,7 +116,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe auto response = std::make_shared(); ModPlatform::IndexedVersion ver; - netJob->addNetAction(Net::Download::makeByteArray(versions_url, response.get())); + netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response.get())); QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] { QJsonParseError parse_error{}; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 06a895027..5736f16e0 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -12,6 +12,8 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourceFolderModel.h" +#include "net/ApiDownload.h" + static FlameAPI api; bool FlameCheckUpdate::abort() @@ -32,7 +34,7 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info) auto response = new QByteArray(); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(ver_info.addonId.toString()); - auto dl = Net::Download::makeByteArray(url, response); + auto dl = Net::ApiDownload::makeByteArray(url, response); get_project_job->addNetAction(dl); QObject::connect(get_project_job, &NetJob::succeeded, [response, &pack]() { @@ -76,7 +78,7 @@ ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId) auto response = new QByteArray(); auto url = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(QString::number(addonId), QString::number(fileId)); - auto dl = Net::Download::makeByteArray(url, response); + auto dl = Net::ApiDownload::makeByteArray(url, response); get_file_info_job->addNetAction(dl); QObject::connect(get_file_info_job, &NetJob::succeeded, [response, &ver]() { diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index dae93d1c6..099e3ae4f 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -60,6 +60,8 @@ #include "minecraft/World.h" #include "minecraft/mod/tasks/LocalResourceParse.h" +#include "net/ApiDownload.h" + const static QMap forgemap = { { "1.2.5", "3.4.9.171" }, { "1.4.2", "6.0.1.355" }, @@ -473,7 +475,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) case Flame::File::Type::Mod: { if (!result.url.isEmpty()) { qDebug() << "Will download" << result.url << "to" << path; - auto dl = Net::Download::makeFile(result.url, path); + auto dl = Net::ApiDownload::makeFile(result.url, path); m_files_job->addNetAction(dl); } break; diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index a3c592fdc..0ff8ac8a4 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -9,6 +9,8 @@ #include "modplatform/ModIndex.h" +#include "net/ApiDownload.h" + Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&& callbacks) const { auto search_url_optional = getSearchURL(args); @@ -22,7 +24,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& auto response = new QByteArray(); auto netJob = makeShared(QString("%1::Search").arg(debugName()), APPLICATION->network()); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(search_url), response)); QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks]{ QJsonParseError parse_error{}; @@ -90,7 +92,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi auto netJob = makeShared(QString("%1::Versions").arg(args.pack.name), APPLICATION->network()); auto response = new QByteArray(); - netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response)); QObject::connect(netJob.get(), &NetJob::succeeded, [response, callbacks, args] { QJsonParseError parse_error{}; @@ -122,7 +124,7 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) auto netJob = makeShared(QString("%1::GetProject").arg(addonId), APPLICATION->network()); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(project_url), response)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp index e8768c5cd..320ddd3e8 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp @@ -40,6 +40,8 @@ #include "BuildConfig.h" #include "Application.h" +#include "net/ApiDownload.h" + namespace LegacyFTB { void PackFetchTask::fetch() @@ -51,11 +53,11 @@ void PackFetchTask::fetch() QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml"); qDebug() << "Downloading public version info from" << publicPacksUrl.toString(); - jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData)); + jobPtr->addNetAction(Net::ApiDownload::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData)); QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml"); qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString(); - jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData)); + jobPtr->addNetAction(Net::ApiDownload::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData)); QObject::connect(jobPtr.get(), &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished); QObject::connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed); @@ -72,7 +74,7 @@ void PackFetchTask::fetchPrivate(const QStringList & toFetch) { QByteArray *data = new QByteArray(); NetJob *job = new NetJob("Fetching private pack", m_network); - job->addNetAction(Net::Download::makeByteArray(privatePackBaseUrl.arg(packCode), data)); + job->addNetAction(Net::ApiDownload::makeByteArray(privatePackBaseUrl.arg(packCode), data)); QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] { diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index 36c142acb..6da8fc882 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -48,6 +48,8 @@ #include "BuildConfig.h" #include "Application.h" +#include "net/ApiDownload.h" + namespace LegacyFTB { PackInstallTask::PackInstallTask(shared_qobject_ptr network, Modpack pack, QString version) @@ -76,7 +78,7 @@ void PackInstallTask::downloadPack() } else { url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(archivePath); } - netJobContainer->addNetAction(Net::Download::makeFile(url, archivePath)); + netJobContainer->addNetAction(Net::ApiDownload::makeFile(url, archivePath)); connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp index 29e3d129d..ab77ef119 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.cpp +++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp @@ -8,12 +8,13 @@ #include "Json.h" #include "net/NetJob.h" #include "net/Upload.h" +#include "net/ApiDownload.h" Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response) { auto netJob = makeShared(QString("Modrinth::GetCurrentVersion"), APPLICATION->network()); - netJob->addNetAction(Net::Download::makeByteArray( + netJob->addNetAction(Net::ApiDownload::makeByteArray( QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); @@ -111,7 +112,7 @@ Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) c auto netJob = makeShared(QString("Modrinth::GetProjects"), APPLICATION->network()); auto searchUrl = getMultipleModInfoURL(addonIds); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response)); QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] { delete response; diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index bb8227aa2..0edd696f7 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -12,6 +12,7 @@ #include "net/ChecksumValidator.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" #include "settings/INISettingsObject.h" #include "ui/dialogs/CustomMessageBox.h" @@ -238,7 +239,7 @@ bool ModrinthCreationTask::createInstance() } qDebug() << "Will try to download" << file.downloads.front() << "to" << file_path; - auto dl = Net::Download::makeFile(file.downloads.dequeue(), file_path); + auto dl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); m_files_job->addNetAction(dl); @@ -247,7 +248,7 @@ bool ModrinthCreationTask::createInstance() // MultipleOptionsTask's , once those exist :) auto param = dl.toWeakRef(); connect(dl.get(), &NetAction::failed, [this, &file, file_path, param] { - auto ndl = Net::Download::makeFile(file.downloads.dequeue(), file_path); + auto ndl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); ndl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); m_files_job->addNetAction(ndl); if (auto shared = param.lock()) shared->succeeded(); diff --git a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp index f07ca24af..21b0defc0 100644 --- a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp +++ b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp @@ -23,6 +23,8 @@ #include "Application.h" +#include "net/ApiDownload.h" + Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion) { m_sourceUrl = sourceUrl; @@ -45,7 +47,7 @@ void Technic::SingleZipPackInstallTask::executeTask() auto entry = APPLICATION->metacache()->resolveEntry("general", path); entry->setStale(true); m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network())); - m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry)); + m_filesNetJob->addNetAction(Net::ApiDownload::makeCached(m_sourceUrl, entry)); m_archivePath = entry->getFullPath(); auto job = m_filesNetJob.get(); connect(job, &NetJob::succeeded, this, &Technic::SingleZipPackInstallTask::downloadSucceeded); diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index c26d6a5a6..0035c8808 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -43,6 +43,7 @@ #include "TechnicPackProcessor.h" #include "SolderPackManifest.h" #include "net/ChecksumValidator.h" +#include "net/ApiDownload.h" Technic::SolderPackInstallTask::SolderPackInstallTask( shared_qobject_ptr network, @@ -72,7 +73,7 @@ void Technic::SolderPackInstallTask::executeTask() m_filesNetJob.reset(new NetJob(tr("Resolving modpack files"), m_network)); auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version); - m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, &m_response)); + m_filesNetJob->addNetAction(Net::ApiDownload::makeByteArray(sourceUrl, &m_response)); auto job = m_filesNetJob.get(); connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded); @@ -113,7 +114,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded() for (const auto &mod : build.mods) { auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i)); - auto dl = Net::Download::makeFile(mod.url, path); + auto dl = Net::ApiDownload::makeFile(mod.url, path); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); diff --git a/launcher/net/ApiDownload.h b/launcher/net/ApiDownload.h new file mode 100644 index 000000000..3ffda445a --- /dev/null +++ b/launcher/net/ApiDownload.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "ApiHeaderProxy.h" +#include "Download.h" + +namespace Net { + +class ApiDownload : public Download { + public: + ApiDownload() : Download() + { + auto api_headers = new ApiHeaderProxy(); + addHeaderProxy(api_headers); + } + virtual ~ApiDownload() = default; +}; + +} // namespace Net diff --git a/launcher/net/ApiHeaderProxy.h b/launcher/net/ApiHeaderProxy.h new file mode 100644 index 000000000..0da92a745 --- /dev/null +++ b/launcher/net/ApiHeaderProxy.h @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "Application.h" +#include "BuildConfig.h" +#include "net/HeaderProxy.h" + +namespace Net { + +class ApiHeaderProxy : public HeaderProxy { + public: + ApiHeaderProxy() : HeaderProxy(){}; + virtual ~ApiHeaderProxy() = default; + + public: + virtual QList headers(const QNetworkRequest& request) const override + { + QList hdrs; + if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { + hdrs.append({ "x-api-key", APPLICATION->getFlameAPIKey().toUtf8() }); + } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || + request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { + QString token = APPLICATION->getModrinthAPIToken(); + if (!token.isNull()) + hdrs.append({ "Authorization", token.toUtf8() }); + } + return hdrs; + }; +}; + +} // namespace Net diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 7f8d3a067..6c2173793 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -124,15 +124,11 @@ void Download::executeTask() } request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8()); - // TODO remove duplication - if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { - request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8()); - } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || - request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { - QString token = APPLICATION->getModrinthAPIToken(); - if (!token.isNull()) - request.setRawHeader("Authorization", token.toUtf8()); + for ( auto header_proxy : m_headerProxies ) { + header_proxy->writeHeaders(request); } + // TODO remove duplication + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) request.setTransferTimeout(); diff --git a/launcher/net/HeaderProxy.h b/launcher/net/HeaderProxy.h new file mode 100644 index 000000000..e94579e74 --- /dev/null +++ b/launcher/net/HeaderProxy.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +namespace Net { + +struct HeaderPair { + QByteArray headerName; + QByteArray headerValue; +}; + +class HeaderProxy { + public: + HeaderProxy(){}; + virtual ~HeaderProxy(){}; + + public: + virtual QList headers(const QNetworkRequest& request) const = 0; + + public: + void writeHeaders(QNetworkRequest& request) { + for (auto header : headers(request)) { + request.setRawHeader(header.headerName, header.headerValue); + } + }; +}; + +} // namespace Net diff --git a/launcher/net/NetAction.h b/launcher/net/NetAction.h index ab9322c26..acb0672fc 100644 --- a/launcher/net/NetAction.h +++ b/launcher/net/NetAction.h @@ -42,6 +42,8 @@ #include "QObjectPtr.h" #include "tasks/Task.h" +#include "HeaderProxy.h" + class NetAction : public Task { Q_OBJECT protected: @@ -56,13 +58,16 @@ class NetAction : public Task { void setNetwork(shared_qobject_ptr network) { m_network = network; } + void addHeaderProxy(Net::HeaderProxy* proxy) { m_headerProxies.push_back(std::shared_ptr(proxy)); } + protected slots: virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) = 0; virtual void downloadError(QNetworkReply::NetworkError error) = 0; virtual void downloadFinished() = 0; virtual void downloadReadyRead() = 0; - virtual void sslErrors(const QList& errors) { + virtual void sslErrors(const QList& errors) + { int i = 1; for (auto error : errors) { qCritical() << "Network SSL Error #" << i << " : " << error.errorString(); @@ -70,7 +75,6 @@ class NetAction : public Task { qCritical() << "Certificate in question:\n" << cert.toText(); i++; } - }; public slots: @@ -91,4 +95,5 @@ class NetAction : public Task { /// source URL QUrl m_url; + std::vector> m_headerProxies; }; diff --git a/launcher/net/RawHeaderProxy.h b/launcher/net/RawHeaderProxy.h new file mode 100644 index 000000000..ffe6a81a9 --- /dev/null +++ b/launcher/net/RawHeaderProxy.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "net/HeaderProxy.h" + +namespace Net { + +class ApiHeaderProxy : public HeaderProxy { + public: + ApiHeaderProxy() : HeaderProxy(){}; + virtual ~ApiHeaderProxy() = default; + + public: + virtual QList headers(const QNetworkRequest&) const override { return m_headers; }; + + void addHeader(const HeaderPair& header) { m_headers.append(header); } + void addHeader(const QByteArray& headerName, const QByteArray& headerValue) { m_headers.append({ headerName, headerValue }); } + void addHeaders(const QList& headers) { m_headers.append(headers); } + + private: + QList m_headers; +}; + +} // namespace Net diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index d0701a7ad..68119f06b 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -23,6 +23,8 @@ #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" +#include "net/ApiDownload.h" + /** This is just to override the combo box popup behavior so that the combo box doesn't take the whole screen. * ... thanks Qt. */ @@ -226,7 +228,7 @@ void ModrinthManagedPackPage::parseManagedPack() QString id = m_inst->getManagedPackID(); - m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get())); + m_fetch_job->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get())); QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; @@ -369,7 +371,7 @@ void FlameManagedPackPage::parseManagedPack() QString id = m_inst->getManagedPackID(); - m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get())); + m_fetch_job->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get())); QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 472aa8515..ed741c881 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -15,7 +15,7 @@ #include "BuildConfig.h" #include "Json.h" -#include "net/Download.h" +#include "net/ApiDownload.h" #include "net/NetJob.h" #include "modplatform/ModIndex.h" @@ -276,7 +276,7 @@ std::optional ResourceModel::getIcon(QModelIndex& index, const QUrl& url) auto cache_entry = APPLICATION->metacache()->resolveEntry( metaEntryBase(), QString("logos/%1").arg(QString(QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Algorithm::Sha1).toHex()))); - auto icon_fetch_action = Net::Download::makeCached(url, cache_entry); + auto icon_fetch_action = Net::ApiDownload::makeCached(url, cache_entry); auto full_file_path = cache_entry->getFullPath(); connect(icon_fetch_action.get(), &NetAction::succeeded, this, [=] { diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 9ad26f472..e064919eb 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -20,6 +20,8 @@ #include #include +#include "net/ApiDownload.h" + namespace Atl { ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) @@ -88,7 +90,7 @@ void ListModel::request() auto netJob = makeShared("Atl::Request", APPLICATION->network()); auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/json/packsnew.json"); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), &response)); jobPtr = netJob; jobPtr->start(); @@ -184,7 +186,7 @@ void ListModel::requestLogo(QString file, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file.section(".", 0, 0))); NetJob *job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath] diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp index cdb4532c8..edc73345f 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -43,6 +43,8 @@ #include "modplatform/atlauncher/ATLShareCode.h" #include "Application.h" +#include "net/ApiDownload.h" + AtlOptionalModListModel::AtlOptionalModListModel(QWidget* parent, ATLauncher::PackVersion version, QVector mods) : QAbstractListModel(parent) , m_version(version) @@ -152,7 +154,7 @@ Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const { void AtlOptionalModListModel::useShareCode(const QString& code) { m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network())); auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code); - m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), &m_response)); + m_jobPtr->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), &m_response)); connect(m_jobPtr.get(), &NetJob::succeeded, this, &AtlOptionalModListModel::shareCodeSuccess); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 5961ea026..0205552fb 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -3,6 +3,8 @@ #include "Application.h" #include "ui/widgets/ProjectItem.h" +#include "net/ApiDownload.h" + #include #include @@ -102,7 +104,7 @@ void ListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo.section(".", 0, 0))); auto job = new NetJob(QString("Flame Icon Download %1").arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] { @@ -169,7 +171,7 @@ void ListModel::performPaginatedSearch() .arg(currentSearchTerm) .arg(currentSort + 1); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), &response)); jobPtr = netJob; jobPtr->start(); QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index f9ac4a789..c98e40600 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -46,6 +46,8 @@ #include "ui/widgets/ProjectItem.h" #include "modplatform/flame/FlameAPI.h" +#include "net/ApiDownload.h" + static FlameAPI api; FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog) @@ -132,7 +134,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network()); auto response = new QByteArray(); int addonId = current.addonId; - netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, addonId, curr] { if (addonId != current.addonId) { diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 2343b79f2..c391c1288 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -37,6 +37,7 @@ #include "Application.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" #include "StringUtils.h" #include @@ -254,7 +255,7 @@ void ListModel::requestLogo(QString file) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0))); NetJob *job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::finished, this, [this, file, fullPath] diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 346a00b0e..02c43acee 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -42,6 +42,8 @@ #include "minecraft/PackProfile.h" #include "ui/widgets/ProjectItem.h" +#include "net/ApiDownload.h" + #include namespace Modrinth { @@ -140,7 +142,7 @@ void ModpackListModel::performPaginatedSearch() .arg(currentSearchTerm) .arg(currentSort); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), &m_all_response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchAllUrl), &m_all_response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, [this] { QJsonParseError parse_error_all{}; @@ -233,7 +235,7 @@ void ModpackListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo.section(".", 0, 0))); auto job = new NetJob(QString("%1 Icon Download %2").arg(m_parent->debugName()).arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] { diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 0bb11d834..c450395c3 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -46,6 +46,8 @@ #include "ui/widgets/ProjectItem.h" +#include "net/ApiDownload.h" + #include #include #include @@ -127,7 +129,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) QString id = current.id; - netJob->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/project/%2").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id, curr] { if (id != current.id) { @@ -179,7 +181,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) QString id = current.id; netJob->addNetAction( - Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); + Net::ApiDownload::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id, curr] { if (id != current.id) { diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index 50f0c72d1..0790fb0bc 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -38,6 +38,8 @@ #include "BuildConfig.h" #include "Json.h" +#include "net/ApiDownload.h" + #include Technic::ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) @@ -134,7 +136,7 @@ void Technic::ListModel::performSearch() ).arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm); searchMode = List; } - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), &response)); jobPtr = netJob; jobPtr->start(); QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); @@ -286,7 +288,7 @@ void Technic::ListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo)); NetJob *job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 859da97e9..5aabcf34f 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -49,6 +49,8 @@ #include "Application.h" #include "modplatform/technic/SolderPackManifest.h" +#include "net/ApiDownload.h" + TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget *parent) : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog) { @@ -143,7 +145,7 @@ void TechnicPage::suggestCurrent() auto netJob = makeShared(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network()); QString slug = current.slug; - netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), &response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug] { jobPtr.reset(); @@ -249,7 +251,7 @@ void TechnicPage::metadataLoaded() auto netJob = makeShared(QString("Technic::SolderMeta(%1)").arg(current.name), APPLICATION->network()); auto url = QString("%1/modpack/%2").arg(current.url, current.slug); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), &response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded); diff --git a/launcher/ui/widgets/VariableSizedImageObject.cpp b/launcher/ui/widgets/VariableSizedImageObject.cpp index 991b4a047..3aa3343d0 100644 --- a/launcher/ui/widgets/VariableSizedImageObject.cpp +++ b/launcher/ui/widgets/VariableSizedImageObject.cpp @@ -26,6 +26,7 @@ #include "Application.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" enum FormatProperties { ImageData = QTextFormat::UserProperty + 1 }; @@ -97,7 +98,7 @@ void VariableSizedImageObject::loadImage(QTextDocument* doc, const QUrl& source, QString("images/%1").arg(QString(QCryptographicHash::hash(source.toEncoded(), QCryptographicHash::Algorithm::Sha1).toHex()))); auto job = new NetJob(QString("Load Image: %1").arg(source.fileName()), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(source, entry)); + job->addNetAction(Net::ApiDownload::makeCached(source, entry)); auto full_entry_path = entry->getFullPath(); auto source_url = source; From 0bda885bbff4944b017862a75d91e6b128ece221 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:53:29 -0700 Subject: [PATCH 051/398] packaging: add appimage update capability Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 15 +++++++++++++++ .github/workflows/trigger_release.yml | 2 ++ 2 files changed, 17 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 691e257bf..cb4f5ebe1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -249,6 +249,8 @@ jobs: wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage" wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" + wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/continuous/AppImageUpdate-x86_64.AppImage" + ${{ github.workspace }}/.github/scripts/prepare_JREs.sh - name: Add QT_HOST_PATH var (Windows MSVC arm64) @@ -479,6 +481,12 @@ jobs: LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib" export LD_LIBRARY_PATH + chmod +x AppImageUpdate-x86_64.AppImage + ./AppImageUpdate-x86_64.AppImage --appimage-extract + rsync --ignore-existing -ar squashfs_root/usr/ ${{ env.INSTALL_APPIMAGE_DIR }}/usr/ + + export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-${{ runner.os }}-*-x86_64.AppImage.zsync" + ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg ## @@ -547,6 +555,13 @@ jobs: with: name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage + + - name: Upload AppImage Zsync (Linux) + if: runner.os == 'Linux' && matrix.qt_ver != 5 + uses: actions/upload-artifact@v3 + with: + name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync + path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync - name: ccache stats (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index 3c56a38ea..31e8bde40 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -44,6 +44,7 @@ jobs: mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage + mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage.zsync mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz @@ -89,6 +90,7 @@ jobs: PrismLauncher-Linux-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage + PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage.zsync PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip From 89d8f9b82977dab87aecfe7282ca2b88dbf0991e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 3 Jun 2023 22:43:41 -0700 Subject: [PATCH 052/398] packaging(linux): use vars when refrencing qt install dir Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb4f5ebe1..25abab9eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -469,7 +469,7 @@ jobs: cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk - cp -r /home/runner/work/PrismLauncher/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines + cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}//usr/lib/ @@ -483,6 +483,7 @@ jobs: chmod +x AppImageUpdate-x86_64.AppImage ./AppImageUpdate-x86_64.AppImage --appimage-extract + rm -rf squashfs_root/usr/share rsync --ignore-existing -ar squashfs_root/usr/ ${{ env.INSTALL_APPIMAGE_DIR }}/usr/ export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-${{ runner.os }}-*-x86_64.AppImage.zsync" From 2c959734463d3efd3cd62566e155453de879c7ac Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 4 Jun 2023 10:36:34 -0700 Subject: [PATCH 053/398] packaging(appimage): dont use rsync Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 25abab9eb..ba80885d4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -483,8 +483,14 @@ jobs: chmod +x AppImageUpdate-x86_64.AppImage ./AppImageUpdate-x86_64.AppImage --appimage-extract - rm -rf squashfs_root/usr/share - rsync --ignore-existing -ar squashfs_root/usr/ ${{ env.INSTALL_APPIMAGE_DIR }}/usr/ + + mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional + mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins + + cp -r squashfs-root/usr/bin/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin + cp -r squashfs-root/usr/lib/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib + cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional + cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-${{ runner.os }}-*-x86_64.AppImage.zsync" From ab418162657e95e510a15a4d64e04b2af9856a8a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 4 Jun 2023 12:27:01 -0700 Subject: [PATCH 054/398] packaging: use runner.workspace when copying files Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba80885d4..6dc94dbd4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -386,8 +386,8 @@ jobs: cd ${{ env.INSTALL_DIR }} if ("${{ matrix.qt_ver }}" -eq "5") { - Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll - Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll + Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll + Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll } - name: Fetch codesign certificate (Windows) From 7e0e1ec51dfbcd49204f8e8e7e82b72c9931db11 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 4 Jun 2023 14:10:17 -0700 Subject: [PATCH 055/398] chore: add better default compiler warnings Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- cmake/CompilerWarnings.cmake | 161 +++++++++++++++++++++++++++++++++++ launcher/CMakeLists.txt | 13 +++ 2 files changed, 174 insertions(+) create mode 100644 cmake/CompilerWarnings.cmake diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake new file mode 100644 index 000000000..b03664016 --- /dev/null +++ b/cmake/CompilerWarnings.cmake @@ -0,0 +1,161 @@ +# +# Function to set compiler warnings with reasonable defaults at the project level. +# Taken from https://github.com/aminya/project_options/blob/main/src/CompilerWarnings.cmake +# under the folowing license: +# +# MIT License +# +# Copyright (c) 2022-2100 Amin Yahyaabadi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +include_guard() + +function(_set_project_warnings_add_target_link_option TARGET OPTIONS) + target_link_options(${_project_name} INTERFACE ${OPTIONS}) +endfunction() + +# Set the compiler warnings +# +# https://clang.llvm.org/docs/DiagnosticsReference.html +# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md +function( + set_project_warnings + _project_name + WARNINGS_AS_ERRORS + MSVC_WARNINGS + CLANG_WARNINGS + GCC_WARNINGS +) + if("${MSVC_WARNINGS}" STREQUAL "") + set(MSVC_WARNINGS + /W4 # Baseline reasonable warnings + /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data + /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data + /w14263 # 'function': member function does not override any base class virtual member function + /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not + # be destructed correctly + /w14287 # 'operator': unsigned/negative constant mismatch + /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside + # the for-loop scope + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14555 # expression has no effect; expected expression with side- effect + /w14619 # pragma warning: there is no warning number 'number' + /w14640 # Enable warning on thread un-safe static member initialization + /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied + /permissive- # standards conformance mode for MSVC compiler. + ) + endif() + + if("${CLANG_WARNINGS}" STREQUAL "") + set(CLANG_WARNINGS + -Wall + -Wextra # reasonable and standard + -Wextra-semi # Warn about semicolon after in-class function definition. + -Wshadow # warn the user if a variable declaration shadows one from a parent context + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps + # catch hard to track down memory errors + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wunused # warn on anything being unused + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Wpedantic # warn if non-standard C++ is used + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + -Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation + ) + endif() + + if("${GCC_WARNINGS}" STREQUAL "") + set(GCC_WARNINGS + ${CLANG_WARNINGS} + -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist + -Wduplicated-cond # warn if if / else chain has duplicated conditions + -Wduplicated-branches # warn if if / else branches have duplicated code + -Wlogical-op # warn about logical operations being used where bitwise were probably wanted + -Wuseless-cast # warn if you perform a cast to the same type + ) + endif() + + + if(WARNINGS_AS_ERRORS) + message(TRACE "Warnings are treated as errors") + list(APPEND CLANG_WARNINGS -Werror) + list(APPEND GCC_WARNINGS -Werror) + list(APPEND MSVC_WARNINGS /WX) + endif() + + if(MSVC) + set(PROJECT_WARNINGS_CXX ${MSVC_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + set(PROJECT_WARNINGS_CXX ${CLANG_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(PROJECT_WARNINGS_CXX ${GCC_WARNINGS}) + else() + message(AUTHOR_WARNING "No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'") + # TODO support Intel compiler + endif() + + # Add C warnings + set(PROJECT_WARNINGS_C "${PROJECT_WARNINGS_CXX}") + list( + REMOVE_ITEM + PROJECT_WARNINGS_C + -Wnon-virtual-dtor + -Wold-style-cast + -Woverloaded-virtual + -Wuseless-cast + -Wextra-semi + ) + + target_compile_options( + ${_project_name} + INTERFACE # C++ warnings + $<$:${PROJECT_WARNINGS_CXX}> + # C warnings + $<$:${PROJECT_WARNINGS_C}> + ) + + # If we are using the compiler as a linker driver pass the warnings to it + # (most useful when using LTO or warnings as errors) + if(CMAKE_CXX_LINK_EXECUTABLE MATCHES "^") + _set_project_warnings_add_target_link_option( + ${_project_name} "$<$:${PROJECT_WARNINGS_CXX}>" + ) + endif() + + if(CMAKE_C_LINK_EXECUTABLE MATCHES "^") + _set_project_warnings_add_target_link_option( + ${_project_name} "$<$:${PROJECT_WARNINGS_C}>" + ) + endif() + + endfunction() diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 273b5449a..5f3591b13 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1080,8 +1080,15 @@ if(WIN32) set(LAUNCHER_RCS ${CMAKE_CURRENT_BINARY_DIR}/../${Launcher_Branding_WindowsRC}) endif() +include(CompilerWarnings) + # Add executable add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) +set_project_warnings(Launcher_logic + "${WARNINGS_AS_ERRORS}" + "${Launcher_MSVC_WARNINGS}" + "${Launcher_CLANG_WARNINGS}" + "${Launcher_GCC_WARNINGS}") target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(Launcher_logic systeminfo @@ -1160,6 +1167,12 @@ install(TARGETS ${Launcher_Name} if(WIN32) add_library(filelink_logic STATIC ${LINKEXE_SOURCES}) + set_project_warnings(filelink_logic + "${WARNINGS_AS_ERRORS}" + "${Launcher_MSVC_WARNINGS}" + "${Launcher_CLANG_WARNINGS}" + "${Launcher_GCC_WARNINGS}") + target_include_directories(filelink_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(filelink_logic systeminfo From cc41b039e6ba2a24c0ded9fb573bee6050aa2ac9 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 4 Jun 2023 14:59:37 -0700 Subject: [PATCH 056/398] chore: clean up after new compiler warnings Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/BaseInstance.h | 6 ++-- launcher/BaseVersion.h | 4 +-- launcher/ProblemProvider.h | 5 ++- launcher/Usable.h | 34 ++++++++------------ launcher/minecraft/Component.h | 3 +- launcher/minecraft/LaunchProfile.h | 2 +- launcher/minecraft/MojangDownloadInfo.h | 4 +-- launcher/minecraft/Rule.h | 2 +- launcher/minecraft/mod/ResourceFolderModel.h | 16 ++++----- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/ResourceAPI.h | 16 +++++---- launcher/net/Download.h | 2 +- launcher/net/HttpMetaCache.h | 2 +- launcher/net/NetAction.h | 6 ++-- launcher/net/Validator.h | 5 +-- launcher/pathmatcher/IPathMatcher.h | 2 +- launcher/pathmatcher/RegexpMatcher.h | 2 +- launcher/tasks/ConcurrentTask.h | 4 +-- launcher/tasks/Task.h | 8 ++--- launcher/translations/TranslationsModel.cpp | 2 -- tests/DummyResourceAPI.h | 2 +- tests/FileSystem_test.cpp | 7 ++-- tests/GZip_test.cpp | 2 +- tests/ResourceModel_test.cpp | 10 +++--- tests/Task_test.cpp | 4 +-- 25 files changed, 74 insertions(+), 78 deletions(-) diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index 83a8064fa..f6b5a7a56 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -88,7 +88,7 @@ public: /* types */ public: /// virtual destructor to make sure the destruction is COMPLETE - virtual ~BaseInstance() {}; + virtual ~BaseInstance() {} virtual void saveNow() = 0; @@ -154,7 +154,7 @@ public: virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString &line, MessageLevel::Enum level) { return level; - }; + } virtual QStringList extraArguments(); @@ -291,7 +291,7 @@ public: protected: void changeStatus(Status newStatus); - SettingsObjectPtr globalSettings() const { return m_global_settings.lock(); }; + SettingsObjectPtr globalSettings() const { return m_global_settings.lock(); } bool isSpecificSettingsLoaded() const { return m_specific_settings_loaded; } void setSpecificSettingsLoaded(bool loaded) { m_specific_settings_loaded = loaded; } diff --git a/launcher/BaseVersion.h b/launcher/BaseVersion.h index ca0e45027..7bfc51e3b 100644 --- a/launcher/BaseVersion.h +++ b/launcher/BaseVersion.h @@ -48,11 +48,11 @@ public: virtual bool operator<(BaseVersion &a) { return name() < a.name(); - }; + } virtual bool operator>(BaseVersion &a) { return name() > a.name(); - }; + } }; Q_DECLARE_METATYPE(BaseVersion::Ptr) diff --git a/launcher/ProblemProvider.h b/launcher/ProblemProvider.h index cd4745fa1..d7d4c4e57 100644 --- a/launcher/ProblemProvider.h +++ b/launcher/ProblemProvider.h @@ -1,5 +1,8 @@ #pragma once +#include +#include + enum class ProblemSeverity { None, @@ -16,7 +19,7 @@ struct PatchProblem class ProblemProvider { public: - virtual ~ProblemProvider() {}; + virtual ~ProblemProvider() {} virtual const QList getProblems() const = 0; virtual ProblemSeverity getProblemSeverity() const = 0; }; diff --git a/launcher/Usable.h b/launcher/Usable.h index a3e880f38..f5818cbb4 100644 --- a/launcher/Usable.h +++ b/launcher/Usable.h @@ -12,28 +12,20 @@ class Usable; * * @see UseLock */ -class Usable -{ +class Usable { friend class UseLock; -public: - std::size_t useCount() const - { - return m_useCount; - } - bool isInUse() const - { - return m_useCount > 0; - } -protected: - virtual void decrementUses() - { - m_useCount--; - } - virtual void incrementUses() - { - m_useCount++; - } -private: + + public: + virtual ~Usable() {} + + std::size_t useCount() const { return m_useCount; } + bool isInUse() const { return m_useCount > 0; } + + protected: + virtual void decrementUses() { m_useCount--; } + virtual void incrementUses() { m_useCount++; } + + private: std::size_t m_useCount = 0; }; diff --git a/launcher/minecraft/Component.h b/launcher/minecraft/Component.h index ef7c99470..e7419c41a 100644 --- a/launcher/minecraft/Component.h +++ b/launcher/minecraft/Component.h @@ -27,7 +27,8 @@ public: Component(PackProfile * parent, std::shared_ptr version); Component(PackProfile * parent, const QString & uid, std::shared_ptr file); - virtual ~Component(){}; + virtual ~Component(){} + void applyTo(LaunchProfile *profile); bool isEnabled(); diff --git a/launcher/minecraft/LaunchProfile.h b/launcher/minecraft/LaunchProfile.h index 49c1217d3..79e688246 100644 --- a/launcher/minecraft/LaunchProfile.h +++ b/launcher/minecraft/LaunchProfile.h @@ -42,7 +42,7 @@ class LaunchProfile: public ProblemProvider { public: - virtual ~LaunchProfile() {}; + virtual ~LaunchProfile() {} public: /* application of profile variables from patches */ void applyMinecraftVersion(const QString& id); diff --git a/launcher/minecraft/MojangDownloadInfo.h b/launcher/minecraft/MojangDownloadInfo.h index 13e27e15e..784374c87 100644 --- a/launcher/minecraft/MojangDownloadInfo.h +++ b/launcher/minecraft/MojangDownloadInfo.h @@ -23,8 +23,8 @@ struct MojangDownloadInfo struct MojangLibraryDownloadInfo { - MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact): artifact(artifact) {}; - MojangLibraryDownloadInfo() {}; + MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact): artifact(artifact) {} + MojangLibraryDownloadInfo() {} // types typedef std::shared_ptr Ptr; diff --git a/launcher/minecraft/Rule.h b/launcher/minecraft/Rule.h index 846e8e428..70fd70b68 100644 --- a/launcher/minecraft/Rule.h +++ b/launcher/minecraft/Rule.h @@ -63,7 +63,7 @@ public: Rule(RuleAction result) : m_result(result) { } - virtual ~Rule() {}; + virtual ~Rule() {} virtual QJsonObject toJson() = 0; RuleAction apply(const Library *parent, const RuntimeContext & runtimeContext) { diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 0a35e1bca..7b5256e03 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -44,8 +44,8 @@ class ResourceFolderModel : public QAbstractListModel { bool stopWatching(const QStringList paths); /* Helper methods for subclasses, using a predetermined list of paths. */ - virtual bool startWatching() { return startWatching({ m_dir.absolutePath() }); }; - virtual bool stopWatching() { return stopWatching({ m_dir.absolutePath() }); }; + virtual bool startWatching() { return startWatching({ m_dir.absolutePath() }); } + virtual bool stopWatching() { return stopWatching({ m_dir.absolutePath() }); } /** Given a path in the system, install that resource, moving it to its place in the * instance file hierarchy. @@ -73,7 +73,7 @@ class ResourceFolderModel : public QAbstractListModel { /** Creates a new parse task, if needed, for 'res' and start it.*/ virtual void resolveResource(Resource* res); - [[nodiscard]] size_t size() const { return m_resources.size(); }; + [[nodiscard]] int size() const { return m_resources.size(); } [[nodiscard]] bool empty() const { return size() == 0; } [[nodiscard]] Resource& at(int index) { return *m_resources.at(index); } [[nodiscard]] Resource const& at(int index) const { return *m_resources.at(index); } @@ -94,7 +94,7 @@ class ResourceFolderModel : public QAbstractListModel { enum Columns { ACTIVE_COLUMN = 0, NAME_COLUMN, DATE_COLUMN, NUM_COLUMNS }; [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast(size()); } - [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; }; + [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; } [[nodiscard]] Qt::DropActions supportedDropActions() const override; @@ -151,7 +151,7 @@ class ResourceFolderModel : public QAbstractListModel { * This task should load and parse all heavy info needed by a resource, such as parsing a manifest. It gets executed * in the background, so it slowly updates the UI as tasks get done. */ - [[nodiscard]] virtual Task* createParseTask(Resource&) { return nullptr; }; + [[nodiscard]] virtual Task* createParseTask(Resource&) { return nullptr; } /** Standard implementation of the model update logic. * @@ -210,15 +210,15 @@ class ResourceFolderModel : public QAbstractListModel { /* A macro to define useful functions to handle Resource* -> T* more easily on derived classes */ #define RESOURCE_HELPERS(T) \ - [[nodiscard]] T* operator[](size_t index) \ + [[nodiscard]] T* operator[](int index) \ { \ return static_cast(m_resources[index].get()); \ } \ - [[nodiscard]] T* at(size_t index) \ + [[nodiscard]] T* at(int index) \ { \ return static_cast(m_resources[index].get()); \ } \ - [[nodiscard]] const T* at(size_t index) const \ + [[nodiscard]] const T* at(int index) const \ { \ return static_cast(m_resources.at(index).get()); \ } \ diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 8d0223f91..a4d431e30 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -104,7 +104,7 @@ struct IndexedPack { ExtraPackData extraData; // For internal use, not provided by APIs - [[nodiscard]] bool isVersionSelected(size_t index) const + [[nodiscard]] bool isVersionSelected(int index) const { if (!versionsLoaded) return false; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 34f337791..d4c9af8ad 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -118,28 +118,30 @@ class ResourceAPI { public slots: [[nodiscard]] virtual Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const { - qWarning() << "TODO"; + qWarning() << "TODO: ResourceAPI::searchProjects"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProject(QString addonId, QByteArray* response) const + /** getProject(QString addonId, QByteArray* responce)*/ + [[nodiscard]] virtual Task::Ptr getProject(QString, QByteArray*) const { - qWarning() << "TODO"; + qWarning() << "TODO: ResourceAPI::getProject"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const + /** getProjects(QStringList addonIds, QByteArray* responce) */ + [[nodiscard]] virtual Task::Ptr getProjects(QStringList, QByteArray*) const { - qWarning() << "TODO"; + qWarning() << "TODO: ResourceAPI::getProjects"; return nullptr; } [[nodiscard]] virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const { - qWarning() << "TODO"; + qWarning() << "TODO: ResourceAPI::getProjectInfo"; return nullptr; } [[nodiscard]] virtual Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const { - qWarning() << "TODO"; + qWarning() << "TODO: ResourceAPI::getProjectVersions"; return nullptr; } diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 920164a30..afa0eb5ce 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -66,7 +66,7 @@ class Download : public NetAction { public: void addValidator(Validator* v); auto abort() -> bool override; - auto canAbort() const -> bool override { return true; }; + auto canAbort() const -> bool override { return true; } private: auto handleRedirect() -> bool; diff --git a/launcher/net/HttpMetaCache.h b/launcher/net/HttpMetaCache.h index 0dcb5668d..036a8dd94 100644 --- a/launcher/net/HttpMetaCache.h +++ b/launcher/net/HttpMetaCache.h @@ -74,7 +74,7 @@ class MetaEntry { auto getMaximumAge() -> qint64 { return m_max_age; } void setMaximumAge(qint64 age) { m_max_age = age; } - bool isExpired(qint64 offset) { return !m_is_eternal && (m_current_age >= m_max_age - offset); }; + bool isExpired(qint64 offset) { return !m_is_eternal && (m_current_age >= m_max_age - offset); } protected: QString m_baseId; diff --git a/launcher/net/NetAction.h b/launcher/net/NetAction.h index ab9322c26..c22eaf9f3 100644 --- a/launcher/net/NetAction.h +++ b/launcher/net/NetAction.h @@ -45,7 +45,7 @@ class NetAction : public Task { Q_OBJECT protected: - explicit NetAction() : Task(){}; + explicit NetAction() : Task(){} public: using Ptr = shared_qobject_ptr; @@ -71,7 +71,7 @@ class NetAction : public Task { i++; } - }; + } public slots: void startAction(shared_qobject_ptr network) @@ -81,7 +81,7 @@ class NetAction : public Task { } protected: - void executeTask() override{}; + void executeTask() override{} public: shared_qobject_ptr m_network; diff --git a/launcher/net/Validator.h b/launcher/net/Validator.h index 6b3d46352..c8ce79223 100644 --- a/launcher/net/Validator.h +++ b/launcher/net/Validator.h @@ -40,8 +40,9 @@ namespace Net { class Validator { public: /* con/des */ - Validator() {}; - virtual ~Validator() {}; + Validator() {} + + virtual ~Validator() {} public: /* methods */ virtual bool init(QNetworkRequest & request) = 0; diff --git a/launcher/pathmatcher/IPathMatcher.h b/launcher/pathmatcher/IPathMatcher.h index 192782d7c..1457d3e5b 100644 --- a/launcher/pathmatcher/IPathMatcher.h +++ b/launcher/pathmatcher/IPathMatcher.h @@ -8,6 +8,6 @@ public: typedef std::shared_ptr Ptr; public: - virtual ~IPathMatcher(){}; + virtual ~IPathMatcher() {} virtual bool matches(const QString &string) const = 0; }; diff --git a/launcher/pathmatcher/RegexpMatcher.h b/launcher/pathmatcher/RegexpMatcher.h index 825d488c3..6da651ef1 100644 --- a/launcher/pathmatcher/RegexpMatcher.h +++ b/launcher/pathmatcher/RegexpMatcher.h @@ -4,7 +4,7 @@ class RegexpMatcher : public IPathMatcher { public: - virtual ~RegexpMatcher() {}; + virtual ~RegexpMatcher() {} RegexpMatcher(const QString ®exp) { m_regexp.setPattern(regexp); diff --git a/launcher/tasks/ConcurrentTask.h b/launcher/tasks/ConcurrentTask.h index 6325fc9e7..481ebf852 100644 --- a/launcher/tasks/ConcurrentTask.h +++ b/launcher/tasks/ConcurrentTask.h @@ -53,7 +53,7 @@ class ConcurrentTask : public Task { bool canAbort() const override { return true; } - inline auto isMultiStep() const -> bool override { return totalSize() > 1; }; + inline auto isMultiStep() const -> bool override { return totalSize() > 1; } auto getStepProgress() const -> TaskStepProgressList override; void addTask(Task::Ptr task); @@ -80,7 +80,7 @@ class ConcurrentTask : public Task { protected: // NOTE: This is not thread-safe. - [[nodiscard]] unsigned int totalSize() const { return m_queue.size() + m_doing.size() + m_done.size(); } + [[nodiscard]] unsigned int totalSize() const { return static_cast(m_queue.size() + m_doing.size() + m_done.size()); } enum class Operation { ADDED, REMOVED, CHANGED }; void updateStepProgress(TaskStepProgress const& changed_progress, Operation); diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index 6d8bbbb46..d3bcc84f7 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -71,12 +71,12 @@ struct TaskStepProgress { this->uid = uid; } bool isDone() const { return (state == TaskStepState::Failed) || (state == TaskStepState::Succeeded); } - void update(qint64 current, qint64 total) { + void update(qint64 new_current, qint64 new_total) { this->old_current = this->current; this->old_total = this->total; - this->current = current; - this->total = total; + this->current = new_current; + this->total = new_total; this->state = TaskStepState::Running; } }; @@ -155,7 +155,7 @@ class Task : public QObject, public QRunnable { void run() override { start(); } virtual void start(); - virtual bool abort() { if(canAbort()) emitAborted(); return canAbort(); }; + virtual bool abort() { if(canAbort()) emitAborted(); return canAbort(); } void setAbortable(bool can_abort) { m_can_abort = can_abort; emit abortStatusChanged(can_abort); } diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 46db48049..8a0043152 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -274,7 +274,6 @@ void readIndex(const QString & path, QMap& languages) return; } - int index = 1; try { auto toplevel_doc = Json::requireDocument(data); @@ -307,7 +306,6 @@ void readIndex(const QString & path, QMap& languages) lang.file_size = Json::requireInteger(langObj, "size"); languages.insert(lang.key, lang); - index++; } } catch (Json::JsonException & e) diff --git a/tests/DummyResourceAPI.h b/tests/DummyResourceAPI.h index 0cc909584..35de95151 100644 --- a/tests/DummyResourceAPI.h +++ b/tests/DummyResourceAPI.h @@ -32,7 +32,7 @@ class DummyResourceAPI : public ResourceAPI { } DummyResourceAPI() : ResourceAPI() {} - [[nodiscard]] auto getSortingMethods() const -> QList override { return {}; }; + [[nodiscard]] auto getSortingMethods() const -> QList override { return {}; } [[nodiscard]] Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&& callbacks) const override { diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index ec1f0bcff..9bb681aef 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -91,10 +91,9 @@ class LinkTask : public Task { emitSucceeded(); } - }; + } FS::create_link *m_lnk; - bool m_useHard = false; bool m_linkRecursive = true; }; @@ -346,7 +345,7 @@ slots: void test_link() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder, this]() + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); @@ -640,7 +639,7 @@ slots: void test_link_with_max_depth() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder, this]() + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); diff --git a/tests/GZip_test.cpp b/tests/GZip_test.cpp index 82503d81d..ccaa36101 100644 --- a/tests/GZip_test.cpp +++ b/tests/GZip_test.cpp @@ -29,7 +29,7 @@ slots: // initialize random buffer for(int i = 0; i < size; i++) { - random.append((char)idis(eng)); + random.append(static_cast(idis(eng))); } // initialize fibonacci diff --git a/tests/ResourceModel_test.cpp b/tests/ResourceModel_test.cpp index c0d9cd95d..ecaea5245 100644 --- a/tests/ResourceModel_test.cpp +++ b/tests/ResourceModel_test.cpp @@ -39,17 +39,17 @@ class DummyResourceModel : public ResourceModel { public: DummyResourceModel() : ResourceModel(new DummyResourceAPI) {} - [[nodiscard]] auto metaEntryBase() const -> QString override { return ""; }; + [[nodiscard]] auto metaEntryBase() const -> QString override { return ""; } - ResourceAPI::SearchArgs createSearchArguments() override { return {}; }; - ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override { return {}; }; - ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override { return {}; }; + ResourceAPI::SearchArgs createSearchArguments() override { return {}; } + ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override { return {}; } + ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override { return {}; } QJsonArray documentToArray(QJsonDocument& doc) const override { return doc.object().value("hits").toArray(); } void loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) override { - pack.authors.append({ Json::requireString(obj, "author") }); + pack.authors.append({ Json::requireString(obj, "author"), "" }); pack.description = Json::requireString(obj, "description"); pack.addonId = Json::requireString(obj, "project_id"); } diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index dabe5da26..04f2abcc1 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -22,7 +22,7 @@ class BasicTask : public Task { void executeTask() override { emitSucceeded(); - }; + } }; /* Does nothing. Only used for testing. */ @@ -34,7 +34,7 @@ class BasicTask_MultiStep : public Task { private: auto isMultiStep() const -> bool override { return true; } - void executeTask() override {}; + void executeTask() override {} }; class BigConcurrentTask : public ConcurrentTask { From 3531c5bb8c29ede39371a4430da0f0f17c026bf5 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 4 Jun 2023 16:58:46 -0700 Subject: [PATCH 057/398] packaging(appimage): put zsync in relase:x Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/trigger_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index 31e8bde40..2041747f9 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -44,7 +44,7 @@ jobs: mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage - mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage.zsync + mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage.zsync mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz From df18d8560dd4648d21cfdddb463e5e9770a822f7 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 4 Jun 2023 22:46:05 -0700 Subject: [PATCH 058/398] chore: fix test & clean up one last warning Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/java/JavaVersion.h | 2 +- tests/FileSystem_test.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h index 9bbf06425..6b92d401f 100644 --- a/launcher/java/JavaVersion.h +++ b/launcher/java/JavaVersion.h @@ -14,7 +14,7 @@ class JavaVersion { friend class JavaVersionTest; public: - JavaVersion() {}; + JavaVersion() {} JavaVersion(const QString & rhs); JavaVersion & operator=(const QString & rhs); diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index 9bb681aef..49397e073 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -94,6 +94,7 @@ class LinkTask : public Task { } FS::create_link *m_lnk; + [[maybe_unused]] bool m_useHard = false; bool m_linkRecursive = true; }; From 53d40df292b5771bf6637704d948d441093aa2a4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:53:29 -0700 Subject: [PATCH 059/398] packaging: add appimage update capability Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging(linux): use vars when refrencing qt install dir Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging(appimage): dont use rsync Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging: use runner.workspace when copying files Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> packaging(appimage): put zsync in relase:x Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> use with:token insted of env for GITHUB_TOKEN (which is depricated) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> fix: appimage zsync needs consistant filenames across verisons Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> upload proper zsync Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> fix: non versioned appimage filename Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 32 +++++++++++++++++++++++---- .github/workflows/trigger_release.yml | 9 ++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a6a6eceaa..76833f7b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -249,6 +249,8 @@ jobs: wget "https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage" wget "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" + wget "https://github.com/AppImageCommunity/AppImageUpdate/releases/download/continuous/AppImageUpdate-x86_64.AppImage" + ${{ github.workspace }}/.github/scripts/prepare_JREs.sh - name: Add QT_HOST_PATH var (Windows MSVC arm64) @@ -386,8 +388,8 @@ jobs: cd ${{ env.INSTALL_DIR }} if ("${{ matrix.qt_ver }}" -eq "5") { - Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll - Copy-Item D:/a/PrismLauncher/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll + Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll + Copy-Item ${{ runner.workspace }}/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll } cd ${{ github.workspace }} @@ -468,7 +470,7 @@ jobs: run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr - export OUTPUT="PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" + export OUTPUT="PrismLauncher-Linux-x86_64.AppImage" chmod +x linuxdeploy-*.AppImage @@ -479,7 +481,7 @@ jobs: cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk - cp -r /home/runner/work/PrismLauncher/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines + cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}//usr/lib/ @@ -491,7 +493,22 @@ jobs: LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk/lib" export LD_LIBRARY_PATH + chmod +x AppImageUpdate-x86_64.AppImage + ./AppImageUpdate-x86_64.AppImage --appimage-extract + + mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional + mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins + + cp -r squashfs-root/usr/bin/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin + cp -r squashfs-root/usr/lib/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib + cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional + cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins + + export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync" + ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg + + mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" ## # UPLOAD BUILDS @@ -559,6 +576,13 @@ jobs: with: name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage + + - name: Upload AppImage Zsync (Linux) + if: runner.os == 'Linux' && matrix.qt_ver != 5 + uses: actions/upload-artifact@v3 + with: + name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage.zsync + path: PrismLauncher-Linux-x86_64.AppImage.zsync - name: ccache stats (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index f19b83986..2a46ff5e7 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -43,7 +43,8 @@ jobs: mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz - mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage + mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage + mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz mv PrismLauncher-macOS*/PrismLauncher.tar.gz PrismLauncher-macOS-${{ env.VERSION }}.tar.gz @@ -78,9 +79,8 @@ jobs: - name: Create release id: create_release uses: softprops/action-gh-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: + token: ${{ secrets.GITHUB_TOKEN }} tag_name: ${{ github.ref }} name: Prism Launcher ${{ env.VERSION }} draft: true @@ -88,7 +88,8 @@ jobs: files: | PrismLauncher-Linux-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz - PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage + PrismLauncher-Linux-x86_64.AppImage + PrismLauncher-Linux-x86_64.AppImage.zsync PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip From 66858100810fd9072237d22624efdce948ce46cf Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 19 Jun 2023 01:26:04 -0700 Subject: [PATCH 060/398] packaging: sign appimages with gpg Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76833f7b0..d57b04e4f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,12 @@ on: CACHIX_AUTH_TOKEN: description: Private token for authenticating against Cachix cache required: false + GPG_PRIVATE_KEY: + description: Private key for AppImage signing + required: false + GPG_PRIVATE_KEY_ID: + description: ID for the GPG_PRIVATE_KEY, to select the signign key + required: false jobs: build: @@ -426,7 +432,7 @@ jobs: run: | cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable - + Get-ChildItem ${{ env.INSTALL_PORTABLE_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_PORTABLE_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows, installer) @@ -467,6 +473,8 @@ jobs: - name: Package AppImage (Linux) if: runner.os == 'Linux' && matrix.qt_ver != 5 shell: bash + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} run: | cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_APPIMAGE_DIR }}/usr @@ -482,7 +490,7 @@ jobs: cp -r ${{ github.workspace }}/JREs/jre17/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/jvm/java-17-openjdk cp -r ${{ runner.workspace }}/Qt/${{ matrix.qt_version }}/gcc_64/plugins/iconengines/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins/iconengines - + cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib/ cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 ${{ env.INSTALL_APPIMAGE_DIR }}//usr/lib/ @@ -506,8 +514,18 @@ jobs: export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync" + if [ '${{ secrets.GPG_PRIVATE_KEY_ID }}' != '' ]; then + export SIGN=1 + export SIGN_KEY=${{ secrets.GPG_PRIVATE_KEY_ID }} + mkdir -p ~/.gnupg/ + printf "$GPG_PRIVATE_KEY" | base64 --decode > ~/.gnupg/private.key + gpg --import ~/.gnupg/private.key + else + echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $env:GITHUB_STEP_SUMMARY + fi + ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg - + mv "PrismLauncher-Linux-x86_64.AppImage" "PrismLauncher-Linux-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage" ## From 6ccc7e77f918503125c363eb8ac9455aa9fc095e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 19 Jun 2023 22:42:27 +0100 Subject: [PATCH 061/398] Basic, unfinished & broken impl Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 3 + launcher/resources/multimc/multimc.qrc | 4 + .../multimc/scalable/fabric-loader.svg | 1 + .../multimc/scalable/forge-loader.svg | 1 + .../multimc/scalable/quilt-loader.svg | 70 +++++++++ launcher/ui/InstanceWindow.cpp | 5 + launcher/ui/InstanceWindow.h | 1 + launcher/ui/dialogs/InstallLoaderDialog.cpp | 121 +++++++++++++++ launcher/ui/dialogs/InstallLoaderDialog.h | 42 ++++++ .../ui/dialogs/ResourceDownloadDialog.cpp | 26 +--- launcher/ui/dialogs/ResourceDownloadDialog.h | 3 +- launcher/ui/pages/BasePageContainer.h | 1 + launcher/ui/pages/instance/VersionPage.cpp | 140 +----------------- launcher/ui/pages/instance/VersionPage.h | 5 +- launcher/ui/pages/instance/VersionPage.ui | 71 +++------ .../ui/pages/modplatform/ResourcePage.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 5 + launcher/ui/widgets/PageContainer.h | 3 +- 18 files changed, 287 insertions(+), 217 deletions(-) create mode 100644 launcher/resources/multimc/scalable/fabric-loader.svg create mode 100644 launcher/resources/multimc/scalable/forge-loader.svg create mode 100644 launcher/resources/multimc/scalable/quilt-loader.svg create mode 100644 launcher/ui/dialogs/InstallLoaderDialog.cpp create mode 100644 launcher/ui/dialogs/InstallLoaderDialog.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce2771a49..d09895773 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -944,6 +944,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/ChooseProviderDialog.cpp ui/dialogs/ModUpdateDialog.cpp ui/dialogs/ModUpdateDialog.h + ui/dialogs/InstallLoaderDialog.cpp + ui/dialogs/InstallLoaderDialog.h # GUI - widgets ui/widgets/Common.cpp @@ -1066,6 +1068,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui ui/dialogs/ChooseProviderDialog.ui + ui/dialogs/InstallLoaderDialog.ui ) qt_add_resources(LAUNCHER_RESOURCES diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 2c00f28fa..f018e8748 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -347,5 +347,9 @@ scalable/export.svg scalable/launch.svg scalable/server.svg + + scalable/fabric-loader.svg + scalable/quilt-loader.svg + scalable/forge-loader.svg diff --git a/launcher/resources/multimc/scalable/fabric-loader.svg b/launcher/resources/multimc/scalable/fabric-loader.svg new file mode 100644 index 000000000..06aa7801e --- /dev/null +++ b/launcher/resources/multimc/scalable/fabric-loader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/forge-loader.svg b/launcher/resources/multimc/scalable/forge-loader.svg new file mode 100644 index 000000000..b73360b86 --- /dev/null +++ b/launcher/resources/multimc/scalable/forge-loader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/quilt-loader.svg b/launcher/resources/multimc/scalable/quilt-loader.svg new file mode 100644 index 000000000..fd6faea4b --- /dev/null +++ b/launcher/resources/multimc/scalable/quilt-loader.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index c62b370fd..d9a21f6f2 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -263,6 +263,11 @@ bool InstanceWindow::selectPage(QString pageId) return m_container->selectPage(pageId); } +BasePage* InstanceWindow::selectedPage() +{ + return m_container->selectedPage(); +} + void InstanceWindow::refreshContainer() { m_container->refreshContainer(); diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index 554c4c740..78d7474da 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -56,6 +56,7 @@ public: virtual ~InstanceWindow(); bool selectPage(QString pageId) override; + BasePage* selectedPage() override; void refreshContainer() override; QString instanceId(); diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp new file mode 100644 index 000000000..34c91c681 --- /dev/null +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -0,0 +1,121 @@ +#include "InstallLoaderDialog.h" + +#include +#include +#include +#include "Application.h" +#include "BuildConfig.h" +#include "DesktopServices.h" +#include "meta/Index.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" +#include "ui/widgets/PageContainer.h" +#include "ui/widgets/VersionSelectWidget.h" + +class LoaderPage : public VersionSelectWidget, public BasePage { + public: + LoaderPage(const QString&& id, + const QString&& icon, + const QString&& name, + // "lightweight" loaders are independent to any game version + const bool lightweight, + const std::shared_ptr profile, + QWidget* parent = nullptr) + : VersionSelectWidget(parent), m_id(std::move(id)), m_icon(std::move(icon)), m_name(std::move(name)) + { + const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); + setEmptyErrorString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); + if (!lightweight) + setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + + if (const QString currentVersion = profile->getComponentVersion(id); !currentVersion.isNull()) + setCurrentVersion(currentVersion); + } + + QString id() const override { return m_id; } + QString displayName() const override { return m_name; } + QIcon icon() const override { return APPLICATION->getThemedIcon(m_icon); } + + void openedImpl() override + { + if (m_loaded) + return; + + const auto versions = APPLICATION->metadataIndex()->get(m_id); + if (!versions) + return; + + initialize(versions.get()); + m_loaded = true; + } + + private: + const QString m_id; + const QString m_icon; + const QString m_name; + bool m_loaded = false; +}; + +InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, QWidget* parent) + : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)) +{ + auto layout = new QVBoxLayout(this); + + m_container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + layout->addWidget(m_container); + + auto buttonLayout = new QHBoxLayout(this); + + auto refreshButton = new QPushButton(tr("&Refresh"), this); + connect(refreshButton, &QPushButton::pressed, this, [this] { + LoaderPage* page = dynamic_cast(m_container->selectedPage()); + Q_ASSERT(page != nullptr); + page->loadList(); + }); + buttonLayout->addWidget(refreshButton); + + auto buttons = new QDialogButtonBox(this); + buttons->setOrientation(Qt::Horizontal); + buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonLayout->addWidget(buttons); + + layout->addLayout(buttonLayout); + + setWindowTitle(dialogTitle()); + resize(650, 400); +} + +QList InstallLoaderDialog::getPages() +{ + return { // Fabric + new LoaderPage("net.fabricmc.fabric-loader", "fabric-loader", tr("Fabric"), true, m_profile, this), + // Quilt + new LoaderPage("org.quiltmc.quilt-loader", "quilt-loader", tr("Quilt"), true, m_profile, this), + // Forge + new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), + // LiteLoader + new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) + }; +} + +QString InstallLoaderDialog::dialogTitle() +{ + return tr("Install Loader"); +} + +void InstallLoaderDialog::done(int result) +{ + if (result == Accepted) { + LoaderPage* page = dynamic_cast(m_container->selectedPage()); + Q_ASSERT(page != nullptr); + + if (page->selectedVersion()) { + m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); + m_profile->resolve(Net::Mode::Online); + } + } + + QDialog::done(result); +} diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h new file mode 100644 index 000000000..26b39e4a9 --- /dev/null +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include "ui/pages/BasePageProvider.h" + +class MinecraftInstance; +class PageContainer; +class PackProfile; + +class InstallLoaderDialog : public QDialog, public BasePageProvider { + Q_OBJECT + + public: + explicit InstallLoaderDialog(std::shared_ptr instance, QWidget* parent = nullptr); + + QList getPages() override; + QString dialogTitle() override; + + void done(int result) override; + + private: + std::shared_ptr m_profile; + PageContainer* m_container; +}; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 6d90480ff..784662a07 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -148,15 +148,17 @@ bool ResourceDownloadDialog::selectPage(QString pageId) return m_container->selectPage(pageId); } -ResourcePage* ResourceDownloadDialog::getSelectedPage() +ResourcePage* ResourceDownloadDialog::selectedPage() { - return m_selectedPage; + ResourcePage* result = dynamic_cast(m_container->selectedPage()); + Q_ASSERT(result != nullptr); + return result; } void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver) { removeResource(pack->name); - m_selectedPage->addResourceToPage(pack, ver, getBaseModel()); + selectedPage()->addResourceToPage(pack, ver, getBaseModel()); setButtonStatus(); } @@ -196,14 +198,8 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s return; } - m_selectedPage = dynamic_cast(selected); - if (!m_selectedPage) { - qCritical() << "Page '" << selected->displayName() << "' in ResourceDownloadDialog is not a ResourcePage!"; - return; - } - // Same effect as having a global search bar - m_selectedPage->setSearchTerm(prev_page->getSearchTerm()); + selectedPage()->setSearchTerm(prev_page->getSearchTerm()); } ModDownloadDialog::ModDownloadDialog(QWidget* parent, const std::shared_ptr& mods, BaseInstance* instance) @@ -226,8 +222,6 @@ QList ModDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameModPage::create(this, *m_instance)); - m_selectedPage = dynamic_cast(pages[0]); - return pages; } @@ -253,8 +247,6 @@ QList ResourcePackDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameResourcePackPage::create(this, *m_instance)); - m_selectedPage = dynamic_cast(pages[0]); - return pages; } @@ -280,8 +272,6 @@ QList TexturePackDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameTexturePackPage::create(this, *m_instance)); - m_selectedPage = dynamic_cast(pages[0]); - return pages; } @@ -302,11 +292,7 @@ ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, QList ShaderPackDownloadDialog::getPages() { QList pages; - pages.append(ModrinthShaderPackPage::create(this, *m_instance)); - - m_selectedPage = dynamic_cast(pages[0]); - return pages; } diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 5b5b48c63..5077b2ca0 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -60,7 +60,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { QString dialogTitle() override { return tr("Download %1").arg(resourcesString()); }; bool selectPage(QString pageId); - ResourcePage* getSelectedPage(); + ResourcePage* selectedPage(); void addResource(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&); void removeResource(const QString&); @@ -85,7 +85,6 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { const std::shared_ptr m_base_model; PageContainer* m_container = nullptr; - ResourcePage* m_selectedPage = nullptr; QDialogButtonBox m_buttons; QVBoxLayout m_vertical_layout; diff --git a/launcher/ui/pages/BasePageContainer.h b/launcher/ui/pages/BasePageContainer.h index b41fe12af..4cb7fe29c 100644 --- a/launcher/ui/pages/BasePageContainer.h +++ b/launcher/ui/pages/BasePageContainer.h @@ -7,6 +7,7 @@ class BasePageContainer public: virtual ~BasePageContainer(){}; virtual bool selectPage(QString pageId) = 0; + virtual BasePage* selectedPage() = 0; virtual BasePage* getPage(QString pageId) { return nullptr; }; virtual void refreshContainer() = 0; virtual bool requestClose() = 0; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 74b7ec7c2..97a6bbe4a 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -52,6 +52,7 @@ #include #include "VersionPage.h" +#include "ui/dialogs/InstallLoaderDialog.h" #include "ui_VersionPage.h" #include "ui/dialogs/CustomMessageBox.h" @@ -254,20 +255,6 @@ void VersionPage::updateRunningStatus(bool running) void VersionPage::updateVersionControls() { - // FIXME: this is a dirty hack - auto minecraftVersion = Version(m_profile->getComponentVersion("net.minecraft")); - - ui->actionInstall_Forge->setEnabled(controlsEnabled); - - bool supportsFabric = minecraftVersion >= Version("1.14"); - ui->actionInstall_Fabric->setEnabled(controlsEnabled && supportsFabric); - - bool supportsQuilt = minecraftVersion >= Version("1.14"); - ui->actionInstall_Quilt->setEnabled(controlsEnabled && supportsQuilt); - - bool supportsLiteLoader = minecraftVersion <= Version("1.12.2"); - ui->actionInstall_LiteLoader->setEnabled(controlsEnabled && supportsLiteLoader); - updateButtons(); } @@ -287,7 +274,6 @@ void VersionPage::updateButtons(int row) ui->actionAdd_Empty->setEnabled(controlsEnabled); ui->actionImport_Components->setEnabled(controlsEnabled); ui->actionReload->setEnabled(controlsEnabled); - ui->actionInstall_mods->setEnabled(controlsEnabled); ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_Agents->setEnabled(controlsEnabled); @@ -446,17 +432,6 @@ void VersionPage::on_actionChange_version_triggered() return; } auto uid = list->uid(); - // FIXME: this is a horrible HACK. Get version filtering information from the actual metadata... - if(uid == "net.minecraftforge") - { - on_actionInstall_Forge_triggered(); - return; - } - else if (uid == "com.mumfrey.liteloader") - { - on_actionInstall_LiteLoader_triggered(); - return; - } VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { @@ -508,87 +483,11 @@ void VersionPage::on_actionDownload_All_triggered() m_container->refreshContainer(); } -void VersionPage::on_actionInstall_Forge_triggered() +void VersionPage::on_actionInstall_Loader_triggered() { - auto vlist = APPLICATION->metadataIndex()->get("net.minecraftforge"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Forge version"), this); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Forge version lists!")); - - auto currentVersion = m_profile->getComponentVersion("net.minecraftforge"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("net.minecraftforge", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - // m_profile->installVersion(); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - -void VersionPage::on_actionInstall_Fabric_triggered() -{ - auto vlist = APPLICATION->metadataIndex()->get("net.fabricmc.fabric-loader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Fabric Loader version"), this); - vselect.setEmptyString(tr("No Fabric Loader versions are currently available.")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Fabric Loader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("net.fabricmc.fabric-loader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("net.fabricmc.fabric-loader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - -void VersionPage::on_actionInstall_Quilt_triggered() -{ - auto vlist = APPLICATION->metadataIndex()->get("org.quiltmc.quilt-loader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Quilt Loader version"), this); - vselect.setEmptyString(tr("No Quilt Loader versions are currently available.")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Quilt Loader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("org.quiltmc.quilt-loader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("org.quiltmc.quilt-loader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } + InstallLoaderDialog dialog(m_inst->getPackProfile(), this); + dialog.exec(); + m_container->refreshContainer(); } void VersionPage::on_actionAdd_Empty_triggered() @@ -609,35 +508,6 @@ void VersionPage::on_actionAdd_Empty_triggered() } } -void VersionPage::on_actionInstall_LiteLoader_triggered() -{ - auto vlist = APPLICATION->metadataIndex()->get("com.mumfrey.liteloader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select LiteLoader version"), this); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyErrorString(tr("Couldn't load or download the LiteLoader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("com.mumfrey.liteloader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("com.mumfrey.liteloader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - // m_profile->installVersion(vselect.selectedVersion()); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - void VersionPage::on_actionLibrariesFolder_triggered() { DesktopServices::openDirectory(m_inst->getLocalLibraryPath(), true); diff --git a/launcher/ui/pages/instance/VersionPage.h b/launcher/ui/pages/instance/VersionPage.h index d00877142..0dcb4635a 100644 --- a/launcher/ui/pages/instance/VersionPage.h +++ b/launcher/ui/pages/instance/VersionPage.h @@ -79,11 +79,8 @@ public: private slots: void on_actionChange_version_triggered(); - void on_actionInstall_Forge_triggered(); - void on_actionInstall_Fabric_triggered(); - void on_actionInstall_Quilt_triggered(); + void on_actionInstall_Loader_triggered(); void on_actionAdd_Empty_triggered(); - void on_actionInstall_LiteLoader_triggered(); void on_actionReload_triggered(); void on_actionRemove_triggered(); void on_actionMove_up_triggered(); diff --git a/launcher/ui/pages/instance/VersionPage.ui b/launcher/ui/pages/instance/VersionPage.ui index 4777eafe0..cf7c659bc 100644 --- a/launcher/ui/pages/instance/VersionPage.ui +++ b/launcher/ui/pages/instance/VersionPage.ui @@ -98,12 +98,7 @@ - - - - - - + @@ -118,26 +113,26 @@ - Change version + Change Version - Change version of the selected package. + Change version of the selected component. - Move up + Move Up - Make the selected package apply sooner. + Make the selected component apply sooner. - Move down + Move Down - Make the selected package apply later. + Make the selected component apply later. @@ -145,7 +140,7 @@ Remove - Remove selected package from the instance. + Remove selected component from the instance. @@ -153,7 +148,7 @@ Customize - Customize selected package. + Customize selected component. @@ -161,7 +156,7 @@ Edit - Edit selected package. + Edit selected component. @@ -169,47 +164,15 @@ Revert - Revert the selected package to default. + Revert the selected component to default. - + - Install Forge + Install Loader - Install the Minecraft Forge package. - - - - - Install Fabric - - - Install the Fabric Loader package. - - - - - Install Quilt - - - Install the Quilt Loader package. - - - - - Install LiteLoader - - - Install the LiteLoader package. - - - - - Install mods - - - Install normal mods. + Install a mod loader. @@ -238,7 +201,7 @@ Add Empty - Add an empty custom package. + Add an empty custom component. @@ -246,12 +209,12 @@ Reload - Reload all packages. + Reload all components. - Download All + Download all Download the files needed to launch the instance now. diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 1d2509d80..91d722fca 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -389,7 +389,7 @@ void ResourcePage::openUrl(const QUrl& url) if (slug != getCurrentPack()->slug) { m_parent_dialog->selectPage(page); - auto newPage = m_parent_dialog->getSelectedPage(); + auto newPage = m_parent_dialog->selectedPage(); QLineEdit* searchEdit = newPage->m_ui->searchEdit; auto model = newPage->m_model; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 38a228973..c3606b789 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -137,6 +137,11 @@ BasePage* PageContainer::getPage(QString pageId) return m_model->findPageEntryById(pageId); } +BasePage* PageContainer::selectedPage() +{ + return m_currentPage; +} + const QList PageContainer::getPages() const { return m_model->pages(); diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index ad74d43a2..89c3343ed 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -78,7 +78,8 @@ public: return false; } - virtual bool selectPage(QString pageId) override; + bool selectPage(QString pageId) override; + BasePage* selectedPage() override; BasePage* getPage(QString pageId) override; const QList getPages() const; From 82d3755e25fc01e3468e6940abab9dcc0a819e22 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 19 Jun 2023 23:36:18 +0100 Subject: [PATCH 062/398] License all the things Signed-off-by: TheKodeToad --- launcher/ui/InstanceWindow.cpp | 3 ++- launcher/ui/InstanceWindow.h | 3 ++- launcher/ui/dialogs/InstallLoaderDialog.cpp | 18 ++++++++++++++++++ launcher/ui/dialogs/InstallLoaderDialog.h | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.h | 2 +- launcher/ui/pages/instance/VersionPage.cpp | 2 +- launcher/ui/pages/modplatform/ResourcePage.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 3 ++- launcher/ui/widgets/PageContainer.h | 3 ++- 10 files changed, 31 insertions(+), 9 deletions(-) diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index d9a21f6f2..30a215e33 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index 78d7474da..adbc46ace 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 34c91c681..1b003e522 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "InstallLoaderDialog.h" #include diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 26b39e4a9..7a32e4274 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 784662a07..8d4e51b24 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 5077b2ca0..b56a9adc0 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 97a6bbe4a..53a710083 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -6,7 +6,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022-2023 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 91d722fca..ace7fb1b2 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -4,7 +4,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index c3606b789..308fad6b3 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 89c3343ed..1da269ced 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From a389983d7dfb78a2bf6c1b85e5837dcdac789070 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 20 Jun 2023 00:28:42 +0100 Subject: [PATCH 063/398] Just use the old ordering Signed-off-by: TheKodeToad --- launcher/resources/multimc/multimc.qrc | 2 +- launcher/ui/dialogs/InstallLoaderDialog.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index f018e8748..13052760b 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,8 +348,8 @@ scalable/launch.svg scalable/server.svg + scalable/forge-loader.svg scalable/fabric-loader.svg scalable/quilt-loader.svg - scalable/forge-loader.svg diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 1b003e522..5df27dba2 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -107,12 +107,12 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q QList InstallLoaderDialog::getPages() { - return { // Fabric + return { // Forge + new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), + // Fabric new LoaderPage("net.fabricmc.fabric-loader", "fabric-loader", tr("Fabric"), true, m_profile, this), // Quilt new LoaderPage("org.quiltmc.quilt-loader", "quilt-loader", tr("Quilt"), true, m_profile, this), - // Forge - new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), // LiteLoader new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) }; From 94510edd722b72e375011c6d4a6629c478728c72 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 20 Jun 2023 19:57:15 +0100 Subject: [PATCH 064/398] Rework icons (Fabric is blurry now but looks better) Signed-off-by: TheKodeToad --- .../multimc/128x128/instances/fabricmc.png | Bin 0 -> 4839 bytes .../multimc/128x128/instances/liteloader.png | Bin 0 -> 20337 bytes .../multimc/22x22/fabricmc-small.png | Bin 0 -> 5672 bytes launcher/resources/multimc/multimc.qrc | 8 +- .../multimc/scalable/fabric-loader.svg | 1 - .../multimc/scalable/forge-loader.svg | 1 - .../multimc/scalable/instances/forge.svg | 43 ++++++++ .../multimc/scalable/instances/quiltmc.svg | 98 ++++++++++++++++++ .../multimc/scalable/quilt-loader.svg | 70 ------------- launcher/ui/dialogs/InstallLoaderDialog.cpp | 8 +- 10 files changed, 150 insertions(+), 79 deletions(-) create mode 100644 launcher/resources/multimc/128x128/instances/fabricmc.png create mode 100644 launcher/resources/multimc/128x128/instances/liteloader.png create mode 100644 launcher/resources/multimc/22x22/fabricmc-small.png delete mode 100644 launcher/resources/multimc/scalable/fabric-loader.svg delete mode 100644 launcher/resources/multimc/scalable/forge-loader.svg create mode 100644 launcher/resources/multimc/scalable/instances/forge.svg create mode 100644 launcher/resources/multimc/scalable/instances/quiltmc.svg delete mode 100644 launcher/resources/multimc/scalable/quilt-loader.svg diff --git a/launcher/resources/multimc/128x128/instances/fabricmc.png b/launcher/resources/multimc/128x128/instances/fabricmc.png new file mode 100644 index 0000000000000000000000000000000000000000..c78543aeebf2b630810d2f5c8bd4d58ea6949ef7 GIT binary patch literal 4839 zcmeHLdsGzH8J}HNP*95q8i^^>jj0bZJF~OPvb)^{3=mmmfhr=_v~_l77Dm{eWoKX) z4B??w%ma^F^DqRBnwlCPZE7slB2Xnws|klx(b!0QR31rzB0f-b>7ChKgrn#5cuw;l zvwQd6`R@1qzVH6-cfT{Un=;ZCO$m++h9GE)DJ5ws=*xvRF%bNoj3Z7%kR+VWHd#%k z1<*tw3jqQdBoTB#lZ+ZmB>_+XkZlERszeHff&OjK!hl@R7h0rbg4pi|Lz!#E28@2{PvjFBj&?LJa#w+;oUypifx1{|B=&xrI z6EjSSiLk@TTA6$rg4{KwTZ}0u6J|I6a@8mD0Z zF>rxqnoZrB|lEx{%&w7#i~Hkk&i53iLCmdw1i($ndgeQC`XmV|^k zwZsNy`r+y6wu^zCrIv~adi!9F`_$f$uz2Us`v>3Pny$kw;b-_Y)!Fcj5ahrSEP6*| zzpNnh9RK$pSPfY^wxDfsL|fh5GGfj?6fJnK0}jh>l+UTk$Y=^&{JUv;md|Z|;nmyM z;yjY`=$0ivIv@CyuH&a00>8SoZn&w>e(?U_+i!($3g|(r2b8k)u8NX#1t&H?v+ot@ z`r3-<`fl`md3XAkADNL7*-d-E%=2dRR{;uFxo2*ohF%feI=N$@acEZQvKd{+CmhSF zZ;u?(mO@{iU4A1_tCejC`E`BAK<^iA?H=Ply841%k9Ph(zVvT3AdlTlW;UN~PSumF zO+iqsg;uz24sja|@oon}=FvQCp>r6!QQmjFK@KyNQNAL^jF}yYbS{%p;-r_Aq-ByN zd8Ce#$HxU5+^$+w$$4-ffhNxOy-a#Hbt=RroxkJR4+NBI~4KwL-1HkYqPg zgv;ZCVS|&h>X#Pm4bEVph}%ihhjL2;|S0|xMDj`xDh+| ztN`J~NTNB?$vAk1wZj4?VPOk-qg)Q=VSju!huJ&=Z|8h006tJR;XsuN47J(N(H0z^ zTm(RT0X^1&%Pe-#=u( zr&yAq^x{ybCM{Nq(ju5vsY28g9gAqK7>Vdejn0B&RvL7ppiFj-C+s9GKml+C18{Vd zg@{#BBw|roEr{BpR3d~9i$ySvPNRv5wbHm+GYTTz$$+dR@<&G{Kv4k7s#B>5wGKlp z7L5i`YtagdC69VD-g&8KJ99MW% zMM*|J!CQfWQJ%`!3*8S@GZ`Dbj3)#(l^Sg<4p@kd#nc*H<&9ai&Z3r8*Oj>eRF z%p1M{XJ#qJTKvDXg~J0IfIisr6o%tjXR#>qo~UJXf%ndPo6m?x35LZ(p(jZ15;&rW zro=b_mUoKGCG0sgs2;v_^~;&ZqynjpiHV_T3Q?*^EuzM?8ib&f7^2hQN*u6DlB9Ml zI>%ah7vZEA<^Uc6S0Ft_uHbp%M$I3q?aHNvT>ylE>_TwNPgtyvFx0nTRHzyL6&uh; zI5CI{qlyf$^U6T+0<{nwDTY4IgtGHJUcSBf9z6i)aVJm2?>JrKbUhIRPozAaUE_2; z5d%-8Jf2e+z*f9@Z%4)Ft7o2?x%wRZ<7?4NwEB!Tp9D4cN0?(gHi>o_b8{5_Z#|g{N)XA7t?|y#gZ2!>4SAKi=%7M*w z7iBOcD~CcMY2)n1xZ!ud`zY%JANl$wW@%l3C`xJJ|{T zK+B=Q-ErMfaC^?3k2_@V*<1GIkDklCmvgCgNVbJ3YaeX`fonl`K;-2rrpk5ts&H#c MPD?uU!s^QZ0?GJ_YXATM literal 0 HcmV?d00001 diff --git a/launcher/resources/multimc/128x128/instances/liteloader.png b/launcher/resources/multimc/128x128/instances/liteloader.png new file mode 100644 index 0000000000000000000000000000000000000000..88295e6448fdea083a04969c0e2cc7eae0fbc259 GIT binary patch literal 20337 zcmeFZbyQnV*EXC43m)7{poQY@8VVG5cMWdE-CYV4N^zGKFIFfH1&S2+7B2;gyThCQ zZeP#4*0-LuzW2ZTgvrd=v*((bYxeBS3@3?ERhGfVAjbdz0N8S}QtF5}_)h?%BHnw& z%!UB~AR$~=&Pq;>2>?dOFcAV|0Pv3vA^`s_4FVzokPxyrh=2nG0q_xVIwIgBW%?N`*bG5Lh=$E0n%MIB5w_n=SQ#IG!);Uwy zWbeMZFKqDlqr4ML8_e377U5K3AzajTvM8~!`=ap$Piu-XZ`iw%YuUW=ZH4@4?q0-N zc1PWad*)MFQ#=I-4eTWmU8>pBmlevf5rq2#0e8LCCePj}R^t=8vgCuX-|V8@hOI2= zUk{?QGg6`nnNV(75Q6tX37H%I)WXUe$Y3!f9p7P-4@lg3#dG@lKf&AIQQ4{uGTYD$ z4*-%Xk(Tn+gvEoKr(L&X0UE@l%_zRJZOfUr0s(-@X{{4f0RiMflp*6wA1^OI=f_;z zi%TSL64wus=H?j)JNCBK)OFWYQWUaqc4RZNbT)^xc{{rNHH;$S-Y#Yq_HcKoIo#UT zNtE`mwUZWVYbi>r!>h!h1=hBXE`OCmko_N;?zUF{BI`fe_9y4B?)-a05XJwA z`ybl>==)#F2rVTgAt`4Ik3Y?mlM<^oqd;q9cV}0hzeInV zQ5x`9f4lqJt%L1fQwa+FYf=cAS^TXFZf2fv%fH%*!1`O3g^ih$H5}nR{%)@SklX%W zOhHhP$4r2a*MimDjMJQz2hPRIYR)TQ&T3|6$;-jP!E0&8Z}Fe#Zq8QjUS_Uv32Ow8 z2(A$3`Pb(dl;N*|V*F2SFB|xuQ9uyJ%E8CV#qkfqc>hiq``NwhqsJob|AP~e zzZCw>$so%8O@?q@2w%wlPiOdd&i=Ta|A*J#$KwBC4G8G}R`S2%_rG-gm#+U61OF@K z|6137>H1$W@V`?2uXX+ZMi<7vwo`B?#45-Ou~`y^7%C#RTBzmn#HlWUboVPRn% zlc4+aEPm(ZHoc$M)c|r@pj1ip^oRqJ+YwFDC5?c+qn6gWYYR(7-5CH1I$j<&Z>c?O zzcs#Ac^G`O0&)Q4oCg4RvtyZA4olzj2=G$Xk5SThUadq$KNBsy-ELp;7O&#%8)Ny_ z?z1%fg#DJkDffAf3@T)DBhjPC`dJXj^kGf>3Qeclr1PPF?JcwO-r->o%~+i%K)W;QbtTIczueRL&Zfp+W*{7{>!HqH!`)vD9IYyxUf+o}4T zNBWr6!$nTw9vXEUwIRGuk3v}`amnlP4EOFBC3IH*1>_l-xIFO4f(hm;1O)ItK9ZJr zPgk{|-pLVmi9AJ7m6~q#IsH{-@X0A)V|8_vcm!pMBYY1Ez5? z^`r?G3RmTJvl(G$G?&)2msXJ0MCy@(K$!q|RUo&`Y_CzD3mRxRFL&ogeX*-v@w-yzpLe!~5UVuf8W|eob68;#u0yj~W-{*?6vT{ep zkd~5XtRj?%36+h#0)UZeqs7CZs1C?gsqg#Mr~2V$w8TmHC84CmQrBTL_|Wwn+=6m@ zna1zf@p0uBUOI1?b2riNc*1XJ82~^IlgEXc!=+}Q)3`8+$K9~Cqh09aP-r{^dE`a;Mmah%Z7^6Lz#wh@)jh1156M)wNx?Jj zEtSzo+I`WKoG0fKX8+etd9k27na8!2(ZF9-pFEfSPZQo%uQVSwhK1edQQ+J-|MUse zVw{mAFiDY0R@Y;I$--+@G<-^D~3jRPdYwJsEzxxN?A|)D5 zws{WM1VNqH{Oyx@;g{cRxSz;(NJ>HAO#5R*VA_PZ{MnvL)|jsA;6)+Bku-OIu|9X> z(C8#;}AzPfD?d;KkFD78T6)3ubuPJ@`@P1Juc1fF_nGeX z6dB*FQU~(xiqKEdDUVt;r?Y+3opE7)M?L4o5*Ai;ZP^&OeW|j zJ|A>UNb6P+C4_cdEc#d?w$3wS^R4=j!^`d1{6^!vvuD%q0pz7>!Ds#!JiaXwR_jX09{vV(#%Kh~vX=yH~F`*&g>)I*smsIX{$2SDJ*gmRx-RsqRK?NaMwj z$sy!JW{VL`dpEnfy=Tn6 zW$h2EmWQiHXIp^}>?SZv{Ls8n>(k@Gu#E-&&g*Y|hYtsj>Sji{_lgYR*Y4pej^VT5 z*H1i&a0j-gVN&jleDXP4a$%Qs!6Dx?6M@vtT3>$M7lFK46yg?r0QoH33ohf-`+M=R z-KNoPU%8}T zzn^5!$;-=ocOTg4Il3@ox0&O1GAexdb!!lWjQ4895M5yj%0G#R?-73G(w*>RL;uOc zqk?=n6rzhv+ji`r3`jZ$ig8H6VhJ-we(I%d^^@Anpk_u!W6<)_65*uIE|Xehw3z== zPu~g)d~}#Uq%!LCJU^K0xR~AVyyk!Gf2EbSacwTx-Yk%pn`6S#epyjoxtAmC)#Lnl z@i?DA_Vc+Kkd$`Rud~iWG=$4dZJ{9Yci7?^lL5roUum~ zX>E27WhLw(03|7TX1G)_z^pj>BE}`B_A)biMB384N;K=6l}w+vKVkaeZP&nZlm@>$ zK?;2M@uc&nX1LYsaQ1Om{Kn|AkfCQv8}PB|B<0v=v)$xpd-o(EQjI$*EsWpR_+*%V zczpLfUx^q=VDU3$D9+^E{Q~*yKE37lz3l2;C@lmt6(3TvnmR|?4KIj_g%8osLd~jB z3JJ&;G^B*(Cx`&K8CA2sY_w(2bLeo~M#Wq;Rm`dYvRM7Ba+@0gP~~wn=*Ek9Bkptt z?Xc72{-);9cWIE}in|7|WnFf6aoMpE8`wEn`rbnuS)Frh?3D6ef?6-FHyul-+PIIo zrY%&WbI$d+_^J1ryF8pVwcpV_C@`bNMuo4W5W*OY%=CpzoLe%S|ErfP`dMWRRBAjQ z8y3S*_c=OR>Y0vw2FqA|fqHKxgHybxXNP4@p73t}>>{T9eumoxPxw)Obp-)Op7tlF zocqO^`^BH10(U?C0x$tC^vd3D7y|fR4{o7d!#B} zDe$P@vM^Jxft~@q`N&{nca0Wt)b-xM327i%E9JsEV5}!)vseYq(B2 zd5gfR12D+wCeY&QeY85G)9G@O;OxI~_Aco9-B?9Axrw3S$iq*A75zK@&SMI=JgfM5 z`Wj*ZQ(>R|WaTLgFO^>PrM$h3MQtnhmosy;alxBjD*t25Px*4HmZ*AZA*pug(A|01 z6Rt-!*~#?>mS8uaht~SuPjFe;^P^=M*jG|Zz1Je_`ARr62}4L)`vtO}obuI#h*6Qj zELEX>DY><%jcH<{gpE97&lyTmIq7wzgoYJWnm;LoQ^-&32D60w42`5fdJt>H=Tkdp zf#9{}a|-^0$EwcrPh(CiEus~>b~`yWZ`Fxm-dj1;Czv$=&K`4sA~-jgd=FS1a=Ixv znmCnmVcczU>-Fdeu{5Go|6NeITA-d-sqk6pRdfp@37TPc&T5o%5VeO<$!E#eg$$}^ zXxryeUvGqi$+|RN7j8>;bC=1;VbFj_Ob^zv@rQ?_!-+l@+s$;1#)6BVl1QX-fk;8V z6Il>~FLAPTv~aLlGJFAr@f?=5XVXycb-48~$(|kT^5g|6JMrnUgHVog+37;q)YQzx z{q052&28sKUYZt%xALcIlOP7y71^C99baQE2|ifvlryV9tXN36e>|*Gu@IkrWtp7# z{8Kt);(>S1s6FE0fcIxF5}{9&%^SivjhGA+h?y*iMH)<7uEbryFHWT<@`wSj)gR!j zLve%f&^~_=Cp$*U&86pQQ+K!7ZQ39r&|FtLs#H}^vT5hR^<>M7rrCmOh0QmvsB$|8 zN%tAau{k4*z({FRaIFnmu z$Q0UU>sK^T6_INZfdi#IW-%BNN{dP$>YlLk5o76S_{ z%q7yc8y;yh{TYJELb&lyLt1(@+YXZ+YwJ!fh!?Nc8G^rVu%(FTXPym;;54m=M>;SK z<{<^w6A2(kgEi&l{93y6P4ZWUldbhw_!#9GX=ylUxZV*&78G44N>@61Q!sKTS1tAz zea7VTkjD=$CuFo}0LD_P3QPTpO!BF6^>(wp{%y)*3`{Sn>~0Tc3m*Tzl&n~h4-SE@ z`*+pV1zQC3bm1uTkRr=nY7=a~@^x#$A50^oEqQ{e!QU9l!o5vIb|Mlc*H=_(bM~G; z7RVqYEzuw}iJFjIm)01ePUSj8UgoWfLWn2zfxdehumfoxP;F(gdslD+_2`ce00n=Z)4T4dV(mV@!(IpF0my}T<`by7y9P-pcZ#Du)o@n^jH6GymYpU5- zVd}_cA-Kp^A=cgHb-Jl(m0Mp+HHuS?&TXu9SbxCUqml(`uiKs6GJ$7CZffsaA}dF!;23|aC>cJurFmGLGF&xc4cdgDXls%J#K=_oA| z2o^mfMVYYRXhnBN{eh3)g6>ov6OY}wN)iu#1aahyy?eY5x}|uKRt4N-==il$_+8J` zv=CDUmLW+5mc3z#ea!*Gqcpu@rL5yd0&8H5CON+Y`oEs-eh`V3QjioAqY0V<3%tw)*_4OaZJ^?jO3n3B@}2#kbH&Om5ImF*GsSsOhSlpM^6k)}2EWzzF$)s7XR1+WAe z8VQr=f|L$#n8{tOTbw~rv(>uewZS8c*W;KYb787$AiLd7q%l_mWb3i-D8;Gt-xnx| zKY2#B*LZU}&q%bZ`z^XjaFqa*-gKn`Q1Z*jUSL9X!CC1NGU?baP+y>gyMoDrF~H|g zCWTH7)_&ZQZYG%!ECv#A?^DA^b=2KU4K@{Ucdt(r9Z~vERJh6~vAKrnk5SC=oVL?Isk@7X8EG#v*Vc&`U=Dbs19eiPJ8N_Ntl8?a%0eS%l|W_W+Ss9 z<$Y>*7+JQSka=2@`|c)TDdTfp0%5`uYx590X~#qf zi%g0keN1&;?NG6514TYxlGgV4_-G!cnCe0WJ)Q7`>i21?c%-vvnvH#Rl^+dfbW?e) zPKo-bN-{@v>^jN^TgFS<#uR{r!Fv__XlTM=cL}lI3{n>TuZv=QZP(tf#3}Q8{;)CC z1n9i%YQ!_;8RuI|vQyC|xh->wgej##!bF2%_<&acN}d|i@bO(gSrwsdBoKGEZ&-@D zSqp%k#f1^Lk7}kAOR|flgbS)t=uMmpd5NuW$$3J(acK&Q=0{m!cp({)=z%Q(rz$+pTbuCd2la8ayBbd} zSC%SztWMA(884!|6m5{s#)-rzkog%nEiqAheF&ZhjB;19;}!3tg{yG_>_;38E)M~G zO9Ne;`}R)^#EN1$fm4}&-X9j6BFX{S46!xCldODl69JVysZPkyl(I5kcYd)#Zj7lJf2gZo!sZ-`oiZmO!y*~RWZ7|s*elIC$yQ%6Io6%o;pb%}Kl<>XH&lae}hZEDjKhb}*1;nEbPM@1Y9zQ;HmM-L3D~rrDL~ zA*P~cZOE^!!Z!rhEXh{p7@!97B2^#vP2p(G;Xt9Yo&*|byQa| zS1f9uUXQ$1NzBUwS!QaL7GOFmt;nWPlxX$7eIeg1p#76eDG4x=7VL(RA$R?WN94hK zE=Sp{WPPO(BPnp!{ceQ0$6GGF60D_^ltk~rX-a?!rRBgMmw`E%TYTUnAF{#n6}<4e znWwr)vMwzt0m4>2@N7gst;$pwG^U;*heve1uawl&XBomcm5vxJ{NkWz_OVV^i@4F_ zqb;gUYnFu-#F}1jtFp1FysFA-DyH?aI}c%`rb)6GV-}6sW=-nkMH=FrkZdF?EEZ-v zl~=><3LRR!*B%uByD9)N6@~9c?d3WxUS#(^OrvNm_h#txL%QGOzA-j zU6FePbwvt@gmkpUG^ZxV?XA}`+b{0NoKGu$fql@O+J;PFU?CJ&`e=dVWb(!uxc%Nw22}{l* zeXF1`p3Hm7a84R*;iD(VPtjGP#BP6J&cZY^Yt~ZEnNj27%Q=9UDLZxH9%ea$rU{Bx zN;`r9hotEk>*GAt;c&(zSI)c^l_B)2FR*dXGd2Uc?*yk{oBCjU4M`xkV`-?-K?k4* zRsbgBWyv}BLj$s)+a15x>n*|6`6-BV`Evd{8C0dmd8$hjXqZR|myMPLQ=qCNQ4b6# zN!6e~%OIQeVHqY*S-^Ns!kw)`oX#R&$%IB-c*JcnE1D$5p)XlR4q$jiwIJ;-@r9sP zQ_8JKNs!EBeybdC_Ec49dxL>DQAj!|iU=tSqks`kV)R{VVm%2T+4X%108@f7p*ugy zK1x_%o~rPx(lGtvI7c$hwfj;Osd$j$y1COzSF62o@MQtfgZsyx1@DlJda}_n1x>C(tTS6a72O^M{AF)XAn`rr}hJZ`Nmc$(6`gsGuvFA*7nJ^%}Z(As) zdei&ra1y=f+fC3rml-PjkJ_0w^dK~32GSHW9`e=2H8vd2sIT=7qOSBr9-sXITcXfp z2}_7QIQvfTC)g!R3pvf^V3@q#CuXP6uST_1R@(VQSMG!Bvm#g84^nFsRg2BRlEO>z zKmk0@V3D^EAu7cHHn6os+o^fgR;H}rY)@>f?f2dZZpUcC94i%Hft3|L{uhZ~;-2(9 ze{GrwjRx7aTRpxyzl&UDRH zFDgP?_e|tnMk&?Oah$&6#oec{T<~t*ppbKE6%(0R9J#VVnbA+zhT^VeGNWU`2f{H})sNUJc?9@foQZX}>-mA%{b zW_f>I`Nwj~%2OqR-=Dn;XOXyq=le#Kv}v|e)3YM=VfJ({3F`4>B;Kv7qE6L?=H+3M zvS&!<`!3_sNib~<{)%kQm@QzyW3ZXRXP6nh{J!m_u}zW8$2N%Hl)A3Q8C7gLj?xve zokuc^k2_ild0SLX!_=p zT{9pE&|@PgP{2h6C-G^(}SLNm9mO)lj}1Q>RH}gb-nLsNRukqqbaxIE83bCv@FB<~|3p(2M7wBs~6N zM)fTU>Oy0xC#*~2B0=O^k1rfXgqSe`KPUYD0gbJ#yu186U(Em5Vd@UN#G>Ap?( zGZ*Y=;`5xoL8jfyU@i$h=OJ*B|5DB~ZP%X&SFzcCo|!Lo-Xf(egm4e`H;i}0DZ3e9`qO#?L>URRkn zT1<-|*WoETgN?BAPo7BGBkSi0ki3X{Y9_-JA`5lS|VZyRx&Rjn_0$HRQ zh}wtg-^`YO87O+mx&k|b=x^(Fbr*Stn)<4?Q(4~QxpRhdiE`|mo1%~RUkS=Juxue^ zpB{-xi7$~kRpE!X9^55|Uk_-sO>{Ul;ZKM2sK2;tQ0I7A@@xL;_MBnKY9l_HBMK6l z6+gCw=KR=wiVG5EVH%+Ifav>_mT04A7b&I;nPWF94XP_p@Kzm~^{R|NbrTX1dt6DU zfwF!YMFaV^GI&Zaybpm z7K$rLfH$#|KEuh4o>HGnt&PkE$pu6(Zo$paX}qc1&b#MQj^{hvE_YZOt}J1YIPXX= z3GLY_T^KGXmFqMxY(y+u><&DKCLxajXiI?UC%gAhWlC5|vndsbRk(rW>n-24@G&JuAn4sf)>ZW-r)KA?SIwX!T4;#rmfD4rjJrwFAwQL56rKS+I7_ z){;16DGBY8=3ko%79=PE=Yi`_Uoc@$Xu^D{eQR;+-LQRY(PU8Bz}bmU&GRk3!=E!;W&n2^aC`9oO>GlSszMmlx zA{3vm3@o>0ObLb*YSr#6PYy~oapmy3l7&h=d)^YMxZ9+o+AQ2quJ$Iq-%c8W(-R^p zl}*2?t|pt?3NlRXAt{-re$A;&zeAca^|)*jVB6q#o{$x0;GDj8{;nf?Q zc%$@Y@pEolLt5i)a>+tsskY6-CkJQQLS@T%7~0_wy-rAXU~*`YxOe=RqWV< z=I5fcuSTO}9q2+LqrraYW@bhK`frCd4BlZ@&aI1ip?F(5%?pi|n#nKnQTNPle~Q|( ze$Ge;4yBKtWEF!vy^u-`kDLqVAbqiKEPc3&8d)TPJgT=C_#!g&ov#A$=fpyoyKu}z z#cEpim1RAg0vDQaEpT9Es2EbR#V;{T-&voHfY{2CnDw1xjP85|;V5Ke z9AG8UGiF#Hp!6Mm2p#k#zQ+h!q;@rmV-uQECD{N|_aN3=fA5WfETH!pr`Q2sP_EL_-v~sqaKfM2sRGU>fTZ5yjw9~-C7YB7JPs*!o1Ch zx@Jpst=m6(t~s1{&20Mh7&7cvbDe3CxCDGGe+l1zPZ1M#^pw+a?zwuCt|XJ$#c%xH zobax1&>dc)N*dcQMlUBY2s0$qer})pGhs)I!y$&E zZAvmgjskf9iq?;HU&lc2zAeE$@HArUXwg^f;LS3;Gv&)!)*GS66zNN@%ZtUV_1I4s zM4W4T?J_-TSnt0#gA#oi=hC&R(6i@y5^9Y6kC=2jRS-3cqm@85Q^}wEV#?Y?aKhx{fH#bhy=!S{lAMBskmS=Ky zYaaK!w}x2D6mgUj(nALhG4AGl8`M=7gBwCDOh48^nC4m|2&Vd@=AE5$R%!t~c!iGg zU-ds!;hpS01Q3}$|4EABTwLA>gR{ z-Dpb-u9@enz`9I-jGo77LQ`hxGq}+$9%H|63NH}Maaasvv$tgR9Eejc+p?k@Usw&(%O@15ic|+S{7-c%vUUfMC z*}qf&+u`h{e-l&KqargbMZr2lBF$P=NOD~1oMmQSi`<{F?O0z<*eeZ!$5tdiY3-F3Ne`M4)v!1B#O3&VqNU{sjE9r z24rXb%(gHH-yzYbJ!FbD17B;E>?*N_^WTmJtcasy>qDL4g=tj(exj~)+2|3svpCSu z&m#%_Dbj(`53|4uG&V0pS+)UMi=d5^^7AbP>7y5lSLF{AW!vxIp+@Mgfo9SU` zlW~A1+qOGbaHCI=I>OZvL?bQn@i8DY5L*mw2gz`3*3SXhQqjC)Q_j z^;(LKY;Wmf)jIje8sw;i(49?it$$a)(~~KhMvl~fvkDJOnn;qUj2m}w6lTa#ZZG@b zI;VM9*w^h_=@5lG?sz_$AQ#7p1*Lt`tpKiA-D|0zk@0Bp_Y=(X5AydsxoH1>7$}fs zn0?V*E4svcu4{~la>=4aU5;Gim{+#6brPbqalLv_i>sqPb3k+SpjJ>{* z!Rl4E^gQ&P#~F6t%ID`XK9Az-A`=QTZ|s&`3x7*0OHfVZ^TLvPtop8GmG3c8DzTO6 zCo3lA`ADztO}@PvAS-`R!i|x^$lj3pkdhq!B#__cb zb^B%SY0<4$#pUv~+t`>**gUry07oKSP?lvv@XK39`NhHD9ru#OVEGhS7E>0(Otr_t z9=BYUXlMg>K+9>{x9N|q6}8-{<=hieP0*-=4^Dxf`p-&?SQ?k9#=+w1ql-pJP#ReX zI_BY$oY7nH?APoa9=@(8?VIKo5B_{&xyIR}4}Fj4e!OD42EA;pf?I~amROL3DBEsT zZKt00p|Oz0x&ZN(CacqdDBFA<(;v)ei&GL3?poDAJoNl<>~DtDkPsq~(xqO9R;-vHK0ZZ7Kc7|wU35Mcd3E0AIOieh zt_wQS1kuCB&BgR2c8We5wi(s@YN^d*NNJ}TXOA1#ipBz{eK!o5S4#){qD;RPmBVEOv^#Xb#Zaiqvn|3;{`$imauA@1S! zN_U}aU|lU6-(K;lu6aFspqsAgAZI>=g}qF(De~kmm8U5DF_>=mciK)_MXFVf%)O?`Gr7uF1_}vG}6s1id(Y3Kh|P&aIELd*#V8 zh5S!CP<3pfQSDBO>=Ssw`yCKEqpl?mq@V$}xwX#0Xvo$MJ;C{9y+HYt)iS;SK{H{p zEXp8l|M)bauTLc8#qN{%3C;kNIB>m7E#;kvfZxyElN?vU`-i@TL9c_A>(!;cvvqHO z&mcar*4-;CYy{-*g&P3cB`5O<#O-BI^MPSN95-sAH6)%I7V zGKGFjcR%B}r`N(k7mlbM`*@6-8xy13SJpwtE1jJ|=lv5dmqP(X+v(h=3_YCI88acU!Z;r`m}P}ou{b6UV0%dc+4IPa+m0V za7Re%Dy!_d@MLNUb&ic3G98id9PcvtI@_fL#iaV^rHTQHqddMlSYB|1rM^h}?3mRP ze<{WYY|Kw`e=cdlrC%;huAvqUcpuL<+l696)sceggr_!p8#bpzzC2KF=5Vb1 zI+7}sbxp_O>N;S4=T&2yfLKO0b%47k=ff)X!^Y#~lXX{_OIplFY4u?2IG4kRSG*lT zl!zx-_4N`w=~)COwa#g5Pf=4J%3=44kaN`h>JWF_V#OZ3MG@n&9u=$Ep7?to+vi7g z&a596zO?9Kc-qbr@DfN$LHF=ppnnnw$ytud`H|-9yTZmcYQ0rfHg$T6MmPIK$#;SX z)|sEDK-opzcG@H?++l$DFO@4N#aIq2$#R;O%P1-_JFRgzl2ka@yrGnK>?^6Hew9wU zI&FLtN=_=7<;x<(BKP9db6tnKv$O64jL7;fn!XnQ`H{j&g+}@FPiiX5VFqpN=j%m- z?kB57DO1P$#|OJ(dHY=HQEUYUs zkgX$-2w?rBT9z%7`Wm!U)duw%w{I_FOrW3?V(yFBuX`xtIFT+PS?h#xE~}=ys!9Rr zD{7uMz=grqpYNzcmLj}OMz@A<9_0KAXYYLAt_ZXLqiG1YW~Vigtv$kWyL^ zY8fz!l!GfOp+kiBH#nDu((tGQtAlN!THZoMX-!OI{Cq!TdLW4dC@TTzd(ncqZIFl; zoO5=qgaN9G=D~c@TQaew!rB#iMA1!x_yL8;9Wek0n1-;TPZ3XTwTt<1Z{)l0i`5Kz z7N92}g_f&0l{o35U;&*FKlKMsASq!>j8D7v2dokBGTPx@9UIB>xSi{XtFzIVyf$mM z+iuyY6rkk{6fP~pJ!7M;HGYuGKMvCkt_u9u=K@r*0U>P{3{m) zps(!rdXjq1yeCUd!-IN`I#YlPEc7pX(&_Edx-b#$sMU5HN=?(!((?C>FO$j6;wal` z6LZ>n_HwGq%d;!fPK)~7@7DTu+WoA(9{jDeSLTGT7v7Fc3p24^6HC-8mu_UV20b?T zbL1`#T0Sux2qoi*!=WxWll$S$cGBVnG+Nt|`+EQEC{R6`7BL$6`vH7{b9)M`d*^my zYDMk6t_?w(2QHVZ-KNdLL$|%VrQ7YG$=heewqXRY94AAoi)zHW(cCxC_4e%SXVJpX zyV0L##{2Zt2SzPog3uwoWG9HUnZzn|R*=owO()UXc+z^WY@pK3ndJovIHn7)OP<2z z=)^}Wct2$Y+<_P9ww@I?2R3GY;Y5g<(H)XD^KJ85n16Thc8D> zJ>u&SKX0RSaOw-iX@_Kc86qWKl4pdf8V*<*?Grb#jgizJ-%o9{Qnx*h=B)?{c6jv< zKXr4o<{d9Di*5ilMsnjg6CBgj=CEgH_0t*qGQZyW3|jgKhJ>I+!Q>?czHTW2*$5t* zTE^G}&*@q37g@2Yi3N>^xY|mIoER~57z}MXb*oBe9Msv_N<};JsRZ5IbCy2Ot;{&Q z95RcJZ}_PXim7pE$=2-nEKZi!>E-Hvc(Ei*o%`eZsC{Q)Q0@Nr+s$s9ab~U}Un!$c z3$MfQf%7$T57T&ci})SO?&#_=@(NS0@VofxEk{Wn$=o=@fe;sB>Il z@8Y|M^*7*EE(zeLU>*gnsL$k8dtnbEt<1viN%meTHkU%~ufUEMQe@K(e%xhOJs*Xu ziBrCNiTOS*9R_U~$Xp%-HVBA{xdP5~j2DX}RtV`CyNc3GzxLj58?C4q#7;;{NJDc4 z!^cukwqM@1KRZ+N-E&6oT#Gu3?+;|}JvV->Q^#;+pufh1=NU8p92$p|HeS?R(;{xd z@=B47eK%?UE%OYuG4$||^SaL*Z*RYaEKu{^aBKbX&b{9!ae?;x?$*<|(|Xiz+&(W$ zzcTQX3#xgg@Pv@pxs`Q$DX?$jOWO?NB!GD8Vbqx^rv&AI#Mmn|1F_CV{MhkfZpt&R zwrp!}UjB)n_7Re_STRXO+(C@Tf;Y6=GdRuZ0=j-!207!Squ{VLu`~1Em3k~`)y)Fp z!lI%brw>n)%km#LK4G7*C7?3xzuso@z``Welm< z6OF`G0*o}~zny2vSxkkY*jBhj!5Z*xMwn zTP4Rd9s<3t>QD9%@B|V_yL?1!S&OM~*=YB|1h!f(ScuT3RiJH->8$`&uR5yB6bGQq zE|0a`(UQm`7fl^F`&_qnRdKfJLbRk-hSSBrkbk9)Ib#;D!K}L)eDSs?SACwFytPLF z&vcaKDGb$C)XZS400#%coT8$5*rAAiqM#~yE!P0}j*;Yu{-{=#K4p&g9K;NIP9=7q z;z;W4&Q}Ny0AksmHTHC?}Yvrrt1B5nq5$@4@} z#tp^~29!c3GhR*%*J@Y_jPT$z_BaWNl7Elup*^I zx}My}_OnW*;OYrw(O5k&b@OGKD~$6wQmI49XVp{`{dLAq3d^#%oxI`-*9|MBcvDfX_(6kxmrd_P>n1>#kwKwNg{L3V2ciKC`&H zx9%Vfe+~%@&Tjyc46Q5wUNnyB#zuG))VdxPO=VhNNU444w~^R8Gj5}H-x{iB2Oo~U8+%c=nsOk!v%vaY;F(}&iv z5V4Cdc!*zQihyd)#cPq(>gp?6&6+4W@@D9@>iQtL4L?tq zp!)?fdh2q(CJ+8?3*+{gl~0MC|viyUJq|N|#DG$Xz3^%>sBv zP7DpZ&lnvOuC&gKa||<3?+V zo=ixrDQ3zT3Re%6$q33Kbe&NPw$_ID&PtemLM9g?ZC+9jeI64k*oX4)=Ab%?tpR{9 zup9*^eI4rMX^`}FHYN>QZj_E&f@-Kf_EtH6{ZQ-6~`{<>4D*M ze(Q%7;G!R^`pIiEBdfesuQc#3qLUmWew?I(sSFzbPXNRNJNybKf>~f3JCFBjhYzjC z-M}~#L51zv_UqH{li+J?7J~#o;nl$H=(oBg5L9@2`EawPJ~IjQ3g{i)VWJpBE1BxZsd3frg(3G8QdB-1^!x8Uv#+ zRD=SZ`Edd`i9zC-54ht4?gz%10C8CZMPW*`5KEExJm>L#S>ydxje9m=%u#W+1JP~a zuhM;){{N{ig#4^1fP9QHJWVBN{Iy5)*-iwtG-+2n`K!Qq-~v9f4)4?sANYVHW?YD% zgv6mv$wHiYk2}`k-OA#_%He@$OhwwkPjZRH^Bv(Y)4dz{^XE+gwteH{6yf87u_t*G zk+?V7hJcy{r9=U&04#&x+;vvQk2|Hs?b6{v zh+tEV&ECK5jHfaC+roe5zW+t31#HIy-Jf*}K--NWKdvHhngOwN1TPMYz&LXrBdsE- zBrujPVCn*)ti@+W=R!mFst-{pTwD7fAuOGlK94$atGY z+~pK1Jk)pBmSgD&+@CzbXS+=3VM|eMNBDKeTDUE!_k|b`@nR0HS${Uwi4D4iqecO? zmEaK#m_KqhA&(F|cdW*?;C)Bf-P3-V;N?ZS$auk(V4FkOC_^Loyz~F&5w1Z!CUB&W zIq8?hC1K0lUv~E|vfw`}3h*eTa9bH3r2zUdu7Muo3N91;Wy1Gc!VaCs@Q9%GrwZ_t z6rt-Pw(AMouHZ>5!N;BaZ3WnB>f8umG9KaA77aYH<1gKb}_qe;k;Yp2TPZ7@!2fKt$t@m>vMbP^i;M1pqq6!tV+_ Ra037U002ovPDHLkV1k0UW?29L literal 0 HcmV?d00001 diff --git a/launcher/resources/multimc/22x22/fabricmc-small.png b/launcher/resources/multimc/22x22/fabricmc-small.png new file mode 100644 index 0000000000000000000000000000000000000000..e21ae9e88b7cfb9b26b3a81725bea57759d63846 GIT binary patch literal 5672 zcmeHLc~}$I79SP?BUnLD+%U$aTA5_BkYpkeksw43QURrk!enLwQL;1{B%&xHqTnu8 zC`B+Xv}#2~ajBG6L=btR2-ar>T(DY;h|6=uC+|)`gs=U+_xZio|D1d`_s+TJ{LZ<* zd+wP`(t?8moEU={5Cl2N17$NoKY(rycHq10XzT z)opBTWdqp&`4-UnT3JIbpw9x$1;}ZAx(&AKW$E{U@sQ4OAsCPC)S>OUz}5-$KY+#q zV^`3h15LfU!*4wp)0czg<7Xf-iX@ovYAS{qAXfxKB5TNE^RB0bOdgwyu=xUji17Fl zL@41QOfD+n3ncR1wjOgV|0rGaNA4LutfQp9rewMiEf-);9?lP+H1mL5E!j&VSewQ-qmM(U`uXFu1& z;+KcR5#VFz{FQ4}R{yi3mR4MqTF3sl_ONHWaruV%UeV(wO=9MTIo6J8Wac&= zbt-QwE1tPE^tSOfH-jDc<{WjcNmSk|6Wvz%&HXxW?hH@YU&FQdo|pw?A!W{Cwd3-t zOyBbwmEV80f9liR2di%7lobAh${raQ=nBm6%%Ky1VkXr$4t1N(>p`exg^xFU5`7ZQ?}e za$VRHJF(byXRq_~Uo4J~U!rTzRX=}WV;X4K>!(zH4RUX;Iy9ULS4@}SIt?2mbV`zK z(&#PQ=~B&p;;|+& znBE3LC7CIk(g^|Xq^uZ<(n~m;`1p8sJfE#IM02<(igFMhhsT3~25elcr7#n$HIAeq zIxu9U5jUvylv<}{(wLZ17e`51EHKY}7oSG2P;|j-jh!q2J~$>!&*8EWjz+`jZegVS z7XgsYfd10L7`j+ba%Pf7U7P_Y{TGp1YGii^0`Icd#~ETR%OP+M8B1z_su6hQ_Hap` z%PtF=f@rlyZ?OVo_t2!&s`q5|h>f1HET?-Qz`P5$hxWU*Ta;1VLc17!~2LkV}$Ek}FVQUi@wlGYo2wl~`=|sAwnxK;a~!5+eu- zV_dNa7Kps~uo5SEFs?+r1ek!Y@ACS2khESIu) zY~;NpI2NN+z(C5HuGYqx-cN+8HDm~d(QI;sVi8X)kjl zVJ+tLwn)HY0I?XIrvShr2Wyd7%Bao|s?)_vSzWccYgz%06M<2f3{-Uh+EuMX-&O1J z2v>r1gipgMbc9;9_`hk>hllA6^ud+~s*RM+u-GE%I8h!YUPx!vX{m!AgQpz&MGD#C#MHgM{rF^#8iVjwiUF=Mud+bXk12 zsotDFZF`48w>k=_>5zf?49Y#HtKN5VMpxFq@#;*sztIDL{^;a``29%NN4h?Ufe%vt zm|Y*~`XB~ANcm%S{om+fynkaPwcv+dJa`{0(WmVKZlaqdcd12kix-L6mS-IT15#HPYnWLZdvrr<{o!Xt+t1APp1g)&_KR)4pI%*`{WVAG7`-uBGsO1i zUHei!Q!eCAe=c9$_d$ajqu0der;xWN(oQXM(k*-Z=yYP!X8oZfd;V~E{o|uo#q8tP zuhm|?Iv)1)6f78jpniFVPd|@kl1i7uPH)Xb>t;n_!|;|Hr;Lb8??RtXb)|*2rDn+G z@z^6N?uSy=Jf|x1RWt8fLkkuEJnhVbo3}qcEUf^JhW!y#WyhE=y!C_9T zl!H>$W_W1Infv-1#c@lbxEX$hKYe>N3*K#&bffn5l3jH*H4p86UuBA}cw7^G?8WHY zp9gNSRb0Woux4l4_^nKQl+Ykv{&=uwZE{6ZYW@&!cgGS(rtQrKiD^|=rj)g8-B6Nn z=Tgn)VRMhik5(35Y_=Nt!wX4N_5dhZW0Q)RBleCs9+84ESYyy{F60+w!AqaFmbD!G z$)Jy9c_dCiFHP_kKeEj#i^>`^s{E$@9Fu20DsbOtmvpJY&95Z9wCs+n%i|#1Hzi9a zUMy(rb3P#8nE2_d+tY^pI+nIZ@4a?Bu&pmE`FacFyu#Sq<9PqLGbvcsA5o zYeF|w-jx;2YHzsoEUn%Uv~qpkm@y&C50nZYX_w43&DhCj^gE4AN6K#+&>i>f=D<$* zYTs>WPTxWM_L;*y7iO|&R4Xo4C(31!l@SAERHUyss?BlUuKdd~bNDLFbqBlRsC7(Z z-xEo%r}j_Zxw9r1k@8nJha3?x&R+iZ9(!K9)1)Tfc{h)(Z(aCIGJ`|p@f`ceY|Gt? zJqC(1p}?qh=2`n$nVdPbdtZ%@uFh@$6zm|l@#t->oA;wwGNz2SS>Z&dQ!)EIlNi-(y3R}rFwY=s8o>LKS)+EIV$-- DtF#j+ literal 0 HcmV?d00001 diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 13052760b..907fbb5d3 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,8 +348,10 @@ scalable/launch.svg scalable/server.svg - scalable/forge-loader.svg - scalable/fabric-loader.svg - scalable/quilt-loader.svg + scalable/instances/forge.svg + scalable/instances/quiltmc.svg + 22x22/fabricmc-small.png + 128x128/instances/fabricmc.png + 128x128/instances/liteloader.png diff --git a/launcher/resources/multimc/scalable/fabric-loader.svg b/launcher/resources/multimc/scalable/fabric-loader.svg deleted file mode 100644 index 06aa7801e..000000000 --- a/launcher/resources/multimc/scalable/fabric-loader.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/forge-loader.svg b/launcher/resources/multimc/scalable/forge-loader.svg deleted file mode 100644 index b73360b86..000000000 --- a/launcher/resources/multimc/scalable/forge-loader.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/launcher/resources/multimc/scalable/instances/forge.svg b/launcher/resources/multimc/scalable/instances/forge.svg new file mode 100644 index 000000000..ea402c5b2 --- /dev/null +++ b/launcher/resources/multimc/scalable/instances/forge.svg @@ -0,0 +1,43 @@ + + diff --git a/launcher/resources/multimc/scalable/instances/quiltmc.svg b/launcher/resources/multimc/scalable/instances/quiltmc.svg new file mode 100644 index 000000000..a7aaca53f --- /dev/null +++ b/launcher/resources/multimc/scalable/instances/quiltmc.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + diff --git a/launcher/resources/multimc/scalable/quilt-loader.svg b/launcher/resources/multimc/scalable/quilt-loader.svg deleted file mode 100644 index fd6faea4b..000000000 --- a/launcher/resources/multimc/scalable/quilt-loader.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 5df27dba2..a9d08fc55 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -42,7 +42,7 @@ class LoaderPage : public VersionSelectWidget, public BasePage { : VersionSelectWidget(parent), m_id(std::move(id)), m_icon(std::move(icon)), m_name(std::move(name)) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); - setEmptyErrorString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); + setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); if (!lightweight) setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); @@ -108,11 +108,11 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q QList InstallLoaderDialog::getPages() { return { // Forge - new LoaderPage("net.minecraftforge", "forge-loader", tr("Forge"), false, m_profile, this), + new LoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), // Fabric - new LoaderPage("net.fabricmc.fabric-loader", "fabric-loader", tr("Fabric"), true, m_profile, this), + new LoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), // Quilt - new LoaderPage("org.quiltmc.quilt-loader", "quilt-loader", tr("Quilt"), true, m_profile, this), + new LoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), // LiteLoader new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) }; From 1f16380efce61fa028d6c25308c8cac7925da72a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 22 Jun 2023 12:56:47 +0100 Subject: [PATCH 065/398] Fix I could use rvalue references and fix my brain fart, but i think regular references are more readable and safer here. Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index a9d08fc55..cc8d7e546 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -32,14 +32,14 @@ class LoaderPage : public VersionSelectWidget, public BasePage { public: - LoaderPage(const QString&& id, - const QString&& icon, - const QString&& name, + LoaderPage(const QString& id, + const QString& icon, + const QString& name, // "lightweight" loaders are independent to any game version const bool lightweight, const std::shared_ptr profile, QWidget* parent = nullptr) - : VersionSelectWidget(parent), m_id(std::move(id)), m_icon(std::move(icon)), m_name(std::move(name)) + : VersionSelectWidget(parent), m_id(id), m_icon(icon), m_name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); From dea33a3c1d3936cc5cfdd0917673af84e94d70de Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 22 Jun 2023 13:11:55 +0100 Subject: [PATCH 066/398] =?UTF-8?q?Make=20`selectedPage`=20const=20?= =?UTF-8?q?=F0=9F=A4=A6=E2=80=8D=E2=99=80=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TheKodeToad --- launcher/ui/InstanceWindow.cpp | 2 +- launcher/ui/InstanceWindow.h | 2 +- launcher/ui/pages/BasePageContainer.h | 2 +- launcher/ui/widgets/PageContainer.cpp | 2 +- launcher/ui/widgets/PageContainer.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index 30a215e33..d784a40fc 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -264,7 +264,7 @@ bool InstanceWindow::selectPage(QString pageId) return m_container->selectPage(pageId); } -BasePage* InstanceWindow::selectedPage() +BasePage* InstanceWindow::selectedPage() const { return m_container->selectedPage(); } diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index adbc46ace..582cff138 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -57,7 +57,7 @@ public: virtual ~InstanceWindow(); bool selectPage(QString pageId) override; - BasePage* selectedPage() override; + BasePage* selectedPage() const override; void refreshContainer() override; QString instanceId(); diff --git a/launcher/ui/pages/BasePageContainer.h b/launcher/ui/pages/BasePageContainer.h index 4cb7fe29c..eb3c94272 100644 --- a/launcher/ui/pages/BasePageContainer.h +++ b/launcher/ui/pages/BasePageContainer.h @@ -7,7 +7,7 @@ class BasePageContainer public: virtual ~BasePageContainer(){}; virtual bool selectPage(QString pageId) = 0; - virtual BasePage* selectedPage() = 0; + virtual BasePage* selectedPage() const = 0; virtual BasePage* getPage(QString pageId) { return nullptr; }; virtual void refreshContainer() = 0; virtual bool requestClose() = 0; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 308fad6b3..7b5b26b74 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -138,7 +138,7 @@ BasePage* PageContainer::getPage(QString pageId) return m_model->findPageEntryById(pageId); } -BasePage* PageContainer::selectedPage() +BasePage* PageContainer::selectedPage() const { return m_currentPage; } diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 1da269ced..bb365c826 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -80,7 +80,7 @@ public: } bool selectPage(QString pageId) override; - BasePage* selectedPage() override; + BasePage* selectedPage() const override; BasePage* getPage(QString pageId) override; const QList getPages() const; From 05d2c1f0b06519eba9cc5ad22848106b49f9bd15 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 22 Jun 2023 18:18:33 +0100 Subject: [PATCH 067/398] Dynamic button text Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 23 ++++++++++++++------- launcher/ui/dialogs/InstallLoaderDialog.h | 3 +++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index cc8d7e546..6e1ad1c04 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -75,7 +75,7 @@ class LoaderPage : public VersionSelectWidget, public BasePage { }; InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, QWidget* parent) - : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)) + : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)), m_buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); @@ -92,17 +92,20 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q }); buttonLayout->addWidget(refreshButton); - auto buttons = new QDialogButtonBox(this); - buttons->setOrientation(Qt::Horizontal); - buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - buttonLayout->addWidget(buttons); + m_buttons->setOrientation(Qt::Horizontal); + m_buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonLayout->addWidget(m_buttons); layout->addLayout(buttonLayout); setWindowTitle(dialogTitle()); resize(650, 400); + + connect(m_container, &PageContainer::selectedPageChanged, this, + [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); + updateAcceptButton(m_container->selectedPage()); } QList InstallLoaderDialog::getPages() @@ -123,6 +126,12 @@ QString InstallLoaderDialog::dialogTitle() return tr("Install Loader"); } +void InstallLoaderDialog::updateAcceptButton(const BasePage* page) +{ + auto installed = !m_profile->getComponentVersion(page->id()).isNull(); + m_buttons->button(QDialogButtonBox::Ok)->setText(installed ? tr("&Update") : tr("&Install")); +} + void InstallLoaderDialog::done(int result) { if (result == Accepted) { diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 7a32e4274..6c8762dc0 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -24,6 +24,7 @@ class MinecraftInstance; class PageContainer; class PackProfile; +class QDialogButtonBox; class InstallLoaderDialog : public QDialog, public BasePageProvider { Q_OBJECT @@ -34,9 +35,11 @@ class InstallLoaderDialog : public QDialog, public BasePageProvider { QList getPages() override; QString dialogTitle() override; + void updateAcceptButton(const BasePage* page); void done(int result) override; private: std::shared_ptr m_profile; PageContainer* m_container; + QDialogButtonBox* m_buttons; }; From 0e7f43592191ecd7946366f2807c89dbaa5d5caf Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 23 Jun 2023 20:56:07 -0700 Subject: [PATCH 068/398] echo to correct var for summary Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a752afb77..fa6f0f61b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -526,7 +526,7 @@ jobs: printf "$GPG_PRIVATE_KEY" | base64 --decode > ~/.gnupg/private.key gpg --import ~/.gnupg/private.key else - echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $env:GITHUB_STEP_SUMMARY + echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY fi ./linuxdeploy-x86_64.AppImage --appdir ${{ env.INSTALL_APPIMAGE_DIR }} --output appimage --plugin qt -i ${{ env.INSTALL_APPIMAGE_DIR }}/usr/share/icons/hicolor/scalable/apps/org.prismlauncher.PrismLauncher.svg From 564e394ec80fed5174a7c42edcd6801ba8c29058 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 21:48:12 +0300 Subject: [PATCH 069/398] feat:Update mods now fills missing dependencies Signed-off-by: Trial97 --- launcher/modplatform/CheckUpdateTask.h | 20 +++++-- .../modplatform/flame/FlameCheckUpdate.cpp | 23 +++---- .../modrinth/ModrinthCheckUpdate.cpp | 23 +++---- launcher/ui/dialogs/ModUpdateDialog.cpp | 60 +++++++++++++++++-- 4 files changed, 94 insertions(+), 32 deletions(-) diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index f7582b8f1..94b16dcc9 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -1,8 +1,9 @@ #pragma once #include "minecraft/mod/Mod.h" -#include "modplatform/ResourceAPI.h" +#include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "tasks/Task.h" class ResourceDownloadTask; @@ -12,8 +13,11 @@ class CheckUpdateTask : public Task { Q_OBJECT public: - CheckUpdateTask(QList& mods, std::list& mcVersions, std::optional loaders, std::shared_ptr mods_folder) - : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder) {}; + CheckUpdateTask(QList& mods, + std::list& mcVersions, + std::optional loaders, + std::shared_ptr mods_folder) + : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){}; struct UpdatableMod { QString name; @@ -25,12 +29,19 @@ class CheckUpdateTask : public Task { shared_qobject_ptr download; public: - UpdatableMod(QString name, QString old_h, QString old_v, QString new_v, QString changelog, ModPlatform::ResourceProvider p, shared_qobject_ptr t) + UpdatableMod(QString name, + QString old_h, + QString old_v, + QString new_v, + QString changelog, + ModPlatform::ResourceProvider p, + shared_qobject_ptr t) : name(name), old_hash(old_h), old_version(old_v), new_version(new_v), changelog(changelog), provider(p), download(t) {} }; auto getUpdatable() -> std::vector&& { return std::move(m_updatable); } + auto getDependencies() -> QList>&& { return std::move(m_deps); } public slots: bool abort() override = 0; @@ -48,4 +59,5 @@ class CheckUpdateTask : public Task { std::shared_ptr m_mods_folder; std::vector m_updatable; + QList> m_deps; }; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index a2628e34c..dd6dd1eac 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -12,6 +12,7 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourceFolderModel.h" +#include "minecraft/mod/tasks/GetModDependenciesTask.h" static FlameAPI api; @@ -154,18 +155,17 @@ void FlameCheckUpdate::executeTask() continue; } + // Fake pack with the necessary info to pass to the download task :) + auto pack = std::make_shared(); + pack->name = mod->name(); + pack->slug = mod->metadata()->slug; + pack->addonId = mod->metadata()->project_id; + pack->websiteUrl = mod->homeurl(); + for (auto& author : mod->authors()) + pack->authors.append({ author }); + pack->description = mod->description(); + pack->provider = ModPlatform::ResourceProvider::FLAME; if (!latest_ver.hash.isEmpty() && (mod->metadata()->hash != latest_ver.hash || mod->status() == ModStatus::NotInstalled)) { - // Fake pack with the necessary info to pass to the download task :) - auto pack = std::make_shared(); - pack->name = mod->name(); - pack->slug = mod->metadata()->slug; - pack->addonId = mod->metadata()->project_id; - pack->websiteUrl = mod->homeurl(); - for (auto& author : mod->authors()) - pack->authors.append({ author }); - pack->description = mod->description(); - pack->provider = ModPlatform::ResourceProvider::FLAME; - auto old_version = mod->version(); if (old_version.isEmpty() && mod->status() != ModStatus::NotInstalled) { auto current_ver = getFileInfo(latest_ver.addonId.toInt(), mod->metadata()->file_id.toInt()); @@ -177,6 +177,7 @@ void FlameCheckUpdate::executeTask() api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), ModPlatform::ResourceProvider::FLAME, download_task); } + m_deps.append(std::make_shared(pack, latest_ver)); } emitSucceeded(); diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index a7c22832a..dac110226 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -145,26 +145,27 @@ void ModrinthCheckUpdate::executeTask() auto mod = *mod_iter; auto key = project_ver.hash; + + // Fake pack with the necessary info to pass to the download task :) + auto pack = std::make_shared(); + pack->name = mod->name(); + pack->slug = mod->metadata()->slug; + pack->addonId = mod->metadata()->project_id; + pack->websiteUrl = mod->homeurl(); + for (auto& author : mod->authors()) + pack->authors.append({ author }); + pack->description = mod->description(); + pack->provider = ModPlatform::ResourceProvider::MODRINTH; if ((key != hash && project_ver.is_preferred) || (mod->status() == ModStatus::NotInstalled)) { if (mod->version() == project_ver.version_number) continue; - // Fake pack with the necessary info to pass to the download task :) - auto pack = std::make_shared(); - pack->name = mod->name(); - pack->slug = mod->metadata()->slug; - pack->addonId = mod->metadata()->project_id; - pack->websiteUrl = mod->homeurl(); - for (auto& author : mod->authors()) - pack->authors.append({ author }); - pack->description = mod->description(); - pack->provider = ModPlatform::ResourceProvider::MODRINTH; - auto download_task = makeShared(pack, project_ver, m_mods_folder); m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task); } + m_deps.append(std::make_shared(pack, project_ver)); } } catch (Json::JsonException& e) { failed(e.cause() + " : " + e.what()); diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 8618b9240..6629b1f23 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -3,6 +3,9 @@ #include "CustomMessageBox.h" #include "ProgressDialog.h" #include "ScrollMessageBox.h" +#include "minecraft/mod/tasks/GetModDependenciesTask.h" +#include "modplatform/ModIndex.h" +#include "modplatform/flame/FlameAPI.h" #include "ui_ReviewMessageBox.h" #include "FileSystem.h" @@ -89,15 +92,17 @@ void ModUpdateDialog::checkCandidates() if (!m_modrinth_to_update.empty()) { m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, m_mod_model)); - connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_modrinth_check_task); } if (!m_flame_to_update.empty()) { m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loaders, m_mod_model)); - connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_flame_check_task); } @@ -124,6 +129,8 @@ void ModUpdateDialog::checkCandidates() return; } + QList> selectedVers; + // Add found updates for Modrinth if (m_modrinth_check_task) { auto modrinth_updates = m_modrinth_check_task->getUpdatable(); @@ -133,6 +140,7 @@ void ModUpdateDialog::checkCandidates() appendMod(updatable); m_tasks.insert(updatable.name, updatable.download); } + selectedVers.append(m_modrinth_check_task->getDependencies()); } // Add found updated for Flame @@ -144,6 +152,7 @@ void ModUpdateDialog::checkCandidates() appendMod(updatable); m_tasks.insert(updatable.name, updatable.download); } + selectedVers.append(m_flame_check_task->getDependencies()); } // Report failed update checking @@ -162,7 +171,7 @@ void ModUpdateDialog::checkCandidates() if (!recover_url.isEmpty()) //: %1 is the link to download it manually text += tr("Possible solution: Getting the latest version manually:
%1
") - .arg(QString("%1").arg(recover_url.toString())); + .arg(QString("%1").arg(recover_url.toString())); text += "
"; } @@ -178,6 +187,45 @@ void ModUpdateDialog::checkCandidates() } } + { // dependencies + auto depTask = makeShared(this, m_instance, m_mod_model.get(), selectedVers); + + connect(depTask.get(), &Task::failed, this, + [&](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); + + connect(depTask.get(), &Task::succeeded, this, [&]() { + QStringList warnings = depTask->warnings(); + if (warnings.count()) { + CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->exec(); + } + }); + + ProgressDialog progress_dialog_deps(m_parent); + progress_dialog_deps.setSkipButton(true, tr("Abort")); + progress_dialog_deps.setWindowTitle(tr("Checking for dependencies...")); + auto dret = progress_dialog_deps.execWithTask(depTask.get()); + + // If the dialog was skipped / some download error happened + if (dret == QDialog::DialogCode::Rejected) { + m_aborted = true; + QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); + return; + } + static FlameAPI api; + + for (auto dep : depTask->getDependecies()) { + auto changelog = dep->version.changelog; + if (dep->pack->provider == ModPlatform::ResourceProvider::FLAME) + changelog = api.getModFileChangelog(dep->version.addonId.toInt(), dep->version.fileId.toInt()); + auto download_task = makeShared(dep->pack, dep->version, m_mod_model); + CheckUpdateTask::UpdatableMod updatable = { dep->pack->name, dep->version.hash, "", dep->version.version, + changelog, dep->pack->provider, download_task }; + + appendMod(updatable); + m_tasks.insert(updatable.name, updatable.download); + } + } + // If there's no mod to be updated if (ui->modTreeWidget->topLevelItemCount() == 0) { m_no_updates = true; @@ -342,7 +390,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R } else { QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") }; - m_failed_metadata.append({mod, reason}); + m_failed_metadata.append({ mod, reason }); } } From 158b07a39e98467c10682a64fa76eb31642abc9e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 00:24:08 +0300 Subject: [PATCH 070/398] moved getRequiredBy Signed-off-by: Trial97 --- .../mod/tasks/GetModDependenciesTask.cpp | 29 +++++++++++++++++++ .../mod/tasks/GetModDependenciesTask.h | 1 + launcher/ui/dialogs/ModUpdateDialog.cpp | 24 +++++++++++++-- launcher/ui/dialogs/ModUpdateDialog.h | 6 ++-- .../ui/dialogs/ResourceDownloadDialog.cpp | 29 +++---------------- 5 files changed, 60 insertions(+), 29 deletions(-) diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index f8ecdb33e..43d38cfdc 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -250,3 +250,32 @@ void GetModDependenciesTask::removePack(const QVariant addonId) ++it; #endif } + +QHash GetModDependenciesTask::getRequiredBy() +{ + QHash rby; + auto fullList = m_selected + m_pack_dependencies; + for (auto mod : fullList) { + auto addonId = mod->pack->addonId; + auto provider = mod->pack->provider; + auto version = mod->version.fileId; + auto req = QStringList(); + for (auto& smod : fullList) { + if (provider != smod->pack->provider) + continue; + auto deps = smod->version.dependencies; + if (auto dep = std::find_if(deps.begin(), deps.end(), + [addonId, provider, version](const ModPlatform::Dependency& d) { + return d.type == ModPlatform::DependencyType::REQUIRED && + (provider == ModPlatform::ResourceProvider::MODRINTH && d.addonId.toString().isEmpty() + ? version == d.version + : d.addonId == addonId); + }); + dep != deps.end()) { + req.append(smod->pack->name); + } + } + rby[addonId.toString()] = req; + } + return rby; +} \ No newline at end of file diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 50eba6afc..5a29b6eae 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -62,6 +62,7 @@ class GetModDependenciesTask : public SequentialTask { QList> selected); auto getDependecies() const -> QList> { return m_pack_dependencies; } + QHash getRequiredBy(); protected slots: Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int); diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 6629b1f23..33ea5a1d5 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -213,6 +213,8 @@ void ModUpdateDialog::checkCandidates() } static FlameAPI api; + auto getRequiredBy = depTask->getRequiredBy(); + for (auto dep : depTask->getDependecies()) { auto changelog = dep->version.changelog; if (dep->pack->provider == ModPlatform::ResourceProvider::FLAME) @@ -221,7 +223,7 @@ void ModUpdateDialog::checkCandidates() CheckUpdateTask::UpdatableMod updatable = { dep->pack->name, dep->version.hash, "", dep->version.version, changelog, dep->pack->provider, download_task }; - appendMod(updatable); + appendMod(updatable, getRequiredBy.value(dep->version.addonId.toString())); m_tasks.insert(updatable.name, updatable.download); } } @@ -394,7 +396,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R } } -void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info) +void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info, QStringList requiredBy) { auto item_top = new QTreeWidgetItem(ui->modTreeWidget); item_top->setCheckState(0, Qt::CheckState::Checked); @@ -410,6 +412,24 @@ void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info) auto new_version_item = new QTreeWidgetItem(item_top); new_version_item->setText(0, tr("New version: %1").arg(info.new_version)); + if (!requiredBy.isEmpty()) { + auto new_version_item = new QTreeWidgetItem(item_top); + new_version_item->setText(0, tr("New version: %1").arg(info.new_version)); + + auto requiredByItem = new QTreeWidgetItem(item_top); + if (requiredBy.length() == 1) { + requiredByItem->setText(0, tr("Required by: %1").arg(requiredBy.back())); + } else { + requiredByItem->setText(0, tr("Required by:")); + auto i = 0; + for (auto req : requiredBy) { + auto reqItem = new QTreeWidgetItem(requiredByItem); + reqItem->setText(0, req); + reqItem->insertChildren(i++, { reqItem }); + } + } + } + auto changelog_item = new QTreeWidgetItem(item_top); changelog_item->setText(0, tr("Changelog of the latest version")); diff --git a/launcher/ui/dialogs/ModUpdateDialog.h b/launcher/ui/dialogs/ModUpdateDialog.h index 1a92f6134..b79aa4943 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.h +++ b/launcher/ui/dialogs/ModUpdateDialog.h @@ -23,7 +23,7 @@ class ModUpdateDialog final : public ReviewMessageBox { void checkCandidates(); - void appendMod(const CheckUpdateTask::UpdatableMod& info); + void appendMod(const CheckUpdateTask::UpdatableMod& info, QStringList requiredBy = {}); const QList getTasks(); auto indexDir() const -> QDir { return m_mod_model->indexDir(); } @@ -36,7 +36,9 @@ class ModUpdateDialog final : public ReviewMessageBox { private slots: void onMetadataEnsured(Mod*); - void onMetadataFailed(Mod*, bool try_others = false, ModPlatform::ResourceProvider first_choice = ModPlatform::ResourceProvider::MODRINTH); + void onMetadataFailed(Mod*, + bool try_others = false, + ModPlatform::ResourceProvider first_choice = ModPlatform::ResourceProvider::MODRINTH); private: QWidget* m_parent; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 4f59f5605..0e579ce60 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -125,35 +125,12 @@ void ResourceDownloadDialog::connectButtons() static ModPlatform::ProviderCapabilities ProviderCaps; -QStringList getRequiredBy(QList tasks, ResourceDownloadDialog::DownloadTaskPtr pack) -{ - auto addonId = pack->getPack()->addonId; - auto provider = pack->getPack()->provider; - auto version = pack->getVersionID(); - auto req = QStringList(); - for (auto& task : tasks) { - if (provider != task->getPack()->provider) - continue; - auto deps = task->getVersion().dependencies; - if (auto dep = std::find_if(deps.begin(), deps.end(), - [addonId, provider, version](const ModPlatform::Dependency& d) { - return d.type == ModPlatform::DependencyType::REQUIRED && - (provider == ModPlatform::ResourceProvider::MODRINTH && d.addonId.toString().isEmpty() - ? version == d.version - : d.addonId == addonId); - }); - dep != deps.end()) { - req.append(task->getName()); - } - } - return req; -} - void ResourceDownloadDialog::confirm() { auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); confirm_dialog->retranslateUi(resourcesString()); + QHash getRequiredBy; if (auto task = getModDependenciesTask(); task) { connect(task.get(), &Task::failed, this, [&](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); @@ -178,6 +155,7 @@ void ResourceDownloadDialog::confirm() } else { for (auto dep : task->getDependecies()) addResource(dep->pack, dep->version); + getRequiredBy = task->getRequiredBy(); } } @@ -187,7 +165,8 @@ void ResourceDownloadDialog::confirm() }); for (auto& task : selected) { confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(), - ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task) }); + ProviderCaps.name(task->getProvider()), + getRequiredBy.value(task->getPack()->addonId.toString()) }); } if (confirm_dialog->exec()) { From 6f7d901a1f5c02e0629e4bae9172c04bb81ce0d9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 09:17:28 +0300 Subject: [PATCH 071/398] removed extra variable Signed-off-by: Trial97 --- launcher/ui/dialogs/ModUpdateDialog.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 33ea5a1d5..66d7e3afa 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -413,9 +413,6 @@ void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info, QStri new_version_item->setText(0, tr("New version: %1").arg(info.new_version)); if (!requiredBy.isEmpty()) { - auto new_version_item = new QTreeWidgetItem(item_top); - new_version_item->setText(0, tr("New version: %1").arg(info.new_version)); - auto requiredByItem = new QTreeWidgetItem(item_top); if (requiredBy.length() == 1) { requiredByItem->setText(0, tr("Required by: %1").arg(requiredBy.back())); From 9c10965997d873b0de56deef5d5ec5e768db1d8f Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:39:04 -0700 Subject: [PATCH 072/398] refactor: split out setting api headers for downloads Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 4 ++ launcher/InstanceImportTask.cpp | 4 +- launcher/ResourceDownloadTask.cpp | 4 +- launcher/meta/BaseEntity.cpp | 4 +- launcher/minecraft/AssetsUtils.cpp | 4 +- launcher/minecraft/Library.cpp | 6 +-- launcher/minecraft/update/AssetUpdateTask.cpp | 4 +- .../minecraft/update/FMLLibrariesTask.cpp | 4 +- .../atlauncher/ATLPackInstallTask.cpp | 12 +++-- .../modplatform/flame/FileResolvingTask.cpp | 5 +- launcher/modplatform/flame/FlameAPI.cpp | 7 +-- .../modplatform/flame/FlameCheckUpdate.cpp | 6 ++- .../flame/FlameInstanceCreationTask.cpp | 4 +- .../helpers/NetworkResourceAPI.cpp | 8 +-- .../modplatform/legacy_ftb/PackFetchTask.cpp | 8 +-- .../legacy_ftb/PackInstallTask.cpp | 4 +- launcher/modplatform/modrinth/ModrinthAPI.cpp | 5 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 5 +- .../technic/SingleZipPackInstallTask.cpp | 4 +- .../technic/SolderPackInstallTask.cpp | 5 +- launcher/net/ApiDownload.h | 39 ++++++++++++++ launcher/net/ApiHeaderProxy.h | 51 +++++++++++++++++++ launcher/net/Download.cpp | 12 ++--- launcher/net/HeaderProxy.h | 49 ++++++++++++++++++ launcher/net/NetAction.h | 9 +++- launcher/net/RawHeaderProxy.h | 44 ++++++++++++++++ .../ui/pages/instance/ManagedPackPage.cpp | 6 ++- .../ui/pages/modplatform/ResourceModel.cpp | 4 +- .../modplatform/atlauncher/AtlListModel.cpp | 6 ++- .../atlauncher/AtlOptionalModDialog.cpp | 4 +- .../ui/pages/modplatform/flame/FlameModel.cpp | 6 ++- .../ui/pages/modplatform/flame/FlamePage.cpp | 4 +- .../modplatform/legacy_ftb/ListModel.cpp | 3 +- .../modplatform/modrinth/ModrinthModel.cpp | 6 ++- .../modplatform/modrinth/ModrinthPage.cpp | 6 ++- .../modplatform/technic/TechnicModel.cpp | 6 ++- .../pages/modplatform/technic/TechnicPage.cpp | 6 ++- .../ui/widgets/VariableSizedImageObject.cpp | 3 +- 38 files changed, 303 insertions(+), 68 deletions(-) create mode 100644 launcher/net/ApiDownload.h create mode 100644 launcher/net/ApiHeaderProxy.h create mode 100644 launcher/net/HeaderProxy.h create mode 100644 launcher/net/RawHeaderProxy.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce2771a49..631564715 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -136,6 +136,10 @@ set(NET_SOURCES net/Validator.h net/Upload.cpp net/Upload.h + net/HeaderProxy.h + net/RawHeaderProxy.h + net/ApiHeaderProxy.h + net/ApiDownload.h ) # Game launch logic diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 352848f02..7332e917f 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -51,6 +51,8 @@ #include "settings/INISettingsObject.h" +#include "net/ApiDownload.h" + #include #include @@ -95,7 +97,7 @@ void InstanceImportTask::executeTask() m_archivePath = entry->getFullPath(); m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network())); - m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry)); + m_filesNetJob->addNetAction(Net::ApiDownload::makeCached(m_sourceUrl, entry)); connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp index 06c03c779..cd4c3fb4b 100644 --- a/launcher/ResourceDownloadTask.cpp +++ b/launcher/ResourceDownloadTask.cpp @@ -24,6 +24,8 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourceFolderModel.h" +#include "net/ApiDownload.h" + ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, @@ -51,7 +53,7 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, } } - m_filesNetJob->addNetAction(Net::Download::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename()))); + m_filesNetJob->addNetAction(Net::ApiDownload::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename()))); connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ResourceDownloadTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &ResourceDownloadTask::downloadProgressChanged); connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propogateStepProgress); diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 97815eba8..fd810a91b 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -15,7 +15,7 @@ #include "BaseEntity.h" -#include "net/Download.h" +#include "net/ApiDownload.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" #include "Json.h" @@ -130,7 +130,7 @@ void Meta::BaseEntity::load(Net::Mode loadType) auto url = this->url(); auto entry = APPLICATION->metacache()->resolveEntry("meta", localFilename()); entry->setStale(true); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); /* * The validator parses the file and loads it into the object. * If that fails, the file is not written to storage. diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp index 16fdfdb1c..65ad6da69 100644 --- a/launcher/minecraft/AssetsUtils.cpp +++ b/launcher/minecraft/AssetsUtils.cpp @@ -45,7 +45,7 @@ #include "AssetsUtils.h" #include "FileSystem.h" -#include "net/Download.h" +#include "net/ApiDownload.h" #include "net/ChecksumValidator.h" #include "BuildConfig.h" @@ -311,7 +311,7 @@ NetAction::Ptr AssetObject::getDownloadAction() QFileInfo objectFile(getLocalPath()); if ((!objectFile.isFile()) || (objectFile.size() != size)) { - auto objectDL = Net::Download::makeFile(getUrl(), objectFile.filePath()); + auto objectDL = Net::ApiDownload::makeFile(getUrl(), objectFile.filePath()); if(hash.size()) { auto rawHash = QByteArray::fromHex(hash.toLatin1()); diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index cb2b5254d..e0318ef22 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -36,7 +36,7 @@ #include "Library.h" #include "MinecraftInstance.h" -#include +#include #include #include #include @@ -129,14 +129,14 @@ QList Library::getDownloads( if(sha1.size()) { auto rawSha1 = QByteArray::fromHex(sha1.toLatin1()); - auto dl = Net::Download::makeCached(url, entry, options); + auto dl = Net::ApiDownload::makeCached(url, entry, options); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); qDebug() << "Checksummed Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; out.append(dl); } else { - out.append(Net::Download::makeCached(url, entry, options)); + out.append(Net::ApiDownload::makeCached(url, entry, options)); qDebug() << "Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; } return true; diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index 31fd5eb11..bafbe75f1 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -7,6 +7,8 @@ #include "Application.h" +#include "net/ApiDownload.h" + AssetUpdateTask::AssetUpdateTask(MinecraftInstance * inst) { m_inst = inst; @@ -34,7 +36,7 @@ void AssetUpdateTask::executeTask() entry->setStale(true); auto hexSha1 = assets->sha1.toLatin1(); qDebug() << "Asset index SHA1:" << hexSha1; - auto dl = Net::Download::makeCached(indexUrl, entry); + auto dl = Net::ApiDownload::makeCached(indexUrl, entry); auto rawSha1 = QByteArray::fromHex(assets->sha1.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); job->addNetAction(dl); diff --git a/launcher/minecraft/update/FMLLibrariesTask.cpp b/launcher/minecraft/update/FMLLibrariesTask.cpp index 75e5c5720..3651f4f40 100644 --- a/launcher/minecraft/update/FMLLibrariesTask.cpp +++ b/launcher/minecraft/update/FMLLibrariesTask.cpp @@ -8,6 +8,8 @@ #include "BuildConfig.h" #include "Application.h" +#include "net/ApiDownload.h" + FMLLibrariesTask::FMLLibrariesTask(MinecraftInstance * inst) { m_inst = inst; @@ -68,7 +70,7 @@ void FMLLibrariesTask::executeTask() { auto entry = metacache->resolveEntry("fmllibs", lib.filename); QString urlString = BuildConfig.FMLLIBS_BASE_URL + lib.filename; - dljob->addNetAction(Net::Download::makeCached(QUrl(urlString), entry, options)); + dljob->addNetAction(Net::ApiDownload::makeCached(QUrl(urlString), entry, options)); } connect(dljob.get(), &NetJob::succeeded, this, &FMLLibrariesTask::fmllibsFinished); diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 07e0bf23b..f763cc029 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -53,6 +53,8 @@ #include "meta/Version.h" #include "meta/VersionList.h" +#include "net/ApiDownload.h" + #include "BuildConfig.h" #include "Application.h" @@ -84,7 +86,7 @@ void PackInstallTask::executeTask() NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) }; auto searchUrl = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json") .arg(m_pack_safe_name).arg(m_version_name); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), &response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); @@ -658,7 +660,7 @@ void PackInstallTask::installConfigs() auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", path); entry->setStale(true); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!m_version.configs.sha1.isEmpty()) { auto rawSha1 = QByteArray::fromHex(m_version.configs.sha1.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); @@ -781,7 +783,7 @@ void PackInstallTask::downloadMods() entry->setStale(true); modsToExtract.insert(entry->getFullPath(), mod); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); @@ -793,7 +795,7 @@ void PackInstallTask::downloadMods() entry->setStale(true); modsToDecomp.insert(entry->getFullPath(), mod); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); @@ -807,7 +809,7 @@ void PackInstallTask::downloadMods() auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", cacheName); entry->setStale(true); - auto dl = Net::Download::makeCached(url, entry); + auto dl = Net::ApiDownload::makeCached(url, entry); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 83db642e7..011c4cdf2 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -2,6 +2,7 @@ #include "Json.h" #include "net/Upload.h" +#include "net/ApiDownload.h" #include "modplatform/modrinth/ModrinthPackIndex.h" @@ -94,7 +95,7 @@ void Flame::FileResolvingTask::netJobFinished() if(!hash.isEmpty()) { auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); auto output = std::make_shared(); - auto dl = Net::Download::makeByteArray(QUrl(url), output.get()); + auto dl = Net::ApiDownload::makeByteArray(QUrl(url), output.get()); QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; }); @@ -169,7 +170,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { auto projectId = mod->projectId; auto output = std::make_shared(); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); - auto dl = Net::Download::makeByteArray(url, output.get()); + auto dl = Net::ApiDownload::makeByteArray(url, output.get()); qDebug() << "Fetching url slug for file:" << mod->fileName; QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 92590a084..49ab06db2 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -9,6 +9,7 @@ #include "BuildConfig.h" #include "Json.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" #include "net/Upload.h" Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, QByteArray* response) @@ -40,7 +41,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString auto netJob = makeShared(QString("Flame::FileChangelog"), APPLICATION->network()); auto response = std::make_shared(); - netJob->addNetAction(Net::Download::makeByteArray( + netJob->addNetAction(Net::ApiDownload::makeByteArray( QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog") .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))), response.get())); @@ -75,7 +76,7 @@ auto FlameAPI::getModDescription(int modId) -> QString auto netJob = makeShared(QString("Flame::ModDescription"), APPLICATION->network()); auto response = std::make_shared(); - netJob->addNetAction(Net::Download::makeByteArray( + netJob->addNetAction(Net::ApiDownload::makeByteArray( QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get())); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { @@ -115,7 +116,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe auto response = std::make_shared(); ModPlatform::IndexedVersion ver; - netJob->addNetAction(Net::Download::makeByteArray(versions_url, response.get())); + netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response.get())); QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] { QJsonParseError parse_error{}; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index e09aeb3d9..c81d13375 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -13,6 +13,8 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourceFolderModel.h" +#include "net/ApiDownload.h" + static FlameAPI api; bool FlameCheckUpdate::abort() @@ -33,7 +35,7 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info) auto response = new QByteArray(); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(ver_info.addonId.toString()); - auto dl = Net::Download::makeByteArray(url, response); + auto dl = Net::ApiDownload::makeByteArray(url, response); get_project_job->addNetAction(dl); QObject::connect(get_project_job, &NetJob::succeeded, [response, &pack]() { @@ -77,7 +79,7 @@ ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId) auto response = new QByteArray(); auto url = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(QString::number(addonId), QString::number(fileId)); - auto dl = Net::Download::makeByteArray(url, response); + auto dl = Net::ApiDownload::makeByteArray(url, response); get_file_info_job->addNetAction(dl); QObject::connect(get_file_info_job, &NetJob::succeeded, [response, &ver]() { diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index dae93d1c6..099e3ae4f 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -60,6 +60,8 @@ #include "minecraft/World.h" #include "minecraft/mod/tasks/LocalResourceParse.h" +#include "net/ApiDownload.h" + const static QMap forgemap = { { "1.2.5", "3.4.9.171" }, { "1.4.2", "6.0.1.355" }, @@ -473,7 +475,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) case Flame::File::Type::Mod: { if (!result.url.isEmpty()) { qDebug() << "Will download" << result.url << "to" << path; - auto dl = Net::Download::makeFile(result.url, path); + auto dl = Net::ApiDownload::makeFile(result.url, path); m_files_job->addNetAction(dl); } break; diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index a3c592fdc..0ff8ac8a4 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -9,6 +9,8 @@ #include "modplatform/ModIndex.h" +#include "net/ApiDownload.h" + Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&& callbacks) const { auto search_url_optional = getSearchURL(args); @@ -22,7 +24,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& auto response = new QByteArray(); auto netJob = makeShared(QString("%1::Search").arg(debugName()), APPLICATION->network()); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(search_url), response)); QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks]{ QJsonParseError parse_error{}; @@ -90,7 +92,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi auto netJob = makeShared(QString("%1::Versions").arg(args.pack.name), APPLICATION->network()); auto response = new QByteArray(); - netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response)); QObject::connect(netJob.get(), &NetJob::succeeded, [response, callbacks, args] { QJsonParseError parse_error{}; @@ -122,7 +124,7 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) auto netJob = makeShared(QString("%1::GetProject").arg(addonId), APPLICATION->network()); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(project_url), response)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp index e8768c5cd..320ddd3e8 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp @@ -40,6 +40,8 @@ #include "BuildConfig.h" #include "Application.h" +#include "net/ApiDownload.h" + namespace LegacyFTB { void PackFetchTask::fetch() @@ -51,11 +53,11 @@ void PackFetchTask::fetch() QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml"); qDebug() << "Downloading public version info from" << publicPacksUrl.toString(); - jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData)); + jobPtr->addNetAction(Net::ApiDownload::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData)); QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml"); qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString(); - jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData)); + jobPtr->addNetAction(Net::ApiDownload::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData)); QObject::connect(jobPtr.get(), &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished); QObject::connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed); @@ -72,7 +74,7 @@ void PackFetchTask::fetchPrivate(const QStringList & toFetch) { QByteArray *data = new QByteArray(); NetJob *job = new NetJob("Fetching private pack", m_network); - job->addNetAction(Net::Download::makeByteArray(privatePackBaseUrl.arg(packCode), data)); + job->addNetAction(Net::ApiDownload::makeByteArray(privatePackBaseUrl.arg(packCode), data)); QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] { diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index 36c142acb..6da8fc882 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -48,6 +48,8 @@ #include "BuildConfig.h" #include "Application.h" +#include "net/ApiDownload.h" + namespace LegacyFTB { PackInstallTask::PackInstallTask(shared_qobject_ptr network, Modpack pack, QString version) @@ -76,7 +78,7 @@ void PackInstallTask::downloadPack() } else { url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(archivePath); } - netJobContainer->addNetAction(Net::Download::makeFile(url, archivePath)); + netJobContainer->addNetAction(Net::ApiDownload::makeFile(url, archivePath)); connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp index 29e3d129d..ab77ef119 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.cpp +++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp @@ -8,12 +8,13 @@ #include "Json.h" #include "net/NetJob.h" #include "net/Upload.h" +#include "net/ApiDownload.h" Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response) { auto netJob = makeShared(QString("Modrinth::GetCurrentVersion"), APPLICATION->network()); - netJob->addNetAction(Net::Download::makeByteArray( + netJob->addNetAction(Net::ApiDownload::makeByteArray( QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); @@ -111,7 +112,7 @@ Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) c auto netJob = makeShared(QString("Modrinth::GetProjects"), APPLICATION->network()); auto searchUrl = getMultipleModInfoURL(addonIds); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response)); QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] { delete response; diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index bb8227aa2..0edd696f7 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -12,6 +12,7 @@ #include "net/ChecksumValidator.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" #include "settings/INISettingsObject.h" #include "ui/dialogs/CustomMessageBox.h" @@ -238,7 +239,7 @@ bool ModrinthCreationTask::createInstance() } qDebug() << "Will try to download" << file.downloads.front() << "to" << file_path; - auto dl = Net::Download::makeFile(file.downloads.dequeue(), file_path); + auto dl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); m_files_job->addNetAction(dl); @@ -247,7 +248,7 @@ bool ModrinthCreationTask::createInstance() // MultipleOptionsTask's , once those exist :) auto param = dl.toWeakRef(); connect(dl.get(), &NetAction::failed, [this, &file, file_path, param] { - auto ndl = Net::Download::makeFile(file.downloads.dequeue(), file_path); + auto ndl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); ndl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); m_files_job->addNetAction(ndl); if (auto shared = param.lock()) shared->succeeded(); diff --git a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp index f07ca24af..21b0defc0 100644 --- a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp +++ b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp @@ -23,6 +23,8 @@ #include "Application.h" +#include "net/ApiDownload.h" + Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion) { m_sourceUrl = sourceUrl; @@ -45,7 +47,7 @@ void Technic::SingleZipPackInstallTask::executeTask() auto entry = APPLICATION->metacache()->resolveEntry("general", path); entry->setStale(true); m_filesNetJob.reset(new NetJob(tr("Modpack download"), APPLICATION->network())); - m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry)); + m_filesNetJob->addNetAction(Net::ApiDownload::makeCached(m_sourceUrl, entry)); m_archivePath = entry->getFullPath(); auto job = m_filesNetJob.get(); connect(job, &NetJob::succeeded, this, &Technic::SingleZipPackInstallTask::downloadSucceeded); diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index c26d6a5a6..0035c8808 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -43,6 +43,7 @@ #include "TechnicPackProcessor.h" #include "SolderPackManifest.h" #include "net/ChecksumValidator.h" +#include "net/ApiDownload.h" Technic::SolderPackInstallTask::SolderPackInstallTask( shared_qobject_ptr network, @@ -72,7 +73,7 @@ void Technic::SolderPackInstallTask::executeTask() m_filesNetJob.reset(new NetJob(tr("Resolving modpack files"), m_network)); auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version); - m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, &m_response)); + m_filesNetJob->addNetAction(Net::ApiDownload::makeByteArray(sourceUrl, &m_response)); auto job = m_filesNetJob.get(); connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded); @@ -113,7 +114,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded() for (const auto &mod : build.mods) { auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i)); - auto dl = Net::Download::makeFile(mod.url, path); + auto dl = Net::ApiDownload::makeFile(mod.url, path); if (!mod.md5.isEmpty()) { auto rawMd5 = QByteArray::fromHex(mod.md5.toLatin1()); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); diff --git a/launcher/net/ApiDownload.h b/launcher/net/ApiDownload.h new file mode 100644 index 000000000..3ffda445a --- /dev/null +++ b/launcher/net/ApiDownload.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "ApiHeaderProxy.h" +#include "Download.h" + +namespace Net { + +class ApiDownload : public Download { + public: + ApiDownload() : Download() + { + auto api_headers = new ApiHeaderProxy(); + addHeaderProxy(api_headers); + } + virtual ~ApiDownload() = default; +}; + +} // namespace Net diff --git a/launcher/net/ApiHeaderProxy.h b/launcher/net/ApiHeaderProxy.h new file mode 100644 index 000000000..0da92a745 --- /dev/null +++ b/launcher/net/ApiHeaderProxy.h @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "Application.h" +#include "BuildConfig.h" +#include "net/HeaderProxy.h" + +namespace Net { + +class ApiHeaderProxy : public HeaderProxy { + public: + ApiHeaderProxy() : HeaderProxy(){}; + virtual ~ApiHeaderProxy() = default; + + public: + virtual QList headers(const QNetworkRequest& request) const override + { + QList hdrs; + if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { + hdrs.append({ "x-api-key", APPLICATION->getFlameAPIKey().toUtf8() }); + } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || + request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { + QString token = APPLICATION->getModrinthAPIToken(); + if (!token.isNull()) + hdrs.append({ "Authorization", token.toUtf8() }); + } + return hdrs; + }; +}; + +} // namespace Net diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 7f8d3a067..6c2173793 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -124,15 +124,11 @@ void Download::executeTask() } request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8()); - // TODO remove duplication - if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { - request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8()); - } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || - request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { - QString token = APPLICATION->getModrinthAPIToken(); - if (!token.isNull()) - request.setRawHeader("Authorization", token.toUtf8()); + for ( auto header_proxy : m_headerProxies ) { + header_proxy->writeHeaders(request); } + // TODO remove duplication + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) request.setTransferTimeout(); diff --git a/launcher/net/HeaderProxy.h b/launcher/net/HeaderProxy.h new file mode 100644 index 000000000..e94579e74 --- /dev/null +++ b/launcher/net/HeaderProxy.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +namespace Net { + +struct HeaderPair { + QByteArray headerName; + QByteArray headerValue; +}; + +class HeaderProxy { + public: + HeaderProxy(){}; + virtual ~HeaderProxy(){}; + + public: + virtual QList headers(const QNetworkRequest& request) const = 0; + + public: + void writeHeaders(QNetworkRequest& request) { + for (auto header : headers(request)) { + request.setRawHeader(header.headerName, header.headerValue); + } + }; +}; + +} // namespace Net diff --git a/launcher/net/NetAction.h b/launcher/net/NetAction.h index ab9322c26..acb0672fc 100644 --- a/launcher/net/NetAction.h +++ b/launcher/net/NetAction.h @@ -42,6 +42,8 @@ #include "QObjectPtr.h" #include "tasks/Task.h" +#include "HeaderProxy.h" + class NetAction : public Task { Q_OBJECT protected: @@ -56,13 +58,16 @@ class NetAction : public Task { void setNetwork(shared_qobject_ptr network) { m_network = network; } + void addHeaderProxy(Net::HeaderProxy* proxy) { m_headerProxies.push_back(std::shared_ptr(proxy)); } + protected slots: virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) = 0; virtual void downloadError(QNetworkReply::NetworkError error) = 0; virtual void downloadFinished() = 0; virtual void downloadReadyRead() = 0; - virtual void sslErrors(const QList& errors) { + virtual void sslErrors(const QList& errors) + { int i = 1; for (auto error : errors) { qCritical() << "Network SSL Error #" << i << " : " << error.errorString(); @@ -70,7 +75,6 @@ class NetAction : public Task { qCritical() << "Certificate in question:\n" << cert.toText(); i++; } - }; public slots: @@ -91,4 +95,5 @@ class NetAction : public Task { /// source URL QUrl m_url; + std::vector> m_headerProxies; }; diff --git a/launcher/net/RawHeaderProxy.h b/launcher/net/RawHeaderProxy.h new file mode 100644 index 000000000..ffe6a81a9 --- /dev/null +++ b/launcher/net/RawHeaderProxy.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "net/HeaderProxy.h" + +namespace Net { + +class ApiHeaderProxy : public HeaderProxy { + public: + ApiHeaderProxy() : HeaderProxy(){}; + virtual ~ApiHeaderProxy() = default; + + public: + virtual QList headers(const QNetworkRequest&) const override { return m_headers; }; + + void addHeader(const HeaderPair& header) { m_headers.append(header); } + void addHeader(const QByteArray& headerName, const QByteArray& headerValue) { m_headers.append({ headerName, headerValue }); } + void addHeaders(const QList& headers) { m_headers.append(headers); } + + private: + QList m_headers; +}; + +} // namespace Net diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index d0701a7ad..68119f06b 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -23,6 +23,8 @@ #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" +#include "net/ApiDownload.h" + /** This is just to override the combo box popup behavior so that the combo box doesn't take the whole screen. * ... thanks Qt. */ @@ -226,7 +228,7 @@ void ModrinthManagedPackPage::parseManagedPack() QString id = m_inst->getManagedPackID(); - m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get())); + m_fetch_job->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get())); QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; @@ -369,7 +371,7 @@ void FlameManagedPackPage::parseManagedPack() QString id = m_inst->getManagedPackID(); - m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get())); + m_fetch_job->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get())); QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 49405a02b..3e0c0257d 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -17,7 +17,7 @@ #include "BuildConfig.h" #include "Json.h" -#include "net/Download.h" +#include "net/ApiDownload.h" #include "net/NetJob.h" #include "modplatform/ModIndex.h" @@ -281,7 +281,7 @@ std::optional ResourceModel::getIcon(QModelIndex& index, const QUrl& url) auto cache_entry = APPLICATION->metacache()->resolveEntry( metaEntryBase(), QString("logos/%1").arg(QString(QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Algorithm::Sha1).toHex()))); - auto icon_fetch_action = Net::Download::makeCached(url, cache_entry); + auto icon_fetch_action = Net::ApiDownload::makeCached(url, cache_entry); auto full_file_path = cache_entry->getFullPath(); connect(icon_fetch_action.get(), &NetAction::succeeded, this, [=] { diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 9ad26f472..e064919eb 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -20,6 +20,8 @@ #include #include +#include "net/ApiDownload.h" + namespace Atl { ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) @@ -88,7 +90,7 @@ void ListModel::request() auto netJob = makeShared("Atl::Request", APPLICATION->network()); auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/json/packsnew.json"); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), &response)); jobPtr = netJob; jobPtr->start(); @@ -184,7 +186,7 @@ void ListModel::requestLogo(QString file, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file.section(".", 0, 0))); NetJob *job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath] diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp index cdb4532c8..edc73345f 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -43,6 +43,8 @@ #include "modplatform/atlauncher/ATLShareCode.h" #include "Application.h" +#include "net/ApiDownload.h" + AtlOptionalModListModel::AtlOptionalModListModel(QWidget* parent, ATLauncher::PackVersion version, QVector mods) : QAbstractListModel(parent) , m_version(version) @@ -152,7 +154,7 @@ Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const { void AtlOptionalModListModel::useShareCode(const QString& code) { m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network())); auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code); - m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), &m_response)); + m_jobPtr->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), &m_response)); connect(m_jobPtr.get(), &NetJob::succeeded, this, &AtlOptionalModListModel::shareCodeSuccess); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index d9d5ef5b3..0a5fd9cea 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -3,6 +3,8 @@ #include "Application.h" #include "ui/widgets/ProjectItem.h" +#include "net/ApiDownload.h" + #include #include @@ -104,7 +106,7 @@ void ListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo.section(".", 0, 0))); auto job = new NetJob(QString("Flame Icon Download %1").arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] { @@ -171,7 +173,7 @@ void ListModel::performPaginatedSearch() .arg(currentSearchTerm) .arg(currentSort + 1); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), &response)); jobPtr = netJob; jobPtr->start(); QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index f9ac4a789..c98e40600 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -46,6 +46,8 @@ #include "ui/widgets/ProjectItem.h" #include "modplatform/flame/FlameAPI.h" +#include "net/ApiDownload.h" + static FlameAPI api; FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog) @@ -132,7 +134,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network()); auto response = new QByteArray(); int addonId = current.addonId; - netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, addonId, curr] { if (addonId != current.addonId) { diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 2343b79f2..c391c1288 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -37,6 +37,7 @@ #include "Application.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" #include "StringUtils.h" #include @@ -254,7 +255,7 @@ void ListModel::requestLogo(QString file) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0))); NetJob *job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::finished, this, [this, file, fullPath] diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 55d287b09..b28845fc3 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -42,6 +42,8 @@ #include "minecraft/PackProfile.h" #include "ui/widgets/ProjectItem.h" +#include "net/ApiDownload.h" + #include namespace Modrinth { @@ -142,7 +144,7 @@ void ModpackListModel::performPaginatedSearch() .arg(currentSearchTerm) .arg(currentSort); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), &m_all_response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchAllUrl), &m_all_response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, [this] { QJsonParseError parse_error_all{}; @@ -235,7 +237,7 @@ void ModpackListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo.section(".", 0, 0))); auto job = new NetJob(QString("%1 Icon Download %2").arg(m_parent->debugName()).arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] { diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 0bb11d834..c450395c3 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -46,6 +46,8 @@ #include "ui/widgets/ProjectItem.h" +#include "net/ApiDownload.h" + #include #include #include @@ -127,7 +129,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) QString id = current.id; - netJob->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("%1/project/%2").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id, curr] { if (id != current.id) { @@ -179,7 +181,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) QString id = current.id; netJob->addNetAction( - Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); + Net::ApiDownload::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id, curr] { if (id != current.id) { diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index 50f0c72d1..0790fb0bc 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -38,6 +38,8 @@ #include "BuildConfig.h" #include "Json.h" +#include "net/ApiDownload.h" + #include Technic::ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) @@ -134,7 +136,7 @@ void Technic::ListModel::performSearch() ).arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm); searchMode = List; } - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), &response)); jobPtr = netJob; jobPtr->start(); QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); @@ -286,7 +288,7 @@ void Technic::ListModel::requestLogo(QString logo, QString url) MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo)); NetJob *job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); + job->addNetAction(Net::ApiDownload::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 859da97e9..5aabcf34f 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -49,6 +49,8 @@ #include "Application.h" #include "modplatform/technic/SolderPackManifest.h" +#include "net/ApiDownload.h" + TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget *parent) : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog) { @@ -143,7 +145,7 @@ void TechnicPage::suggestCurrent() auto netJob = makeShared(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network()); QString slug = current.slug; - netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), &response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug] { jobPtr.reset(); @@ -249,7 +251,7 @@ void TechnicPage::metadataLoaded() auto netJob = makeShared(QString("Technic::SolderMeta(%1)").arg(current.name), APPLICATION->network()); auto url = QString("%1/modpack/%2").arg(current.url, current.slug); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), &response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded); diff --git a/launcher/ui/widgets/VariableSizedImageObject.cpp b/launcher/ui/widgets/VariableSizedImageObject.cpp index 991b4a047..3aa3343d0 100644 --- a/launcher/ui/widgets/VariableSizedImageObject.cpp +++ b/launcher/ui/widgets/VariableSizedImageObject.cpp @@ -26,6 +26,7 @@ #include "Application.h" #include "net/NetJob.h" +#include "net/ApiDownload.h" enum FormatProperties { ImageData = QTextFormat::UserProperty + 1 }; @@ -97,7 +98,7 @@ void VariableSizedImageObject::loadImage(QTextDocument* doc, const QUrl& source, QString("images/%1").arg(QString(QCryptographicHash::hash(source.toEncoded(), QCryptographicHash::Algorithm::Sha1).toHex()))); auto job = new NetJob(QString("Load Image: %1").arg(source.fileName()), APPLICATION->network()); - job->addNetAction(Net::Download::makeCached(source, entry)); + job->addNetAction(Net::ApiDownload::makeCached(source, entry)); auto full_entry_path = entry->getFullPath(); auto source_url = source; From 418677ef310ebde9e2ce6fa98e224b6d4d1aa9f4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 1 Jun 2023 20:15:39 -0700 Subject: [PATCH 073/398] refactor: override / mask static `make` functions for ApiDownload Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 1 + launcher/net/ApiDownload.cpp | 67 +++++++++++++++++++++++ launcher/net/ApiDownload.h | 14 ++--- launcher/net/ApiHeaderProxy.h | 28 +++++----- launcher/net/Download.cpp | 5 +- launcher/net/Download.h | 4 +- launcher/net/HeaderProxy.h | 3 +- launcher/net/NetAction.h | 1 + launcher/net/Upload.h | 1 + launcher/screenshots/ImgurAlbumCreation.h | 2 + launcher/screenshots/ImgurUpload.h | 1 + 11 files changed, 101 insertions(+), 26 deletions(-) create mode 100644 launcher/net/ApiDownload.cpp diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 631564715..1e28591ea 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -140,6 +140,7 @@ set(NET_SOURCES net/RawHeaderProxy.h net/ApiHeaderProxy.h net/ApiDownload.h + net/ApiDownload.cpp ) # Game launch logic diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp new file mode 100644 index 000000000..69b39c4aa --- /dev/null +++ b/launcher/net/ApiDownload.cpp @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "ByteArraySink.h" +#include "ChecksumValidator.h" +#include "MetaCacheSink.h" +#include "net/ApiDownload.h" +#include "net/NetAction.h" + +namespace Net { + +auto ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr +{ + auto dl = makeShared(); + dl->m_url = url; + dl->setObjectName(QString("CACHE:") + url.toString()); + dl->m_options = options; + auto md5Node = new ChecksumValidator(QCryptographicHash::Md5); + auto cachedNode = new MetaCacheSink(entry, md5Node, options.testFlag(Option::MakeEternal)); + dl->m_sink.reset(cachedNode); + return dl; +} + +auto ApiDownload::makeByteArray(QUrl url, QByteArray* output, Options options) -> Download::Ptr +{ + auto dl = makeShared(); + dl->m_url = url; + dl->setObjectName(QString("BYTES:") + url.toString()); + dl->m_options = options; + dl->m_sink.reset(new ByteArraySink(output)); + return dl; +} + +auto ApiDownload::makeFile(QUrl url, QString path, Options options) -> Download::Ptr +{ + auto dl = makeShared(); + dl->m_url = url; + dl->setObjectName(QString("FILE:") + url.toString()); + dl->m_options = options; + dl->m_sink.reset(new FileSink(path)); + return dl; +} + + +void ApiDownload::init() +{ + qDebug() << "Setting up api download"; + auto api_headers = new ApiHeaderProxy(); + addHeaderProxy(api_headers); +} +} // namespace Net diff --git a/launcher/net/ApiDownload.h b/launcher/net/ApiDownload.h index 3ffda445a..7a1f2e92c 100644 --- a/launcher/net/ApiDownload.h +++ b/launcher/net/ApiDownload.h @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2022 flowln - * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> * * This program is free software: you can redistribute it and/or modify @@ -28,12 +26,14 @@ namespace Net { class ApiDownload : public Download { public: - ApiDownload() : Download() - { - auto api_headers = new ApiHeaderProxy(); - addHeaderProxy(api_headers); - } virtual ~ApiDownload() = default; + + static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; + static auto makeByteArray(QUrl url, QByteArray* output, Options options = Option::NoOptions) -> Download::Ptr; + static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; + + void init() override; + }; } // namespace Net diff --git a/launcher/net/ApiHeaderProxy.h b/launcher/net/ApiHeaderProxy.h index 0da92a745..5de503a60 100644 --- a/launcher/net/ApiHeaderProxy.h +++ b/launcher/net/ApiHeaderProxy.h @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2022 flowln - * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> * * This program is free software: you can redistribute it and/or modify @@ -21,9 +19,9 @@ #pragma once +#include "net/HeaderProxy.h" #include "Application.h" #include "BuildConfig.h" -#include "net/HeaderProxy.h" namespace Net { @@ -33,19 +31,19 @@ class ApiHeaderProxy : public HeaderProxy { virtual ~ApiHeaderProxy() = default; public: - virtual QList headers(const QNetworkRequest& request) const override - { - QList hdrs; - if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { - hdrs.append({ "x-api-key", APPLICATION->getFlameAPIKey().toUtf8() }); - } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || - request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { - QString token = APPLICATION->getModrinthAPIToken(); - if (!token.isNull()) - hdrs.append({ "Authorization", token.toUtf8() }); - } - return hdrs; + virtual QList headers(const QNetworkRequest& request) const override { + QList hdrs; + if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { + hdrs.append({ "x-api-key", APPLICATION->getFlameAPIKey().toUtf8() }); + } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || + request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { + QString token = APPLICATION->getModrinthAPIToken(); + if (!token.isNull()) + hdrs.append({ "Authorization", token.toUtf8() }); + } + return hdrs; }; + }; } // namespace Net diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 6c2173793..071a9659a 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -96,6 +96,8 @@ void Download::addValidator(Validator* v) void Download::executeTask() { + init(); + setStatus(tr("Downloading %1").arg(StringUtils::truncateUrlHumanFriendly(m_url, 80))); if (getState() == Task::State::AbortedByUser) { @@ -124,7 +126,8 @@ void Download::executeTask() } request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8()); - for ( auto header_proxy : m_headerProxies ) { + for ( auto& header_proxy : m_headerProxies ) { + header_proxy->writeHeaders(request); } // TODO remove duplication diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 920164a30..fee04febc 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -63,6 +63,8 @@ class Download : public NetAction { static auto makeByteArray(QUrl url, QByteArray* output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; + void init() override {}; + public: void addValidator(Validator* v); auto abort() -> bool override; @@ -81,7 +83,7 @@ class Download : public NetAction { public slots: void executeTask() override; - private: + protected: std::unique_ptr m_sink; Options m_options; diff --git a/launcher/net/HeaderProxy.h b/launcher/net/HeaderProxy.h index e94579e74..bb3c8b039 100644 --- a/launcher/net/HeaderProxy.h +++ b/launcher/net/HeaderProxy.h @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher - * Copyright (c) 2022 flowln - * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> * * This program is free software: you can redistribute it and/or modify @@ -22,6 +20,7 @@ #pragma once #include +#include namespace Net { diff --git a/launcher/net/NetAction.h b/launcher/net/NetAction.h index acb0672fc..93076abce 100644 --- a/launcher/net/NetAction.h +++ b/launcher/net/NetAction.h @@ -59,6 +59,7 @@ class NetAction : public Task { void setNetwork(shared_qobject_ptr network) { m_network = network; } void addHeaderProxy(Net::HeaderProxy* proxy) { m_headerProxies.push_back(std::shared_ptr(proxy)); } + virtual void init() = 0; protected slots: virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) = 0; diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h index e8f0ea40d..484427316 100644 --- a/launcher/net/Upload.h +++ b/launcher/net/Upload.h @@ -51,6 +51,7 @@ namespace Net { static Upload::Ptr makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data); auto abort() -> bool override; auto canAbort() const -> bool override { return true; }; + virtual void init() override {}; protected slots: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; diff --git a/launcher/screenshots/ImgurAlbumCreation.h b/launcher/screenshots/ImgurAlbumCreation.h index 0228b6e4a..a2b70d8b0 100644 --- a/launcher/screenshots/ImgurAlbumCreation.h +++ b/launcher/screenshots/ImgurAlbumCreation.h @@ -57,6 +57,8 @@ public: return m_id; } + void init() override {}; + protected slots: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; diff --git a/launcher/screenshots/ImgurUpload.h b/launcher/screenshots/ImgurUpload.h index 404dc8765..e8a6d8d70 100644 --- a/launcher/screenshots/ImgurUpload.h +++ b/launcher/screenshots/ImgurUpload.h @@ -46,6 +46,7 @@ public: static Ptr make(ScreenShot::Ptr shot) { return Ptr(new ImgurUpload(shot)); } + void init() override {}; protected slots: From 6db906d62378a040e55c35f196d208bed7aebbef Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 1 Jun 2023 20:31:23 -0700 Subject: [PATCH 074/398] chore: format Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/net/ApiDownload.cpp | 3 +-- launcher/net/ApiDownload.h | 1 - launcher/net/ApiHeaderProxy.h | 26 +++++++++++++------------- launcher/net/HeaderProxy.h | 5 +++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp index 69b39c4aa..df476ce8f 100644 --- a/launcher/net/ApiDownload.cpp +++ b/launcher/net/ApiDownload.cpp @@ -17,10 +17,10 @@ * */ +#include "net/ApiDownload.h" #include "ByteArraySink.h" #include "ChecksumValidator.h" #include "MetaCacheSink.h" -#include "net/ApiDownload.h" #include "net/NetAction.h" namespace Net { @@ -57,7 +57,6 @@ auto ApiDownload::makeFile(QUrl url, QString path, Options options) -> Download: return dl; } - void ApiDownload::init() { qDebug() << "Setting up api download"; diff --git a/launcher/net/ApiDownload.h b/launcher/net/ApiDownload.h index 7a1f2e92c..4d0a32923 100644 --- a/launcher/net/ApiDownload.h +++ b/launcher/net/ApiDownload.h @@ -33,7 +33,6 @@ class ApiDownload : public Download { static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; void init() override; - }; } // namespace Net diff --git a/launcher/net/ApiHeaderProxy.h b/launcher/net/ApiHeaderProxy.h index 5de503a60..6fd3e4c19 100644 --- a/launcher/net/ApiHeaderProxy.h +++ b/launcher/net/ApiHeaderProxy.h @@ -19,9 +19,9 @@ #pragma once -#include "net/HeaderProxy.h" #include "Application.h" #include "BuildConfig.h" +#include "net/HeaderProxy.h" namespace Net { @@ -31,19 +31,19 @@ class ApiHeaderProxy : public HeaderProxy { virtual ~ApiHeaderProxy() = default; public: - virtual QList headers(const QNetworkRequest& request) const override { - QList hdrs; - if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { - hdrs.append({ "x-api-key", APPLICATION->getFlameAPIKey().toUtf8() }); - } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || - request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { - QString token = APPLICATION->getModrinthAPIToken(); - if (!token.isNull()) - hdrs.append({ "Authorization", token.toUtf8() }); - } - return hdrs; + virtual QList headers(const QNetworkRequest& request) const override + { + QList hdrs; + if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { + hdrs.append({ "x-api-key", APPLICATION->getFlameAPIKey().toUtf8() }); + } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || + request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { + QString token = APPLICATION->getModrinthAPIToken(); + if (!token.isNull()) + hdrs.append({ "Authorization", token.toUtf8() }); + } + return hdrs; }; - }; } // namespace Net diff --git a/launcher/net/HeaderProxy.h b/launcher/net/HeaderProxy.h index bb3c8b039..308455e48 100644 --- a/launcher/net/HeaderProxy.h +++ b/launcher/net/HeaderProxy.h @@ -19,8 +19,8 @@ #pragma once -#include #include +#include namespace Net { @@ -38,7 +38,8 @@ class HeaderProxy { virtual QList headers(const QNetworkRequest& request) const = 0; public: - void writeHeaders(QNetworkRequest& request) { + void writeHeaders(QNetworkRequest& request) + { for (auto header : headers(request)) { request.setRawHeader(header.headerName, header.headerValue); } From 3105f314cb5cbc6c1e040ceab0f776a0e39849d4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 1 Jun 2023 20:47:03 -0700 Subject: [PATCH 075/398] fix: class rename (lsp acitons undid the first rename :P) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/net/RawHeaderProxy.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/net/RawHeaderProxy.h b/launcher/net/RawHeaderProxy.h index ffe6a81a9..c1aea0a8d 100644 --- a/launcher/net/RawHeaderProxy.h +++ b/launcher/net/RawHeaderProxy.h @@ -25,10 +25,10 @@ namespace Net { -class ApiHeaderProxy : public HeaderProxy { +class RawHeaderProxy : public HeaderProxy { public: - ApiHeaderProxy() : HeaderProxy(){}; - virtual ~ApiHeaderProxy() = default; + RawHeaderProxy() : HeaderProxy(){}; + virtual ~RawHeaderProxy() = default; public: virtual QList headers(const QNetworkRequest&) const override { return m_headers; }; From c8ff812ab89044890d88779e33f3c6f86c4b8f74 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 12:02:46 -0700 Subject: [PATCH 076/398] feat(net): ApiUpload ^& fix unfired `finished` signals Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .../modplatform/flame/FileResolvingTask.cpp | 3 +- launcher/modplatform/flame/FlameAPI.cpp | 7 +- launcher/modplatform/modrinth/ModrinthAPI.cpp | 14 +- launcher/net/ApiUpload.cpp | 43 ++ launcher/net/ApiUpload.h | 36 ++ launcher/net/Download.cpp | 29 +- launcher/net/Upload.cpp | 381 +++++++++--------- launcher/net/Upload.h | 44 +- 8 files changed, 330 insertions(+), 227 deletions(-) create mode 100644 launcher/net/ApiUpload.cpp create mode 100644 launcher/net/ApiUpload.h diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 011c4cdf2..09f0588f6 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -1,6 +1,7 @@ #include "FileResolvingTask.h" #include "Json.h" +#include "net/ApiUpload.h" #include "net/Upload.h" #include "net/ApiDownload.h" @@ -34,7 +35,7 @@ void Flame::FileResolvingTask::executeTask() return l; })); QByteArray data = Json::toText(object); - auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result.get(), data); + auto dl = Net::ApiUpload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result.get(), data); m_dljob->addNetAction(dl); auto step_progress = std::make_shared(); diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 49ab06db2..5a8286d4d 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -8,6 +8,7 @@ #include "Application.h" #include "BuildConfig.h" #include "Json.h" +#include "net/ApiUpload.h" #include "net/NetJob.h" #include "net/ApiDownload.h" #include "net/Upload.h" @@ -27,7 +28,7 @@ Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, QByteArra QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw)); + netJob->addNetAction(Net::ApiUpload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); @@ -176,7 +177,7 @@ Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) cons QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw)); + netJob->addNetAction(Net::ApiUpload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); @@ -199,7 +200,7 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) c QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw)); + netJob->addNetAction(Net::ApiUpload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp index ab77ef119..4089c3661 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.cpp +++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp @@ -6,9 +6,10 @@ #include "Application.h" #include "Json.h" +#include "net/ApiDownload.h" +#include "net/ApiUpload.h" #include "net/NetJob.h" #include "net/Upload.h" -#include "net/ApiDownload.h" Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response) { @@ -34,7 +35,7 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw)); + netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); @@ -65,7 +66,7 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash, QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::Upload::makeByteArray( + netJob->addNetAction(Net::ApiUpload::makeByteArray( QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), response, body_raw)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); @@ -100,7 +101,8 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes, QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw)); + netJob->addNetAction( + Net::ApiUpload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw)); QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); @@ -114,9 +116,7 @@ Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) c netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response)); - QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] { - delete response; - }); + QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] { delete response; }); return netJob; } diff --git a/launcher/net/ApiUpload.cpp b/launcher/net/ApiUpload.cpp new file mode 100644 index 000000000..497573b28 --- /dev/null +++ b/launcher/net/ApiUpload.cpp @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "net/ApiUpload.h" +#include "ByteArraySink.h" +#include "ChecksumValidator.h" +#include "MetaCacheSink.h" +#include "net/NetAction.h" + +namespace Net { + +Upload::Ptr ApiUpload::makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data) +{ + auto up = makeShared(); + up->m_url = std::move(url); + up->m_sink.reset(new ByteArraySink(output)); + up->m_post_data = std::move(m_post_data); + return up; +} + +void ApiUpload::init() +{ + qDebug() << "Setting up api upload"; + auto api_headers = new ApiHeaderProxy(); + addHeaderProxy(api_headers); +} +} // namespace Net diff --git a/launcher/net/ApiUpload.h b/launcher/net/ApiUpload.h new file mode 100644 index 000000000..3aeac99d8 --- /dev/null +++ b/launcher/net/ApiUpload.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "ApiHeaderProxy.h" +#include "Upload.h" + +namespace Net { + +class ApiUpload : public Upload { + public: + virtual ~ApiUpload() = default; + + static Upload::Ptr makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data); + + void init() override; +}; + +} // namespace Net diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 071a9659a..47966da5b 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -46,7 +46,10 @@ #include "ChecksumValidator.h" #include "MetaCacheSink.h" +#if defined(LAUNCHER_APPLICATION) #include "Application.h" +#endif + #include "BuildConfig.h" #include "net/Logging.h" @@ -57,6 +60,7 @@ namespace Net { +#if defined(LAUNCHER_APPLICATION) auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr { auto dl = makeShared(); @@ -68,6 +72,7 @@ auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Down dl->m_sink.reset(cachedNode); return dl; } +#endif auto Download::makeByteArray(QUrl url, QByteArray* output, Options options) -> Download::Ptr { @@ -110,8 +115,8 @@ void Download::executeTask() m_state = m_sink->init(request); switch (m_state) { case State::Succeeded: - emit succeeded(); qCDebug(taskDownloadLogC) << getUid().toString() << "Download cache hit " << m_url.toString(); + emitSucceeded(); return; case State::Running: qCDebug(taskDownloadLogC) << getUid().toString() << "Downloading " << m_url.toString(); @@ -125,7 +130,13 @@ void Download::executeTask() return; } - request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8()); +#if defined (LAUNCHER_APPLICATION) + auto user_agent = APPLICATION->getUserAgent(); +#else + auto user_agent = BuildConfig.USER_AGENT; +#endif + + request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8()); for ( auto& header_proxy : m_headerProxies ) { header_proxy->writeHeaders(request); @@ -162,7 +173,7 @@ void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) auto elapsed_ms = std::chrono::duration_cast(elapsed); auto bytes_received_since = bytesReceived - m_last_progress_bytes; auto dl_speed_bps = (double)bytes_received_since / elapsed_ms.count() * 1000; - auto remaing_time_s = (bytesTotal - bytesReceived) / dl_speed_bps; + auto remaining_time_s = (bytesTotal - bytesReceived) / dl_speed_bps; //: Current amount of bytes downloaded, out of the total amount of bytes in the download QString dl_progress = @@ -170,7 +181,7 @@ void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) QString dl_speed_str; if (elapsed_ms.count() > 0) { - auto str_eta = bytesTotal > 0 ? Time::humanReadableDuration(remaing_time_s) : tr("unknown"); + auto str_eta = bytesTotal > 0 ? Time::humanReadableDuration(remaining_time_s) : tr("unknown"); //: Download speed, in bytes per second (remaining download time in parenthesis) dl_speed_str = tr("%1 /s (%2)").arg(StringUtils::humanReadableFileSize(dl_speed_bps)).arg(str_eta); @@ -282,19 +293,19 @@ void Download::downloadFinished() qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed but we are allowed to proceed:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emit succeeded(); + emitSucceeded(); return; } else if (m_state == State::Failed) { qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emit failed(""); + emitFailed(""); return; } else if (m_state == State::AbortedByUser) { qCDebug(taskDownloadLogC) << getUid().toString() << "Download aborted in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emit aborted(); + emitAborted(); return; } @@ -311,13 +322,13 @@ void Download::downloadFinished() qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed to finalize:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emit failed(""); + emitFailed(""); return; } m_reply.reset(); qCDebug(taskDownloadLogC) << getUid().toString() << "Download succeeded:" << m_url.toString(); - emit succeeded(); + emitSucceeded(); } void Download::downloadReadyRead() diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index 4f9553edf..27759f531 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -39,218 +39,229 @@ #include "Upload.h" #include -#include "ByteArraySink.h" #include "BuildConfig.h" +#include "ByteArraySink.h" + +#if defined(LAUNCHER_APPLICATION) #include "Application.h" +#endif #include "net/Logging.h" namespace Net { - bool Upload::abort() - { - if (m_reply) { - m_reply->abort(); - } else { - m_state = State::AbortedByUser; +bool Upload::abort() +{ + if (m_reply) { + m_reply->abort(); + } else { + m_state = State::AbortedByUser; + } + return true; +} + +void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + setProgress(bytesReceived, bytesTotal); +} + +void Upload::downloadError(QNetworkReply::NetworkError error) +{ + if (error == QNetworkReply::OperationCanceledError) { + qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString(); + m_state = State::AbortedByUser; + } else { + // error happened during download. + qCCritical(taskUploadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; + m_state = State::Failed; + } +} + +void Upload::sslErrors(const QList& errors) +{ + int i = 1; + for (const auto& error : errors) { + qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " + << error.errorString(); + auto cert = error.certificate(); + qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); + i++; + } +} + +bool Upload::handleRedirect() +{ + QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); + if (!redirect.isValid()) { + if (!m_reply->hasRawHeader("Location")) { + // no redirect -> it's fine to continue + return false; } - return true; - } - - void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - setProgress(bytesReceived, bytesTotal); - } - - void Upload::downloadError(QNetworkReply::NetworkError error) { - if (error == QNetworkReply::OperationCanceledError) { - qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString(); - m_state = State::AbortedByUser; - } else { - // error happened during download. - qCCritical(taskUploadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; - m_state = State::Failed; + // there is a Location header, but it's not correct. we need to apply some workarounds... + QByteArray redirectBA = m_reply->rawHeader("Location"); + if (redirectBA.size() == 0) { + // empty, yet present redirect header? WTF? + return false; } - } - - void Upload::sslErrors(const QList &errors) { - int i = 1; - for (const auto& error : errors) { - qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); - auto cert = error.certificate(); - qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); - i++; - } - } - - bool Upload::handleRedirect() - { - QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); - if (!redirect.isValid()) { - if (!m_reply->hasRawHeader("Location")) { - // no redirect -> it's fine to continue - return false; - } - // there is a Location header, but it's not correct. we need to apply some workarounds... - QByteArray redirectBA = m_reply->rawHeader("Location"); - if (redirectBA.size() == 0) { - // empty, yet present redirect header? WTF? - return false; - } - QString redirectStr = QString::fromUtf8(redirectBA); - - if (redirectStr.startsWith("//")) { - /* - * IF the URL begins with //, we need to insert the URL scheme. - * See: https://bugreports.qt.io/browse/QTBUG-41061 - * See: http://tools.ietf.org/html/rfc3986#section-4.2 - */ - redirectStr = m_reply->url().scheme() + ":" + redirectStr; - } else if (redirectStr.startsWith("/")) { - /* - * IF the URL begins with /, we need to process it as a relative URL - */ - auto url = m_reply->url(); - url.setPath(redirectStr, QUrl::TolerantMode); - redirectStr = url.toString(); - } + QString redirectStr = QString::fromUtf8(redirectBA); + if (redirectStr.startsWith("//")) { /* - * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. - * FIXME: report Qt bug for this + * IF the URL begins with //, we need to insert the URL scheme. + * See: https://bugreports.qt.io/browse/QTBUG-41061 + * See: http://tools.ietf.org/html/rfc3986#section-4.2 */ - redirect = QUrl(redirectStr, QUrl::TolerantMode); - if (!redirect.isValid()) { - qCWarning(taskUploadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; - downloadError(QNetworkReply::ProtocolFailure); - return false; - } - qCDebug(taskUploadLogC) << getUid().toString() << "Fixed location header:" << redirect; - } else { - qCDebug(taskUploadLogC) << getUid().toString() << "Location header:" << redirect; + redirectStr = m_reply->url().scheme() + ":" + redirectStr; + } else if (redirectStr.startsWith("/")) { + /* + * IF the URL begins with /, we need to process it as a relative URL + */ + auto url = m_reply->url(); + url.setPath(redirectStr, QUrl::TolerantMode); + redirectStr = url.toString(); } - m_url = QUrl(redirect.toString()); - qCDebug(taskUploadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); - startAction(m_network); - return true; + /* + * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. + * FIXME: report Qt bug for this + */ + redirect = QUrl(redirectStr, QUrl::TolerantMode); + if (!redirect.isValid()) { + qCWarning(taskUploadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; + downloadError(QNetworkReply::ProtocolFailure); + return false; + } + qCDebug(taskUploadLogC) << getUid().toString() << "Fixed location header:" << redirect; + } else { + qCDebug(taskUploadLogC) << getUid().toString() << "Location header:" << redirect; } - void Upload::downloadFinished() { - // handle HTTP redirection first - // very unlikely for post requests, still can happen - if (handleRedirect()) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload redirected:" << m_url.toString(); - return; - } + m_url = QUrl(redirect.toString()); + qCDebug(taskUploadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); + startAction(m_network); + return true; +} - // if the download failed before this point ... - if (m_state == State::Succeeded) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit succeeded(); - return; - } else if (m_state == State::Failed) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - return; - } else if (m_state == State::AbortedByUser) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit aborted(); - return; - } +void Upload::downloadFinished() +{ + // handle HTTP redirection first + // very unlikely for post requests, still can happen + if (handleRedirect()) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload redirected:" << m_url.toString(); + return; + } - // make sure we got all the remaining data, if any - auto data = m_reply->readAll(); - if (data.size()) { - qCDebug(taskUploadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; - m_state = m_sink->write(data); - } - - // otherwise, finalize the whole graph - m_state = m_sink->finalize(*m_reply.get()); - if (m_state != State::Succeeded) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - return; - } + // if the download failed before this point ... + if (m_state == State::Succeeded) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString(); + m_sink->abort(); m_reply.reset(); - qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString(); - emit succeeded(); + emitSucceeded(); + return; + } else if (m_state == State::Failed) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emitFailed(""); + return; + } else if (m_state == State::AbortedByUser) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emitAborted(); + return; } - void Upload::downloadReadyRead() { - if (m_state == State::Running) { - auto data = m_reply->readAll(); - m_state = m_sink->write(data); - } + // make sure we got all the remaining data, if any + auto data = m_reply->readAll(); + if (data.size()) { + qCDebug(taskUploadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; + m_state = m_sink->write(data); } - void Upload::executeTask() { - setStatus(tr("Uploading %1").arg(m_url.toString())); + // otherwise, finalize the whole graph + m_state = m_sink->finalize(*m_reply.get()); + if (m_state != State::Succeeded) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emitFailed(""); + return; + } + m_reply.reset(); + qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString(); + emitSucceeded(); +} - if (m_state == State::AbortedByUser) { - qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString(); - emit aborted(); +void Upload::downloadReadyRead() +{ + if (m_state == State::Running) { + auto data = m_reply->readAll(); + m_state = m_sink->write(data); + } +} + +void Upload::executeTask() +{ + setStatus(tr("Uploading %1").arg(m_url.toString())); + + if (m_state == State::AbortedByUser) { + qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString(); + emitAborted(); + return; + } + QNetworkRequest request(m_url); + m_state = m_sink->init(request); + switch (m_state) { + case State::Succeeded: + emitSucceeded(); + qCDebug(taskUploadLogC) << getUid().toString() << "Upload cache hit " << m_url.toString(); return; - } - QNetworkRequest request(m_url); - m_state = m_sink->init(request); - switch (m_state) { - case State::Succeeded: - emitSucceeded(); - qCDebug(taskUploadLogC) << getUid().toString() << "Upload cache hit " << m_url.toString(); - return; - case State::Running: - qCDebug(taskUploadLogC) << getUid().toString() << "Uploading " << m_url.toString(); - break; - case State::Inactive: - case State::Failed: - emitFailed(""); - return; - case State::AbortedByUser: - emitAborted(); - return; - } + case State::Running: + qCDebug(taskUploadLogC) << getUid().toString() << "Uploading " << m_url.toString(); + break; + case State::Inactive: + case State::Failed: + emitFailed(""); + return; + case State::AbortedByUser: + emitAborted(); + return; + } - request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8()); - // TODO remove duplication - if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { - request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8()); - } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || - request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { - QString token = APPLICATION->getModrinthAPIToken(); - if (!token.isNull()) - request.setRawHeader("Authorization", token.toUtf8()); - } - - //TODO other types of post requests ? - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QNetworkReply* rep = m_network->post(request, m_post_data); - - m_reply.reset(rep); - connect(rep, &QNetworkReply::downloadProgress, this, &Upload::downloadProgress); - connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 - connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError); +#if defined(LAUNCHER_APPLICATION) + auto user_agent = APPLICATION->getUserAgent(); #else - connect(rep, QOverload::of(&QNetworkReply::error), this, &Upload::downloadError); + auto user_agent = BuildConfig.USER_AGENT; #endif - connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors); - connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead); + request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8()); + + for (auto& header_proxy : m_headerProxies) { + header_proxy->writeHeaders(request); } - Upload::Ptr Upload::makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data) { - auto up = makeShared(); - up->m_url = std::move(url); - up->m_sink.reset(new ByteArraySink(output)); - up->m_post_data = std::move(m_post_data); - return up; - } -} // Net + // TODO other types of post requests ? + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + QNetworkReply* rep = m_network->post(request, m_post_data); + + m_reply.reset(rep); + connect(rep, &QNetworkReply::downloadProgress, this, &Upload::downloadProgress); + connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError); +#else + connect(rep, QOverload::of(&QNetworkReply::error), this, &Upload::downloadError); +#endif + connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors); + connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead); +} + +Upload::Ptr Upload::makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data) +{ + auto up = makeShared(); + up->m_url = std::move(url); + up->m_sink.reset(new ByteArraySink(output)); + up->m_post_data = std::move(m_post_data); + return up; +} +} // namespace Net diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h index 484427316..2220c0354 100644 --- a/launcher/net/Upload.h +++ b/launcher/net/Upload.h @@ -42,32 +42,32 @@ namespace Net { - class Upload : public NetAction { - Q_OBJECT +class Upload : public NetAction { + Q_OBJECT - public: - using Ptr = shared_qobject_ptr; + public: + using Ptr = shared_qobject_ptr; - static Upload::Ptr makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data); - auto abort() -> bool override; - auto canAbort() const -> bool override { return true; }; - virtual void init() override {}; + static Upload::Ptr makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data); + auto abort() -> bool override; + auto canAbort() const -> bool override { return true; }; + virtual void init() override{}; - protected slots: - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; - void downloadError(QNetworkReply::NetworkError error) override; - void sslErrors(const QList & errors) override; - void downloadFinished() override; - void downloadReadyRead() override; + protected slots: + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; + void downloadError(QNetworkReply::NetworkError error) override; + void sslErrors(const QList& errors) override; + void downloadFinished() override; + void downloadReadyRead() override; - public slots: - void executeTask() override; - private: - std::unique_ptr m_sink; - QByteArray m_post_data; + public slots: + void executeTask() override; - bool handleRedirect(); - }; + protected: + std::unique_ptr m_sink; + QByteArray m_post_data; -} // Net + bool handleRedirect(); +}; +} // namespace Net From 013a26aafecdd8a9944ad1ec94893d7efe7874ea Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 13:23:43 -0700 Subject: [PATCH 077/398] fix: add `ApiUpload` to CMakeLists.txt Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index f4308caa6..20372dbc3 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -141,6 +141,8 @@ set(NET_SOURCES net/ApiHeaderProxy.h net/ApiDownload.h net/ApiDownload.cpp + net/ApiUpload.cpp + net/ApiUpload.h ) # Game launch logic From 98174b7a377aea8466c6a5fae97ee0db9b2419ae Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:15:25 -0700 Subject: [PATCH 078/398] refactor: use Net tasks for github api download Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 30 ++++++- launcher/net/Download.cpp | 9 +- launcher/net/Download.h | 1 + .../updater/prismupdater/PrismUpdater.cpp | 89 +++++++++---------- launcher/updater/prismupdater/PrismUpdater.h | 17 ++-- 5 files changed, 90 insertions(+), 56 deletions(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 68fd5f7b7..58bd57a87 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -584,6 +584,7 @@ set(PRISMUPDATER_SOURCES updater/prismupdater/UpdaterDialogs.h updater/prismupdater/UpdaterDialogs.cpp updater/prismupdater/GitHubRelease.h + Json.h Json.cpp FileSystem.h @@ -595,6 +596,31 @@ set(PRISMUPDATER_SOURCES Version.h Version.cpp Markdown.h + + # Time + MMCTime.h + MMCTime.cpp + + + net/ByteArraySink.h + net/ChecksumValidator.h + net/Download.cpp + net/Download.h + net/FileSink.cpp + net/FileSink.h + net/HttpMetaCache.cpp + net/HttpMetaCache.h + net/Logging.h + net/Logging.cpp + net/NetAction.h + net/NetJob.cpp + net/NetJob.h + net/NetUtils.h + net/Sink.h + net/Validator.h + net/HeaderProxy.h + net/RawHeaderProxy.h + ) ######## Logging categories ######## @@ -1125,6 +1151,7 @@ endif() add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_link_libraries(Launcher_logic systeminfo Launcher_murmur2 @@ -1202,7 +1229,7 @@ install(TARGETS ${Launcher_Name} if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) # Updater - add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${PRISMUPDATER_UI}) + add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(prism_updater_logic systeminfo @@ -1213,6 +1240,7 @@ if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) Qt${QT_VERSION_MAJOR}::Network ${Launcher_QT_LIBS} cmark::cmark + Katabasis ) add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp) diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index c86452137..de6f43380 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -131,13 +131,12 @@ void Download::executeTask() return; } -#if defined (LAUNCHER_APPLICATION) - auto user_agent = APPLICATION->getUserAgent(); +#if defined(LAUNCHER_APPLICATION) + auto user_agent = APPLICATION->getUserAgent().toUtf8(); #else - auto user_agent = BuildConfig.USER_AGENT; + auto user_agent = BuildConfig.USER_AGENT.toUtf8(); #endif - - request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8()); + request.setHeader(QNetworkRequest::UserAgentHeader, user_agent); for ( auto& header_proxy : m_headerProxies ) { header_proxy->writeHeaders(request); diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 19f675adc..65141a04c 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -59,6 +59,7 @@ class Download : public NetAction { public: ~Download() override = default; + #if defined(LAUNCHER_APPLICATION) static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; static auto makeByteArray(QUrl url, std::shared_ptr output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 923b891f9..0e6620085 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -34,7 +34,9 @@ #include #include +#include #include +#include #include #include @@ -74,6 +76,9 @@ namespace fs = ghc::filesystem; #include "Json.h" #include "StringUtils.h" +#include "net/Download.h" +#include "net/RawHeaderProxy.h" + /** output to the log file */ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) { @@ -205,8 +210,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar } #endif } - m_network = new QNetworkAccessManager(); - + { // setup logging static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; auto moveFile = [](const QString& oldName, const QString& newName) { @@ -292,6 +296,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "<> Log initialized."; } + + { // log debug program info qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater" << ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); @@ -310,7 +316,14 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "<> Paths set."; } - loadReleaseList(); + { // network + m_network = makeShared(new QNetworkAccessManager()); + qDebug() << "Detecting proxy settings..."; + QNetworkProxy proxy = QNetworkProxy::applicationProxy(); + m_network->setProxy(proxy); + } + + QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection); } PrismUpdaterApp::~PrismUpdaterApp() @@ -329,9 +342,6 @@ PrismUpdaterApp::~PrismUpdaterApp() } #endif - m_network->deleteLater(); - if (m_reply) - m_reply->deleteLater(); } void PrismUpdaterApp::fail(const QString& reason) @@ -460,7 +470,7 @@ GitHubRelease PrismUpdaterApp::selectRelease() } else { releases = newerReleases(); } - + if (releases.isEmpty()) return {}; @@ -530,34 +540,40 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) { int per_page = 30; auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page)); - QNetworkRequest request(page_url); - request.setRawHeader("Accept", "application/vnd.github+json"); - request.setRawHeader("X-GitHub-Api-Version", "2022-11-28"); + auto responce = std::make_shared(); + auto download = Net::Download::makeByteArray(page_url, responce.get()); + download->setNetwork(m_network); + m_current_url = page_url; - QNetworkReply* rep = m_network->get(request); - m_reply = rep; - auto responce = new QByteArray(); - - connect(rep, &QNetworkReply::finished, this, [this, responce, per_page, api_url, page]() { - int num_found = parseReleasePage(responce); - delete responce; + auto githup_api_headers = new Net::RawHeaderProxy(); + githup_api_headers->addHeaders({ + { "Accept", "application/vnd.github+json" }, + { "X-GitHub-Api-Version", "2022-11-28" }, + }); + download->addHeaderProxy(githup_api_headers); + connect(download.get(), &Net::Download::succeeded, this, [this, responce, per_page, api_url, page]() { + int num_found = parseReleasePage(responce.get()); if (!(num_found < per_page)) { // there may be more, fetch next page downloadReleasePage(api_url, page + 1); } else { run(); } }); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 - connect(rep, &QNetworkReply::errorOccurred, this, &PrismUpdaterApp::downloadError); -#else - connect(rep, QOverload::of(&QNetworkReply::error), this, &WindowsUpdaterApp::downloadError); -#endif - connect(rep, &QNetworkReply::sslErrors, this, &PrismUpdaterApp::sslErrors); - connect(rep, &QNetworkReply::readyRead, this, [this, responce]() { - auto data = m_reply->readAll(); - responce->append(data); + connect(download.get(), &Net::Download::failed, this, &PrismUpdaterApp::downloadError); + + + m_current_task.reset(download); + connect(download.get(), &Net::Download::finished, this, [this](){ + qDebug() << "Download" << m_current_task->getUid().toString() << "finsihed"; + m_current_task.reset(); + m_current_url = ""; }); + + + QCoreApplication::processEvents(); + + QMetaObject::invokeMethod(download.get(), &Task::start, Qt::QueuedConnection); } int PrismUpdaterApp::parseReleasePage(const QByteArray* responce) @@ -624,24 +640,7 @@ bool PrismUpdaterApp::needUpdate(const GitHubRelease& release) return current_ver < release.version; } -void PrismUpdaterApp::downloadError(QNetworkReply::NetworkError error) +void PrismUpdaterApp::downloadError(QString reason) { - if (error == QNetworkReply::OperationCanceledError) { - abort(QString("Aborted %1").arg(m_reply->url().toString())); - } else { - fail(QString("Network request Failed: %1 with reason %2").arg(m_reply->url().toString()).arg(error)); - } -} - -void PrismUpdaterApp::sslErrors(const QList& errors) -{ - int i = 1; - QString err_msg; - for (auto error : errors) { - err_msg.append(QString("Network request %1 SSL Error %2: %3\n").arg(m_reply->url().toString()).arg(i).arg(error.errorString())); - auto cert = error.certificate(); - err_msg.append(QString("Certificate in question:\n%1").arg(cert.toText())); - i++; - } - fail(err_msg); + fail(QString("Network request Failed: %1 with reason %2").arg(m_current_url).arg(reason)); } diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index da6b4bf71..52bb7e71b 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -36,6 +36,10 @@ #include #include +#include "QObjectPtr.h" +#include "net/Download.h" + + #define PRISM_EXTERNAL_EXE #include "FileSystem.h" @@ -58,7 +62,7 @@ class PrismUpdaterApp : public QApplication { void showFatalErrorMessage(const QString& title, const QString& content); void loadPrismVersionFromExe(const QString& exe_path); - + void downloadReleasePage(const QString& api_url, int page); int parseReleasePage(const QByteArray* responce); GitHubRelease getLatestRelease(); @@ -69,8 +73,10 @@ class PrismUpdaterApp : public QApplication { QList newerReleases(); QList nonDraftReleases(); - void downloadError(QNetworkReply::NetworkError error); - void sslErrors(const QList& errors); + public slots: + void downloadError(QString reason); + + private: const QString& root() { return m_rootPath; } @@ -95,8 +101,9 @@ class PrismUpdaterApp : public QApplication { QString m_prismGitCommit; Status m_status = Status::Starting; - QNetworkAccessManager* m_network; - QNetworkReply* m_reply; + shared_qobject_ptr m_network; + QString m_current_url; + Task::Ptr m_current_task; QList m_releases; public: From bee88b1c7fbba6556e9a3f4a1644556274a0f1cb Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 3 Jun 2023 18:41:54 -0700 Subject: [PATCH 079/398] feat(updater) select valid asset Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 1 + .../updater/prismupdater/GitHubRelease.cpp | 36 +++++ launcher/updater/prismupdater/GitHubRelease.h | 6 + .../updater/prismupdater/PrismUpdater.cpp | 130 +++++++++++++----- launcher/updater/prismupdater/PrismUpdater.h | 18 ++- .../updater/prismupdater/UpdaterDialogs.cpp | 68 +++++++++ .../updater/prismupdater/UpdaterDialogs.h | 20 +++ 7 files changed, 243 insertions(+), 36 deletions(-) create mode 100644 launcher/updater/prismupdater/GitHubRelease.cpp diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 58bd57a87..d9bd577a0 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -584,6 +584,7 @@ set(PRISMUPDATER_SOURCES updater/prismupdater/UpdaterDialogs.h updater/prismupdater/UpdaterDialogs.cpp updater/prismupdater/GitHubRelease.h + updater/prismupdater/GitHubRelease.cpp Json.h Json.cpp diff --git a/launcher/updater/prismupdater/GitHubRelease.cpp b/launcher/updater/prismupdater/GitHubRelease.cpp new file mode 100644 index 000000000..25e60e885 --- /dev/null +++ b/launcher/updater/prismupdater/GitHubRelease.cpp @@ -0,0 +1,36 @@ +#include "GitHubRelease.h" + +QDebug operator<<(QDebug debug, const GitHubReleaseAsset& asset) +{ + QDebugStateSaver saver(debug); + debug.nospace() << "GitHubReleaseAsset( " + "id: " << asset.id << ", " + "name " << asset.name << ", " + "label: " << asset.label << ", " + "content_type: " << asset.content_type << ", " + "size: " << asset.size << ", " + "created_at: " << asset.created_at << ", " + "updated_at: " << asset.updated_at << ", " + "browser_download_url: " << asset.browser_download_url << " " + ")"; + return debug; +} + +QDebug operator<<(QDebug debug, const GitHubRelease& rls) +{ + QDebugStateSaver saver(debug); + debug.nospace() << "GitHubRelease( " + "id: " << rls.id << ", " + "name " << rls.name << ", " + "tag_name: " << rls.tag_name << ", " + "created_at: " << rls.created_at << ", " + "published_at: " << rls.published_at << ", " + "prerelease: " << rls.prerelease << ", " + "draft: " << rls.draft << ", " + "version" << rls.version << ", " + "body: " << rls.body << ", " + "assets: " << rls.assets << " " + ")"; + return debug; +} + diff --git a/launcher/updater/prismupdater/GitHubRelease.h b/launcher/updater/prismupdater/GitHubRelease.h index 1326a69f1..0c190333f 100644 --- a/launcher/updater/prismupdater/GitHubRelease.h +++ b/launcher/updater/prismupdater/GitHubRelease.h @@ -3,6 +3,8 @@ #include #include +#include + #include "Version.h" struct GitHubReleaseAsset { @@ -32,3 +34,7 @@ struct GitHubRelease { bool isValid() const { return id > 0; } }; + +QDebug operator<<(QDebug debug, const GitHubReleaseAsset& rls); +QDebug operator<<(QDebug debug, const GitHubRelease& rls); + diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 0e6620085..70ff1f81d 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -33,8 +33,8 @@ #include #include -#include #include +#include #include #include @@ -128,17 +128,16 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar QCommandLineParser parser; parser.setApplicationDescription(QObject::tr("An auto-updater for Prism Launcher")); - parser.addOptions({ { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory).", "directory" }, - { { "I", "install-version" }, "Install a spesfic version.", "version name" }, - { { "U", "update-url" }, "Update from the spesified repo.", "github repo url" }, - { { "e", "executable" }, "Path to the prismluancher executable.", "path" }, + parser.addOptions({ { { "d", "dir" }, tr("Use a custom path as application root (use '.' for current directory)."), tr("directory") }, + { { "I", "install-version" }, "Install a spesfic version.", tr("version name") }, + { { "U", "update-url" }, tr("Update from the spesified repo."), tr("github repo url") }, { { "c", "check-only" }, - "Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error)." }, - { { "F", "force" }, "Force an update, even if one is not needed." }, - { { "l", "list" }, "List avalible releases." }, - { "debug", "Log debug to console." }, - { { "L", "latest" }, "Update to the latest avalible version." }, - { { "D", "allow-downgrade" }, "Allow the updater to downgrade to previous verisons." } }); + tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") }, + { { "F", "force" }, tr("Force an update, even if one is not needed.") }, + { { "l", "list" }, tr("List avalible releases.") }, + { "debug", tr("Log debug to console.") }, + { { "L", "latest" }, tr("Update to the latest avalible version.") }, + { { "D", "allow-downgrade" }, tr("Allow the updater to downgrade to previous verisons.") } }); parser.addHelpOption(); parser.addVersionOption(); @@ -146,13 +145,25 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar logToConsole = parser.isSet("debug"); - auto prism_executable = parser.value("executable"); - if (prism_executable.isEmpty()) { - prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME; + auto prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME; #if defined(Q_OS_WIN32) - prism_executable += ".exe"; + prism_executable += ".exe"; #endif + + if (BuildConfig.BUILD_PLATFORM.toLower() == "macos") + showFatalErrorMessage(tr("MacOS Not Supported"), tr("The updater does not support instaltions on MacOS")); + + if (!QFileInfo(prism_executable).isFile()) + showFatalErrorMessage(tr("Unsupprted Instaltion"), tr("The updater can not find the main exacutable.")); + + if (prism_executable.startsWith("/tmp/.mount_")) { + m_appimage = true; + m_appimagePath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); + if (m_appimagePath.isEmpty()) + showFatalErrorMessage(tr("Unsupprted Instaltion"), + tr("Updater is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)")); } + m_prismExecutable = prism_executable; auto prism_update_url = parser.value("update-url"); @@ -210,7 +221,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar } #endif } - + { // setup logging static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; auto moveFile = [](const QString& oldName, const QString& newName) { @@ -226,13 +237,13 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar logFile = std::unique_ptr(new QFile(logBase.arg(0))); if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { - showFatalErrorMessage("The launcher data folder is not writable!", - QString("The launcher couldn't create a log file - the data folder is not writable.\n" - "\n" - "Make sure you have write permissions to the data folder.\n" - "(%1)\n" - "\n" - "The launcher cannot continue until you fix this problem.") + showFatalErrorMessage(tr("The launcher data folder is not writable!"), + tr("The launcher couldn't create a log file - the data folder is not writable.\n" + "\n" + "Make sure you have write permissions to the data folder.\n" + "(%1)\n" + "\n" + "The launcher cannot continue until you fix this problem.") .arg(dataPath)); return; } @@ -296,8 +307,6 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "<> Log initialized."; } - - { // log debug program info qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater" << ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); @@ -316,7 +325,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "<> Paths set."; } - { // network + { // network m_network = makeShared(new QNetworkAccessManager()); qDebug() << "Detecting proxy settings..."; QNetworkProxy proxy = QNetworkProxy::applicationProxy(); @@ -341,7 +350,6 @@ PrismUpdaterApp::~PrismUpdaterApp() FreeConsole(); } #endif - } void PrismUpdaterApp::fail(const QString& reason) @@ -477,17 +485,79 @@ GitHubRelease PrismUpdaterApp::selectRelease() SelectReleaseDialog dlg(Version(m_prismVerison), releases); auto result = dlg.exec(); + if (result == QDialog::Rejected) { + return {}; + } GitHubRelease release = dlg.selectedRelease(); + + return release; +} + +QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRelease& release) +{ + QList valid; + + qDebug() << "Selecting best asset from" << release.tag_name << "for platfom" << BuildConfig.BUILD_PLATFORM << "portable:" << m_portable; + if (BuildConfig.BUILD_PLATFORM.isEmpty()) + qWarning() << "Build platform is not set!"; + for (auto asset : release.assets) { + if (!m_appimage && asset.name.toLower().endsWith("appimage")) + continue; + else if (m_appimage && !asset.name.toLower().endsWith("appimage")) + continue; + + bool for_platform = !BuildConfig.BUILD_PLATFORM.isEmpty() && asset.name.toLower().contains(BuildConfig.BUILD_PLATFORM.toLower()); + bool for_portable = asset.name.toLower().contains("portable"); + if (((m_portable && for_portable) || (!m_portable && !for_portable)) && for_platform) { + valid.append(asset); + } + } + return valid; +} + +GitHubReleaseAsset PrismUpdaterApp::selectAsset(const QList& assets) +{ + SelectReleaseAssetDialog dlg(assets); + auto result = dlg.exec(); + if (result == QDialog::Rejected) { return {}; } - return release; + GitHubReleaseAsset asset = dlg.selectedAsset(); + return asset; } void PrismUpdaterApp::performUpdate(const GitHubRelease& release) { qDebug() << "Updating to" << release.tag_name; + auto valid_assets = validReleaseArtifacts(release); + qDebug() << "vallid release assets:" << valid_assets; + + GitHubReleaseAsset selected_asset; + if (valid_assets.isEmpty()) { + showFatalErrorMessage(tr("No Valid Release Assets"), + tr("Github release %1 has no valid assets for this platform: %2") + .arg(release.tag_name) + .arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_PLATFORM).arg(m_portable))); + return; + } else if (valid_assets.length() > 1) { + selected_asset = selectAsset(valid_assets); + } else { + selected_asset = valid_assets.takeFirst(); + } + + if (! selected_asset.isValid()) { + showFatalErrorMessage("No version selected.", "No version was selected."); + return; + } + + qDebug() << "will intall" << selected_asset; +} + +QFileInfo PrismUpdaterApp::downloadAsset(const GitHubReleaseAsset& asset) +{ + // TODO! (researching what to do with appimages) } void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) @@ -562,14 +632,12 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) }); connect(download.get(), &Net::Download::failed, this, &PrismUpdaterApp::downloadError); - m_current_task.reset(download); - connect(download.get(), &Net::Download::finished, this, [this](){ + connect(download.get(), &Net::Download::finished, this, [this]() { qDebug() << "Download" << m_current_task->getUid().toString() << "finsihed"; m_current_task.reset(); m_current_url = ""; }); - QCoreApplication::processEvents(); diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index 52bb7e71b..1a461fcc8 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -39,7 +39,6 @@ #include "QObjectPtr.h" #include "net/Download.h" - #define PRISM_EXTERNAL_EXE #include "FileSystem.h" @@ -65,25 +64,34 @@ class PrismUpdaterApp : public QApplication { void downloadReleasePage(const QString& api_url, int page); int parseReleasePage(const QByteArray* responce); - GitHubRelease getLatestRelease(); + bool needUpdate(const GitHubRelease& release); + + GitHubRelease getLatestRelease(); GitHubRelease selectRelease(); - void performUpdate(const GitHubRelease& release); - void printReleases(); QList newerReleases(); QList nonDraftReleases(); + void printReleases(); + + QList validReleaseArtifacts(const GitHubRelease& release); + GitHubReleaseAsset selectAsset(const QList& assets); + void performUpdate(const GitHubRelease& release); + + QFileInfo downloadAsset(const GitHubReleaseAsset& asset); + public slots: void downloadError(QString reason); private: - const QString& root() { return m_rootPath; } bool isPortable() { return m_portable; } QString m_rootPath; bool m_portable = false; + bool m_appimage = false; + QString m_appimagePath; QString m_prismExecutable; QUrl m_prismRepoUrl; Version m_userSelectedVersion; diff --git a/launcher/updater/prismupdater/UpdaterDialogs.cpp b/launcher/updater/prismupdater/UpdaterDialogs.cpp index 5949194b2..72fdf3404 100644 --- a/launcher/updater/prismupdater/UpdaterDialogs.cpp +++ b/launcher/updater/prismupdater/UpdaterDialogs.cpp @@ -76,3 +76,71 @@ void SelectReleaseDialog::selectionChanged(QTreeWidgetItem* current, QTreeWidget ui->changelogTextBrowser->setHtml(body); } + + +SelectReleaseAssetDialog::SelectReleaseAssetDialog( const QList& assets, QWidget* parent) + : QDialog(parent), m_assets(assets), ui(new Ui::SelectReleaseDialog) +{ + ui->setupUi(this); + + ui->changelogTextBrowser->setOpenExternalLinks(true); + ui->changelogTextBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth); + ui->changelogTextBrowser->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + + ui->versionsTree->setColumnCount(2); + + ui->versionsTree->header()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::Stretch); + ui->versionsTree->setHeaderLabels({tr("Verison"), tr("Published Date")}); + ui->versionsTree->header()->setStretchLastSection(false); + + ui->eplainLabel->setText(tr("Select a version to install.")); + + ui->changelogTextBrowser->setHidden(true); + + loadAssets(); + + connect(ui->versionsTree, &QTreeWidget::currentItemChanged, this, &SelectReleaseAssetDialog::selectionChanged); + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SelectReleaseAssetDialog::accept); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &SelectReleaseAssetDialog::reject); +} + +SelectReleaseAssetDialog::~SelectReleaseAssetDialog() +{ + delete ui; +} + +void SelectReleaseAssetDialog::loadAssets() +{ + for (auto rls : m_assets) { + appendAsset(rls); + } +} + +void SelectReleaseAssetDialog::appendAsset(GitHubReleaseAsset const& asset) +{ + auto rls_item = new QTreeWidgetItem(ui->versionsTree); + rls_item->setText(0, asset.name); + rls_item->setExpanded(true); + rls_item->setText(1, asset.updated_at.toString()); + rls_item->setData(0, Qt::UserRole, QVariant(asset.id)); + + ui->versionsTree->addTopLevelItem(rls_item); +} + +GitHubReleaseAsset SelectReleaseAssetDialog::getAsset(QTreeWidgetItem* item) { + int id = item->data(0, Qt::UserRole).toInt(); + GitHubReleaseAsset selected_asset; + for (auto asset: m_assets) { + if (asset.id == id) + selected_asset = asset; + } + return selected_asset; +} + +void SelectReleaseAssetDialog::selectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous) +{ + GitHubReleaseAsset asset = getAsset(current); + m_selectedAsset = asset; +} diff --git a/launcher/updater/prismupdater/UpdaterDialogs.h b/launcher/updater/prismupdater/UpdaterDialogs.h index 1449befbd..c5e31b5a4 100644 --- a/launcher/updater/prismupdater/UpdaterDialogs.h +++ b/launcher/updater/prismupdater/UpdaterDialogs.h @@ -31,3 +31,23 @@ class SelectReleaseDialog : public QDialog { Ui::SelectReleaseDialog* ui; }; + +class SelectReleaseAssetDialog : public QDialog { + Q_OBJECT + public: + explicit SelectReleaseAssetDialog(const QList& assets, QWidget* parent = 0); + ~SelectReleaseAssetDialog(); + + void loadAssets(); + void appendAsset(GitHubReleaseAsset const& asset); + GitHubReleaseAsset selectedAsset() { return m_selectedAsset; } + private slots: + GitHubReleaseAsset getAsset(QTreeWidgetItem* item); + void selectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous); + + protected: + QList m_assets; + GitHubReleaseAsset m_selectedAsset; + + Ui::SelectReleaseDialog* ui; +}; From 50d5eb0621b0523db175672a511fd711d4018bac Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 4 Jun 2023 20:58:28 -0700 Subject: [PATCH 080/398] feat(updater): download new & back up old Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 2 +- .../updater/prismupdater/PrismUpdater.cpp | 180 +++++++++++++++--- launcher/updater/prismupdater/PrismUpdater.h | 13 +- 3 files changed, 166 insertions(+), 29 deletions(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index d9bd577a0..41a916d12 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1228,7 +1228,7 @@ install(TARGETS ${Launcher_Name} FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime ) -if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) +if(NOT APPLE OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) # Updater add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 70ff1f81d..8df19bf80 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -22,6 +22,7 @@ #include "PrismUpdater.h" #include "BuildConfig.h" +#include "ui/dialogs/ProgressDialog.h" #include #include @@ -136,7 +137,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar { { "F", "force" }, tr("Force an update, even if one is not needed.") }, { { "l", "list" }, tr("List avalible releases.") }, { "debug", tr("Log debug to console.") }, - { { "L", "latest" }, tr("Update to the latest avalible version.") }, + { { "S", "select-ui" }, tr("Select the version to install with a GUI.") }, { { "D", "allow-downgrade" }, tr("Allow the updater to downgrade to previous verisons.") } }); parser.addHelpOption(); @@ -145,10 +146,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar logToConsole = parser.isSet("debug"); - auto prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME; -#if defined(Q_OS_WIN32) - prism_executable += ".exe"; -#endif + auto prism_executable = QCoreApplication::applicationFilePath(); if (BuildConfig.BUILD_PLATFORM.toLower() == "macos") showFatalErrorMessage(tr("MacOS Not Supported"), tr("The updater does not support instaltions on MacOS")); @@ -157,13 +155,15 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar showFatalErrorMessage(tr("Unsupprted Instaltion"), tr("The updater can not find the main exacutable.")); if (prism_executable.startsWith("/tmp/.mount_")) { - m_appimage = true; + m_isAppimage = true; m_appimagePath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); if (m_appimagePath.isEmpty()) showFatalErrorMessage(tr("Unsupprted Instaltion"), tr("Updater is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)")); } + m_isFlatpak = DesktopServices::isFlatpak(); + m_prismExecutable = prism_executable; auto prism_update_url = parser.value("update-url"); @@ -178,7 +178,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar if (!user_version.isEmpty()) { m_userSelectedVersion = Version(user_version); } - m_updateLatest = parser.isSet("latest"); + m_selectUI = parser.isSet("select-ui"); m_allowDowngrade = parser.isSet("allow-downgrade"); QString origcwdPath = QDir::currentPath(); @@ -217,7 +217,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) { dataPath = m_rootPath; adjustedBy = "Portable data path"; - m_portable = true; + m_isPortable = true; } #endif } @@ -411,6 +411,24 @@ void PrismUpdaterApp::run() return exit(0); } + if (m_isFlatpak) { + showFatalErrorMessage(tr("Updating flatpack not supported"), tr("Actions outside of checking if an update is avalible are not " + "supported when running the flatpak verison of Prism Launcher.")); + return; + } + if (m_isAppimage) { + bool result = true; + if (need_update) + result = callAppimageUpdate(); + return exit(result ? 0 : 1); + } + + if (BuildConfig.BUILD_PLATFORM.toLower() == "linux" && !m_isPortable) { + showFatalErrorMessage(tr("Updating Not Supported"), + tr("Updating non-portable linux instalations is not supported. Please use your system package manager")); + return; + } + if (need_update || m_forceUpdate || !m_userSelectedVersion.isEmpty()) { GitHubRelease update_release = latest; if (!m_userSelectedVersion.isEmpty()) { @@ -428,7 +446,7 @@ void PrismUpdaterApp::run() QString("Can not find a github relase for user spesified verison %1").arg(m_userSelectedVersion.toString())); return; } - } else if (!m_updateLatest) { + } else if (m_selectUI) { update_release = selectRelease(); if (!update_release.isValid()) { showFatalErrorMessage("No version selected.", "No version was selected."); @@ -497,18 +515,19 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel { QList valid; - qDebug() << "Selecting best asset from" << release.tag_name << "for platfom" << BuildConfig.BUILD_PLATFORM << "portable:" << m_portable; + qDebug() << "Selecting best asset from" << release.tag_name << "for platfom" << BuildConfig.BUILD_PLATFORM + << "portable:" << m_isPortable; if (BuildConfig.BUILD_PLATFORM.isEmpty()) qWarning() << "Build platform is not set!"; for (auto asset : release.assets) { - if (!m_appimage && asset.name.toLower().endsWith("appimage")) + if (!m_isAppimage && asset.name.toLower().endsWith("appimage")) continue; - else if (m_appimage && !asset.name.toLower().endsWith("appimage")) + else if (m_isAppimage && !asset.name.toLower().endsWith("appimage")) continue; bool for_platform = !BuildConfig.BUILD_PLATFORM.isEmpty() && asset.name.toLower().contains(BuildConfig.BUILD_PLATFORM.toLower()); bool for_portable = asset.name.toLower().contains("portable"); - if (((m_portable && for_portable) || (!m_portable && !for_portable)) && for_platform) { + if (((m_isPortable && for_portable) || (!m_isPortable && !for_portable)) && for_platform) { valid.append(asset); } } @@ -536,35 +555,148 @@ void PrismUpdaterApp::performUpdate(const GitHubRelease& release) GitHubReleaseAsset selected_asset; if (valid_assets.isEmpty()) { - showFatalErrorMessage(tr("No Valid Release Assets"), - tr("Github release %1 has no valid assets for this platform: %2") - .arg(release.tag_name) - .arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_PLATFORM).arg(m_portable))); - return; + return showFatalErrorMessage(tr("No Valid Release Assets"), + tr("Github release %1 has no valid assets for this platform: %2") + .arg(release.tag_name) + .arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_PLATFORM).arg(m_isPortable))); } else if (valid_assets.length() > 1) { selected_asset = selectAsset(valid_assets); } else { selected_asset = valid_assets.takeFirst(); } - if (! selected_asset.isValid()) { - showFatalErrorMessage("No version selected.", "No version was selected."); - return; + if (!selected_asset.isValid()) { + return showFatalErrorMessage(tr("No version selected."), tr("No version was selected.")); } - qDebug() << "will intall" << selected_asset; + qDebug() << "will install" << selected_asset; + auto file = downloadAsset(selected_asset); + + if (!file.exists()) { + return showFatalErrorMessage(tr("Failed to Download"), tr("Failed to download the selected asset.")); + } + + performInstall(file); } QFileInfo PrismUpdaterApp::downloadAsset(const GitHubReleaseAsset& asset) { - // TODO! (researching what to do with appimages) + auto temp_dir = QDir::tempPath(); + auto file_url = QUrl(asset.browser_download_url); + auto out_file_path = FS::PathCombine(temp_dir, file_url.fileName()); + + auto download = Net::Download::makeFile(file_url, out_file_path); + + auto progress_dialog = ProgressDialog(); + + if (progress_dialog.execWithTask(download.get()) == QDialog::Rejected) + showFatalErrorMessage(tr("Download Aborted"), tr("Download of %1 aborted by user").arg(file_url.toString())); + + QFileInfo out_file(out_file_path); + return out_file; +} + +bool PrismUpdaterApp::callAppimageUpdate() +{ + QProcess proc = QProcess(); + proc.setProgram("AppImageUpdate"); + proc.setArguments({ QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")) }); + return proc.startDetached(); +} + +void PrismUpdaterApp::performInstall(QFileInfo file) +{ + // TODO setup marker file + if (m_isPortable) { + unpackAndInstall(file); + } else { + QProcess proc = QProcess(); + proc.setProgram(file.absoluteFilePath()); + bool result = proc.startDetached(); + exit(result ? 0 : 1); + } +} + +void PrismUpdaterApp::unpackAndInstall(QFileInfo to_install_file) +{ + backupAppDir(); + // TODO: uppack (rename access failures) + +} + +void PrismUpdaterApp::backupAppDir() +{ + auto manifest_path = FS::PathCombine(QCoreApplication::applicationDirPath(), "manifest.txt"); + QFileInfo manifest(manifest_path); + + QStringList file_list; + if (manifest.isFile()) { + // load manifest from file + try { + auto contents = QString::fromUtf8(FS::read(manifest.absoluteFilePath())); + file_list.append(contents.split('\n')); + } catch (FS::FileSystemException) { + } + } + + if (file_list.isEmpty()) { + // best guess + if (BuildConfig.BUILD_PLATFORM.toLower() == "linux") { + file_list.append({ "PrismLauncher", "bin/*", "share/*", "lib/*" }); + } else { // windows by process of elimination + file_list.append({ + "jars/*", + "prismlauncher.exe", + "prismlauncher_filelink.exe", + "qtlogging.ini", + "imageformats/*", + "iconengines/*", + "platforms/*", + "styles/*", + "styles/*", + "tls/*", + }); + } + file_list.append("portable.txt"); + qDebug() << "manifest.txt empty or missing. makking best guess at files to back up."; + } + qDebug() << "Backing up" << file_list; + + QDir app_dir = QCoreApplication::applicationDirPath(); + auto backup_dir = FS::PathCombine(app_dir.absolutePath(), QStringLiteral("backup_") + m_prismVerison + ":" + m_prismGitCommit); + FS::ensureFolderPathExists(backup_dir); + + for (auto glob : file_list) { + QDirIterator iter(app_dir.absolutePath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, + QDirIterator::Subdirectories); + while (iter.hasNext()) { + auto to_bak_file = iter.next(); + auto rel_path = app_dir.relativeFilePath(to_bak_file); + auto bak_path = FS::PathCombine(backup_dir, rel_path); + + if (QFileInfo(to_bak_file).isFile()) { + qDebug() << "Backing up and then removing" << to_bak_file; + FS::ensureFilePathExists(bak_path); + auto result = FS::copy(to_bak_file, bak_path)(); + if (!result) { + qWarning() << "Failed to backup" << to_bak_file << "to" << bak_path; + } else { + if (!FS::deletePath(to_bak_file)) + qWarning() << "Failed to remove" << to_bak_file; + } + } + } + } } void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) { QProcess proc = QProcess(); proc.start(exe_path, { "-v" }); - proc.waitForFinished(); + if (!proc.waitForStarted(5000)) // wait 5 seconds to start + return showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read verison.")); + if (!proc.waitForFinished(5000)) + return showFatalErrorMessage(tr("Failed to Check Version"), tr("Child launcher process failed.")); auto out = proc.readAll(); auto lines = out.split('\n'); if (lines.length() < 2) diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index 1a461fcc8..8404969a5 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -77,8 +77,12 @@ class PrismUpdaterApp : public QApplication { QList validReleaseArtifacts(const GitHubRelease& release); GitHubReleaseAsset selectAsset(const QList& assets); void performUpdate(const GitHubRelease& release); + void performInstall(QFileInfo file); + void unpackAndInstall(QFileInfo file); + void backupAppDir(); QFileInfo downloadAsset(const GitHubReleaseAsset& asset); + bool callAppimageUpdate(); public slots: void downloadError(QString reason); @@ -86,11 +90,12 @@ class PrismUpdaterApp : public QApplication { private: const QString& root() { return m_rootPath; } - bool isPortable() { return m_portable; } + bool isPortable() { return m_isPortable; } QString m_rootPath; - bool m_portable = false; - bool m_appimage = false; + bool m_isPortable = false; + bool m_isAppimage = false; + bool m_isFlatpak = false; QString m_appimagePath; QString m_prismExecutable; QUrl m_prismRepoUrl; @@ -98,7 +103,7 @@ class PrismUpdaterApp : public QApplication { bool m_checkOnly; bool m_forceUpdate; bool m_printOnly; - bool m_updateLatest; + bool m_selectUI; bool m_allowDowngrade; QString m_prismBinaryName; From 44bc60021d0e84b9a62e406c4ea69f0257573e3b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:34:23 -0700 Subject: [PATCH 081/398] feat(updater): unpack portable archive Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 5 +- launcher/FileSystem.cpp | 34 ++++ launcher/FileSystem.h | 12 ++ .../updater/prismupdater/PrismUpdater.cpp | 181 ++++++++++++------ launcher/updater/prismupdater/PrismUpdater.h | 12 +- 5 files changed, 186 insertions(+), 58 deletions(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 41a916d12..5cdb0383e 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -597,12 +597,15 @@ set(PRISMUPDATER_SOURCES Version.h Version.cpp Markdown.h + + # Zip + MMCZip.h + MMCZip.cpp # Time MMCTime.h MMCTime.cpp - net/ByteArraySink.h net/ChecksumValidator.h net/Download.cpp diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 835ad925d..2a0ca76b5 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -193,6 +193,40 @@ void write(const QString& filename, const QByteArray& data) } } +void appendSafe(const QString& filename, const QByteArray& data) +{ + ensureExists(QFileInfo(filename).dir()); + QByteArray buffer; + try { + buffer = read(filename); + } catch (FileSystemException) { + buffer = QByteArray(); + } + buffer.append(data); + QSaveFile file(filename); + if (!file.open(QSaveFile::WriteOnly)) { + throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString()); + } + if (buffer.size() != file.write(buffer)) { + throw FileSystemException("Error writing data to " + filename + ": " + file.errorString()); + } + if (!file.commit()) { + throw FileSystemException("Error while committing data to " + filename + ": " + file.errorString()); + } +} + +void append(const QString& filename, const QByteArray& data) +{ + ensureExists(QFileInfo(filename).dir()); + QFile file(filename); + if (!file.open(QFile::Append)) { + throw FileSystemException("Couldn't open " + filename + " for writing: " + file.errorString()); + } + if (data.size() != file.write(data)) { + throw FileSystemException("Error writing data to " + filename + ": " + file.errorString()); + } +} + QByteArray read(const QString& filename) { QFile file(filename); diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index cb581d0c5..ca26c1ee7 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -60,6 +60,18 @@ class FileSystemException : public ::Exception { */ void write(const QString& filename, const QByteArray& data); + +/** + * append data to a file safely + */ +void appendSafe(const QString& filename, const QByteArray& data); + +/** + * append data to a file + */ +void append(const QString& filename, const QByteArray& data); + + /** * read data from a file safely\ */ diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 8df19bf80..001ecb10c 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -80,6 +80,8 @@ namespace fs = ghc::filesystem; #include "net/Download.h" #include "net/RawHeaderProxy.h" +#include + /** output to the log file */ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) { @@ -103,14 +105,16 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar #if defined Q_OS_WIN32 // attach the parent console if (AttachConsole(ATTACH_PARENT_PROCESS)) { + FILE* _stream; + errno_t err; // if attach succeeds, reopen and sync all the i/o - if (freopen("CON", "w", stdout)) { + if (err = freopen_s(&_stream, "CON", "w", stdout); err == 0) { std::cout.sync_with_stdio(); } - if (freopen("CON", "w", stderr)) { + if (err = freopen_s(&_stream, "CON", "w", stderr); err == 0) { std::cerr.sync_with_stdio(); } - if (freopen("CON", "r", stdin)) { + if (err = freopen_s(&_stream, "CON", "r", stdin); err == 0) { std::cin.sync_with_stdio(); } auto out = GetStdHandle(STD_OUTPUT_HANDLE); @@ -125,20 +129,20 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar setApplicationName(BuildConfig.LAUNCHER_NAME + "Updater"); setApplicationVersion(BuildConfig.printableVersionString() + "\n" + BuildConfig.GIT_COMMIT); - // Commandline parsing + // Command line parsing QCommandLineParser parser; parser.setApplicationDescription(QObject::tr("An auto-updater for Prism Launcher")); parser.addOptions({ { { "d", "dir" }, tr("Use a custom path as application root (use '.' for current directory)."), tr("directory") }, - { { "I", "install-version" }, "Install a spesfic version.", tr("version name") }, - { { "U", "update-url" }, tr("Update from the spesified repo."), tr("github repo url") }, + { { "I", "install-version" }, "Install a specific version.", tr("version name") }, + { { "U", "update-url" }, tr("Update from the specified repo."), tr("github repo url") }, { { "c", "check-only" }, tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") }, { { "F", "force" }, tr("Force an update, even if one is not needed.") }, - { { "l", "list" }, tr("List avalible releases.") }, + { { "l", "list" }, tr("List available releases.") }, { "debug", tr("Log debug to console.") }, { { "S", "select-ui" }, tr("Select the version to install with a GUI.") }, - { { "D", "allow-downgrade" }, tr("Allow the updater to downgrade to previous verisons.") } }); + { { "D", "allow-downgrade" }, tr("Allow the updater to downgrade to previous versions.") } }); parser.addHelpOption(); parser.addVersionOption(); @@ -149,16 +153,16 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar auto prism_executable = QCoreApplication::applicationFilePath(); if (BuildConfig.BUILD_PLATFORM.toLower() == "macos") - showFatalErrorMessage(tr("MacOS Not Supported"), tr("The updater does not support instaltions on MacOS")); + showFatalErrorMessage(tr("MacOS Not Supported"), tr("The updater does not support installations on MacOS")); if (!QFileInfo(prism_executable).isFile()) - showFatalErrorMessage(tr("Unsupprted Instaltion"), tr("The updater can not find the main exacutable.")); + showFatalErrorMessage(tr("Unsupported Installation"), tr("The updater can not find the main executable.")); if (prism_executable.startsWith("/tmp/.mount_")) { m_isAppimage = true; m_appimagePath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); if (m_appimagePath.isEmpty()) - showFatalErrorMessage(tr("Unsupprted Instaltion"), + showFatalErrorMessage(tr("Unsupported Installation"), tr("Updater is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)")); } @@ -181,7 +185,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_selectUI = parser.isSet("select-ui"); m_allowDowngrade = parser.isSet("allow-downgrade"); - QString origcwdPath = QDir::currentPath(); + QString origCwdPath = QDir::currentPath(); QString binPath = applicationDirPath(); { // find data director @@ -200,22 +204,21 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar } QString adjustedBy; - QString dataPath; // change folder QString dirParam = parser.value("dir"); if (!dirParam.isEmpty()) { - // the dir param. it makes multimc data path point to whatever the user specified + // the dir param. it makes prism launcher data path point to whatever the user specified // on command line adjustedBy = "Command line"; - dataPath = dirParam; + m_dataPath = dirParam; } else { QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); - dataPath = foo.absolutePath(); + m_dataPath = foo.absolutePath(); adjustedBy = "Persistent data path"; #ifndef Q_OS_MACOS if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) { - dataPath = m_rootPath; + m_dataPath = m_rootPath; adjustedBy = "Portable data path"; m_isPortable = true; } @@ -230,8 +233,6 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar QFile::remove(oldName); }; - moveFile(logBase.arg(3), logBase.arg(4)); - moveFile(logBase.arg(2), logBase.arg(3)); moveFile(logBase.arg(1), logBase.arg(2)); moveFile(logBase.arg(0), logBase.arg(1)); @@ -244,7 +245,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar "(%1)\n" "\n" "The launcher cannot continue until you fix this problem.") - .arg(dataPath)); + .arg(m_dataPath)); return; } qInstallMessageHandler(appDebugOutput); @@ -266,7 +267,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar bool foundLoggingRules = false; auto logRulesFile = QStringLiteral("qtlogging.ini"); - auto logRulesPath = FS::PathCombine(dataPath, logRulesFile); + auto logRulesPath = FS::PathCombine(m_dataPath, logRulesFile); qDebug() << "Testing" << logRulesPath << "..."; foundLoggingRules = QFile::exists(logRulesPath); @@ -314,7 +315,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; if (adjustedBy.size()) { - qDebug() << "Work dir before adjustment : " << origcwdPath; + qDebug() << "Work dir before adjustment : " << origCwdPath; qDebug() << "Work dir after adjustment : " << QDir::currentPath(); qDebug() << "Adjusted by : " << adjustedBy; } else { @@ -394,7 +395,7 @@ void PrismUpdaterApp::run() loadPrismVersionFromExe(m_prismExecutable); m_status = Succeeded; - qDebug() << "Executable reports as:" << m_prismBinaryName << "version:" << m_prismVerison; + qDebug() << "Executable reports as:" << m_prismBinaryName << "version:" << m_prismVersion; qDebug() << "Version major:" << m_prismVersionMajor; qDebug() << "Verison minor:" << m_prismVersionMinor; qDebug() << "Verison channel:" << m_prsimVersionChannel; @@ -412,8 +413,8 @@ void PrismUpdaterApp::run() } if (m_isFlatpak) { - showFatalErrorMessage(tr("Updating flatpack not supported"), tr("Actions outside of checking if an update is avalible are not " - "supported when running the flatpak verison of Prism Launcher.")); + showFatalErrorMessage(tr("Updating flatpack not supported"), tr("Actions outside of checking if an update is available are not " + "supported when running the flatpak version of Prism Launcher.")); return; } if (m_isAppimage) { @@ -425,7 +426,7 @@ void PrismUpdaterApp::run() if (BuildConfig.BUILD_PLATFORM.toLower() == "linux" && !m_isPortable) { showFatalErrorMessage(tr("Updating Not Supported"), - tr("Updating non-portable linux instalations is not supported. Please use your system package manager")); + tr("Updating non-portable linux installations is not supported. Please use your system package manager")); return; } @@ -443,7 +444,7 @@ void PrismUpdaterApp::run() if (!found) { showFatalErrorMessage( "No release for version!", - QString("Can not find a github relase for user spesified verison %1").arg(m_userSelectedVersion.toString())); + QString("Can not find a github release for specified version %1").arg(m_userSelectedVersion.toString())); return; } } else if (m_selectUI) { @@ -481,7 +482,7 @@ QList PrismUpdaterApp::newerReleases() { QList newer; for (auto rls : nonDraftReleases()) { - if (rls.version > m_prismVerison) + if (rls.version > m_prismVersion) newer.append(rls); } return newer; @@ -500,7 +501,7 @@ GitHubRelease PrismUpdaterApp::selectRelease() if (releases.isEmpty()) return {}; - SelectReleaseDialog dlg(Version(m_prismVerison), releases); + SelectReleaseDialog dlg(Version(m_prismVersion), releases); auto result = dlg.exec(); if (result == QDialog::Rejected) { @@ -515,7 +516,7 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel { QList valid; - qDebug() << "Selecting best asset from" << release.tag_name << "for platfom" << BuildConfig.BUILD_PLATFORM + qDebug() << "Selecting best asset from" << release.tag_name << "for platform" << BuildConfig.BUILD_PLATFORM << "portable:" << m_isPortable; if (BuildConfig.BUILD_PLATFORM.isEmpty()) qWarning() << "Build platform is not set!"; @@ -549,9 +550,10 @@ GitHubReleaseAsset PrismUpdaterApp::selectAsset(const QList& void PrismUpdaterApp::performUpdate(const GitHubRelease& release) { + m_install_release = release; qDebug() << "Updating to" << release.tag_name; auto valid_assets = validReleaseArtifacts(release); - qDebug() << "vallid release assets:" << valid_assets; + qDebug() << "valid release assets:" << valid_assets; GitHubReleaseAsset selected_asset; if (valid_assets.isEmpty()) { @@ -604,12 +606,32 @@ bool PrismUpdaterApp::callAppimageUpdate() return proc.startDetached(); } +void PrismUpdaterApp::clearUpdateLog() +{ + auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); + QFile::remove(update_log_path); +} + +void PrismUpdaterApp::logUpdate(const QString& msg) +{ + qDebug() << msg; + auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); + FS::append(update_log_path, QStringLiteral("%1\n").arg(msg).toUtf8()); +} + void PrismUpdaterApp::performInstall(QFileInfo file) { + auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"); + FS::write(update_lock_path, QStringLiteral("FROM=%1\nTO=%2\n").arg(m_prismVersion).arg(m_install_release.tag_name).toUtf8()); + clearUpdateLog(); + + logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name)); // TODO setup marker file if (m_isPortable) { + logUpdate(tr("Updating portable install at %1").arg(applicationDirPath())); unpackAndInstall(file); } else { + logUpdate(tr("Running installer file at %1").arg(file.absoluteFilePath())); QProcess proc = QProcess(); proc.setProgram(file.absoluteFilePath()); bool result = proc.startDetached(); @@ -617,21 +639,24 @@ void PrismUpdaterApp::performInstall(QFileInfo file) } } -void PrismUpdaterApp::unpackAndInstall(QFileInfo to_install_file) +void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) { + logUpdate(tr("Backing up install")); backupAppDir(); - // TODO: uppack (rename access failures) - + auto loc = unpackArchive(archive); + // TODO: unpack (rename access failures) } void PrismUpdaterApp::backupAppDir() { - auto manifest_path = FS::PathCombine(QCoreApplication::applicationDirPath(), "manifest.txt"); + auto manifest_path = FS::PathCombine(applicationDirPath(), "manifest.txt"); QFileInfo manifest(manifest_path); QStringList file_list; if (manifest.isFile()) { // load manifest from file + + logUpdate(tr("Reading manifest from %1").arg(manifest.absoluteFilePath())); try { auto contents = QString::fromUtf8(FS::read(manifest.absoluteFilePath())); file_list.append(contents.split('\n')); @@ -658,12 +683,12 @@ void PrismUpdaterApp::backupAppDir() }); } file_list.append("portable.txt"); - qDebug() << "manifest.txt empty or missing. makking best guess at files to back up."; + logUpdate("manifest.txt empty or missing. making best guess at files to back up."); } - qDebug() << "Backing up" << file_list; + logUpdate(tr("Backing up:\n %1").arg(file_list.join(",\n "))); QDir app_dir = QCoreApplication::applicationDirPath(); - auto backup_dir = FS::PathCombine(app_dir.absolutePath(), QStringLiteral("backup_") + m_prismVerison + ":" + m_prismGitCommit); + auto backup_dir = FS::PathCombine(app_dir.absolutePath(), QStringLiteral("backup_") + m_prismVersion + ":" + m_prismGitCommit); FS::ensureFolderPathExists(backup_dir); for (auto glob : file_list) { @@ -675,26 +700,72 @@ void PrismUpdaterApp::backupAppDir() auto bak_path = FS::PathCombine(backup_dir, rel_path); if (QFileInfo(to_bak_file).isFile()) { - qDebug() << "Backing up and then removing" << to_bak_file; + logUpdate(tr("Backing up and then removing %1").arg(to_bak_file)); FS::ensureFilePathExists(bak_path); auto result = FS::copy(to_bak_file, bak_path)(); if (!result) { - qWarning() << "Failed to backup" << to_bak_file << "to" << bak_path; + logUpdate(tr("Failed to backup %1 to %2").arg(to_bak_file).arg(bak_path)); } else { if (!FS::deletePath(to_bak_file)) - qWarning() << "Failed to remove" << to_bak_file; + logUpdate(tr("Failed to remove %1").arg(to_bak_file)); } } } } } +std::optional PrismUpdaterApp::unpackArchive(QFileInfo archive) +{ + auto temp_extract_path = FS::PathCombine(m_dataPath, "prism_launcher_update_release"); + FS::ensureFolderPathExists(temp_extract_path); + auto tmp_extract_dir = QDir(temp_extract_path); + + if (archive.fileName().endsWith(".zip")) { + auto result = MMCZip::extractDir(archive.absoluteFilePath(), tmp_extract_dir.absolutePath()); + if (result) { + logUpdate( + tr("Extracted the following to \"%1\":\n %2").arg(tmp_extract_dir.absolutePath()).arg(result->join("\n "))); + } else { + logUpdate(tr("Failed to extract %1 to %2").arg(archive.absoluteFilePath()).arg(tmp_extract_dir.absolutePath())); + showFatalErrorMessage("Failed to extract archive", + tr("Failed to extract %1 to %2").arg(archive.absoluteFilePath()).arg(tmp_extract_dir.absolutePath())); + return {}; + } + + } else if (archive.fileName().endsWith(".tar.gz")) { + QString cmd = "tar"; + QStringList args = { "-xvf", archive.absoluteFilePath(), "-C", tmp_extract_dir.absolutePath() }; + logUpdate(tr("Running: `%1 %2`").arg(cmd).arg(args.join(" "))); + QProcess proc = QProcess(); + proc.start(cmd, args); + if (!proc.waitForStarted(5000)) { // wait 5 seconds to start + showFatalErrorMessage(tr("Failed extract archive"), + tr("Failed to launcher child process \"%1 %2\".").arg(cmd).arg(args.join(" "))); + return {}; + } + auto result = proc.waitForFinished(5000); + auto out = proc.readAll(); + logUpdate(out); + if (!result) { + showFatalErrorMessage(tr("Failed to extract archive"), tr("Child process \"%1 %2\" failed.").arg(cmd).arg(args.join(" "))); + return {}; + } + + } else { + logUpdate(tr("Unknown archive format for %1").arg(archive.absoluteFilePath())); + showFatalErrorMessage("Can not extract", QStringLiteral("Unknown archive format %1").arg(archive.absoluteFilePath())); + return {}; + } + + return tmp_extract_dir; +} + void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) { QProcess proc = QProcess(); proc.start(exe_path, { "-v" }); if (!proc.waitForStarted(5000)) // wait 5 seconds to start - return showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read verison.")); + return showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read version.")); if (!proc.waitForFinished(5000)) return showFatalErrorMessage(tr("Failed to Check Version"), tr("Child launcher process failed.")); auto out = proc.readAll(); @@ -707,7 +778,7 @@ void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) return; m_prismBinaryName = first_parts.takeFirst(); auto version = first_parts.takeFirst(); - m_prismVerison = version; + m_prismVersion = version; if (version.contains('-')) { auto index = version.indexOf('-'); m_prsimVersionChannel = version.mid(index + 1); @@ -742,20 +813,20 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) { int per_page = 30; auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page)); - auto responce = std::make_shared(); - auto download = Net::Download::makeByteArray(page_url, responce.get()); + auto response = std::make_shared(); + auto download = Net::Download::makeByteArray(page_url, response.get()); download->setNetwork(m_network); m_current_url = page_url; - auto githup_api_headers = new Net::RawHeaderProxy(); - githup_api_headers->addHeaders({ + auto github_api_headers = new Net::RawHeaderProxy(); + github_api_headers->addHeaders({ { "Accept", "application/vnd.github+json" }, { "X-GitHub-Api-Version", "2022-11-28" }, }); - download->addHeaderProxy(githup_api_headers); + download->addHeaderProxy(github_api_headers); - connect(download.get(), &Net::Download::succeeded, this, [this, responce, per_page, api_url, page]() { - int num_found = parseReleasePage(responce.get()); + connect(download.get(), &Net::Download::succeeded, this, [this, response, per_page, api_url, page]() { + int num_found = parseReleasePage(response.get()); if (!(num_found < per_page)) { // there may be more, fetch next page downloadReleasePage(api_url, page + 1); } else { @@ -766,7 +837,7 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) m_current_task.reset(download); connect(download.get(), &Net::Download::finished, this, [this]() { - qDebug() << "Download" << m_current_task->getUid().toString() << "finsihed"; + qDebug() << "Download" << m_current_task->getUid().toString() << "finished"; m_current_task.reset(); m_current_url = ""; }); @@ -776,13 +847,13 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) QMetaObject::invokeMethod(download.get(), &Task::start, Qt::QueuedConnection); } -int PrismUpdaterApp::parseReleasePage(const QByteArray* responce) +int PrismUpdaterApp::parseReleasePage(const QByteArray* response) { - if (responce->isEmpty()) // empty page + if (response->isEmpty()) // empty page return 0; int num_releases = 0; try { - auto doc = Json::requireDocument(*responce); + auto doc = Json::requireDocument(*response); auto release_list = Json::requireArray(doc); for (auto release_json : release_list) { auto release_obj = Json::requireObject(release_json); @@ -817,7 +888,7 @@ int PrismUpdaterApp::parseReleasePage(const QByteArray* responce) } } catch (Json::JsonException& e) { auto err_msg = - QString("Failed to parse releases from github: %1\n%2").arg(e.what()).arg(QString::fromStdString(responce->toStdString())); + QString("Failed to parse releases from github: %1\n%2").arg(e.what()).arg(QString::fromStdString(response->toStdString())); fail(err_msg); } return num_releases; diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index 8404969a5..af7af7dee 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -63,7 +63,7 @@ class PrismUpdaterApp : public QApplication { void loadPrismVersionFromExe(const QString& exe_path); void downloadReleasePage(const QString& api_url, int page); - int parseReleasePage(const QByteArray* responce); + int parseReleasePage(const QByteArray* response); bool needUpdate(const GitHubRelease& release); @@ -80,6 +80,7 @@ class PrismUpdaterApp : public QApplication { void performInstall(QFileInfo file); void unpackAndInstall(QFileInfo file); void backupAppDir(); + std::optional unpackArchive(QFileInfo file); QFileInfo downloadAsset(const GitHubReleaseAsset& asset); bool callAppimageUpdate(); @@ -92,7 +93,12 @@ class PrismUpdaterApp : public QApplication { bool isPortable() { return m_isPortable; } + void clearUpdateLog(); + void logUpdate(const QString& msg); + + QString m_rootPath; + QString m_dataPath; bool m_isPortable = false; bool m_isAppimage = false; bool m_isFlatpak = false; @@ -107,12 +113,14 @@ class PrismUpdaterApp : public QApplication { bool m_allowDowngrade; QString m_prismBinaryName; - QString m_prismVerison; + QString m_prismVersion; int m_prismVersionMajor; int m_prismVersionMinor; QString m_prsimVersionChannel; QString m_prismGitCommit; + GitHubRelease m_install_release; + Status m_status = Status::Starting; shared_qobject_ptr m_network; QString m_current_url; From 516dd6bd1ad8f9ff939b72f87e88c5803f82eaaf Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 24 Jun 2023 05:02:48 -0700 Subject: [PATCH 082/398] support windows console Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 764 +++++++++--------- launcher/CMakeLists.txt | 11 +- .../updater/prismupdater/PrismUpdater.cpp | 287 +++++-- launcher/updater/prismupdater/PrismUpdater.h | 10 +- .../updater/prismupdater/UpdaterDialogs.cpp | 8 +- 5 files changed, 602 insertions(+), 478 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 20eabc8af..f094a8ec9 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -48,27 +48,27 @@ #include "pathmatcher/MultiMatcher.h" #include "pathmatcher/SimplePrefixMatcher.h" #include "settings/INIFile.h" -#include "ui/MainWindow.h" #include "ui/InstanceWindow.h" +#include "ui/MainWindow.h" #include "ui/dialogs/ProgressDialog.h" #include "ui/instanceview/AccessibleInstanceView.h" #include "ui/pages/BasePageProvider.h" -#include "ui/pages/global/LauncherPage.h" -#include "ui/pages/global/MinecraftPage.h" +#include "ui/pages/global/APIPage.h" +#include "ui/pages/global/AccountListPage.h" +#include "ui/pages/global/CustomCommandsPage.h" +#include "ui/pages/global/ExternalToolsPage.h" #include "ui/pages/global/JavaPage.h" #include "ui/pages/global/LanguagePage.h" +#include "ui/pages/global/LauncherPage.h" +#include "ui/pages/global/MinecraftPage.h" #include "ui/pages/global/ProxyPage.h" -#include "ui/pages/global/ExternalToolsPage.h" -#include "ui/pages/global/AccountListPage.h" -#include "ui/pages/global/APIPage.h" -#include "ui/pages/global/CustomCommandsPage.h" -#include "ui/setupwizard/SetupWizard.h" -#include "ui/setupwizard/LanguageWizardPage.h" #include "ui/setupwizard/JavaWizardPage.h" +#include "ui/setupwizard/LanguageWizardPage.h" #include "ui/setupwizard/PasteWizardPage.h" +#include "ui/setupwizard/SetupWizard.h" #include "ui/setupwizard/ThemeWizardPage.h" #include "ui/dialogs/CustomMessageBox.h" @@ -82,20 +82,20 @@ #include #include -#include #include #include +#include #include #include -#include -#include +#include +#include #include #include +#include #include -#include #include +#include #include -#include #include "InstanceList.h" #include "MTPixmapCache.h" @@ -115,32 +115,35 @@ #include "settings/INISettingsObject.h" #include "settings/Setting.h" -#include "translations/TranslationsModel.h" #include "meta/Index.h" +#include "translations/TranslationsModel.h" -#include #include +#include #include #include #ifdef Q_OS_LINUX #include -#include "gamemode_client.h" #include "MangoHud.h" +#include "gamemode_client.h" #endif #ifdef Q_OS_MAC #include "updater/MacSparkleUpdater.h" #endif - #if defined Q_OS_WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif -#include +#include +#include #include +#include +#include + #endif #define STRINGIFY(x) #x @@ -153,10 +156,10 @@ PixmapCache* PixmapCache::s_instance = nullptr; namespace { /** This is used so that we can output to the log file in addition to the CLI. */ -void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) { static std::mutex loggerMutex; - const std::lock_guard lock(loggerMutex); // synchronized, QFile logFile is not thread-safe + const std::lock_guard lock(loggerMutex); // synchronized, QFile logFile is not thread-safe QString out = qFormatLogMessage(type, context, msg); out += QChar::LineFeed; @@ -167,31 +170,110 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt fflush(stderr); } -} +} // namespace -Application::Application(int &argc, char **argv) : QApplication(argc, argv) +#if defined Q_OS_WIN32 + +// taken from https://stackoverflow.com/a/25927081 +// getting a proper output to console with redirection support on windows is apearently hell +void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) +{ + // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been + // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 + // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our + // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value + // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to + // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target + // using the "_dup2" function. + if (bindStdIn) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "r", stdin); + } + if (bindStdOut) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stdout); + } + if (bindStdErr) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stderr); + } + + // Redirect unbuffered stdin from the current standard input handle + if (bindStdIn) { + HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "r"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdin)); + if (dup2Result == 0) { + setvbuf(stdin, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stdout to the current standard output handle + if (bindStdOut) { + HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdout)); + if (dup2Result == 0) { + setvbuf(stdout, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stderr to the current standard error handle + if (bindStdErr) { + HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stderr)); + if (dup2Result == 0) { + setvbuf(stderr, NULL, _IONBF, 0); + } + } + } + } + } + + // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the + // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In + // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything + // has been read from or written to the targets or not. + if (bindStdIn) { + std::wcin.clear(); + std::cin.clear(); + } + if (bindStdOut) { + std::wcout.clear(); + std::cout.clear(); + } + if (bindStdErr) { + std::wcerr.clear(); + std::cerr.clear(); + } +} +#endif + +Application::Application(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 // attach the parent console - if(AttachConsole(ATTACH_PARENT_PROCESS)) - { - // if attach succeeds, reopen and sync all the i/o - if(freopen("CON", "w", stdout)) - { - std::cout.sync_with_stdio(); - } - if(freopen("CON", "w", stderr)) - { - std::cerr.sync_with_stdio(); - } - if(freopen("CON", "r", stdin)) - { - std::cin.sync_with_stdio(); - } - auto out = GetStdHandle (STD_OUTPUT_HANDLE); - DWORD written; - const char * endline = "\n"; - WriteConsole(out, endline, strlen(endline), &written, NULL); + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + BindCrtHandlesToStdHandles(true, true, true); consoleAttached = true; } #endif @@ -210,15 +292,14 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) QCommandLineParser parser; parser.setApplicationDescription(BuildConfig.LAUNCHER_DISPLAYNAME); - parser.addOptions({ - {{"d", "dir"}, "Use a custom path as application root (use '.' for current directory)", "directory"}, - {{"l", "launch"}, "Launch the specified instance (by instance ID)", "instance"}, - {{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"}, - {{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"}, - {"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"}, - {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}, - {"show", "Opens the window for the specified instance (by instance ID)", "show"} - }); + parser.addOptions( + { { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory)", "directory" }, + { { "l", "launch" }, "Launch the specified instance (by instance ID)", "instance" }, + { { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" }, + { { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" }, + { "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" }, + { { "I", "import" }, "Import instance from specified zip (local path or URL)", "file" }, + { "show", "Opens the window for the specified instance (by instance ID)", "show" } }); parser.addHelpOption(); parser.addVersionOption(); @@ -231,7 +312,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_instanceIdToShowWindowOf = parser.value("show"); - for (auto zip_path : parser.values("import")){ + for (auto zip_path : parser.values("import")) { m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); } @@ -240,10 +321,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); } - // error if --launch is missing with --server or --profile - if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) - { + if ((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; m_status = Application::Failed; return; @@ -255,7 +334,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) { // Root path is used for updates and portable data #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr + QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr m_rootPath = foo.absolutePath(); #elif defined(Q_OS_WIN32) m_rootPath = binPath; @@ -271,15 +350,12 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) QString dataPath; // change folder QString dirParam = parser.value("dir"); - if (!dirParam.isEmpty()) - { + if (!dirParam.isEmpty()) { // the dir param. it makes multimc data path point to whatever the user specified // on command line adjustedBy = "Command line"; dataPath = dirParam; - } - else - { + } else { QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); dataPath = foo.absolutePath(); adjustedBy = "Persistent data path"; @@ -293,34 +369,27 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) #endif } - if (!FS::ensureFolderPathExists(dataPath)) - { + if (!FS::ensureFolderPathExists(dataPath)) { showFatalErrorMessage( "The launcher data folder could not be created.", - QString( - "The launcher data folder could not be created.\n" - "\n" - "Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n" - "(%1)\n" - "\n" - "The launcher cannot continue until you fix this problem." - ).arg(dataPath) - ); + QString("The launcher data folder could not be created.\n" + "\n" + "Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n" + "(%1)\n" + "\n" + "The launcher cannot continue until you fix this problem.") + .arg(dataPath)); return; } - if (!QDir::setCurrent(dataPath)) - { - showFatalErrorMessage( - "The launcher data folder could not be opened.", - QString( - "The launcher data folder could not be opened.\n" - "\n" - "Make sure you have the right permissions to the launcher data folder.\n" - "(%1)\n" - "\n" - "The launcher cannot continue until you fix this problem." - ).arg(dataPath) - ); + if (!QDir::setCurrent(dataPath)) { + showFatalErrorMessage("The launcher data folder could not be opened.", + QString("The launcher data folder could not be opened.\n" + "\n" + "Make sure you have the right permissions to the launcher data folder.\n" + "(%1)\n" + "\n" + "The launcher cannot continue until you fix this problem.") + .arg(dataPath)); return; } @@ -334,17 +403,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // FIXME: you can run the same binaries with multiple data dirs and they won't clash. This could cause issues for updates. m_peerInstance = new LocalPeer(this, appID); connect(m_peerInstance, &LocalPeer::messageReceived, this, &Application::messageReceived); - if(m_peerInstance->isClient()) { + if (m_peerInstance->isClient()) { int timeout = 2000; - if(m_instanceIdToLaunch.isEmpty()) - { + if (m_instanceIdToLaunch.isEmpty()) { ApplicationMessage activate; activate.command = "activate"; m_peerInstance->sendMessage(activate.serialize(), timeout); - if(!m_zipsToImport.isEmpty()) - { + if (!m_zipsToImport.isEmpty()) { for (auto zip_url : m_zipsToImport) { ApplicationMessage import; import.command = "import"; @@ -352,19 +419,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_peerInstance->sendMessage(import.serialize(), timeout); } } - } - else - { + } else { ApplicationMessage launch; launch.command = "launch"; launch.args["id"] = m_instanceIdToLaunch; - if(!m_serverToJoin.isEmpty()) - { + if (!m_serverToJoin.isEmpty()) { launch.args["server"] = m_serverToJoin; } - if(!m_profileToUse.isEmpty()) - { + if (!m_profileToUse.isEmpty()) { launch.args["profile"] = m_profileToUse; } m_peerInstance->sendMessage(launch.serialize(), timeout); @@ -408,40 +471,47 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) qInstallMessageHandler(appDebugOutput); qSetMessagePattern( - "%{time process}" " " - "%{if-debug}D%{endif}" "%{if-info}I%{endif}" "%{if-warning}W%{endif}" "%{if-critical}C%{endif}" "%{if-fatal}F%{endif}" - " " "|" " " - "%{if-category}[%{category}]: %{endif}" - "%{message}"); - + "%{time process}" + " " + "%{if-debug}D%{endif}" + "%{if-info}I%{endif}" + "%{if-warning}W%{endif}" + "%{if-critical}C%{endif}" + "%{if-fatal}F%{endif}" + " " + "|" + " " + "%{if-category}[%{category}]: %{endif}" + "%{message}"); + bool foundLoggingRules = false; - + auto logRulesFile = QStringLiteral("qtlogging.ini"); auto logRulesPath = FS::PathCombine(dataPath, logRulesFile); - - qDebug() << "Testing" << logRulesPath << "..."; + + qDebug() << "Testing" << logRulesPath << "..."; foundLoggingRules = QFile::exists(logRulesPath); // search the dataPath() // seach app data standard path - if(!foundLoggingRules && !isPortable() && dirParam.isEmpty()) { + if (!foundLoggingRules && !isPortable() && dirParam.isEmpty()) { logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, FS::PathCombine("..", logRulesFile)); - if(!logRulesPath.isEmpty()) { + if (!logRulesPath.isEmpty()) { qDebug() << "Found" << logRulesPath << "..."; foundLoggingRules = true; } } // seach root path - if(!foundLoggingRules) { - logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); + if (!foundLoggingRules) { + logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); qDebug() << "Testing" << logRulesPath << "..."; foundLoggingRules = QFile::exists(logRulesPath); } - - if(foundLoggingRules) { + + if (foundLoggingRules) { // load and set logging rules qDebug() << "Loading logging rules from:" << logRulesPath; - QSettings loggingRules(logRulesPath, QSettings::IniFormat); + QSettings loggingRules(logRulesPath, QSettings::IniFormat); loggingRules.beginGroup("Rules"); QStringList rule_names = loggingRules.childKeys(); QStringList rules; @@ -462,48 +532,44 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) bool migrated = false; if (!migrated) - migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", "polymc.cfg"); + migrated = handleDataMigration( + dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", + "polymc.cfg"); if (!migrated) - migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", "multimc.cfg"); + migrated = handleDataMigration( + dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", + "multimc.cfg"); } { - - qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); + qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << ", (c) 2022-2023 " + << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); qDebug() << "Version : " << BuildConfig.printableVersionString(); qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; - if (adjustedBy.size()) - { + if (adjustedBy.size()) { qDebug() << "Work dir before adjustment : " << origcwdPath; qDebug() << "Work dir after adjustment : " << QDir::currentPath(); qDebug() << "Adjusted by : " << adjustedBy; - } - else - { + } else { qDebug() << "Work dir : " << QDir::currentPath(); } qDebug() << "Binary path : " << binPath; qDebug() << "Application root path : " << m_rootPath; - if(!m_instanceIdToLaunch.isEmpty()) - { + if (!m_instanceIdToLaunch.isEmpty()) { qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; } - if(!m_serverToJoin.isEmpty()) - { + if (!m_serverToJoin.isEmpty()) { qDebug() << "Address of server to join :" << m_serverToJoin; } qDebug() << "<> Paths set."; } - if(m_liveCheck) - { + if (m_liveCheck) { QFile check(liveCheckFile); - if(check.open(QIODevice::WriteOnly | QIODevice::Truncate)) - { + if (check.open(QIODevice::WriteOnly | QIODevice::Truncate)) { auto payload = appID.toString().toUtf8(); - if(check.write(payload) == payload.size()) - { + if (check.write(payload) == payload.size()) { check.close(); } else { qWarning() << "Could not write into" << liveCheckFile << "!"; @@ -549,7 +615,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) QString resolvedDefaultMonospace = consoleFontInfo.family(); QFont resolvedFont(resolvedDefaultMonospace); qDebug() << "Detected default console font:" << resolvedDefaultMonospace - << ", substitutions:" << resolvedFont.substitutions().join(','); + << ", substitutions:" << resolvedFont.substitutions().join(','); m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace); m_settings->registerSetting("ConsoleFontSize", defaultSize); @@ -558,7 +624,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Folders m_settings->registerSetting("InstanceDir", "instances"); - m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods"); + m_settings->registerSetting({ "CentralModsDir", "ModsDir" }, "mods"); m_settings->registerSetting("IconsDir", "icons"); m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); m_settings->registerSetting("DownloadsDirWatchRecursive", false); @@ -576,20 +642,20 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("LogPrePostOutput", true); // Window Size - m_settings->registerSetting({"LaunchMaximized", "MCWindowMaximize"}, false); - m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854); - m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480); + m_settings->registerSetting({ "LaunchMaximized", "MCWindowMaximize" }, false); + m_settings->registerSetting({ "MinecraftWinWidth", "MCWindowWidth" }, 854); + m_settings->registerSetting({ "MinecraftWinHeight", "MCWindowHeight" }, 480); // Proxy Settings m_settings->registerSetting("ProxyType", "None"); - m_settings->registerSetting({"ProxyAddr", "ProxyHostName"}, "127.0.0.1"); + m_settings->registerSetting({ "ProxyAddr", "ProxyHostName" }, "127.0.0.1"); m_settings->registerSetting("ProxyPort", 8080); - m_settings->registerSetting({"ProxyUser", "ProxyUsername"}, ""); - m_settings->registerSetting({"ProxyPass", "ProxyPassword"}, ""); + m_settings->registerSetting({ "ProxyUser", "ProxyUsername" }, ""); + m_settings->registerSetting({ "ProxyPass", "ProxyPassword" }, ""); // Memory - m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512); - m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, suitableMaxMem()); + m_settings->registerSetting({ "MinMemAlloc", "MinMemoryAlloc" }, 512); + m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, suitableMaxMem()); m_settings->registerSetting("PermGen", 128); // Java Settings @@ -631,8 +697,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("WrapperCommand", ""); // Custom Commands - m_settings->registerSetting({"PreLaunchCommand", "PreLaunchCmd"}, ""); - m_settings->registerSetting({"PostExitCommand", "PostExitCmd"}, ""); + m_settings->registerSetting({ "PreLaunchCommand", "PreLaunchCmd" }, ""); + m_settings->registerSetting({ "PostExitCommand", "PostExitCmd" }, ""); // The cat m_settings->registerSetting("TheCat", false); @@ -671,8 +737,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) QString pastebinURL = m_settings->get("PastebinURL").toString(); bool userHadDefaultPastebin = pastebinURL == "https://0x0.st"; - if (!pastebinURL.isEmpty() && !userHadDefaultPastebin) - { + if (!pastebinURL.isEmpty() && !userHadDefaultPastebin) { m_settings->set("PastebinType", PasteUpload::PasteType::NullPointer); m_settings->set("PastebinCustomAPIBase", pastebinURL); m_settings->reset("PastebinURL"); @@ -681,8 +746,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) bool ok; int pasteType = m_settings->get("PastebinType").toInt(&ok); // If PastebinType is invalid then reset the related settings. - if (!ok || !(PasteUpload::PasteType::First <= pasteType && pasteType <= PasteUpload::PasteType::Last)) - { + if (!ok || !(PasteUpload::PasteType::First <= pasteType && pasteType <= PasteUpload::PasteType::Last)) { m_settings->reset("PastebinType"); m_settings->reset("PastebinCustomAPIBase"); } @@ -755,8 +819,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) } // initialize the updater - if(BuildConfig.UPDATER_ENABLED) - { + if (BuildConfig.UPDATER_ENABLED) { qDebug() << "Initializing updater"; #ifdef Q_OS_MAC m_updater.reset(new MacSparkleUpdater()); @@ -767,18 +830,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Instance icons { auto setting = APPLICATION->settings()->getSetting("IconsDir"); - QStringList instFolders = - { - ":/icons/multimc/32x32/instances/", - ":/icons/multimc/50x50/instances/", - ":/icons/multimc/128x128/instances/", - ":/icons/multimc/scalable/instances/" - }; + QStringList instFolders = { ":/icons/multimc/32x32/instances/", ":/icons/multimc/50x50/instances/", + ":/icons/multimc/128x128/instances/", ":/icons/multimc/scalable/instances/" }; m_icons.reset(new IconList(instFolders, setting->get().toString())); - connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value) - { - m_icons->directoryChanged(value.toString()); - }); + connect(setting.get(), &Setting::SettingChanged, + [&](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); }); qDebug() << "<> Instance icons intialized."; } @@ -792,8 +848,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // and remember that we have to show him a dialog when the gui starts (if it does so) QString instDir = InstDirSetting->get().toString(); qDebug() << "Instance path : " << instDir; - if (FS::checkProblemticPathJava(QDir(instDir))) - { + if (FS::checkProblemticPathJava(QDir(instDir))) { qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!"; } m_instances.reset(new InstanceList(m_settings, instDir, this)); @@ -843,11 +898,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // now we have network, download translation updates m_translations->downloadIndex(); - //FIXME: what to do with these? + // FIXME: what to do with these? m_profilers.insert("jprofiler", std::shared_ptr(new JProfilerFactory())); m_profilers.insert("jvisualvm", std::shared_ptr(new JVisualVMFactory())); - for (auto profiler : m_profilers.values()) - { + for (auto profiler : m_profilers.values()) { profiler->registerSettings(m_settings); } @@ -857,19 +911,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) } #ifdef Q_OS_MACOS - connect(this, &Application::clickedOnDock, [this]() { - this->showMainWindow(); - }); + connect(this, &Application::clickedOnDock, [this]() { this->showMainWindow(); }); #endif - connect(this, &Application::aboutToQuit, [this](){ - if(m_instances) - { + connect(this, &Application::aboutToQuit, [this]() { + if (m_instances) { // save any remaining instance state m_instances->saveNow(); } - if(logFile) - { + if (logFile) { logFile->flush(); logFile->close(); } @@ -879,8 +929,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) updateCapabilities(); - if(createSetupWizard()) - { + if (createSetupWizard()) { return; } @@ -889,29 +938,25 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) bool Application::createSetupWizard() { - bool javaRequired = [&]() - { + bool javaRequired = [&]() { bool ignoreJavaWizard = m_settings->get("IgnoreJavaWizard").toBool(); - if(ignoreJavaWizard) { + if (ignoreJavaWizard) { return false; } QString currentHostName = QHostInfo::localHostName(); QString oldHostName = settings()->get("LastHostname").toString(); - if (currentHostName != oldHostName) - { + if (currentHostName != oldHostName) { settings()->set("LastHostname", currentHostName); return true; } QString currentJavaPath = settings()->get("JavaPath").toString(); QString actualPath = FS::ResolveExecutable(currentJavaPath); - if (actualPath.isNull()) - { + if (actualPath.isNull()) { return true; } return false; }(); - bool languageRequired = [&]() - { + bool languageRequired = [&]() { if (settings()->get("Language").toString().isEmpty()) return true; return false; @@ -920,27 +965,22 @@ bool Application::createSetupWizard() bool themeInterventionRequired = settings()->get("ApplicationTheme") == ""; bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired; - if(wizardRequired) - { + if (wizardRequired) { m_setupWizard = new SetupWizard(nullptr); - if (languageRequired) - { + if (languageRequired) { m_setupWizard->addPage(new LanguageWizardPage(m_setupWizard)); } - if (javaRequired) - { + if (javaRequired) { m_setupWizard->addPage(new JavaWizardPage(m_setupWizard)); } - if (pasteInterventionRequired) - { + if (pasteInterventionRequired) { m_setupWizard->addPage(new PasteWizardPage(m_setupWizard)); } - if (themeInterventionRequired) - { - settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard + if (themeInterventionRequired) { + settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard)); } connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished); @@ -980,26 +1020,22 @@ void Application::setupWizardFinished(int status) void Application::performMainStartupAction() { m_status = Application::Initialized; - if(!m_instanceIdToLaunch.isEmpty()) - { + if (!m_instanceIdToLaunch.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToLaunch); - if(inst) - { + if (inst) { MinecraftServerTargetPtr serverToJoin = nullptr; MinecraftAccountPtr accountToUse = nullptr; qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; - if(!m_serverToJoin.isEmpty()) - { + if (!m_serverToJoin.isEmpty()) { // FIXME: validate the server string serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin))); qDebug() << " Launching with server" << m_serverToJoin; } - if(!m_profileToUse.isEmpty()) - { + if (!m_profileToUse.isEmpty()) { accountToUse = accounts()->getAccountByProfileName(m_profileToUse); - if(!accountToUse) { + if (!accountToUse) { return; } qDebug() << " Launching with account" << m_profileToUse; @@ -1009,26 +1045,22 @@ void Application::performMainStartupAction() return; } } - if(!m_instanceIdToShowWindowOf.isEmpty()) - { + if (!m_instanceIdToShowWindowOf.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf); - if(inst) - { + if (inst) { qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf; showInstanceWindow(inst); return; } } - if(!m_mainWindow) - { + if (!m_mainWindow) { // normal main window showMainWindow(false); qDebug() << "<> Main window shown."; } - if(!m_zipsToImport.isEmpty()) - { + if (!m_zipsToImport.isEmpty()) { qDebug() << "<> Importing from zip:" << m_zipsToImport; - m_mainWindow->processURLs( m_zipsToImport ); + m_mainWindow->processURLs(m_zipsToImport); } } @@ -1046,8 +1078,7 @@ Application::~Application() #if defined Q_OS_WIN32 // Detach from Windows console - if(consoleAttached) - { + if (consoleAttached) { fclose(stdout); fclose(stdin); fclose(stderr); @@ -1058,8 +1089,7 @@ Application::~Application() void Application::messageReceived(const QByteArray& message) { - if(status() != Initialized) - { + if (status() != Initialized) { qDebug() << "Received message" << message << "while still initializing. It will be ignored."; return; } @@ -1067,66 +1097,51 @@ void Application::messageReceived(const QByteArray& message) ApplicationMessage received; received.parse(message); - auto & command = received.command; + auto& command = received.command; - if(command == "activate") - { + if (command == "activate") { showMainWindow(); - } - else if(command == "import") - { + } else if (command == "import") { QString path = received.args["path"]; - if(path.isEmpty()) - { + if (path.isEmpty()) { qWarning() << "Received" << command << "message without a zip path/URL."; return; } m_mainWindow->processURLs({ QUrl::fromLocalFile(QFileInfo(path).absoluteFilePath()) }); - } - else if(command == "launch") - { + } else if (command == "launch") { QString id = received.args["id"]; QString server = received.args["server"]; QString profile = received.args["profile"]; InstancePtr instance; - if(!id.isEmpty()) { + if (!id.isEmpty()) { instance = instances()->getInstanceById(id); - if(!instance) { + if (!instance) { qWarning() << "Launch command requires an valid instance ID. " << id << "resolves to nothing."; return; } - } - else { + } else { qWarning() << "Launch command called without an instance ID..."; return; } MinecraftServerTargetPtr serverObject = nullptr; - if(!server.isEmpty()) { + if (!server.isEmpty()) { serverObject = std::make_shared(MinecraftServerTarget::parse(server)); } MinecraftAccountPtr accountObject; - if(!profile.isEmpty()) { + if (!profile.isEmpty()) { accountObject = accounts()->getAccountByProfileName(profile); - if(!accountObject) { - qWarning() << "Launch command requires the specified profile to be valid. " << profile << "does not resolve to any account."; + if (!accountObject) { + qWarning() << "Launch command requires the specified profile to be valid. " << profile + << "does not resolve to any account."; return; } } - launch( - instance, - true, - false, - nullptr, - serverObject, - accountObject - ); - } - else - { + launch(instance, true, false, nullptr, serverObject, accountObject); + } else { qWarning() << "Received invalid message" << message; } } @@ -1138,8 +1153,7 @@ std::shared_ptr Application::translations() std::shared_ptr Application::javalist() { - if (!m_javalist) - { + if (!m_javalist) { m_javalist.reset(new JavaInstallList()); } return m_javalist; @@ -1167,50 +1181,41 @@ void Application::setIconTheme(const QString& name) QIcon Application::getThemedIcon(const QString& name) { - if(name == "logo") { + if (name == "logo") { return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME); } return QIcon::fromTheme(name); } -bool Application::openJsonEditor(const QString &filename) +bool Application::openJsonEditor(const QString& filename) { const QString file = QDir::current().absoluteFilePath(filename); - if (m_settings->get("JsonEditor").toString().isEmpty()) - { + if (m_settings->get("JsonEditor").toString().isEmpty()) { return DesktopServices::openUrl(QUrl::fromLocalFile(file)); - } - else - { - //return DesktopServices::openFile(m_settings->get("JsonEditor").toString(), file); - return DesktopServices::run(m_settings->get("JsonEditor").toString(), {file}); + } else { + // return DesktopServices::openFile(m_settings->get("JsonEditor").toString(), file); + return DesktopServices::run(m_settings->get("JsonEditor").toString(), { file }); } } -bool Application::launch( - InstancePtr instance, - bool online, - bool demo, - BaseProfilerFactory *profiler, - MinecraftServerTargetPtr serverToJoin, - MinecraftAccountPtr accountToUse -) { - if(m_updateRunning) - { +bool Application::launch(InstancePtr instance, + bool online, + bool demo, + BaseProfilerFactory* profiler, + MinecraftServerTargetPtr serverToJoin, + MinecraftAccountPtr accountToUse) +{ + if (m_updateRunning) { qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; - } - else if(instance->canLaunch()) - { - auto & extras = m_instanceExtras[instance->id()]; - auto & window = extras.window; - if(window) - { - if(!window->saveAll()) - { + } else if (instance->canLaunch()) { + auto& extras = m_instanceExtras[instance->id()]; + auto& window = extras.window; + if (window) { + if (!window->saveAll()) { return false; } } - auto & controller = extras.controller; + auto& controller = extras.controller; controller.reset(new LaunchController()); controller->setInstance(instance); controller->setOnline(online); @@ -1218,30 +1223,21 @@ bool Application::launch( controller->setProfiler(profiler); controller->setServerToJoin(serverToJoin); controller->setAccountToUse(accountToUse); - if(window) - { + if (window) { controller->setParentWidget(window); - } - else if(m_mainWindow) - { + } else if (m_mainWindow) { controller->setParentWidget(m_mainWindow); } connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded); connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed); - connect(controller.get(), &LaunchController::aborted, this, [this] { - controllerFailed(tr("Aborted")); - }); + connect(controller.get(), &LaunchController::aborted, this, [this] { controllerFailed(tr("Aborted")); }); addRunningInstance(); controller->start(); return true; - } - else if (instance->isRunning()) - { + } else if (instance->isRunning()) { showInstanceWindow(instance, "console"); return true; - } - else if (instance->canEdit()) - { + } else if (instance->canEdit()) { showInstanceWindow(instance); return true; } @@ -1250,16 +1246,14 @@ bool Application::launch( bool Application::kill(InstancePtr instance) { - if (!instance->isRunning()) - { + if (!instance->isRunning()) { qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running."; return false; } - auto & extras = m_instanceExtras[instance->id()]; + auto& extras = m_instanceExtras[instance->id()]; // NOTE: copy of the shared pointer keeps it alive auto controller = extras.controller; - if(controller) - { + if (controller) { return controller->abort(); } return true; @@ -1273,23 +1267,20 @@ void Application::closeCurrentWindow() void Application::addRunningInstance() { - m_runningInstances ++; - if(m_runningInstances == 1) - { + m_runningInstances++; + if (m_runningInstances == 1) { emit updateAllowedChanged(false); } } void Application::subRunningInstance() { - if(m_runningInstances == 0) - { + if (m_runningInstances == 0) { qCritical() << "Something went really wrong and we now have less than 0 running instances... WTF"; return; } - m_runningInstances --; - if(m_runningInstances == 0) - { + m_runningInstances--; + if (m_runningInstances == 0) { emit updateAllowedChanged(true); } } @@ -1309,20 +1300,17 @@ void Application::updateIsRunning(bool running) m_updateRunning = running; } - void Application::controllerSucceeded() { - auto controller = qobject_cast(QObject::sender()); - if(!controller) + auto controller = qobject_cast(QObject::sender()); + if (!controller) return; auto id = controller->id(); - auto & extras = m_instanceExtras[id]; + auto& extras = m_instanceExtras[id]; // on success, do... - if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) - { - if(extras.window) - { + if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) { + if (extras.window) { extras.window->close(); } } @@ -1330,8 +1318,7 @@ void Application::controllerSucceeded() subRunningInstance(); // quit when there are no more windows. - if(shouldExitNow()) - { + if (shouldExitNow()) { m_status = Status::Succeeded; exit(0); } @@ -1340,19 +1327,18 @@ void Application::controllerSucceeded() void Application::controllerFailed(const QString& error) { Q_UNUSED(error); - auto controller = qobject_cast(QObject::sender()); - if(!controller) + auto controller = qobject_cast(QObject::sender()); + if (!controller) return; auto id = controller->id(); - auto & extras = m_instanceExtras[id]; + auto& extras = m_instanceExtras[id]; // on failure, do... nothing extras.controller.reset(); subRunningInstance(); // quit when there are no more windows. - if(shouldExitNow()) - { + if (shouldExitNow()) { m_status = Status::Failed; exit(1); } @@ -1360,7 +1346,7 @@ void Application::controllerFailed(const QString& error) void Application::ShowGlobalSettings(class QWidget* parent, QString open_page) { - if(!m_globalSettingsProvider) { + if (!m_globalSettingsProvider) { return; } emit globalSettingsAboutToOpen(); @@ -1374,24 +1360,18 @@ void Application::ShowGlobalSettings(class QWidget* parent, QString open_page) MainWindow* Application::showMainWindow(bool minimized) { - if(m_mainWindow) - { + if (m_mainWindow) { m_mainWindow->setWindowState(m_mainWindow->windowState() & ~Qt::WindowMinimized); m_mainWindow->raise(); m_mainWindow->activateWindow(); - } - else - { + } else { m_mainWindow = new MainWindow(); m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray())); m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray())); - if(minimized) - { + if (minimized) { m_mainWindow->showMinimized(); - } - else - { + } else { m_mainWindow->show(); } @@ -1403,31 +1383,26 @@ MainWindow* Application::showMainWindow(bool minimized) return m_mainWindow; } -InstanceWindow *Application::showInstanceWindow(InstancePtr instance, QString page) +InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString page) { - if(!instance) + if (!instance) return nullptr; auto id = instance->id(); - auto & extras = m_instanceExtras[id]; - auto & window = extras.window; + auto& extras = m_instanceExtras[id]; + auto& window = extras.window; - if(window) - { + if (window) { window->raise(); window->activateWindow(); - } - else - { + } else { window = new InstanceWindow(instance); - m_openWindows ++; + m_openWindows++; connect(window, &InstanceWindow::isClosing, this, &Application::on_windowClose); } - if(!page.isEmpty()) - { + if (!page.isEmpty()) { window->selectPage(page); } - if(extras.controller) - { + if (extras.controller) { extras.controller->setParentWidget(window); } return window; @@ -1436,24 +1411,20 @@ InstanceWindow *Application::showInstanceWindow(InstancePtr instance, QString pa void Application::on_windowClose() { m_openWindows--; - auto instWindow = qobject_cast(QObject::sender()); - if(instWindow) - { - auto & extras = m_instanceExtras[instWindow->instanceId()]; + auto instWindow = qobject_cast(QObject::sender()); + if (instWindow) { + auto& extras = m_instanceExtras[instWindow->instanceId()]; extras.window = nullptr; - if(extras.controller) - { + if (extras.controller) { extras.controller->setParentWidget(m_mainWindow); } } - auto mainWindow = qobject_cast(QObject::sender()); - if(mainWindow) - { + auto mainWindow = qobject_cast(QObject::sender()); + if (mainWindow) { m_mainWindow = nullptr; } // quit when there are no more windows. - if(shouldExitNow()) - { + if (shouldExitNow()) { exit(0); } } @@ -1461,23 +1432,14 @@ void Application::on_windowClose() void Application::updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password) { // Set the application proxy settings. - if (proxyTypeStr == "SOCKS5") - { - QNetworkProxy::setApplicationProxy( - QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password)); - } - else if (proxyTypeStr == "HTTP") - { - QNetworkProxy::setApplicationProxy( - QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password)); - } - else if (proxyTypeStr == "None") - { + if (proxyTypeStr == "SOCKS5") { + QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password)); + } else if (proxyTypeStr == "HTTP") { + QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password)); + } else if (proxyTypeStr == "None") { // If we have no proxy set, set no proxy and return. QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy)); - } - else - { + } else { // If we have "Default" selected, set Qt to use the system proxy settings. QNetworkProxyFactory::setUseSystemConfiguration(true); } @@ -1487,39 +1449,35 @@ void Application::updateProxySettings(QString proxyTypeStr, QString addr, int po m_network->setProxy(proxy); QString proxyDesc; - if (proxy.type() == QNetworkProxy::NoProxy) - { + if (proxy.type() == QNetworkProxy::NoProxy) { qDebug() << "Using no proxy is an option!"; return; } - switch (proxy.type()) - { - case QNetworkProxy::DefaultProxy: - proxyDesc = "Default proxy: "; - break; - case QNetworkProxy::Socks5Proxy: - proxyDesc = "Socks5 proxy: "; - break; - case QNetworkProxy::HttpProxy: - proxyDesc = "HTTP proxy: "; - break; - case QNetworkProxy::HttpCachingProxy: - proxyDesc = "HTTP caching: "; - break; - case QNetworkProxy::FtpCachingProxy: - proxyDesc = "FTP caching: "; - break; - default: - proxyDesc = "DERP proxy: "; - break; + switch (proxy.type()) { + case QNetworkProxy::DefaultProxy: + proxyDesc = "Default proxy: "; + break; + case QNetworkProxy::Socks5Proxy: + proxyDesc = "Socks5 proxy: "; + break; + case QNetworkProxy::HttpProxy: + proxyDesc = "HTTP proxy: "; + break; + case QNetworkProxy::HttpCachingProxy: + proxyDesc = "HTTP caching: "; + break; + case QNetworkProxy::FtpCachingProxy: + proxyDesc = "FTP caching: "; + break; + default: + proxyDesc = "DERP proxy: "; + break; } - proxyDesc += QString("%1:%2") - .arg(proxy.hostName()) - .arg(proxy.port()); + proxyDesc += QString("%1:%2").arg(proxy.hostName()).arg(proxy.port()); qDebug() << proxyDesc; } -shared_qobject_ptr< HttpMetaCache > Application::metacache() +shared_qobject_ptr Application::metacache() { return m_metacache; } @@ -1531,8 +1489,7 @@ shared_qobject_ptr Application::network() shared_qobject_ptr Application::metadataIndex() { - if (!m_metadataIndex) - { + if (!m_metadataIndex) { m_metadataIndex.reset(new Meta::Index()); } return m_metadataIndex; @@ -1563,10 +1520,9 @@ QString Application::getJarPath(QString jarFile) #endif FS::PathCombine(m_rootPath, "jars"), FS::PathCombine(applicationDirPath(), "jars"), - FS::PathCombine(applicationDirPath(), "..", "jars") // from inside build dir, for debuging + FS::PathCombine(applicationDirPath(), "..", "jars") // from inside build dir, for debuging }; - for(QString p : potentialPaths) - { + for (QString p : potentialPaths) { QString jarPath = FS::PathCombine(p, jarFile); if (QFileInfo(jarPath).isFile()) return jarPath; @@ -1631,7 +1587,7 @@ int Application::suitableMaxMem() // If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB if (totalRAM < (4096 * 1.5)) - maxMemoryAlloc = (int) (totalRAM / 1.5); + maxMemoryAlloc = (int)(totalRAM / 1.5); else maxMemoryAlloc = 4096; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 5cdb0383e..dc413bb62 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -625,6 +625,11 @@ set(PRISMUPDATER_SOURCES net/HeaderProxy.h net/RawHeaderProxy.h + ui/dialogs/ProgressDialog.cpp + ui/dialogs/ProgressDialog.h + ui/widgets/SubTaskProgressBar.h + ui/widgets/SubTaskProgressBar.cpp + ) ######## Logging categories ######## @@ -1144,6 +1149,8 @@ qt_add_resources(LAUNCHER_RESOURCES qt_wrap_ui(PRISMUPDATER_UI updater/prismupdater/SelectReleaseDialog.ui + ui/widgets/SubTaskProgressBar.ui + ui/dialogs/ProgressDialog.ui ) ######## Windows resource files ######## @@ -1231,11 +1238,13 @@ install(TARGETS ${Launcher_Name} FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime ) -if(NOT APPLE OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) +if(NOT APPLE OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER)) # Updater add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(prism_updater_logic + QuaZip::QuaZip + ${ZLIB_LIBRARIES} systeminfo BuildConfig ghcFilesystem::ghc_filesystem diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 001ecb10c..2b62feeb3 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -46,8 +46,11 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include +#include #include #include +#include #endif // Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header @@ -100,27 +103,108 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt } } +#if defined Q_OS_WIN32 + +// taken from https://stackoverflow.com/a/25927081 +// getting a proper output to console with redirection support on windows is apearently hell +void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) +{ + // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been + // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 + // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our + // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value + // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to + // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target + // using the "_dup2" function. + if (bindStdIn) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "r", stdin); + } + if (bindStdOut) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stdout); + } + if (bindStdErr) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stderr); + } + + // Redirect unbuffered stdin from the current standard input handle + if (bindStdIn) { + HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "r"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdin)); + if (dup2Result == 0) { + setvbuf(stdin, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stdout to the current standard output handle + if (bindStdOut) { + HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdout)); + if (dup2Result == 0) { + setvbuf(stdout, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stderr to the current standard error handle + if (bindStdErr) { + HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stderr)); + if (dup2Result == 0) { + setvbuf(stderr, NULL, _IONBF, 0); + } + } + } + } + } + + // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the + // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In + // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything + // has been read from or written to the targets or not. + if (bindStdIn) { + std::wcin.clear(); + std::cin.clear(); + } + if (bindStdOut) { + std::wcout.clear(); + std::cout.clear(); + } + if (bindStdErr) { + std::wcerr.clear(); + std::cerr.clear(); + } +} +#endif + PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 // attach the parent console if (AttachConsole(ATTACH_PARENT_PROCESS)) { - FILE* _stream; - errno_t err; - // if attach succeeds, reopen and sync all the i/o - if (err = freopen_s(&_stream, "CON", "w", stdout); err == 0) { - std::cout.sync_with_stdio(); - } - if (err = freopen_s(&_stream, "CON", "w", stderr); err == 0) { - std::cerr.sync_with_stdio(); - } - if (err = freopen_s(&_stream, "CON", "r", stdin); err == 0) { - std::cin.sync_with_stdio(); - } - auto out = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD written; - const char* endline = "\n"; - WriteConsole(out, endline, strlen(endline), &written, NULL); + BindCrtHandlesToStdHandles(true, true, true); consoleAttached = true; } #endif @@ -133,16 +217,20 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar QCommandLineParser parser; parser.setApplicationDescription(QObject::tr("An auto-updater for Prism Launcher")); - parser.addOptions({ { { "d", "dir" }, tr("Use a custom path as application root (use '.' for current directory)."), tr("directory") }, - { { "I", "install-version" }, "Install a specific version.", tr("version name") }, - { { "U", "update-url" }, tr("Update from the specified repo."), tr("github repo url") }, - { { "c", "check-only" }, - tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") }, - { { "F", "force" }, tr("Force an update, even if one is not needed.") }, - { { "l", "list" }, tr("List available releases.") }, - { "debug", tr("Log debug to console.") }, - { { "S", "select-ui" }, tr("Select the version to install with a GUI.") }, - { { "D", "allow-downgrade" }, tr("Allow the updater to downgrade to previous versions.") } }); + parser.addOptions( + { { { "d", "dir" }, tr("Use a custom path as application root (use '.' for current directory)."), tr("directory") }, + { { "V", "prism-version" }, + tr("Use this version as the installed launcher version. (provided because stdout can not be reliably captured on windows)"), + tr("installed launcher version") }, + { { "I", "install-version" }, "Install a specific version.", tr("version name") }, + { { "U", "update-url" }, tr("Update from the specified repo."), tr("github repo url") }, + { { "c", "check-only" }, + tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") }, + { { "F", "force" }, tr("Force an update, even if one is not needed.") }, + { { "l", "list" }, tr("List available releases.") }, + { "debug", tr("Log debug to console.") }, + { { "S", "select-ui" }, tr("Select the version to install with a GUI.") }, + { { "D", "allow-downgrade" }, tr("Allow the updater to downgrade to previous versions.") } }); parser.addHelpOption(); parser.addVersionOption(); @@ -150,24 +238,31 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar logToConsole = parser.isSet("debug"); - auto prism_executable = QCoreApplication::applicationFilePath(); + auto updater_executable = QCoreApplication::applicationFilePath(); if (BuildConfig.BUILD_PLATFORM.toLower() == "macos") showFatalErrorMessage(tr("MacOS Not Supported"), tr("The updater does not support installations on MacOS")); - if (!QFileInfo(prism_executable).isFile()) - showFatalErrorMessage(tr("Unsupported Installation"), tr("The updater can not find the main executable.")); - - if (prism_executable.startsWith("/tmp/.mount_")) { + if (updater_executable.startsWith("/tmp/.mount_")) { m_isAppimage = true; m_appimagePath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); - if (m_appimagePath.isEmpty()) + if (m_appimagePath.isEmpty()) { showFatalErrorMessage(tr("Unsupported Installation"), tr("Updater is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)")); + } } m_isFlatpak = DesktopServices::isFlatpak(); + QString prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME; +#if defined Q_OS_WIN32 + prism_executable += ".exe"; +#endif + + if (!QFileInfo(prism_executable).isFile()) { + showFatalErrorMessage(tr("Unsupported Installation"), tr("The updater can not find the main executable.")); + } + m_prismExecutable = prism_executable; auto prism_update_url = parser.value("update-url"); @@ -185,6 +280,20 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_selectUI = parser.isSet("select-ui"); m_allowDowngrade = parser.isSet("allow-downgrade"); + auto version = parser.value("prism-version"); + if (!version.isEmpty()) { + if (version.contains('-')) { + auto index = version.indexOf('-'); + m_prsimVersionChannel = version.mid(index + 1); + version = version.left(index); + } else { + m_prsimVersionChannel = "stable"; + } + auto version_parts = version.split('.'); + m_prismVersionMajor = version_parts.takeFirst().toInt(); + m_prismVersionMinor = version_parts.takeFirst().toInt(); + } + QString origCwdPath = QDir::currentPath(); QString binPath = applicationDirPath(); @@ -338,9 +447,9 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar PrismUpdaterApp::~PrismUpdaterApp() { - qDebug() << "updater shutting down"; // Shut down logger by setting the logger function to nothing qInstallMessageHandler(nullptr); + qDebug() << "updater shutting down"; #if defined Q_OS_WIN32 // Detach from Windows console @@ -392,13 +501,19 @@ void PrismUpdaterApp::run() return exit(0); } - loadPrismVersionFromExe(m_prismExecutable); + if (!loadPrismVersionFromExe(m_prismExecutable)) { + m_prismVersion = BuildConfig.printableVersionString(); + m_prismVersionMajor = BuildConfig.VERSION_MAJOR; + m_prismVersionMinor = BuildConfig.VERSION_MINOR; + m_prsimVersionChannel = BuildConfig.VERSION_CHANNEL; + m_prismGitCommit = BuildConfig.GIT_COMMIT; + } m_status = Succeeded; qDebug() << "Executable reports as:" << m_prismBinaryName << "version:" << m_prismVersion; qDebug() << "Version major:" << m_prismVersionMajor; - qDebug() << "Verison minor:" << m_prismVersionMinor; - qDebug() << "Verison channel:" << m_prsimVersionChannel; + qDebug() << "Version minor:" << m_prismVersionMinor; + qDebug() << "Version channel:" << m_prsimVersionChannel; qDebug() << "Git Commit:" << m_prismGitCommit; auto latest = getLatestRelease(); @@ -420,7 +535,7 @@ void PrismUpdaterApp::run() if (m_isAppimage) { bool result = true; if (need_update) - result = callAppimageUpdate(); + result = callAppImageUpdate(); return exit(result ? 0 : 1); } @@ -528,6 +643,13 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel bool for_platform = !BuildConfig.BUILD_PLATFORM.isEmpty() && asset.name.toLower().contains(BuildConfig.BUILD_PLATFORM.toLower()); bool for_portable = asset.name.toLower().contains("portable"); + if (for_platform && asset.name.toLower().contains("legacy") && !BuildConfig.BUILD_PLATFORM.toLower().contains("legacy")) + for_platform = false; + if (for_platform && asset.name.toLower().contains("arm64") && !QSysInfo::buildCpuArchitecture().contains("arm64")) + for_platform = false; + if (for_platform && !asset.name.toLower().contains("arm64") && QSysInfo::buildCpuArchitecture().contains("arm64")) + for_platform = false; + if (((m_isPortable && for_portable) || (!m_isPortable && !for_portable)) && for_platform) { valid.append(asset); } @@ -557,10 +679,11 @@ void PrismUpdaterApp::performUpdate(const GitHubRelease& release) GitHubReleaseAsset selected_asset; if (valid_assets.isEmpty()) { - return showFatalErrorMessage(tr("No Valid Release Assets"), - tr("Github release %1 has no valid assets for this platform: %2") - .arg(release.tag_name) - .arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_PLATFORM).arg(m_isPortable))); + return showFatalErrorMessage( + tr("No Valid Release Assets"), + tr("Github release %1 has no valid assets for this platform: %2") + .arg(release.tag_name) + .arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_PLATFORM).arg(m_isPortable ? tr("yes") : tr("no")))); } else if (valid_assets.length() > 1) { selected_asset = selectAsset(valid_assets); } else { @@ -587,18 +710,21 @@ QFileInfo PrismUpdaterApp::downloadAsset(const GitHubReleaseAsset& asset) auto file_url = QUrl(asset.browser_download_url); auto out_file_path = FS::PathCombine(temp_dir, file_url.fileName()); + qDebug() << "downloading" << file_url << "to" << out_file_path; auto download = Net::Download::makeFile(file_url, out_file_path); - + download->setNetwork(m_network); auto progress_dialog = ProgressDialog(); if (progress_dialog.execWithTask(download.get()) == QDialog::Rejected) showFatalErrorMessage(tr("Download Aborted"), tr("Download of %1 aborted by user").arg(file_url.toString())); + qDebug() << "download complete"; + QFileInfo out_file(out_file_path); return out_file; } -bool PrismUpdaterApp::callAppimageUpdate() +bool PrismUpdaterApp::callAppImageUpdate() { QProcess proc = QProcess(); proc.setProgram("AppImageUpdate"); @@ -614,20 +740,20 @@ void PrismUpdaterApp::clearUpdateLog() void PrismUpdaterApp::logUpdate(const QString& msg) { - qDebug() << msg; + qDebug() << qUtf8Printable(msg); auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); FS::append(update_log_path, QStringLiteral("%1\n").arg(msg).toUtf8()); } void PrismUpdaterApp::performInstall(QFileInfo file) { + qDebug() << "starting install"; auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"); FS::write(update_lock_path, QStringLiteral("FROM=%1\nTO=%2\n").arg(m_prismVersion).arg(m_install_release.tag_name).toUtf8()); clearUpdateLog(); logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name)); - // TODO setup marker file - if (m_isPortable) { + if (m_isPortable || file.suffix().toLower() == "zip") { logUpdate(tr("Updating portable install at %1").arg(applicationDirPath())); unpackAndInstall(file); } else { @@ -635,6 +761,7 @@ void PrismUpdaterApp::performInstall(QFileInfo file) QProcess proc = QProcess(); proc.setProgram(file.absoluteFilePath()); bool result = proc.startDetached(); + logUpdate(tr("Process start result: %1").arg(result ? tr("yes") : tr("no"))); exit(result ? 0 : 1); } } @@ -643,8 +770,24 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) { logUpdate(tr("Backing up install")); backupAppDir(); - auto loc = unpackArchive(archive); - // TODO: unpack (rename access failures) + + if (auto loc = unpackArchive(archive)) { + auto marker_file_path = loc.value().absoluteFilePath(".prism_launcher_updater_unpack.marker"); + FS::write(marker_file_path, applicationDirPath().toUtf8()); + auto new_updater_path = loc.value().absoluteFilePath("prismlauncher-updater"); +#if defined Q_OS_WIN32 + new_updater_path.append(".exe"); +#endif + logUpdate(tr("Starting new updater at '%1'").arg(new_updater_path)); + QProcess proc = QProcess(); + proc.startDetached(new_updater_path, {}, loc.value().absolutePath()); + if (!proc.waitForStarted(5000)) { + logUpdate(tr("Failed to launch '%1' %2").arg(new_updater_path).arg(proc.errorString())); + return exit(10); + } + return exit(); // up to the new updater now + } + return exit(1); // unpack failure } void PrismUpdaterApp::backupAppDir() @@ -680,6 +823,8 @@ void PrismUpdaterApp::backupAppDir() "styles/*", "styles/*", "tls/*", + "qt.conf", + "Qt*.dll", }); } file_list.append("portable.txt"); @@ -688,7 +833,10 @@ void PrismUpdaterApp::backupAppDir() logUpdate(tr("Backing up:\n %1").arg(file_list.join(",\n "))); QDir app_dir = QCoreApplication::applicationDirPath(); - auto backup_dir = FS::PathCombine(app_dir.absolutePath(), QStringLiteral("backup_") + m_prismVersion + ":" + m_prismGitCommit); + auto backup_dir = FS::PathCombine( + app_dir.absolutePath(), QStringLiteral("backup_") + + QString(m_prismVersion).replace(QRegularExpression("[" + QRegularExpression::escape("\\/:*?\"<>|") + "]"), QString("_")) + + "-" + m_prismGitCommit); FS::ensureFolderPathExists(backup_dir); for (auto glob : file_list) { @@ -723,13 +871,12 @@ std::optional PrismUpdaterApp::unpackArchive(QFileInfo archive) if (archive.fileName().endsWith(".zip")) { auto result = MMCZip::extractDir(archive.absoluteFilePath(), tmp_extract_dir.absolutePath()); if (result) { - logUpdate( - tr("Extracted the following to \"%1\":\n %2").arg(tmp_extract_dir.absolutePath()).arg(result->join("\n "))); + logUpdate(tr("Extracted the following to \"%1\":\n %2").arg(tmp_extract_dir.absolutePath()).arg(result->join("\n "))); } else { logUpdate(tr("Failed to extract %1 to %2").arg(archive.absoluteFilePath()).arg(tmp_extract_dir.absolutePath())); showFatalErrorMessage("Failed to extract archive", tr("Failed to extract %1 to %2").arg(archive.absoluteFilePath()).arg(tmp_extract_dir.absolutePath())); - return {}; + return std::nullopt; } } else if (archive.fileName().endsWith(".tar.gz")) { @@ -739,43 +886,52 @@ std::optional PrismUpdaterApp::unpackArchive(QFileInfo archive) QProcess proc = QProcess(); proc.start(cmd, args); if (!proc.waitForStarted(5000)) { // wait 5 seconds to start - showFatalErrorMessage(tr("Failed extract archive"), - tr("Failed to launcher child process \"%1 %2\".").arg(cmd).arg(args.join(" "))); - return {}; + auto msg = tr("Failed to launcher child process \"%1 %2\".").arg(cmd).arg(args.join(" ")); + logUpdate(msg); + showFatalErrorMessage(tr("Failed extract archive"), msg); + return std::nullopt; } auto result = proc.waitForFinished(5000); auto out = proc.readAll(); logUpdate(out); if (!result) { - showFatalErrorMessage(tr("Failed to extract archive"), tr("Child process \"%1 %2\" failed.").arg(cmd).arg(args.join(" "))); - return {}; + auto msg = tr("Child process \"%1 %2\" failed.").arg(cmd).arg(args.join(" ")); + logUpdate(msg); + showFatalErrorMessage(tr("Failed to extract archive"), msg); + return std::nullopt; } } else { logUpdate(tr("Unknown archive format for %1").arg(archive.absoluteFilePath())); showFatalErrorMessage("Can not extract", QStringLiteral("Unknown archive format %1").arg(archive.absoluteFilePath())); - return {}; + return std::nullopt; } return tmp_extract_dir; } -void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) +bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) { QProcess proc = QProcess(); + proc.setProcessChannelMode(QProcess::MergedChannels); + proc.setReadChannel(QProcess::StandardOutput); proc.start(exe_path, { "-v" }); - if (!proc.waitForStarted(5000)) // wait 5 seconds to start - return showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read version.")); - if (!proc.waitForFinished(5000)) - return showFatalErrorMessage(tr("Failed to Check Version"), tr("Child launcher process failed.")); + if (!proc.waitForStarted(5000)) { + showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read version.")); + return false; + } // wait 5 seconds to start + if (!proc.waitForFinished(5000)) { + showFatalErrorMessage(tr("Failed to Check Version"), tr("Child launcher process failed.")); + return false; + } auto out = proc.readAll(); auto lines = out.split('\n'); if (lines.length() < 2) - return; + return false; auto first = lines.takeFirst(); auto first_parts = first.split(' '); if (first_parts.length() < 2) - return; + return false; m_prismBinaryName = first_parts.takeFirst(); auto version = first_parts.takeFirst(); m_prismVersion = version; @@ -790,6 +946,7 @@ void PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) m_prismVersionMajor = version_parts.takeFirst().toInt(); m_prismVersionMinor = version_parts.takeFirst().toInt(); m_prismGitCommit = lines.takeFirst().simplified(); + return true; } void PrismUpdaterApp::loadReleaseList() diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index af7af7dee..909e36056 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -60,7 +60,7 @@ class PrismUpdaterApp : public QApplication { void abort(const QString& reason); void showFatalErrorMessage(const QString& title, const QString& content); - void loadPrismVersionFromExe(const QString& exe_path); + bool loadPrismVersionFromExe(const QString& exe_path); void downloadReleasePage(const QString& api_url, int page); int parseReleasePage(const QByteArray* response); @@ -83,7 +83,9 @@ class PrismUpdaterApp : public QApplication { std::optional unpackArchive(QFileInfo file); QFileInfo downloadAsset(const GitHubReleaseAsset& asset); - bool callAppimageUpdate(); + bool callAppImageUpdate(); + + void moveAndPostProcess(QDir target); public slots: void downloadError(QString reason); @@ -114,8 +116,8 @@ class PrismUpdaterApp : public QApplication { QString m_prismBinaryName; QString m_prismVersion; - int m_prismVersionMajor; - int m_prismVersionMinor; + int m_prismVersionMajor = -1; + int m_prismVersionMinor = -1; QString m_prsimVersionChannel; QString m_prismGitCommit; diff --git a/launcher/updater/prismupdater/UpdaterDialogs.cpp b/launcher/updater/prismupdater/UpdaterDialogs.cpp index 72fdf3404..14c584918 100644 --- a/launcher/updater/prismupdater/UpdaterDialogs.cpp +++ b/launcher/updater/prismupdater/UpdaterDialogs.cpp @@ -17,8 +17,8 @@ SelectReleaseDialog::SelectReleaseDialog(const Version& current_version, const Q ui->versionsTree->setColumnCount(2); ui->versionsTree->header()->setSectionResizeMode(0, QHeaderView::Stretch); - ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::Stretch); - ui->versionsTree->setHeaderLabels({tr("Verison"), tr("Published Date")}); + ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + ui->versionsTree->setHeaderLabels({tr("Version"), tr("Published Date")}); ui->versionsTree->header()->setStretchLastSection(false); ui->eplainLabel->setText(tr("Select a version to install.\n" @@ -90,8 +90,8 @@ SelectReleaseAssetDialog::SelectReleaseAssetDialog( const QListversionsTree->setColumnCount(2); ui->versionsTree->header()->setSectionResizeMode(0, QHeaderView::Stretch); - ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::Stretch); - ui->versionsTree->setHeaderLabels({tr("Verison"), tr("Published Date")}); + ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + ui->versionsTree->setHeaderLabels({tr("Version"), tr("Published Date")}); ui->versionsTree->header()->setStretchLastSection(false); ui->eplainLabel->setText(tr("Select a version to install.")); From d2a3acd493f3da7dab05c0744aa46d274535b9d2 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 24 Jun 2023 10:53:20 -0700 Subject: [PATCH 083/398] fix: filter archive assets from windows non-portable installs Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/prismupdater/PrismUpdater.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 2b62feeb3..7f065f536 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -640,14 +640,19 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel continue; else if (m_isAppimage && !asset.name.toLower().endsWith("appimage")) continue; + auto asset_name = asset.name.toLower(); + auto platform = BuildConfig.BUILD_PLATFORM.toLower(); + auto system_is_arm = QSysInfo::buildCpuArchitecture().contains("arm64"); + auto asset_is_arm = asset_name.contains("arm64"); + auto asset_is_archive = asset_name.endsWith(".zip") || asset_name.endsWith(".tar.gz"); - bool for_platform = !BuildConfig.BUILD_PLATFORM.isEmpty() && asset.name.toLower().contains(BuildConfig.BUILD_PLATFORM.toLower()); - bool for_portable = asset.name.toLower().contains("portable"); - if (for_platform && asset.name.toLower().contains("legacy") && !BuildConfig.BUILD_PLATFORM.toLower().contains("legacy")) + bool for_platform = !platform.isEmpty() && asset_name.contains(platform); + bool for_portable = asset_name.contains("portable"); + if (for_platform && asset_name.contains("legacy") && !platform.contains("legacy")) for_platform = false; - if (for_platform && asset.name.toLower().contains("arm64") && !QSysInfo::buildCpuArchitecture().contains("arm64")) + if (for_platform && ((asset_is_arm && !system_is_arm) || (!asset_is_arm && system_is_arm))) for_platform = false; - if (for_platform && !asset.name.toLower().contains("arm64") && QSysInfo::buildCpuArchitecture().contains("arm64")) + if (for_platform && platform.contains("windows") && !m_isPortable && asset_is_archive) for_platform = false; if (((m_isPortable && for_portable) || (!m_isPortable && !for_portable)) && for_platform) { From 431346658951ef699669b8564fc38366eb62271f Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 24 Jun 2023 22:21:16 -0700 Subject: [PATCH 084/398] feat(updater): final step for portable install Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 4 +- .../minecraft/mod/tasks/LocalModParseTask.cpp | 5 +- launcher/modplatform/packwiz/Packwiz.cpp | 7 +- launcher/ui/dialogs/ProgressDialog.cpp | 9 +- launcher/ui/dialogs/ProgressDialog.ui | 7 +- .../updater/prismupdater/PrismUpdater.cpp | 270 +++++++++++++++--- launcher/updater/prismupdater/PrismUpdater.h | 5 +- .../prismupdater/SelectReleaseDialog.ui | 4 +- 8 files changed, 256 insertions(+), 55 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70a553190..cb75f769c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,8 +148,8 @@ set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_M # Build platform. set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.") -# Channel list URL -set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.") +# Github repo URL with releases for updater +set(Launcher_UPDATER_GITHUB_REPO "" CACHE STRING "Base URL for the updater.") # The metadata server set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.") diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index 264019f84..43fc4831d 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -108,10 +108,11 @@ ModDetails ReadMCModTOML(QByteArray contents) return {}; } #else - tomlData = toml::parse(contents.toStdString()); - if (!tomlData) { + toml::parse_result result = toml::parse(contents.toStdString()); + if (!result) { return {}; } + tomlData = result.table(); #endif // array defined by [[mods]] diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 510c7309d..967b8870c 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -241,12 +241,13 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod return {}; } #else - table = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname))); - if (!table) { + toml::parse_result result = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname))); + if (!result) { qWarning() << QString("Could not open file %1!").arg(normalized_fname); - qWarning() << "Reason: " << QString(table.error().what()); + qWarning() << "Reason: " << result.error().description(); return {}; } + table = result.table(); #endif // index_file.close(); diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 246a0fd49..93f8076f4 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -68,6 +68,8 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true); setSkipButton(false); changeProgress(0, 100); + updateSize(); + adjustSize(); } void ProgressDialog::setSkipButton(bool present, QString label) @@ -96,7 +98,11 @@ ProgressDialog::~ProgressDialog() void ProgressDialog::updateSize() { QSize lastSize = this->size(); - QSize qSize = QSize(480, minimumSizeHint().height()); + auto min_height = minimumSizeHint().height(); + if (ui->taskProgressScrollArea->isHidden()) + min_height -= ui->taskProgressScrollArea->minimumSizeHint().height(); + min_height = std::max(min_height, 0); + QSize qSize = QSize(480, min_height); // if the current window is too small if ((lastSize != qSize) && (lastSize.height() < qSize.height())) @@ -111,7 +117,6 @@ void ProgressDialog::updateSize() } setMinimumSize(qSize); - } int ProgressDialog::execWithTask(Task* task) diff --git a/launcher/ui/dialogs/ProgressDialog.ui b/launcher/ui/dialogs/ProgressDialog.ui index a4d08124c..156ff247f 100644 --- a/launcher/ui/dialogs/ProgressDialog.ui +++ b/launcher/ui/dialogs/ProgressDialog.ui @@ -48,6 +48,9 @@ Global Task Status... + + true +
@@ -109,8 +112,8 @@ 0 0 - 464 - 96 + 460 + 108 diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 7f065f536..221c1c649 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -39,7 +39,7 @@ #include #include -#include +#include #include #if defined Q_OS_WIN32 @@ -106,7 +106,7 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt #if defined Q_OS_WIN32 // taken from https://stackoverflow.com/a/25927081 -// getting a proper output to console with redirection support on windows is apearently hell +// getting a proper output to console with redirection support on windows is apparently hell void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) { // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been @@ -266,8 +266,11 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_prismExecutable = prism_executable; auto prism_update_url = parser.value("update-url"); + if (prism_update_url.isEmpty()) + prism_update_url = BuildConfig.UPDATER_GITHUB_REPO; if (prism_update_url.isEmpty()) prism_update_url = "https://github.com/PrismLauncher/PrismLauncher"; + m_prismRepoUrl = QUrl::fromUserInput(prism_update_url); m_checkOnly = parser.isSet("check-only"); @@ -334,6 +337,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar #endif } + m_updateLogPath = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); + { // setup logging static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; auto moveFile = [](const QString& oldName, const QString& newName) { @@ -424,14 +429,16 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; if (adjustedBy.size()) { - qDebug() << "Work dir before adjustment : " << origCwdPath; - qDebug() << "Work dir after adjustment : " << QDir::currentPath(); + qDebug() << "Data dir before adjustment : " << origCwdPath; + qDebug() << "Data dir after adjustment : " << m_dataPath; qDebug() << "Adjusted by : " << adjustedBy; } else { - qDebug() << "Work dir : " << QDir::currentPath(); + qDebug() << "Data dir : " << QDir::currentPath(); } + qDebug() << "Work dir : " << QDir::currentPath(); qDebug() << "Binary path : " << binPath; qDebug() << "Application root path : " << m_rootPath; + qDebug() << "Portable install : " << m_isPortable; qDebug() << "<> Paths set."; } @@ -442,14 +449,28 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_network->setProxy(proxy); } - QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection); + auto marker_file_path = QDir(applicationDirPath()).absoluteFilePath(".prism_launcher_updater_unpack.marker"); + auto marker_file = QFileInfo(marker_file_path); + if (marker_file.exists()) { + auto target_dir = QString(FS::read(marker_file_path)).trimmed(); + if (target_dir.isEmpty()) { + qWarning() << "Empty updater marker file contains no install target. making best guess of parent dir"; + target_dir = QDir(applicationDirPath()).absoluteFilePath(".."); + } + + QMetaObject::invokeMethod( + this, [this, target_dir]() { moveAndFinishUpdate(target_dir); }, Qt::QueuedConnection); + + } else { + QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection); + } } PrismUpdaterApp::~PrismUpdaterApp() { + qDebug() << "updater shutting down"; // Shut down logger by setting the logger function to nothing qInstallMessageHandler(nullptr); - qDebug() << "updater shutting down"; #if defined Q_OS_WIN32 // Detach from Windows console @@ -576,6 +597,81 @@ void PrismUpdaterApp::run() exit(0); } +void PrismUpdaterApp::moveAndFinishUpdate(QDir target) +{ + logUpdate("Finishing update process"); + auto manifest_path = FS::PathCombine(applicationDirPath(), "manifest.txt"); + QFileInfo manifest(manifest_path); + + auto app_dir = QDir(applicationDirPath()); + + QStringList file_list; + if (manifest.isFile()) { + // load manifest from file + logUpdate(tr("Reading manifest from %1").arg(manifest.absoluteFilePath())); + try { + auto contents = QString::fromUtf8(FS::read(manifest.absoluteFilePath())); + auto files = contents.split('\n'); + for (auto file : files) { + file_list.append(file.trimmed()); + } + } catch (FS::FileSystemException) { + } + } + + if (file_list.isEmpty()) { + logUpdate(tr("Manifest empty, making best guess of the directory contents of %1").arg(applicationDirPath())); + auto entries = target.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); + for (auto entry : entries) { + file_list.append(entry.fileName()); + } + } + logUpdate(tr("Installing the following to %1 :\n %2").arg(target.absolutePath()).arg(file_list.join(",\n "))); + + bool error = false; + + QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); + progress.setCancelButton(nullptr); + progress.show(); + QCoreApplication::processEvents(); + + int i = 0; + for (auto glob : file_list) { + QDirIterator iter(applicationDirPath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); + progress.setValue(i); + QCoreApplication::processEvents(); + while (iter.hasNext()) { + auto to_install_file = iter.next(); + auto rel_path = app_dir.relativeFilePath(to_install_file); + auto install_path = FS::PathCombine(target.absolutePath(), rel_path); + logUpdate(tr("Installing %1 from %2").arg(install_path).arg(to_install_file)); + FS::ensureFilePathExists(install_path); + auto result = FS::copy(to_install_file, install_path)(); + if (!result) { + error = true; + logUpdate(tr("Failed copy %1 to %2").arg(to_install_file).arg(install_path)); + } + } + i++; + } + progress.setValue(i); + QCoreApplication::processEvents(); + + if (error) { + logUpdate(tr("There were errors installing the update.")); + auto fail_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.fail"); + FS::move(m_updateLogPath, fail_marker); + } else { + logUpdate(tr("Update succeed.")); + auto success_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.success"); + FS::move(m_updateLogPath, success_marker); + } + auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"); + FS::deletePath(update_lock_path); + + exit(error ? 1 : 0); +} + void PrismUpdaterApp::printReleases() { for (auto release : m_releases) { @@ -739,24 +835,107 @@ bool PrismUpdaterApp::callAppImageUpdate() void PrismUpdaterApp::clearUpdateLog() { - auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); - QFile::remove(update_log_path); + QFile::remove(m_updateLogPath); } void PrismUpdaterApp::logUpdate(const QString& msg) { qDebug() << qUtf8Printable(msg); - auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); - FS::append(update_log_path, QStringLiteral("%1\n").arg(msg).toUtf8()); + FS::append(m_updateLogPath, QStringLiteral("%1\n").arg(msg).toUtf8()); +} + +std::tuple read_lock_File(const QString& path) +{ + auto contents = QString(FS::read(path)); + auto lines = contents.split('\n'); + + QDateTime timestamp; + QString from, to, target, data_path; + for (auto line : lines) { + auto index = line.indexOf("="); + if (index < 0) + continue; + auto left = line.left(index); + auto right = line.mid(index + 1); + if (left.toLower() == "timestamp") { + timestamp = QDateTime::fromString(right, Qt::ISODate); + } else if (left.toLower() == "from") { + from = right; + } else if (left.toLower() == "to") { + to = right; + } else if (left.toLower() == "target") { + target = right; + } else if (left.toLower() == "data_path") { + data_path = right; + } + } + return std::make_tuple(timestamp, from, to, target, data_path); +} + +bool write_lock_file(const QString& path, QDateTime timestamp, QString from, QString to, QString target, QString data_path) +{ + try { + FS::write(path, QStringLiteral("TIMESTAMP=%1\nFROM=%2\nTO=%3\nTARGET=%4\nDATA_PATH=%5\n") + .arg(timestamp.toString(Qt::ISODate)) + .arg(from) + .arg(to) + .arg(target) + .arg(data_path) + .toUtf8()); + } catch (FS::FileSystemException err) { + qWarning() << "Error writing lockfile:" << err.what() << "\n" << err.cause(); + return false; + } + return true; } void PrismUpdaterApp::performInstall(QFileInfo file) { qDebug() << "starting install"; auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"); - FS::write(update_lock_path, QStringLiteral("FROM=%1\nTO=%2\n").arg(m_prismVersion).arg(m_install_release.tag_name).toUtf8()); + QFileInfo update_lock(update_lock_path); + if (update_lock.exists()) { + auto [timestamp, from, to, target, data_path] = read_lock_File(update_lock_path); + auto msg = tr("Update already in progress\n"); + auto infoMsg = + tr("This installation has a update lock file present at: %1\n" + "\n" + "Timestamp: %2\n" + "Updating from version %3 to %4\n" + "Target install path: %5\n" + "Data Path: %6" + "\n" + "This likely means that a previous update attempt failed. Please ensure your installation is in working order before " + "proceeding.\n" + "Check the Prism Launcher updater log at \n" + "%7\n" + "for details on the last update attempt.\n" + "\n" + "To overwrite this lock and proceed with this update anyway, select \"Ignore\" below.") + .arg(update_lock_path) + .arg(timestamp.toString(Qt::ISODate), from, to, target, data_path) + .arg(m_updateLogPath); + QMessageBox msgBox; + msgBox.setText(msg); + msgBox.setInformativeText(infoMsg); + msgBox.setStandardButtons(QMessageBox::Ignore | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Cancel); + switch (msgBox.exec()) { + case QMessageBox::Ignore: + break; + case QMessageBox::Cancel: + [[fallthrough]]; + default: + return showFatalErrorMessage(tr("Update Aborted"), tr("The update attempt was aborted")); + } + } + write_lock_file(update_lock_path, QDateTime::currentDateTime(), m_prismVersion, m_install_release.tag_name, applicationDirPath(), + m_dataPath); clearUpdateLog(); + auto changelog_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.changelog"); + FS::write(changelog_path, m_install_release.body.toUtf8()); + logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name)); if (m_isPortable || file.suffix().toLower() == "zip") { logUpdate(tr("Updating portable install at %1").arg(applicationDirPath())); @@ -779,14 +958,13 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) if (auto loc = unpackArchive(archive)) { auto marker_file_path = loc.value().absoluteFilePath(".prism_launcher_updater_unpack.marker"); FS::write(marker_file_path, applicationDirPath().toUtf8()); - auto new_updater_path = loc.value().absoluteFilePath("prismlauncher-updater"); + auto new_updater_path = loc.value().absoluteFilePath("prismlauncher_updater"); #if defined Q_OS_WIN32 new_updater_path.append(".exe"); #endif logUpdate(tr("Starting new updater at '%1'").arg(new_updater_path)); QProcess proc = QProcess(); - proc.startDetached(new_updater_path, {}, loc.value().absolutePath()); - if (!proc.waitForStarted(5000)) { + if (!proc.startDetached(new_updater_path, { "-d", m_dataPath }, loc.value().absolutePath())) { logUpdate(tr("Failed to launch '%1' %2").arg(new_updater_path).arg(proc.errorString())); return exit(10); } @@ -807,7 +985,10 @@ void PrismUpdaterApp::backupAppDir() logUpdate(tr("Reading manifest from %1").arg(manifest.absoluteFilePath())); try { auto contents = QString::fromUtf8(FS::read(manifest.absoluteFilePath())); - file_list.append(contents.split('\n')); + auto files = contents.split('\n'); + for (auto file : files) { + file_list.append(file.trimmed()); + } } catch (FS::FileSystemException) { } } @@ -815,19 +996,19 @@ void PrismUpdaterApp::backupAppDir() if (file_list.isEmpty()) { // best guess if (BuildConfig.BUILD_PLATFORM.toLower() == "linux") { - file_list.append({ "PrismLauncher", "bin/*", "share/*", "lib/*" }); + file_list.append({ "PrismLauncher", "bin", "share", "lib" }); } else { // windows by process of elimination file_list.append({ - "jars/*", + "jars", "prismlauncher.exe", "prismlauncher_filelink.exe", + "prismlauncher_updater.exe", "qtlogging.ini", - "imageformats/*", - "iconengines/*", - "platforms/*", - "styles/*", - "styles/*", - "tls/*", + "imageformats", + "iconengines", + "platforms", + "styles", + "tls", "qt.conf", "Qt*.dll", }); @@ -839,32 +1020,41 @@ void PrismUpdaterApp::backupAppDir() QDir app_dir = QCoreApplication::applicationDirPath(); auto backup_dir = FS::PathCombine( - app_dir.absolutePath(), QStringLiteral("backup_") + - QString(m_prismVersion).replace(QRegularExpression("[" + QRegularExpression::escape("\\/:*?\"<>|") + "]"), QString("_")) + - "-" + m_prismGitCommit); + app_dir.absolutePath(), + QStringLiteral("backup_") + + QString(m_prismVersion).replace(QRegularExpression("[" + QRegularExpression::escape("\\/:*?\"<>|") + "]"), QString("_")) + "-" + + m_prismGitCommit); FS::ensureFolderPathExists(backup_dir); + auto backup_marker_path = FS::PathCombine(m_dataPath, ".prism_launcher_update_backup_path.txt"); + FS::write(backup_marker_path, backup_dir.toUtf8()); + QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); + progress.setCancelButton(nullptr); + progress.show(); + QCoreApplication::processEvents(); + int i = 0; for (auto glob : file_list) { - QDirIterator iter(app_dir.absolutePath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, - QDirIterator::Subdirectories); + QDirIterator iter(app_dir.absolutePath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); + progress.setValue(i); + QCoreApplication::processEvents(); while (iter.hasNext()) { auto to_bak_file = iter.next(); auto rel_path = app_dir.relativeFilePath(to_bak_file); auto bak_path = FS::PathCombine(backup_dir, rel_path); - - if (QFileInfo(to_bak_file).isFile()) { - logUpdate(tr("Backing up and then removing %1").arg(to_bak_file)); - FS::ensureFilePathExists(bak_path); - auto result = FS::copy(to_bak_file, bak_path)(); - if (!result) { - logUpdate(tr("Failed to backup %1 to %2").arg(to_bak_file).arg(bak_path)); - } else { - if (!FS::deletePath(to_bak_file)) - logUpdate(tr("Failed to remove %1").arg(to_bak_file)); - } + logUpdate(tr("Backing up and then removing %1").arg(to_bak_file)); + FS::ensureFilePathExists(bak_path); + auto result = FS::copy(to_bak_file, bak_path)(); + if (!result) { + logUpdate(tr("Failed to backup %1 to %2").arg(to_bak_file).arg(bak_path)); + } else { + if (!FS::deletePath(to_bak_file)) + logUpdate(tr("Failed to remove %1").arg(to_bak_file)); } } + i++; } + progress.setValue(i); + QCoreApplication::processEvents(); } std::optional PrismUpdaterApp::unpackArchive(QFileInfo archive) diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index 909e36056..113747b75 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -85,7 +85,7 @@ class PrismUpdaterApp : public QApplication { QFileInfo downloadAsset(const GitHubReleaseAsset& asset); bool callAppImageUpdate(); - void moveAndPostProcess(QDir target); + void moveAndFinishUpdate(QDir target); public slots: void downloadError(QString reason); @@ -98,7 +98,6 @@ class PrismUpdaterApp : public QApplication { void clearUpdateLog(); void logUpdate(const QString& msg); - QString m_rootPath; QString m_dataPath; bool m_isPortable = false; @@ -114,6 +113,8 @@ class PrismUpdaterApp : public QApplication { bool m_selectUI; bool m_allowDowngrade; + QString m_updateLogPath; + QString m_prismBinaryName; QString m_prismVersion; int m_prismVersionMajor = -1; diff --git a/launcher/updater/prismupdater/SelectReleaseDialog.ui b/launcher/updater/prismupdater/SelectReleaseDialog.ui index 9d3613727..a1aa38371 100644 --- a/launcher/updater/prismupdater/SelectReleaseDialog.ui +++ b/launcher/updater/prismupdater/SelectReleaseDialog.ui @@ -6,8 +6,8 @@ 0 0 - 478 - 517 + 468 + 385 From e099a3f7e8846a293d30a884498929ae9f5b2f07 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 24 Jun 2023 22:22:24 -0700 Subject: [PATCH 085/398] feat(updater): packaging - know the updater git repo Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 6 +++--- buildconfig/BuildConfig.cpp.in | 4 ++-- buildconfig/BuildConfig.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3f93337b5..48be91ac8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -277,12 +277,12 @@ jobs: if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_UPDATER_GITHUB_REPO=https://github.com/${{ github.repository }} -G Ninja - name: Configure CMake (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_UPDATER_GITHUB_REPO=https://github.com/${{ github.repository }} # https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix) if ("${{ env.CCACHE_VAR }}") { @@ -297,7 +297,7 @@ jobs: - name: Configure CMake (Linux) if: runner.os == 'Linux' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_UPDATER_GITHUB_REPO=https://github.com/${{ github.repository }} -G Ninja ## # BUILD diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index 8a412b7ff..b03867c3c 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -60,7 +60,7 @@ Config::Config() BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@"; BUILD_DATE = "@Launcher_BUILD_TIMESTAMP@"; - UPDATER_BASE = "@Launcher_UPDATER_BASE@"; + UPDATER_GITHUB_REPO = "@Launcher_UPDATER_GITHUB_REPO@"; MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@"; MAC_SPARKLE_APPCAST_URL = "@MACOSX_SPARKLE_UPDATE_FEED_URL@"; @@ -89,7 +89,7 @@ Config::Config() { VERSION_CHANNEL = GIT_REFSPEC; VERSION_CHANNEL.remove("refs/heads/"); - if(!UPDATER_BASE.isEmpty() && !BUILD_PLATFORM.isEmpty()) { + if(!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_PLATFORM.isEmpty()) { UPDATER_ENABLED = true; } } diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 8543d7241..b6ae6e6d8 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -75,7 +75,7 @@ class Config { QString BUILD_DATE; /// URL for the updater's channel - QString UPDATER_BASE; + QString UPDATER_GITHUB_REPO; /// The public key used to sign releases for the Sparkle updater appcast QString MAC_SPARKLE_PUB_KEY; From 4b65315cdc18b1a4687d8dd1922dc7b10abc8a51 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 14:21:55 -0700 Subject: [PATCH 087/398] chore: add license to headers Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .../updater/prismupdater/GitHubRelease.cpp | 103 ++++++++++++++---- launcher/updater/prismupdater/GitHubRelease.h | 23 +++- launcher/updater/prismupdater/PrismUpdater.h | 2 +- .../updater/prismupdater/UpdaterDialogs.cpp | 72 +++++++----- .../updater/prismupdater/UpdaterDialogs.h | 24 +++- .../updater/prismupdater/updater_main.cpp | 10 +- 6 files changed, 176 insertions(+), 58 deletions(-) diff --git a/launcher/updater/prismupdater/GitHubRelease.cpp b/launcher/updater/prismupdater/GitHubRelease.cpp index 25e60e885..3beae31b1 100644 --- a/launcher/updater/prismupdater/GitHubRelease.cpp +++ b/launcher/updater/prismupdater/GitHubRelease.cpp @@ -1,36 +1,93 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + #include "GitHubRelease.h" QDebug operator<<(QDebug debug, const GitHubReleaseAsset& asset) { QDebugStateSaver saver(debug); - debug.nospace() << "GitHubReleaseAsset( " - "id: " << asset.id << ", " - "name " << asset.name << ", " - "label: " << asset.label << ", " - "content_type: " << asset.content_type << ", " - "size: " << asset.size << ", " - "created_at: " << asset.created_at << ", " - "updated_at: " << asset.updated_at << ", " - "browser_download_url: " << asset.browser_download_url << " " - ")"; + debug.nospace() << "GitHubReleaseAsset( " + "id: " + << asset.id + << ", " + "name " + << asset.name + << ", " + "label: " + << asset.label + << ", " + "content_type: " + << asset.content_type + << ", " + "size: " + << asset.size + << ", " + "created_at: " + << asset.created_at + << ", " + "updated_at: " + << asset.updated_at + << ", " + "browser_download_url: " + << asset.browser_download_url + << " " + ")"; return debug; } QDebug operator<<(QDebug debug, const GitHubRelease& rls) { QDebugStateSaver saver(debug); - debug.nospace() << "GitHubRelease( " - "id: " << rls.id << ", " - "name " << rls.name << ", " - "tag_name: " << rls.tag_name << ", " - "created_at: " << rls.created_at << ", " - "published_at: " << rls.published_at << ", " - "prerelease: " << rls.prerelease << ", " - "draft: " << rls.draft << ", " - "version" << rls.version << ", " - "body: " << rls.body << ", " - "assets: " << rls.assets << " " - ")"; + debug.nospace() << "GitHubRelease( " + "id: " + << rls.id + << ", " + "name " + << rls.name + << ", " + "tag_name: " + << rls.tag_name + << ", " + "created_at: " + << rls.created_at + << ", " + "published_at: " + << rls.published_at + << ", " + "prerelease: " + << rls.prerelease + << ", " + "draft: " + << rls.draft + << ", " + "version" + << rls.version + << ", " + "body: " + << rls.body + << ", " + "assets: " + << rls.assets + << " " + ")"; return debug; } - diff --git a/launcher/updater/prismupdater/GitHubRelease.h b/launcher/updater/prismupdater/GitHubRelease.h index 0c190333f..798c6b7ae 100644 --- a/launcher/updater/prismupdater/GitHubRelease.h +++ b/launcher/updater/prismupdater/GitHubRelease.h @@ -1,3 +1,25 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + #pragma once #include #include @@ -37,4 +59,3 @@ struct GitHubRelease { QDebug operator<<(QDebug debug, const GitHubReleaseAsset& rls); QDebug operator<<(QDebug debug, const GitHubRelease& rls); - diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index 113747b75..f879ad7ad 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -42,7 +42,7 @@ #define PRISM_EXTERNAL_EXE #include "FileSystem.h" -#include "updater/prismupdater/GitHubRelease.h" +#include "GitHubRelease.h" class PrismUpdaterApp : public QApplication { // friends for the purpose of limiting access to deprecated stuff diff --git a/launcher/updater/prismupdater/UpdaterDialogs.cpp b/launcher/updater/prismupdater/UpdaterDialogs.cpp index 14c584918..395b658db 100644 --- a/launcher/updater/prismupdater/UpdaterDialogs.cpp +++ b/launcher/updater/prismupdater/UpdaterDialogs.cpp @@ -1,3 +1,25 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + #include "UpdaterDialogs.h" #include "ui_SelectReleaseDialog.h" @@ -9,25 +31,25 @@ SelectReleaseDialog::SelectReleaseDialog(const Version& current_version, const Q : QDialog(parent), m_releases(releases), m_currentVersion(current_version), ui(new Ui::SelectReleaseDialog) { ui->setupUi(this); - + ui->changelogTextBrowser->setOpenExternalLinks(true); ui->changelogTextBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth); ui->changelogTextBrowser->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - + ui->versionsTree->setColumnCount(2); ui->versionsTree->header()->setSectionResizeMode(0, QHeaderView::Stretch); - ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); - ui->versionsTree->setHeaderLabels({tr("Version"), tr("Published Date")}); + ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + ui->versionsTree->setHeaderLabels({ tr("Version"), tr("Published Date") }); ui->versionsTree->header()->setStretchLastSection(false); - + ui->eplainLabel->setText(tr("Select a version to install.\n" - "\n" - "Currently installed version: %1") - .arg(m_currentVersion.toString())); - + "\n" + "Currently installed version: %1") + .arg(m_currentVersion.toString())); + loadReleases(); - + connect(ui->versionsTree, &QTreeWidget::currentItemChanged, this, &SelectReleaseDialog::selectionChanged); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SelectReleaseDialog::accept); @@ -57,10 +79,11 @@ void SelectReleaseDialog::appendRelease(GitHubRelease const& release) ui->versionsTree->addTopLevelItem(rls_item); } -GitHubRelease SelectReleaseDialog::getRelease(QTreeWidgetItem* item) { +GitHubRelease SelectReleaseDialog::getRelease(QTreeWidgetItem* item) +{ int id = item->data(0, Qt::UserRole).toInt(); GitHubRelease release; - for (auto rls: m_releases) { + for (auto rls : m_releases) { if (rls.id == id) release = rls; } @@ -76,30 +99,28 @@ void SelectReleaseDialog::selectionChanged(QTreeWidgetItem* current, QTreeWidget ui->changelogTextBrowser->setHtml(body); } - - -SelectReleaseAssetDialog::SelectReleaseAssetDialog( const QList& assets, QWidget* parent) - : QDialog(parent), m_assets(assets), ui(new Ui::SelectReleaseDialog) +SelectReleaseAssetDialog::SelectReleaseAssetDialog(const QList& assets, QWidget* parent) + : QDialog(parent), m_assets(assets), ui(new Ui::SelectReleaseDialog) { ui->setupUi(this); - + ui->changelogTextBrowser->setOpenExternalLinks(true); ui->changelogTextBrowser->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth); ui->changelogTextBrowser->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); - + ui->versionsTree->setColumnCount(2); ui->versionsTree->header()->setSectionResizeMode(0, QHeaderView::Stretch); - ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); - ui->versionsTree->setHeaderLabels({tr("Version"), tr("Published Date")}); + ui->versionsTree->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + ui->versionsTree->setHeaderLabels({ tr("Version"), tr("Published Date") }); ui->versionsTree->header()->setStretchLastSection(false); - + ui->eplainLabel->setText(tr("Select a version to install.")); ui->changelogTextBrowser->setHidden(true); - + loadAssets(); - + connect(ui->versionsTree, &QTreeWidget::currentItemChanged, this, &SelectReleaseAssetDialog::selectionChanged); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SelectReleaseAssetDialog::accept); @@ -129,10 +150,11 @@ void SelectReleaseAssetDialog::appendAsset(GitHubReleaseAsset const& asset) ui->versionsTree->addTopLevelItem(rls_item); } -GitHubReleaseAsset SelectReleaseAssetDialog::getAsset(QTreeWidgetItem* item) { +GitHubReleaseAsset SelectReleaseAssetDialog::getAsset(QTreeWidgetItem* item) +{ int id = item->data(0, Qt::UserRole).toInt(); GitHubReleaseAsset selected_asset; - for (auto asset: m_assets) { + for (auto asset : m_assets) { if (asset.id == id) selected_asset = asset; } diff --git a/launcher/updater/prismupdater/UpdaterDialogs.h b/launcher/updater/prismupdater/UpdaterDialogs.h index c5e31b5a4..249ca1b5d 100644 --- a/launcher/updater/prismupdater/UpdaterDialogs.h +++ b/launcher/updater/prismupdater/UpdaterDialogs.h @@ -1,10 +1,32 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + #pragma once #include #include #include "Version.h" -#include "updater/prismupdater/GitHubRelease.h" +#include "GitHubRelease.h" namespace Ui { class SelectReleaseDialog; diff --git a/launcher/updater/prismupdater/updater_main.cpp b/launcher/updater/prismupdater/updater_main.cpp index 6bc7dd208..89c1d1198 100644 --- a/launcher/updater/prismupdater/updater_main.cpp +++ b/launcher/updater/prismupdater/updater_main.cpp @@ -20,17 +20,14 @@ * */ - - -#include "updater/prismupdater/PrismUpdater.h" +#include "PrismUpdater.h" int main(int argc, char* argv[]) { PrismUpdaterApp wUpApp(argc, argv); - switch(wUpApp.status()) { + switch (wUpApp.status()) { case PrismUpdaterApp::Starting: - case PrismUpdaterApp::Initialized: - { + case PrismUpdaterApp::Initialized: { return wUpApp.exec(); } case PrismUpdaterApp::Failed: @@ -40,5 +37,4 @@ int main(int argc, char* argv[]) default: return -1; } - } From 1ba08f4641f32d39efc509247807eca035be62f5 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 14:25:07 -0700 Subject: [PATCH 088/398] fixup! Merge remote-tracking branch 'upstream/develop' into refactor/net-split-headers-to-proxy-class --- launcher/net/Download.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 19f675adc..2fa318ef2 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -59,7 +59,10 @@ class Download : public NetAction { public: ~Download() override = default; +#if defined(LAUNCHER_APPLICATION) static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; +#endif + static auto makeByteArray(QUrl url, std::shared_ptr output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; From 8aeec1d52d30a008c9b7d815d0e3a8eda82878ca Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 14:36:20 -0700 Subject: [PATCH 089/398] fix: use new shared pointer for repsonse buffer Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/prismupdater/PrismUpdater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 221c1c649..60e970597 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -1166,7 +1166,7 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) int per_page = 30; auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page)); auto response = std::make_shared(); - auto download = Net::Download::makeByteArray(page_url, response.get()); + auto download = Net::Download::makeByteArray(page_url, response); download->setNetwork(m_network); m_current_url = page_url; From c49ee8785792142b67d6c431d1913a4d7d2fa936 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 25 Jun 2023 18:49:50 -0400 Subject: [PATCH 091/398] fix(net): fix emit signals in download & upload task Signed-off-by: seth --- launcher/net/Download.cpp | 12 ++++++------ launcher/net/Upload.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index c86452137..40d8a5bba 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -117,7 +117,7 @@ void Download::executeTask() switch (m_state) { case State::Succeeded: qCDebug(taskDownloadLogC) << getUid().toString() << "Download cache hit " << m_url.toString(); - emitSucceeded(); + emit succeeded(); return; case State::Running: qCDebug(taskDownloadLogC) << getUid().toString() << "Downloading " << m_url.toString(); @@ -294,19 +294,19 @@ void Download::downloadFinished() qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed but we are allowed to proceed:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitSucceeded(); + emit succeeded(); return; } else if (m_state == State::Failed) { qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitFailed(""); + emit failed(""); return; } else if (m_state == State::AbortedByUser) { qCDebug(taskDownloadLogC) << getUid().toString() << "Download aborted in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitAborted(); + emit aborted(); return; } @@ -323,13 +323,13 @@ void Download::downloadFinished() qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed to finalize:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitFailed(""); + emit failed(""); return; } m_reply.reset(); qCDebug(taskDownloadLogC) << getUid().toString() << "Download succeeded:" << m_url.toString(); - emitSucceeded(); + emit succeeded(); } void Download::downloadReadyRead() diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index 8881b16a0..0688c5a80 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -157,19 +157,19 @@ void Upload::downloadFinished() qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitSucceeded(); + emit succeeded(); return; } else if (m_state == State::Failed) { qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitFailed(""); + emit failed(""); return; } else if (m_state == State::AbortedByUser) { qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitAborted(); + emit aborted(); return; } @@ -186,12 +186,12 @@ void Upload::downloadFinished() qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString(); m_sink->abort(); m_reply.reset(); - emitFailed(""); + emit failed(""); return; } m_reply.reset(); qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString(); - emitSucceeded(); + emit succeeded(); } void Upload::downloadReadyRead() @@ -208,7 +208,7 @@ void Upload::executeTask() if (m_state == State::AbortedByUser) { qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString(); - emitAborted(); + emit aborted(); return; } QNetworkRequest request(m_url); From 10266f65e409da6ef5132a4433b4e09631d6b77e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 16:10:06 -0700 Subject: [PATCH 092/398] fix: include `^` updater doesn't need to know about mods Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/MMCZip.cpp | 2 ++ launcher/MMCZip.h | 5 +++++ launcher/updater/prismupdater/PrismUpdater.cpp | 4 ++-- launcher/updater/prismupdater/PrismUpdater.h | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 1a336375b..33776d972 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -135,6 +135,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList return result; } +#if defined(LAUNCHER_APPLICATION) // ours bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods) { @@ -235,6 +236,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const } return true; } +#endif // ours QString MMCZip::findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths, const QString& root) diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 2a78f830f..ef0e09777 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -38,7 +38,10 @@ #include #include #include +#include +#if defined(LAUNCHER_APPLICATION) #include "minecraft/mod/Mod.h" +#endif #include #include @@ -74,10 +77,12 @@ namespace MMCZip */ bool compressDirFiles(QString fileCompressed, QString dir, QFileInfoList files, bool followSymlinks = false); +#if defined(LAUNCHER_APPLICATION) /** * take a source jar, add mods to it, resulting in target jar */ bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods); +#endif /** * Find a single file in archive by file name (not path) diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 60e970597..3ca4f235e 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -72,7 +72,7 @@ namespace fs = std::filesystem; namespace fs = ghc::filesystem; #endif -#include +#include "DesktopServices.h" #include "updater/prismupdater/UpdaterDialogs.h" @@ -83,7 +83,7 @@ namespace fs = ghc::filesystem; #include "net/Download.h" #include "net/RawHeaderProxy.h" -#include +#include "MMCZip.h" /** output to the log file */ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index f879ad7ad..90ebeb8d2 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -35,6 +35,7 @@ #include #include #include +#include #include "QObjectPtr.h" #include "net/Download.h" From b142407b218383992f854486cabebb766e83fa93 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 16:13:26 -0700 Subject: [PATCH 093/398] fix: ensure `finished` signal is emited Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/net/Download.cpp | 6 ++++++ launcher/net/Upload.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 40d8a5bba..c08281854 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -118,6 +118,7 @@ void Download::executeTask() case State::Succeeded: qCDebug(taskDownloadLogC) << getUid().toString() << "Download cache hit " << m_url.toString(); emit succeeded(); + emit finished(); return; case State::Running: qCDebug(taskDownloadLogC) << getUid().toString() << "Downloading " << m_url.toString(); @@ -295,18 +296,21 @@ void Download::downloadFinished() m_sink->abort(); m_reply.reset(); emit succeeded(); + emit finished(); return; } else if (m_state == State::Failed) { qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); emit failed(""); + emit finished(); return; } else if (m_state == State::AbortedByUser) { qCDebug(taskDownloadLogC) << getUid().toString() << "Download aborted in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); emit aborted(); + emit finished(); return; } @@ -324,12 +328,14 @@ void Download::downloadFinished() m_sink->abort(); m_reply.reset(); emit failed(""); + emit finished(); return; } m_reply.reset(); qCDebug(taskDownloadLogC) << getUid().toString() << "Download succeeded:" << m_url.toString(); emit succeeded(); + emit finished(); } void Download::downloadReadyRead() diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index 0688c5a80..d9115ede1 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -158,18 +158,21 @@ void Upload::downloadFinished() m_sink->abort(); m_reply.reset(); emit succeeded(); + emit finished(); return; } else if (m_state == State::Failed) { qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); emit failed(""); + emit finished(); return; } else if (m_state == State::AbortedByUser) { qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString(); m_sink->abort(); m_reply.reset(); emit aborted(); + emit finished(); return; } @@ -187,11 +190,13 @@ void Upload::downloadFinished() m_sink->abort(); m_reply.reset(); emit failed(""); + emit finished(); return; } m_reply.reset(); qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString(); emit succeeded(); + emit finished(); } void Upload::downloadReadyRead() @@ -209,6 +214,7 @@ void Upload::executeTask() if (m_state == State::AbortedByUser) { qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString(); emit aborted(); + emit finished(); return; } QNetworkRequest request(m_url); From d8e0b14dc458a662671092b6941609c85348b38a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 21:36:20 -0700 Subject: [PATCH 094/398] feat(updater): tie in updater part 1 Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 15 +- launcher/CMakeLists.txt | 7 + launcher/StringUtils.cpp | 28 ++- launcher/StringUtils.h | 11 +- launcher/updater/PrismExternalUpdater.cpp | 206 ++++++++++++++++++ launcher/updater/PrismExternalUpdater.h | 94 ++++++++ .../updater/prismupdater/PrismUpdater.cpp | 44 +++- launcher/updater/prismupdater/PrismUpdater.h | 1 + 8 files changed, 390 insertions(+), 16 deletions(-) create mode 100644 launcher/updater/PrismExternalUpdater.cpp create mode 100644 launcher/updater/PrismExternalUpdater.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index f094a8ec9..a5103e8e5 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -132,6 +132,8 @@ #ifdef Q_OS_MAC #include "updater/MacSparkleUpdater.h" +#else +#include "updater/PrismExternalUpdater.h" #endif #if defined Q_OS_WIN32 @@ -271,10 +273,15 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr Application::Application(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 - // attach the parent console - if (AttachConsole(ATTACH_PARENT_PROCESS)) { + // attach the parent console if stdout not already captured + auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + BindCrtHandlesToStdHandles(true, true, true); + consoleAttached = true; + } + } else if (stdout_type == FILE_TYPE_DISK || stdout_type == FILE_TYPE_PIPE ) { BindCrtHandlesToStdHandles(true, true, true); - consoleAttached = true; } #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); @@ -823,6 +830,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qDebug() << "Initializing updater"; #ifdef Q_OS_MAC m_updater.reset(new MacSparkleUpdater()); +#else + m_updater.reset(new PrismExternalUpdater(m_rootPath, dataPath)); #endif qDebug() << "<> Updater started."; } diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index dc413bb62..86bf8fc48 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -179,6 +179,11 @@ set(MAC_UPDATE_SOURCES updater/MacSparkleUpdater.mm ) +set(PRISM_UPDATE_SOURCES + updater/PrismExternalUpdater.h + updater/PrismExternalUpdater.cpp +) + # Backend for the news bar... there's usually no news. set(NEWS_SOURCES # News System @@ -728,6 +733,8 @@ set(LOGIC_SOURCES if(APPLE) set (LOGIC_SOURCES ${LOGIC_SOURCES} ${MAC_UPDATE_SOURCES}) +else() + set (LOGIC_SOURCES ${LOGIC_SOURCES} ${PRISM_UPDATE_SOURCES}) endif() SET(LAUNCHER_SOURCES diff --git a/launcher/StringUtils.cpp b/launcher/StringUtils.cpp index e08e6fdce..f437b6dac 100644 --- a/launcher/StringUtils.cpp +++ b/launcher/StringUtils.cpp @@ -35,6 +35,7 @@ */ #include "StringUtils.h" +#include #include #include @@ -149,7 +150,7 @@ QString StringUtils::truncateUrlHumanFriendly(QUrl& url, int max_len, bool hard_ } if ((url_compact.length() >= max_len) && hard_limit) { - // still too long, truncate normaly + // still too long, truncate normally url_compact = QString(str_url); auto to_remove = url_compact.length() - max_len + 3; url_compact.remove(url_compact.length() - to_remove - 1, to_remove); @@ -182,3 +183,28 @@ QString StringUtils::getRandomAlphaNumeric() { return QUuid::createUuid().toString(QUuid::Id128); } + +QPair splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs = Qt::CaseSensitive) { + QString left, right; + auto index = s.indexOf(sep, 0, cs); + left = s.mid(0, index); + right = s.mid(index + 1); + return qMakePair(left, right); +} + +QPair splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs = Qt::CaseSensitive) { + QString left, right; + auto index = s.indexOf(sep, 0, cs); + left = s.mid(0, index); + right = s.mid(index + 1); + return qMakePair(left, right); +} + +QPair splitFirst(const QString& s, const QRegularExpression& re) { + QString left, right; + auto index = s.indexOf(re); + left = s.mid(0, index); + right = s.mid(index + 1); + return qMakePair(left, right); +} + diff --git a/launcher/StringUtils.h b/launcher/StringUtils.h index f90a6ac75..343ac9e4d 100644 --- a/launcher/StringUtils.h +++ b/launcher/StringUtils.h @@ -37,7 +37,9 @@ #pragma once #include +#include #include +#include namespace StringUtils { @@ -70,8 +72,8 @@ int naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs) /** * @brief Truncate a url while keeping its readability py placing the `...` in the middle of the path * @param url Url to truncate - * @param max_len max lenght of url in charaters - * @param hard_limit if truncating the path can't get the url short enough, truncate it normaly. + * @param max_len max length of url in characters + * @param hard_limit if truncating the path can't get the url short enough, truncate it normally. */ QString truncateUrlHumanFriendly(QUrl &url, int max_len, bool hard_limit = false); @@ -79,4 +81,9 @@ QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_poi QString getRandomAlphaNumeric(); + +QPair splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs = Qt::CaseSensitive); +QPair splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs = Qt::CaseSensitive); +QPair splitFirst(const QString& s, const QRegularExpression& re); + } // namespace StringUtils diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp new file mode 100644 index 000000000..f510dfc6c --- /dev/null +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -0,0 +1,206 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "PrismExternalUpdater.h" +#include +#include +#include +#include +#include +#include +#include + +#include "StringUtils.h" + +#include "BuildConfig.h" + +class PrismExternalUpdater::Private { + public: + QDir appDir; + QDir dataDir; + QTimer updateTimer; + bool allowBeta; + bool autoCheck; + double updateInterval; + QDateTime lastCheck; + std::unique_ptr settings; +}; + +PrismExternalUpdater::PrismExternalUpdater(const QString& appDir, const QString& dataDir) +{ + priv = new PrismExternalUpdater::Private(); + priv->appDir = QDir(appDir); + priv->dataDir = QDir(dataDir); + auto settings_file = priv->dataDir.absoluteFilePath("prismlauncher_update.cfg"); + priv->settings = std::make_unique(settings_file, QSettings::Format::IniFormat); + priv->allowBeta = priv->settings->value("allow_beta", false).toBool(); + priv->autoCheck = priv->settings->value("auto_check", false).toBool(); + bool interval_ok; + priv->updateInterval = priv->settings->value("update_interval", 86400).toInt(&interval_ok); + if (!interval_ok) + priv->updateInterval = 86400; + auto last_check = priv->settings->value("last_check"); + if (!last_check.isNull() && last_check.isValid()) { + priv->lastCheck = QDateTime::fromString(last_check.toString(), Qt::ISODate); + } + connectTimer(); + resetAutoCheckTimer(); +} + +PrismExternalUpdater::~PrismExternalUpdater() +{ + if (priv->updateTimer.isActive()) + priv->updateTimer.stop(); + disconnectTimer(); + priv->settings->sync(); + delete priv; +} + +void PrismExternalUpdater::checkForUpdates() +{ + QProgressDialog progress(tr("Checking for updates..."), "", 0, -1); + progress.setCancelButton(nullptr); + progress.show(); + + QProcess proc; + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); +#if defined Q_OS_WIN32 + exe_name.append(".exe"); +#endif + + QStringList args = { "--check-only" }; + if (priv->allowBeta) + args.append("--pre-release"); + + proc.start(priv->appDir.absoluteFilePath(exe_name), args); + auto result_start = proc.waitForStarted(5000); + if (!result_start) { + auto err = proc.error(); + qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString(); + } + auto result_finished = proc.waitForFinished(60000); + if (!result_finished) { + auto err = proc.error(); + qDebug() << "Updater failed to close after 60 seconds." << "reason:" << err << proc.errorString(); + } + + auto exit_code = proc.exitCode(); + + auto std_output = proc.readAllStandardOutput(); + auto std_error = proc.readAllStandardError(); + + switch (exit_code) { + case 0: + // no update available + { + qDebug() << "No update available"; + } + break; + case 1: + // there was an error + { + qDebug() << "Updater subprocess error" << std_error; + } + break; + case 100: + // update available + { + auto [first_line, remainder1] = StringUtils::splitFirst(std_output, '\n'); + auto [second_line, remainder2] = StringUtils::splitFirst(remainder1, '\n'); + auto [third_line, changelog] = StringUtils::splitFirst(remainder2, '\n'); + auto version_name = StringUtils::splitFirst(first_line, ": ").second; + auto version_tag = StringUtils::splitFirst(second_line, ": ").second; + auto release_timestamp = QDateTime::fromString(StringUtils::splitFirst(third_line, ": ").second, Qt::ISODate); + qDebug() << "Update available:" << version_name << version_tag << release_timestamp; + qDebug() << "Update changelog:" << changelog; + } + break; + default: + // unknown error code + { + qDebug() << "Updater exited with unknown code" << exit_code; + } + } + priv->lastCheck = QDateTime::currentDateTime(); + priv->settings->setValue("last_check", priv->lastCheck.toString(Qt::ISODate)); + priv->settings->sync(); +} + +bool PrismExternalUpdater::getAutomaticallyChecksForUpdates() { + return priv->autoCheck; +} + +double PrismExternalUpdater::getUpdateCheckInterval() { + return priv->updateInterval; +} + +bool PrismExternalUpdater::getBetaAllowed() { + return priv->allowBeta; +} + +void PrismExternalUpdater::setAutomaticallyChecksForUpdates(bool check) { + priv->autoCheck = check; + priv->settings->setValue("auto_check", check); + priv->settings->sync(); + resetAutoCheckTimer(); +} + +void PrismExternalUpdater::setUpdateCheckInterval(double seconds) { + priv->updateInterval = seconds; + priv->settings->setValue("update_interval", seconds); + priv->settings->sync(); + resetAutoCheckTimer(); +} + +void PrismExternalUpdater::setBetaAllowed(bool allowed) { + priv->allowBeta = allowed; + priv->settings->setValue("auto_beta", allowed); + priv->settings->sync(); +} + +void PrismExternalUpdater::resetAutoCheckTimer() { + int timeoutDuration = 0; + auto now = QDateTime::currentDateTime(); + if (priv->autoCheck) { + if (priv->lastCheck.isValid()) { + auto diff = priv->lastCheck.secsTo(now); + auto secs_left = priv->updateInterval - diff; + if (secs_left < 0) + secs_left = 0; + timeoutDuration = secs_left * 1000; // to msec + } + priv->updateTimer.start(timeoutDuration); + } else { + if (priv->updateTimer.isActive()) + priv->updateTimer.stop(); + } + +} + +void PrismExternalUpdater::connectTimer() { + connect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired); + +} + +void PrismExternalUpdater::disconnectTimer() { + disconnect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired); +} diff --git a/launcher/updater/PrismExternalUpdater.h b/launcher/updater/PrismExternalUpdater.h new file mode 100644 index 000000000..852fb7d37 --- /dev/null +++ b/launcher/updater/PrismExternalUpdater.h @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +#include "ExternalUpdater.h" + +/*! + * An implementation for the updater on windows and linux that uses out external updater. + */ + +class PrismExternalUpdater : public ExternalUpdater { + Q_OBJECT + + public: + PrismExternalUpdater(const QString& appDir, const QString& dataDir); + ~PrismExternalUpdater() override; + + /*! + * Check for updates manually, showing the user a progress bar and an alert if no updates are found. + */ + void checkForUpdates() override; + + /*! + * Indicates whether or not to check for updates automatically. + */ + bool getAutomaticallyChecksForUpdates() override; + + /*! + * Indicates the current automatic update check interval in seconds. + */ + double getUpdateCheckInterval() override; + + /*! + * Indicates whether or not beta updates should be checked for in addition to regular releases. + */ + bool getBetaAllowed() override; + + /*! + * Set whether or not to check for updates automatically. + * + * The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow + * reverting this property without kicking off a schedule change immediately." + */ + void setAutomaticallyChecksForUpdates(bool check) override; + + /*! + * Set the current automatic update check interval in seconds. + * + * The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow + * reverting this property without kicking off a schedule change immediately." + */ + void setUpdateCheckInterval(double seconds) override; + + /*! + * Set whether or not beta updates should be checked for in addition to regular releases. + */ + void setBetaAllowed(bool allowed) override; + + void resetAutoCheckTimer(); + void disconnectTimer(); + void connectTimer(); + + void performUpdate(); + + public slots: + void autoCheckTimerFired(); + + private: + class Private; + + Private* priv; +}; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 3ca4f235e..f04a12c94 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -41,6 +41,7 @@ #include #include +#include #if defined Q_OS_WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -202,11 +203,17 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 - // attach the parent console - if (AttachConsole(ATTACH_PARENT_PROCESS)) { + // attach the parent console if stdout not already captured + auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + BindCrtHandlesToStdHandles(true, true, true); + consoleAttached = true; + } + } else if (stdout_type == FILE_TYPE_DISK || stdout_type == FILE_TYPE_PIPE ) { BindCrtHandlesToStdHandles(true, true, true); - consoleAttached = true; } + #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN); @@ -226,6 +233,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar { { "U", "update-url" }, tr("Update from the specified repo."), tr("github repo url") }, { { "c", "check-only" }, tr("Only check if an update is needed. Exit status 100 if true, 0 if false (or non 0 if there was an error).") }, + { { "p", "pre-release" }, tr("Allow updating to pre-release releases") }, { { "F", "force" }, tr("Force an update, even if one is not needed.") }, { { "l", "list" }, tr("List available releases.") }, { "debug", tr("Log debug to console.") }, @@ -297,6 +305,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_prismVersionMinor = version_parts.takeFirst().toInt(); } + m_allowPreRelease = parser.isSet("pre-release"); + QString origCwdPath = QDir::currentPath(); QString binPath = applicationDirPath(); @@ -542,10 +552,19 @@ void PrismUpdaterApp::run() auto need_update = needUpdate(latest); if (m_checkOnly) { - if (need_update) + if (need_update) { + QTextStream stdOutStream(stdout); + stdOutStream << "Name: " << latest.name << "\n"; + stdOutStream << "Version: " << latest.tag_name << "\n"; + stdOutStream << "TimeStamp: " << latest.created_at.toString(Qt::ISODate) << "\n"; + stdOutStream << latest.body << "\n"; + stdOutStream.flush(); + return exit(100); - else + } + else { return exit(0); + } } if (m_isFlatpak) { @@ -958,10 +977,11 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) if (auto loc = unpackArchive(archive)) { auto marker_file_path = loc.value().absoluteFilePath(".prism_launcher_updater_unpack.marker"); FS::write(marker_file_path, applicationDirPath().toUtf8()); - auto new_updater_path = loc.value().absoluteFilePath("prismlauncher_updater"); + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 - new_updater_path.append(".exe"); + exe_name.append(".exe"); #endif + auto new_updater_path = loc.value().absoluteFilePath(exe_name); logUpdate(tr("Starting new updater at '%1'").arg(new_updater_path)); QProcess proc = QProcess(); if (!proc.startDetached(new_updater_path, { "-d", m_dataPath }, loc.value().absolutePath())) { @@ -1110,7 +1130,7 @@ bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) QProcess proc = QProcess(); proc.setProcessChannelMode(QProcess::MergedChannels); proc.setReadChannel(QProcess::StandardOutput); - proc.start(exe_path, { "-v" }); + proc.start(exe_path, { "--version" }); if (!proc.waitForStarted(5000)) { showFatalErrorMessage(tr("Failed to Check Version"), tr("Failed to launcher child launcher process to read version.")); return false; @@ -1119,7 +1139,7 @@ bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) showFatalErrorMessage(tr("Failed to Check Version"), tr("Child launcher process failed.")); return false; } - auto out = proc.readAll(); + auto out = proc.readAllStandardOutput(); auto lines = out.split('\n'); if (lines.length() < 2) return false; @@ -1250,7 +1270,11 @@ GitHubRelease PrismUpdaterApp::getLatestRelease() { GitHubRelease latest; for (auto release : m_releases) { - if (!latest.isValid() || (!release.draft && release.version > latest.version)) { + if (release.draft) + continue; + if (release.prerelease && !m_allowPreRelease) + continue; + if (!latest.isValid() || (release.version > latest.version)) { latest = release; } } diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index 90ebeb8d2..f3dd6e062 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -113,6 +113,7 @@ class PrismUpdaterApp : public QApplication { bool m_printOnly; bool m_selectUI; bool m_allowDowngrade; + bool m_allowPreRelease; QString m_updateLogPath; From b7dd32274ca3b04b66ed76f6bb68b77ab5acb338 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 25 Jun 2023 22:30:20 -0700 Subject: [PATCH 095/398] Proper capture on windows Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 2 -- launcher/StringUtils.cpp | 6 +++--- launcher/updater/PrismExternalUpdater.cpp | 15 ++++++++++++++- launcher/updater/prismupdater/PrismUpdater.cpp | 6 +----- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a5103e8e5..4c88a950d 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -280,8 +280,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) BindCrtHandlesToStdHandles(true, true, true); consoleAttached = true; } - } else if (stdout_type == FILE_TYPE_DISK || stdout_type == FILE_TYPE_PIPE ) { - BindCrtHandlesToStdHandles(true, true, true); } #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); diff --git a/launcher/StringUtils.cpp b/launcher/StringUtils.cpp index f437b6dac..b54299721 100644 --- a/launcher/StringUtils.cpp +++ b/launcher/StringUtils.cpp @@ -184,7 +184,7 @@ QString StringUtils::getRandomAlphaNumeric() return QUuid::createUuid().toString(QUuid::Id128); } -QPair splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs = Qt::CaseSensitive) { +QPair StringUtils::splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs) { QString left, right; auto index = s.indexOf(sep, 0, cs); left = s.mid(0, index); @@ -192,7 +192,7 @@ QPair splitFirst(const QString& s, const QString& sep, Qt::Cas return qMakePair(left, right); } -QPair splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs = Qt::CaseSensitive) { +QPair StringUtils::splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs) { QString left, right; auto index = s.indexOf(sep, 0, cs); left = s.mid(0, index); @@ -200,7 +200,7 @@ QPair splitFirst(const QString& s, QChar sep, Qt::CaseSensitiv return qMakePair(left, right); } -QPair splitFirst(const QString& s, const QRegularExpression& re) { +QPair StringUtils::splitFirst(const QString& s, const QRegularExpression& re) { QString left, right; auto index = s.indexOf(re); left = s.mid(0, index); diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index f510dfc6c..9ec033f02 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "StringUtils.h" @@ -80,6 +81,8 @@ void PrismExternalUpdater::checkForUpdates() QProgressDialog progress(tr("Checking for updates..."), "", 0, -1); progress.setCancelButton(nullptr); progress.show(); + QCoreApplication::processEvents(); + QProcess proc; auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); @@ -87,7 +90,7 @@ void PrismExternalUpdater::checkForUpdates() exe_name.append(".exe"); #endif - QStringList args = { "--check-only" }; + QStringList args = { "--check-only", "--dir", priv->dataDir.absolutePath(), "--debug" }; if (priv->allowBeta) args.append("--pre-release"); @@ -97,6 +100,8 @@ void PrismExternalUpdater::checkForUpdates() auto err = proc.error(); qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString(); } + QCoreApplication::processEvents(); + auto result_finished = proc.waitForFinished(60000); if (!result_finished) { auto err = proc.error(); @@ -108,6 +113,9 @@ void PrismExternalUpdater::checkForUpdates() auto std_output = proc.readAllStandardOutput(); auto std_error = proc.readAllStandardError(); + qDebug() << "captured output:" << std_output; + qDebug() << "captured error:" << std_error; + switch (exit_code) { case 0: // no update available @@ -188,6 +196,7 @@ void PrismExternalUpdater::resetAutoCheckTimer() { secs_left = 0; timeoutDuration = secs_left * 1000; // to msec } + qDebug() << "Auto update timer starting," << timeoutDuration / 1000 << "seconds left"; priv->updateTimer.start(timeoutDuration); } else { if (priv->updateTimer.isActive()) @@ -204,3 +213,7 @@ void PrismExternalUpdater::connectTimer() { void PrismExternalUpdater::disconnectTimer() { disconnect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired); } + +void PrismExternalUpdater::autoCheckTimerFired() { + checkForUpdates(); +} diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index f04a12c94..e01295605 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -41,7 +41,6 @@ #include #include -#include #if defined Q_OS_WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -210,10 +209,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar BindCrtHandlesToStdHandles(true, true, true); consoleAttached = true; } - } else if (stdout_type == FILE_TYPE_DISK || stdout_type == FILE_TYPE_PIPE ) { - BindCrtHandlesToStdHandles(true, true, true); - } - + } #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN); From 1f70589debda457b8f43426f7283d9c47a8129f1 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 26 Jun 2023 01:22:33 -0700 Subject: [PATCH 096/398] feat(updater): tie in part 2, let there be UI! Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 115 ++++++++++++- launcher/Application.h | 6 + launcher/CMakeLists.txt | 17 ++ launcher/FileSystem.cpp | 2 +- launcher/ui/dialogs/UpdateAvailableDialog.cpp | 63 +++++++ launcher/ui/dialogs/UpdateAvailableDialog.h | 49 ++++++ launcher/ui/dialogs/UpdateAvailableDialog.ui | 155 ++++++++++++++++++ launcher/updater/PrismExternalUpdater.cpp | 112 ++++++++++--- launcher/updater/PrismExternalUpdater.h | 5 +- .../updater/prismupdater/PrismUpdater.cpp | 24 ++- 10 files changed, 512 insertions(+), 36 deletions(-) create mode 100644 launcher/ui/dialogs/UpdateAvailableDialog.cpp create mode 100644 launcher/ui/dialogs/UpdateAvailableDialog.h create mode 100644 launcher/ui/dialogs/UpdateAvailableDialog.ui diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 4c88a950d..a04f85c28 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -122,6 +122,7 @@ #include #include +#include #include #ifdef Q_OS_LINUX @@ -397,6 +398,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) .arg(dataPath)); return; } + m_dataPath = dataPath; /* * Establish the mechanism for communication with an already running PrismLauncher that uses the same data path. @@ -829,7 +831,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) #ifdef Q_OS_MAC m_updater.reset(new MacSparkleUpdater()); #else - m_updater.reset(new PrismExternalUpdater(m_rootPath, dataPath)); + m_updater.reset(new PrismExternalUpdater(m_rootPath, m_dataPath)); #endif qDebug() << "<> Updater started."; } @@ -1024,9 +1026,120 @@ void Application::setupWizardFinished(int status) performMainStartupAction(); } +std::tuple read_lock_File(const QString& path) +{ + auto contents = QString(FS::read(path)); + auto lines = contents.split('\n'); + + QDateTime timestamp; + QString from, to, target, data_path; + for (auto line : lines) { + auto index = line.indexOf("="); + if (index < 0) + continue; + auto left = line.left(index); + auto right = line.mid(index + 1); + if (left.toLower() == "timestamp") { + timestamp = QDateTime::fromString(right, Qt::ISODate); + } else if (left.toLower() == "from") { + from = right; + } else if (left.toLower() == "to") { + to = right; + } else if (left.toLower() == "target") { + target = right; + } else if (left.toLower() == "data_path") { + data_path = right; + } + } + return std::make_tuple(timestamp, from, to, target, data_path); +} + void Application::performMainStartupAction() { m_status = Application::Initialized; + + auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); + + auto update_lock = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.lock")); + if (update_lock.exists()) { + auto [timestamp, from, to, target, data_path] = read_lock_File(update_lock.absoluteFilePath()); + auto infoMsg = tr("This installation has a update lock file present at: %1\n" + "\n" + "Timestamp: %2\n" + "Updating from version %3 to %4\n" + "Target install path: %5\n" + "Data Path: %6" + "\n" + "This likely means that a update attempt failed. Please ensure your installation is in working order before " + "proceeding.\n" + "Check the Prism Launcher updater log at: \n" + "%7\n" + "for details on the last update attempt.\n" + "\n" + "To delete this lock and proceed select \"Ignore\" below.") + .arg(update_lock.absoluteFilePath()) + .arg(timestamp.toString(Qt::ISODate), from, to, target, data_path) + .arg(update_log_path); + auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update In Progress"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); + msgBox.setDefaultButton(QMessageBox::Abort); + msgBox.setModal(true); + switch (msgBox.exec()) { + case QMessageBox::AcceptRole: { + FS::deletePath(update_lock.absoluteFilePath()); + break; + } + case QMessageBox::RejectRole: + [[fallthrough]]; + default: { + qDebug() << "Exiting because update lockfile is present"; + exit(1); + } + } + } + + auto update_fail_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.fail")); + if (update_fail_marker.exists()) { + auto infoMsg = tr("An update attempt failed\n" + "\n" + "Please ensure your installation is in working order before " + "proceeding.\n" + "Check the Prism Launcher updater log at: \n" + "%1\n" + "for details on the last update attempt.") + .arg(update_log_path); + auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Failed"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); + msgBox.setDefaultButton(QMessageBox::Abort); + msgBox.setModal(true); + switch (msgBox.exec()) { + case QMessageBox::AcceptRole: { + FS::deletePath(update_fail_marker.absoluteFilePath()); + break; + } + case QMessageBox::RejectRole: + [[fallthrough]]; + default: { + qDebug() << "Exiting because update lockfile is present"; + exit(1); + } + } + } + + auto update_success_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.success")); + if (update_success_marker.exists()) { + auto infoMsg = tr("Update succeeded\n" + "\n" + "You are now running %1 .\n" + "Check the Prism Launcher updater log at: \n" + "%1\n" + "for details.") + .arg(BuildConfig.printableVersionString()) + .arg(update_log_path); + auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.open(); + FS::deletePath(update_success_marker.absoluteFilePath()); + } + if (!m_instanceIdToLaunch.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToLaunch); if (inst) { diff --git a/launcher/Application.h b/launcher/Application.h index ced0af17d..baf64575d 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -187,6 +187,11 @@ public: return m_rootPath; } + /// the data path the application is using + const QString& dataRoot() { + return m_dataPath; + } + bool isPortable() { return m_portable; } @@ -277,6 +282,7 @@ private: QMap> m_profilers; QString m_rootPath; + QString m_dataPath; Status m_status = Application::StartingUp; Capabilities m_capabilities; bool m_portable = false; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 86bf8fc48..b68179af8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1078,6 +1078,15 @@ SET(LAUNCHER_SOURCES ui/instanceview/VisualGroup.h ) +if (NOT Apple) +set(LAUNCHER_SOURCES + ${LAUNCHER_SOURCES} + + ui/dialogs/UpdateAvailableDialog.h + ui/dialogs/UpdateAvailableDialog.cpp +) +endif() + qt_wrap_ui(LAUNCHER_UI ui/MainWindow.ui ui/setupwizard/PasteWizardPage.ui @@ -1138,6 +1147,14 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ChooseProviderDialog.ui ) +qt_wrap_ui(PRISM_UPDATE_UI + ui/dialogs/UpdateAvailableDialog.ui +) + +if (NOT Apple) + set (LAUNCHER_UI ${LAUNCHER_UI} ${PRISM_UPDATE_UI}) +endif() + qt_add_resources(LAUNCHER_RESOURCES resources/backgrounds/backgrounds.qrc resources/multimc/multimc.qrc diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 2a0ca76b5..7bfb5b1e3 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -199,7 +199,7 @@ void appendSafe(const QString& filename, const QByteArray& data) QByteArray buffer; try { buffer = read(filename); - } catch (FileSystemException) { + } catch (FileSystemException&) { buffer = QByteArray(); } buffer.append(data); diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.cpp b/launcher/ui/dialogs/UpdateAvailableDialog.cpp new file mode 100644 index 000000000..9f7308cba --- /dev/null +++ b/launcher/ui/dialogs/UpdateAvailableDialog.cpp @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "UpdateAvailableDialog.h" +#include +#include "Application.h" +#include "BuildConfig.h" +#include "Markdown.h" +#include "ui_UpdateAvailableDialog.h" + +UpdateAvailableDialog::UpdateAvailableDialog(const QString& currentVersion, + const QString& availableVersion, + const QString& releaseNotes, + QWidget* parent) + : QDialog(parent), ui(new Ui::UpdateAvailableDialog) +{ + ui->setupUi(this); + + QString launcherName = BuildConfig.LAUNCHER_DISPLAYNAME; + + ui->headerLabel->setText(tr("A new version of %1 is available!").arg(launcherName)); + ui->versionAvailableLabel->setText( + tr("Version %1 is now available - you have %2 . Would you like to download it now?").arg(availableVersion).arg(currentVersion)); + ui->icon->setPixmap(APPLICATION->getThemedIcon("checkupdate").pixmap(64)); + + auto releaseNotesHtml = markdownToHTML(releaseNotes); + ui->releaseNotes->setHtml(releaseNotesHtml); + ui->releaseNotes->setOpenExternalLinks(true); + + connect(ui->skipButton, &QPushButton::clicked, this, [this](){ + this->setResult(DialogCode::Skip); + this->close(); + }); + + connect(ui->delayButton, &QPushButton::clicked, this, [this](){ + this->setResult(DialogCode::DontInstall); + this->close(); + }); + + connect(ui->installButton, &QPushButton::clicked, this, [this](){ + this->setResult(DialogCode::Install); + this->close(); + }); +} diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.h b/launcher/ui/dialogs/UpdateAvailableDialog.h new file mode 100644 index 000000000..d37839fda --- /dev/null +++ b/launcher/ui/dialogs/UpdateAvailableDialog.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include + +namespace Ui { +class UpdateAvailableDialog; +} + +class UpdateAvailableDialog : public QDialog { + Q_OBJECT + + public: + + enum DialogCode { + Install, + DontInstall, + Skip, + }; + + explicit UpdateAvailableDialog(const QString& currentVersion, + const QString& availableVersion, + const QString& releaseNotes, + QWidget* parent = 0); + ~UpdateAvailableDialog(); + + private: + Ui::UpdateAvailableDialog* ui; +}; diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.ui b/launcher/ui/dialogs/UpdateAvailableDialog.ui new file mode 100644 index 000000000..b0d85f6f0 --- /dev/null +++ b/launcher/ui/dialogs/UpdateAvailableDialog.ui @@ -0,0 +1,155 @@ + + + UpdateAvailableDialog + + + + 0 + 0 + 636 + 352 + + + + Update Available + + + + + + + + + + + 64 + 64 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 11 + 75 + true + + + + A new version is available! + + + + + + + Version %1 is now available - you have %2 . Would you like to download it now? + + + + + + + + 75 + true + + + + Release Notes: + + + + + + + + + + + + + + + + Skip This Version + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Remind Me Later + + + false + + + false + + + + + + + Install Update + + + true + + + + + + + + + + diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 9ec033f02..f2c88cf6a 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -21,19 +21,22 @@ */ #include "PrismExternalUpdater.h" -#include +#include #include -#include #include #include -#include +#include #include -#include +#include +#include +#include #include "StringUtils.h" #include "BuildConfig.h" +#include "ui/dialogs/UpdateAvailableDialog.h" + class PrismExternalUpdater::Private { public: QDir appDir; @@ -78,12 +81,11 @@ PrismExternalUpdater::~PrismExternalUpdater() void PrismExternalUpdater::checkForUpdates() { - QProgressDialog progress(tr("Checking for updates..."), "", 0, -1); + QProgressDialog progress(tr("Checking for updates..."), "", 0, 0); progress.setCancelButton(nullptr); progress.show(); QCoreApplication::processEvents(); - QProcess proc; auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 @@ -98,14 +100,16 @@ void PrismExternalUpdater::checkForUpdates() auto result_start = proc.waitForStarted(5000); if (!result_start) { auto err = proc.error(); - qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString(); + qDebug() << "Failed to start updater after 5 seconds." + << "reason:" << err << proc.errorString(); } QCoreApplication::processEvents(); auto result_finished = proc.waitForFinished(60000); if (!result_finished) { auto err = proc.error(); - qDebug() << "Updater failed to close after 60 seconds." << "reason:" << err << proc.errorString(); + qDebug() << "Updater failed to close after 60 seconds." + << "reason:" << err << proc.errorString(); } auto exit_code = proc.exitCode(); @@ -116,6 +120,9 @@ void PrismExternalUpdater::checkForUpdates() qDebug() << "captured output:" << std_output; qDebug() << "captured error:" << std_error; + progress.hide(); + QCoreApplication::processEvents(); + switch (exit_code) { case 0: // no update available @@ -134,12 +141,14 @@ void PrismExternalUpdater::checkForUpdates() { auto [first_line, remainder1] = StringUtils::splitFirst(std_output, '\n'); auto [second_line, remainder2] = StringUtils::splitFirst(remainder1, '\n'); - auto [third_line, changelog] = StringUtils::splitFirst(remainder2, '\n'); + auto [third_line, release_notes] = StringUtils::splitFirst(remainder2, '\n'); auto version_name = StringUtils::splitFirst(first_line, ": ").second; auto version_tag = StringUtils::splitFirst(second_line, ": ").second; auto release_timestamp = QDateTime::fromString(StringUtils::splitFirst(third_line, ": ").second, Qt::ISODate); qDebug() << "Update available:" << version_name << version_tag << release_timestamp; - qDebug() << "Update changelog:" << changelog; + qDebug() << "Update release notes:" << release_notes; + + offerUpdate(version_name, version_tag, release_notes); } break; default: @@ -153,48 +162,55 @@ void PrismExternalUpdater::checkForUpdates() priv->settings->sync(); } -bool PrismExternalUpdater::getAutomaticallyChecksForUpdates() { +bool PrismExternalUpdater::getAutomaticallyChecksForUpdates() +{ return priv->autoCheck; } -double PrismExternalUpdater::getUpdateCheckInterval() { +double PrismExternalUpdater::getUpdateCheckInterval() +{ return priv->updateInterval; } -bool PrismExternalUpdater::getBetaAllowed() { +bool PrismExternalUpdater::getBetaAllowed() +{ return priv->allowBeta; } -void PrismExternalUpdater::setAutomaticallyChecksForUpdates(bool check) { +void PrismExternalUpdater::setAutomaticallyChecksForUpdates(bool check) +{ priv->autoCheck = check; priv->settings->setValue("auto_check", check); priv->settings->sync(); resetAutoCheckTimer(); } -void PrismExternalUpdater::setUpdateCheckInterval(double seconds) { +void PrismExternalUpdater::setUpdateCheckInterval(double seconds) +{ priv->updateInterval = seconds; priv->settings->setValue("update_interval", seconds); priv->settings->sync(); resetAutoCheckTimer(); } -void PrismExternalUpdater::setBetaAllowed(bool allowed) { +void PrismExternalUpdater::setBetaAllowed(bool allowed) +{ priv->allowBeta = allowed; priv->settings->setValue("auto_beta", allowed); priv->settings->sync(); } -void PrismExternalUpdater::resetAutoCheckTimer() { +void PrismExternalUpdater::resetAutoCheckTimer() +{ int timeoutDuration = 0; auto now = QDateTime::currentDateTime(); if (priv->autoCheck) { - if (priv->lastCheck.isValid()) { + if (priv->lastCheck.isValid()) { auto diff = priv->lastCheck.secsTo(now); auto secs_left = priv->updateInterval - diff; if (secs_left < 0) secs_left = 0; - timeoutDuration = secs_left * 1000; // to msec + timeoutDuration = secs_left * 1000; // to msec } qDebug() << "Auto update timer starting," << timeoutDuration / 1000 << "seconds left"; priv->updateTimer.start(timeoutDuration); @@ -202,18 +218,66 @@ void PrismExternalUpdater::resetAutoCheckTimer() { if (priv->updateTimer.isActive()) priv->updateTimer.stop(); } - } -void PrismExternalUpdater::connectTimer() { +void PrismExternalUpdater::connectTimer() +{ connect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired); - } -void PrismExternalUpdater::disconnectTimer() { +void PrismExternalUpdater::disconnectTimer() +{ disconnect(&priv->updateTimer, &QTimer::timeout, this, &PrismExternalUpdater::autoCheckTimerFired); } -void PrismExternalUpdater::autoCheckTimerFired() { +void PrismExternalUpdater::autoCheckTimerFired() +{ checkForUpdates(); } + +void PrismExternalUpdater::offerUpdate(const QString& version_name, const QString& version_tag, const QString& release_notes) +{ + priv->settings->beginGroup("skip"); + auto should_skip = priv->settings->value(version_tag, false).toBool(); + priv->settings->endGroup(); + + if (should_skip) + return; + + UpdateAvailableDialog dlg(BuildConfig.printableVersionString(), version_name, release_notes); + + auto result = dlg.exec(); + switch (result) { + case UpdateAvailableDialog::Install: { + performUpdate(version_tag); + } + case UpdateAvailableDialog::Skip: { + priv->settings->beginGroup("skip"); + priv->settings->setValue(version_tag, true); + priv->settings->endGroup(); + priv->settings->sync(); + return; + } + case UpdateAvailableDialog::DontInstall: { + return; + } + } +} + +void PrismExternalUpdater::performUpdate(const QString& version_tag) { + QProcess proc; + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); +#if defined Q_OS_WIN32 + exe_name.append(".exe"); +#endif + + QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", version_tag }; + if (priv->allowBeta) + args.append("--pre-release"); + + auto result = proc.startDetached(priv->appDir.absoluteFilePath(exe_name), args); + if (!result) { + qDebug() << "Failed to start updater:" << proc.error() << proc.errorString(); + } + QCoreApplication::exit(); +} diff --git a/launcher/updater/PrismExternalUpdater.h b/launcher/updater/PrismExternalUpdater.h index 852fb7d37..f8ed29ccc 100644 --- a/launcher/updater/PrismExternalUpdater.h +++ b/launcher/updater/PrismExternalUpdater.h @@ -34,7 +34,7 @@ class PrismExternalUpdater : public ExternalUpdater { Q_OBJECT public: - PrismExternalUpdater(const QString& appDir, const QString& dataDir); + PrismExternalUpdater(const QString& appDir, const QString& dataDir); ~PrismExternalUpdater() override; /*! @@ -82,7 +82,8 @@ class PrismExternalUpdater : public ExternalUpdater { void disconnectTimer(); void connectTimer(); - void performUpdate(); + void offerUpdate(const QString& version_name, const QString& version_tag, const QString& release_notes); + void performUpdate(const QString& version_tag); public slots: void autoCheckTimerFired(); diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index e01295605..658b1a57b 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -630,7 +630,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) for (auto file : files) { file_list.append(file.trimmed()); } - } catch (FS::FileSystemException) { + } catch (FS::FileSystemException&) { } } @@ -675,15 +675,23 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) if (error) { logUpdate(tr("There were errors installing the update.")); auto fail_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.fail"); - FS::move(m_updateLogPath, fail_marker); + FS::copy(m_updateLogPath, fail_marker)(); } else { logUpdate(tr("Update succeed.")); auto success_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.success"); - FS::move(m_updateLogPath, success_marker); + FS::copy(m_updateLogPath, success_marker)(); } auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"); FS::deletePath(update_lock_path); + QProcess proc; + auto app_exe_name = BuildConfig.LAUNCHER_APP_BINARY_NAME; +#if defined Q_OS_WIN32 + app_exe_name.append(".exe"); +#endif + auto app_exe_path = target.absoluteFilePath(app_exe_name); + proc.startDetached(app_exe_path); + exit(error ? 1 : 0); } @@ -897,7 +905,7 @@ bool write_lock_file(const QString& path, QDateTime timestamp, QString from, QSt .arg(target) .arg(data_path) .toUtf8()); - } catch (FS::FileSystemException err) { + } catch (FS::FileSystemException& err) { qWarning() << "Error writing lockfile:" << err.what() << "\n" << err.cause(); return false; } @@ -922,7 +930,7 @@ void PrismUpdaterApp::performInstall(QFileInfo file) "\n" "This likely means that a previous update attempt failed. Please ensure your installation is in working order before " "proceeding.\n" - "Check the Prism Launcher updater log at \n" + "Check the Prism Launcher updater log at: \n" "%7\n" "for details on the last update attempt.\n" "\n" @@ -936,9 +944,9 @@ void PrismUpdaterApp::performInstall(QFileInfo file) msgBox.setStandardButtons(QMessageBox::Ignore | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); switch (msgBox.exec()) { - case QMessageBox::Ignore: + case QMessageBox::AcceptRole: break; - case QMessageBox::Cancel: + case QMessageBox::RejectRole: [[fallthrough]]; default: return showFatalErrorMessage(tr("Update Aborted"), tr("The update attempt was aborted")); @@ -1005,7 +1013,7 @@ void PrismUpdaterApp::backupAppDir() for (auto file : files) { file_list.append(file.trimmed()); } - } catch (FS::FileSystemException) { + } catch (FS::FileSystemException&) { } } From c0f046255084ce88323375af665c2d6bf27e2385 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 26 Jun 2023 01:41:51 -0700 Subject: [PATCH 097/398] fix(updater): logs/ folder Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 10 ++++++++-- launcher/ui/dialogs/UpdateAvailableDialog.h | 2 +- launcher/updater/prismupdater/PrismUpdater.cpp | 5 +++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a04f85c28..e172472a1 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -831,7 +831,13 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) #ifdef Q_OS_MAC m_updater.reset(new MacSparkleUpdater()); #else - m_updater.reset(new PrismExternalUpdater(m_rootPath, m_dataPath)); + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); +#if defined Q_OS_WIN32 + exe_name.append(".exe"); +#endif + auto updater_binary = QFileInfo(QDir(m_rootPath).absoluteFilePath(exe_name)); + if (updater_binary.isFile()) + m_updater.reset(new PrismExternalUpdater(m_rootPath, m_dataPath)); #endif qDebug() << "<> Updater started."; } @@ -1058,7 +1064,7 @@ void Application::performMainStartupAction() { m_status = Application::Initialized; - auto update_log_path = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); + auto update_log_path = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); auto update_lock = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.lock")); if (update_lock.exists()) { diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.h b/launcher/ui/dialogs/UpdateAvailableDialog.h index d37839fda..7a14c01da 100644 --- a/launcher/ui/dialogs/UpdateAvailableDialog.h +++ b/launcher/ui/dialogs/UpdateAvailableDialog.h @@ -42,7 +42,7 @@ class UpdateAvailableDialog : public QDialog { const QString& availableVersion, const QString& releaseNotes, QWidget* parent = 0); - ~UpdateAvailableDialog(); + ~UpdateAvailableDialog() = default; private: Ui::UpdateAvailableDialog* ui; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 658b1a57b..439457bae 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -343,10 +343,11 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar #endif } - m_updateLogPath = FS::PathCombine(m_dataPath, "prism_launcher_update.log"); + m_updateLogPath = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); { // setup logging - static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; + static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; + static const QString logBase = FS::PathCombine("logs", baseLogFile); auto moveFile = [](const QString& oldName, const QString& newName) { QFile::remove(newName); QFile::copy(oldName, newName); From 385babb4583a10a6c669c80b0f1b75799fa85049 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 27 Jun 2023 01:01:02 +0300 Subject: [PATCH 098/398] Simplify Upload and Download Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 2 + launcher/net/ApiDownload.cpp | 3 + launcher/net/ApiUpload.cpp | 11 +- launcher/net/Download.cpp | 272 +---------------------------- launcher/net/Download.h | 34 +--- launcher/net/NetRequest.cpp | 327 +++++++++++++++++++++++++++++++++++ launcher/net/NetRequest.h | 97 +++++++++++ launcher/net/Upload.cpp | 216 +---------------------- launcher/net/Upload.h | 22 +-- 9 files changed, 451 insertions(+), 533 deletions(-) create mode 100644 launcher/net/NetRequest.cpp create mode 100644 launcher/net/NetRequest.h diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 20372dbc3..df8489e53 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -143,6 +143,8 @@ set(NET_SOURCES net/ApiDownload.cpp net/ApiUpload.cpp net/ApiUpload.h + net/NetRequest.cpp + net/NetRequest.h ) # Game launch logic diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp index aaa8ff650..5dfaa51df 100644 --- a/launcher/net/ApiDownload.cpp +++ b/launcher/net/ApiDownload.cpp @@ -28,6 +28,7 @@ namespace Net { auto ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr { auto dl = makeShared(); + dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("CACHE:") + url.toString()); dl->m_options = options; @@ -40,6 +41,7 @@ auto ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> D auto ApiDownload::makeByteArray(QUrl url, std::shared_ptr output, Options options) -> Download::Ptr { auto dl = makeShared(); + dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("BYTES:") + url.toString()); dl->m_options = options; @@ -50,6 +52,7 @@ auto ApiDownload::makeByteArray(QUrl url, std::shared_ptr output, Op auto ApiDownload::makeFile(QUrl url, QString path, Options options) -> Download::Ptr { auto dl = makeShared(); + dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("FILE:") + url.toString()); dl->m_options = options; diff --git a/launcher/net/ApiUpload.cpp b/launcher/net/ApiUpload.cpp index 96ebc49cb..ec4f14af7 100644 --- a/launcher/net/ApiUpload.cpp +++ b/launcher/net/ApiUpload.cpp @@ -27,11 +27,12 @@ namespace Net { Upload::Ptr ApiUpload::makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data) { - auto up = makeShared(); - up->m_url = std::move(url); - up->m_sink.reset(new ByteArraySink(output)); - up->m_post_data = std::move(m_post_data); - return up; + auto up = makeShared(); + up->logCat = taskUploadLogC; + up->m_url = std::move(url); + up->m_sink.reset(new ByteArraySink(output)); + up->m_post_data = std::move(m_post_data); + return up; } void ApiUpload::init() diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index c08281854..dc3168788 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -65,6 +65,7 @@ namespace Net { auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr { auto dl = makeShared(); + dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("CACHE:") + url.toString()); dl->m_options = options; @@ -78,6 +79,7 @@ auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Down auto Download::makeByteArray(QUrl url, std::shared_ptr output, Options options) -> Download::Ptr { auto dl = makeShared(); + dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("BYTES:") + url.toString()); dl->m_options = options; @@ -88,6 +90,7 @@ auto Download::makeByteArray(QUrl url, std::shared_ptr output, Optio auto Download::makeFile(QUrl url, QString path, Options options) -> Download::Ptr { auto dl = makeShared(); + dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("FILE:") + url.toString()); dl->m_options = options; @@ -95,271 +98,8 @@ auto Download::makeFile(QUrl url, QString path, Options options) -> Download::Pt return dl; } -void Download::addValidator(Validator* v) +QNetworkReply* Download::getReply(QNetworkRequest& request) { - m_sink->addValidator(v); -} - -void Download::executeTask() -{ - init(); - - setStatus(tr("Downloading %1").arg(StringUtils::truncateUrlHumanFriendly(m_url, 80))); - - if (getState() == Task::State::AbortedByUser) { - qCWarning(taskDownloadLogC) << getUid().toString() << "Attempt to start an aborted Download:" << m_url.toString(); - emitAborted(); - return; - } - - QNetworkRequest request(m_url); - m_state = m_sink->init(request); - switch (m_state) { - case State::Succeeded: - qCDebug(taskDownloadLogC) << getUid().toString() << "Download cache hit " << m_url.toString(); - emit succeeded(); - emit finished(); - return; - case State::Running: - qCDebug(taskDownloadLogC) << getUid().toString() << "Downloading " << m_url.toString(); - break; - case State::Inactive: - case State::Failed: - emitFailed(); - return; - case State::AbortedByUser: - emitAborted(); - return; - } - -#if defined (LAUNCHER_APPLICATION) - auto user_agent = APPLICATION->getUserAgent(); -#else - auto user_agent = BuildConfig.USER_AGENT; -#endif - - request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8()); - for ( auto& header_proxy : m_headerProxies ) { - - header_proxy->writeHeaders(request); - } - // TODO remove duplication - - -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - request.setTransferTimeout(); -#endif - - m_last_progress_time = m_clock.now(); - m_last_progress_bytes = 0; - - QNetworkReply* rep = m_network->get(request); - m_reply.reset(rep); - connect(rep, &QNetworkReply::downloadProgress, this, &Download::downloadProgress); - connect(rep, &QNetworkReply::finished, this, &Download::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 - connect(rep, &QNetworkReply::errorOccurred, this, &Download::downloadError); -#else - connect(rep, QOverload::of(&QNetworkReply::error), this, &Download::downloadError); -#endif - connect(rep, &QNetworkReply::sslErrors, this, &Download::sslErrors); - connect(rep, &QNetworkReply::readyRead, this, &Download::downloadReadyRead); -} - -void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - auto now = m_clock.now(); - auto elapsed = now - m_last_progress_time; - - // use milliseconds for speed precision - auto elapsed_ms = std::chrono::duration_cast(elapsed); - auto bytes_received_since = bytesReceived - m_last_progress_bytes; - auto dl_speed_bps = (double)bytes_received_since / elapsed_ms.count() * 1000; - auto remaining_time_s = (bytesTotal - bytesReceived) / dl_speed_bps; - - //: Current amount of bytes downloaded, out of the total amount of bytes in the download - QString dl_progress = - tr("%1 / %2").arg(StringUtils::humanReadableFileSize(bytesReceived)).arg(StringUtils::humanReadableFileSize(bytesTotal)); - - QString dl_speed_str; - if (elapsed_ms.count() > 0) { - auto str_eta = bytesTotal > 0 ? Time::humanReadableDuration(remaining_time_s) : tr("unknown"); - //: Download speed, in bytes per second (remaining download time in parenthesis) - dl_speed_str = - tr("%1 /s (%2)").arg(StringUtils::humanReadableFileSize(dl_speed_bps)).arg(str_eta); - } else { - //: Download speed at 0 bytes per second - dl_speed_str = tr("0 B/s"); - } - - setDetails(dl_progress + "\n" + dl_speed_str); - - setProgress(bytesReceived, bytesTotal); -} - -void Download::downloadError(QNetworkReply::NetworkError error) -{ - if (error == QNetworkReply::OperationCanceledError) { - qCCritical(taskDownloadLogC) << getUid().toString() << "Aborted " << m_url.toString(); - m_state = State::AbortedByUser; - } else { - if (m_options & Option::AcceptLocalFiles) { - if (m_sink->hasLocalData()) { - m_state = State::Succeeded; - return; - } - } - // error happened during download. - qCCritical(taskDownloadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; - m_state = State::Failed; - } -} - -void Download::sslErrors(const QList& errors) -{ - int i = 1; - for (auto error : errors) { - qCCritical(taskDownloadLogC) << getUid().toString() << "Download" << m_url.toString() << "SSL Error #" << i << " : " - << error.errorString(); - auto cert = error.certificate(); - qCCritical(taskDownloadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); - i++; - } -} - -auto Download::handleRedirect() -> bool -{ - QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); - if (!redirect.isValid()) { - if (!m_reply->hasRawHeader("Location")) { - // no redirect -> it's fine to continue - return false; - } - // there is a Location header, but it's not correct. we need to apply some workarounds... - QByteArray redirectBA = m_reply->rawHeader("Location"); - if (redirectBA.size() == 0) { - // empty, yet present redirect header? WTF? - return false; - } - QString redirectStr = QString::fromUtf8(redirectBA); - - if (redirectStr.startsWith("//")) { - /* - * IF the URL begins with //, we need to insert the URL scheme. - * See: https://bugreports.qt.io/browse/QTBUG-41061 - * See: http://tools.ietf.org/html/rfc3986#section-4.2 - */ - redirectStr = m_reply->url().scheme() + ":" + redirectStr; - } else if (redirectStr.startsWith("/")) { - /* - * IF the URL begins with /, we need to process it as a relative URL - */ - auto url = m_reply->url(); - url.setPath(redirectStr, QUrl::TolerantMode); - redirectStr = url.toString(); - } - - /* - * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. - * FIXME: report Qt bug for this - */ - redirect = QUrl(redirectStr, QUrl::TolerantMode); - if (!redirect.isValid()) { - qCWarning(taskDownloadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; - downloadError(QNetworkReply::ProtocolFailure); - return false; - } - qCDebug(taskDownloadLogC) << getUid().toString() << "Fixed location header:" << redirect; - } else { - qCDebug(taskDownloadLogC) << getUid().toString() << "Location header:" << redirect; - } - - m_url = QUrl(redirect.toString()); - qCDebug(taskDownloadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); - startAction(m_network); - - return true; -} - -void Download::downloadFinished() -{ - // handle HTTP redirection first - if (handleRedirect()) { - qCDebug(taskDownloadLogC) << getUid().toString() << "Download redirected:" << m_url.toString(); - return; - } - - // if the download failed before this point ... - if (m_state == State::Succeeded) // pretend to succeed so we continue processing :) - { - qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed but we are allowed to proceed:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit succeeded(); - emit finished(); - return; - } else if (m_state == State::Failed) { - qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - emit finished(); - return; - } else if (m_state == State::AbortedByUser) { - qCDebug(taskDownloadLogC) << getUid().toString() << "Download aborted in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit aborted(); - emit finished(); - return; - } - - // make sure we got all the remaining data, if any - auto data = m_reply->readAll(); - if (data.size()) { - qCDebug(taskDownloadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; - m_state = m_sink->write(data); - } - - // otherwise, finalize the whole graph - m_state = m_sink->finalize(*m_reply.get()); - if (m_state != State::Succeeded) { - qCDebug(taskDownloadLogC) << getUid().toString() << "Download failed to finalize:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - emit finished(); - return; - } - - m_reply.reset(); - qCDebug(taskDownloadLogC) << getUid().toString() << "Download succeeded:" << m_url.toString(); - emit succeeded(); - emit finished(); -} - -void Download::downloadReadyRead() -{ - if (m_state == State::Running) { - auto data = m_reply->readAll(); - m_state = m_sink->write(data); - if (m_state == State::Failed) { - qCCritical(taskDownloadLogC) << getUid().toString() << "Failed to process response chunk"; - } - // qDebug() << "Download" << m_url.toString() << "gained" << data.size() << "bytes"; - } else { - qCCritical(taskDownloadLogC) << getUid().toString() << "Cannot write download data! illegal status " << m_status; - } -} - -} // namespace Net - -auto Net::Download::abort() -> bool -{ - if (m_reply) { - m_reply->abort(); - } else { - m_state = State::AbortedByUser; - } - return true; + return m_network->get(request); } +} // namespace Net \ No newline at end of file diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 2fa318ef2..113875ee7 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -46,15 +46,14 @@ #include "Validator.h" #include "QObjectPtr.h" +#include "net/NetRequest.h" namespace Net { -class Download : public NetAction { +class Download : public NetRequest { Q_OBJECT public: using Ptr = shared_qobject_ptr; - enum class Option { NoOptions = 0, AcceptLocalFiles = 1, MakeEternal = 2 }; - Q_DECLARE_FLAGS(Options, Option) public: ~Download() override = default; @@ -66,34 +65,9 @@ class Download : public NetAction { static auto makeByteArray(QUrl url, std::shared_ptr output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; - void init() override {}; - - public: - void addValidator(Validator* v); - auto abort() -> bool override; - auto canAbort() const -> bool override { return true; }; - - private: - auto handleRedirect() -> bool; - - protected slots: - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; - void downloadError(QNetworkReply::NetworkError error) override; - void sslErrors(const QList& errors) override; - void downloadFinished() override; - void downloadReadyRead() override; - - public slots: - void executeTask() override; + void init() override{}; protected: - std::unique_ptr m_sink; - Options m_options; - - std::chrono::steady_clock m_clock; - std::chrono::time_point m_last_progress_time; - qint64 m_last_progress_bytes; + virtual QNetworkReply* getReply(QNetworkRequest&) override; }; } // namespace Net - -Q_DECLARE_OPERATORS_FOR_FLAGS(Net::Download::Options) diff --git a/launcher/net/NetRequest.cpp b/launcher/net/NetRequest.cpp new file mode 100644 index 000000000..3f7cdbaa8 --- /dev/null +++ b/launcher/net/NetRequest.cpp @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 "NetRequest.h" +#include + +#include +#include +#include + +#include "ByteArraySink.h" +#include "ChecksumValidator.h" +#include "MetaCacheSink.h" + +#if defined(LAUNCHER_APPLICATION) +#include "Application.h" +#endif + +#include "BuildConfig.h" + +#include "net/Logging.h" +#include "net/NetAction.h" + +#include "MMCTime.h" +#include "StringUtils.h" + +namespace Net { + +void NetRequest::addValidator(Validator* v) +{ + m_sink->addValidator(v); +} + +void NetRequest::executeTask() +{ + init(); + + setStatus(tr("Downloading %1").arg(StringUtils::truncateUrlHumanFriendly(m_url, 80))); + + if (getState() == Task::State::AbortedByUser) { + qCWarning(logCat) << getUid().toString() << "Attempt to start an aborted Request:" << m_url.toString(); + emitAborted(); + return; + } + + QNetworkRequest request(m_url); + m_state = m_sink->init(request); + switch (m_state) { + case State::Succeeded: + qCDebug(logCat) << getUid().toString() << "Request cache hit " << m_url.toString(); + emit succeeded(); + emit finished(); + return; + case State::Running: + qCDebug(logCat) << getUid().toString() << "Runninng " << m_url.toString(); + break; + case State::Inactive: + case State::Failed: + emitFailed(); + return; + case State::AbortedByUser: + emitAborted(); + return; + } + +#if defined(LAUNCHER_APPLICATION) + auto user_agent = APPLICATION->getUserAgent(); +#else + auto user_agent = BuildConfig.USER_AGENT; +#endif + + request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8()); + for (auto& header_proxy : m_headerProxies) { + header_proxy->writeHeaders(request); + } + // TODO remove duplication + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + request.setTransferTimeout(); +#endif + + m_last_progress_time = m_clock.now(); + m_last_progress_bytes = 0; + + QNetworkReply* rep = getReply(request); + m_reply.reset(rep); + connect(rep, &QNetworkReply::downloadProgress, this, &NetRequest::downloadProgress); + connect(rep, &QNetworkReply::finished, this, &NetRequest::downloadFinished); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &NetRequest::downloadError); +#else + connect(rep, QOverload::of(&QNetworkReply::error), this, &NetRequest::downloadError); +#endif + connect(rep, &QNetworkReply::sslErrors, this, &NetRequest::sslErrors); + connect(rep, &QNetworkReply::readyRead, this, &NetRequest::downloadReadyRead); +} + +void NetRequest::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + auto now = m_clock.now(); + auto elapsed = now - m_last_progress_time; + + // use milliseconds for speed precision + auto elapsed_ms = std::chrono::duration_cast(elapsed); + auto bytes_received_since = bytesReceived - m_last_progress_bytes; + auto dl_speed_bps = (double)bytes_received_since / elapsed_ms.count() * 1000; + auto remaining_time_s = (bytesTotal - bytesReceived) / dl_speed_bps; + + //: Current amount of bytes downloaded, out of the total amount of bytes in the download + QString dl_progress = + tr("%1 / %2").arg(StringUtils::humanReadableFileSize(bytesReceived)).arg(StringUtils::humanReadableFileSize(bytesTotal)); + + QString dl_speed_str; + if (elapsed_ms.count() > 0) { + auto str_eta = bytesTotal > 0 ? Time::humanReadableDuration(remaining_time_s) : tr("unknown"); + //: Download speed, in bytes per second (remaining download time in parenthesis) + dl_speed_str = tr("%1 /s (%2)").arg(StringUtils::humanReadableFileSize(dl_speed_bps)).arg(str_eta); + } else { + //: Download speed at 0 bytes per second + dl_speed_str = tr("0 B/s"); + } + + setDetails(dl_progress + "\n" + dl_speed_str); + + setProgress(bytesReceived, bytesTotal); +} + +void NetRequest::downloadError(QNetworkReply::NetworkError error) +{ + if (error == QNetworkReply::OperationCanceledError) { + qCCritical(logCat) << getUid().toString() << "Aborted " << m_url.toString(); + m_state = State::AbortedByUser; + } else { + if (m_options & Option::AcceptLocalFiles) { + if (m_sink->hasLocalData()) { + m_state = State::Succeeded; + return; + } + } + // error happened during download. + qCCritical(logCat) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; + m_state = State::Failed; + } +} + +void NetRequest::sslErrors(const QList& errors) +{ + int i = 1; + for (auto error : errors) { + qCCritical(logCat) << getUid().toString() << "Request" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); + auto cert = error.certificate(); + qCCritical(logCat) << getUid().toString() << "Certificate in question:\n" << cert.toText(); + i++; + } +} + +auto NetRequest::handleRedirect() -> bool +{ + QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); + if (!redirect.isValid()) { + if (!m_reply->hasRawHeader("Location")) { + // no redirect -> it's fine to continue + return false; + } + // there is a Location header, but it's not correct. we need to apply some workarounds... + QByteArray redirectBA = m_reply->rawHeader("Location"); + if (redirectBA.size() == 0) { + // empty, yet present redirect header? WTF? + return false; + } + QString redirectStr = QString::fromUtf8(redirectBA); + + if (redirectStr.startsWith("//")) { + /* + * IF the URL begins with //, we need to insert the URL scheme. + * See: https://bugreports.qt.io/browse/QTBUG-41061 + * See: http://tools.ietf.org/html/rfc3986#section-4.2 + */ + redirectStr = m_reply->url().scheme() + ":" + redirectStr; + } else if (redirectStr.startsWith("/")) { + /* + * IF the URL begins with /, we need to process it as a relative URL + */ + auto url = m_reply->url(); + url.setPath(redirectStr, QUrl::TolerantMode); + redirectStr = url.toString(); + } + + /* + * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. + * FIXME: report Qt bug for this + */ + redirect = QUrl(redirectStr, QUrl::TolerantMode); + if (!redirect.isValid()) { + qCWarning(logCat) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; + downloadError(QNetworkReply::ProtocolFailure); + return false; + } + qCDebug(logCat) << getUid().toString() << "Fixed location header:" << redirect; + } else { + qCDebug(logCat) << getUid().toString() << "Location header:" << redirect; + } + + m_url = QUrl(redirect.toString()); + qCDebug(logCat) << getUid().toString() << "Following redirect to " << m_url.toString(); + startAction(m_network); + + return true; +} + +void NetRequest::downloadFinished() +{ + // handle HTTP redirection first + if (handleRedirect()) { + qCDebug(logCat) << getUid().toString() << "Request redirected:" << m_url.toString(); + return; + } + + // if the download failed before this point ... + if (m_state == State::Succeeded) // pretend to succeed so we continue processing :) + { + qCDebug(logCat) << getUid().toString() << "Request failed but we are allowed to proceed:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit succeeded(); + emit finished(); + return; + } else if (m_state == State::Failed) { + qCDebug(logCat) << getUid().toString() << "Request failed in previous step:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit failed(""); + emit finished(); + return; + } else if (m_state == State::AbortedByUser) { + qCDebug(logCat) << getUid().toString() << "Request aborted in previous step:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit aborted(); + emit finished(); + return; + } + + // make sure we got all the remaining data, if any + auto data = m_reply->readAll(); + if (data.size()) { + qCDebug(logCat) << getUid().toString() << "Writing extra" << data.size() << "bytes"; + m_state = m_sink->write(data); + } + + // otherwise, finalize the whole graph + m_state = m_sink->finalize(*m_reply.get()); + if (m_state != State::Succeeded) { + qCDebug(logCat) << getUid().toString() << "Request failed to finalize:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit failed(""); + emit finished(); + return; + } + + m_reply.reset(); + qCDebug(logCat) << getUid().toString() << "Request succeeded:" << m_url.toString(); + emit succeeded(); + emit finished(); +} + +void NetRequest::downloadReadyRead() +{ + if (m_state == State::Running) { + auto data = m_reply->readAll(); + m_state = m_sink->write(data); + if (m_state == State::Failed) { + qCCritical(logCat) << getUid().toString() << "Failed to process response chunk"; + } + // qDebug() << "Request" << m_url.toString() << "gained" << data.size() << "bytes"; + } else { + qCCritical(logCat) << getUid().toString() << "Cannot write download data! illegal status " << m_status; + } +} + +} // namespace Net + +auto Net::NetRequest::abort() -> bool +{ + if (m_reply) { + m_reply->abort(); + } else { + m_state = State::AbortedByUser; + } + return true; +} diff --git a/launcher/net/NetRequest.h b/launcher/net/NetRequest.h new file mode 100644 index 000000000..0105a60c3 --- /dev/null +++ b/launcher/net/NetRequest.h @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 "NetAction.h" +#include "Sink.h" +#include "Validator.h" + +#include "QObjectPtr.h" +#include "net/Logging.h" + +namespace Net { +class NetRequest : public NetAction { + Q_OBJECT + + public: + using Ptr = shared_qobject_ptr; + enum class Option { NoOptions = 0, AcceptLocalFiles = 1, MakeEternal = 2 }; + Q_DECLARE_FLAGS(Options, Option) + + public: + ~NetRequest() override = default; + + void init() override{}; + + public: + void addValidator(Validator* v); + auto abort() -> bool override; + auto canAbort() const -> bool override { return true; }; + + private: + auto handleRedirect() -> bool; + virtual QNetworkReply* getReply(QNetworkRequest&) = 0; + + protected slots: + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; + void downloadError(QNetworkReply::NetworkError error) override; + void sslErrors(const QList& errors) override; + void downloadFinished() override; + void downloadReadyRead() override; + + public slots: + void executeTask() override; + + protected: + std::unique_ptr m_sink; + Options m_options; + + typedef const QLoggingCategory& (*logCatFunc)(); + logCatFunc logCat = taskUploadLogC; + + std::chrono::steady_clock m_clock; + std::chrono::time_point m_last_progress_time; + qint64 m_last_progress_bytes; +}; +} // namespace Net + +Q_DECLARE_OPERATORS_FOR_FLAGS(Net::NetRequest::Options) diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index d9115ede1..245a52aea 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -40,232 +40,22 @@ #include #include -#include "BuildConfig.h" #include "ByteArraySink.h" -#if defined(LAUNCHER_APPLICATION) -#include "Application.h" -#endif - #include "net/Logging.h" namespace Net { -bool Upload::abort() +QNetworkReply* Upload::getReply(QNetworkRequest& request) { - if (m_reply) { - m_reply->abort(); - } else { - m_state = State::AbortedByUser; - } - return true; -} - -void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - setProgress(bytesReceived, bytesTotal); -} - -void Upload::downloadError(QNetworkReply::NetworkError error) -{ - if (error == QNetworkReply::OperationCanceledError) { - qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString(); - m_state = State::AbortedByUser; - } else { - // error happened during download. - qCCritical(taskUploadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; - m_state = State::Failed; - } -} - -void Upload::sslErrors(const QList& errors) -{ - int i = 1; - for (const auto& error : errors) { - qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " - << error.errorString(); - auto cert = error.certificate(); - qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); - i++; - } -} - -bool Upload::handleRedirect() -{ - QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); - if (!redirect.isValid()) { - if (!m_reply->hasRawHeader("Location")) { - // no redirect -> it's fine to continue - return false; - } - // there is a Location header, but it's not correct. we need to apply some workarounds... - QByteArray redirectBA = m_reply->rawHeader("Location"); - if (redirectBA.size() == 0) { - // empty, yet present redirect header? WTF? - return false; - } - QString redirectStr = QString::fromUtf8(redirectBA); - - if (redirectStr.startsWith("//")) { - /* - * IF the URL begins with //, we need to insert the URL scheme. - * See: https://bugreports.qt.io/browse/QTBUG-41061 - * See: http://tools.ietf.org/html/rfc3986#section-4.2 - */ - redirectStr = m_reply->url().scheme() + ":" + redirectStr; - } else if (redirectStr.startsWith("/")) { - /* - * IF the URL begins with /, we need to process it as a relative URL - */ - auto url = m_reply->url(); - url.setPath(redirectStr, QUrl::TolerantMode); - redirectStr = url.toString(); - } - - /* - * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. - * FIXME: report Qt bug for this - */ - redirect = QUrl(redirectStr, QUrl::TolerantMode); - if (!redirect.isValid()) { - qCWarning(taskUploadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; - downloadError(QNetworkReply::ProtocolFailure); - return false; - } - qCDebug(taskUploadLogC) << getUid().toString() << "Fixed location header:" << redirect; - } else { - qCDebug(taskUploadLogC) << getUid().toString() << "Location header:" << redirect; - } - - m_url = QUrl(redirect.toString()); - qCDebug(taskUploadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); - startAction(m_network); - return true; -} - -void Upload::downloadFinished() -{ - // handle HTTP redirection first - // very unlikely for post requests, still can happen - if (handleRedirect()) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload redirected:" << m_url.toString(); - return; - } - - // if the download failed before this point ... - if (m_state == State::Succeeded) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit succeeded(); - emit finished(); - return; - } else if (m_state == State::Failed) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - emit finished(); - return; - } else if (m_state == State::AbortedByUser) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit aborted(); - emit finished(); - return; - } - - // make sure we got all the remaining data, if any - auto data = m_reply->readAll(); - if (data.size()) { - qCDebug(taskUploadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; - m_state = m_sink->write(data); - } - - // otherwise, finalize the whole graph - m_state = m_sink->finalize(*m_reply.get()); - if (m_state != State::Succeeded) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - emit finished(); - return; - } - m_reply.reset(); - qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString(); - emit succeeded(); - emit finished(); -} - -void Upload::downloadReadyRead() -{ - if (m_state == State::Running) { - auto data = m_reply->readAll(); - m_state = m_sink->write(data); - } -} - -void Upload::executeTask() -{ - setStatus(tr("Uploading %1").arg(m_url.toString())); - - if (m_state == State::AbortedByUser) { - qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString(); - emit aborted(); - emit finished(); - return; - } - QNetworkRequest request(m_url); - m_state = m_sink->init(request); - switch (m_state) { - case State::Succeeded: - emitSucceeded(); - qCDebug(taskUploadLogC) << getUid().toString() << "Upload cache hit " << m_url.toString(); - return; - case State::Running: - qCDebug(taskUploadLogC) << getUid().toString() << "Uploading " << m_url.toString(); - break; - case State::Inactive: - case State::Failed: - emitFailed(""); - return; - case State::AbortedByUser: - emitAborted(); - return; - } - -#if defined(LAUNCHER_APPLICATION) - auto user_agent = APPLICATION->getUserAgent(); -#else - auto user_agent = BuildConfig.USER_AGENT; -#endif - request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8()); - - for (auto& header_proxy : m_headerProxies) { - header_proxy->writeHeaders(request); - } - - // TODO other types of post requests ? request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QNetworkReply* rep = m_network->post(request, m_post_data); - - m_reply.reset(rep); - connect(rep, &QNetworkReply::downloadProgress, this, &Upload::downloadProgress); - connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 - connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError); -#else - connect(rep, QOverload::of(&QNetworkReply::error), this, &Upload::downloadError); -#endif - connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors); - connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead); + return m_network->post(request, m_post_data); } Upload::Ptr Upload::makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data) { auto up = makeShared(); + up->logCat = taskUploadLogC; up->m_url = std::move(url); up->m_sink.reset(new ByteArraySink(output)); up->m_post_data = std::move(m_post_data); diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h index 8be3f2c11..51ce410bb 100644 --- a/launcher/net/Upload.h +++ b/launcher/net/Upload.h @@ -37,37 +37,21 @@ #pragma once -#include "NetAction.h" -#include "Sink.h" +#include "net/NetRequest.h" namespace Net { -class Upload : public NetAction { +class Upload : public NetRequest { Q_OBJECT public: using Ptr = shared_qobject_ptr; static Upload::Ptr makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data); - auto abort() -> bool override; - auto canAbort() const -> bool override { return true; }; - virtual void init() override{}; - - protected slots: - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; - void downloadError(QNetworkReply::NetworkError error) override; - void sslErrors(const QList& errors) override; - void downloadFinished() override; - void downloadReadyRead() override; - - public slots: - void executeTask() override; protected: - std::unique_ptr m_sink; + virtual QNetworkReply* getReply(QNetworkRequest&) override; QByteArray m_post_data; - - bool handleRedirect(); }; } // namespace Net From 45c39d078ff4675a87f97bc2e5cc5f072e591856 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 27 Jun 2023 09:23:24 +0300 Subject: [PATCH 099/398] More clenup Signed-off-by: Trial97 --- launcher/net/ApiDownload.cpp | 3 --- launcher/net/ApiUpload.cpp | 1 - launcher/net/Download.cpp | 13 ------------- launcher/net/Download.h | 12 +----------- launcher/net/NetRequest.cpp | 15 ++++----------- launcher/net/NetRequest.h | 2 ++ launcher/net/Upload.cpp | 3 --- launcher/net/Upload.h | 2 +- 8 files changed, 8 insertions(+), 43 deletions(-) diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp index 5dfaa51df..aaa8ff650 100644 --- a/launcher/net/ApiDownload.cpp +++ b/launcher/net/ApiDownload.cpp @@ -28,7 +28,6 @@ namespace Net { auto ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr { auto dl = makeShared(); - dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("CACHE:") + url.toString()); dl->m_options = options; @@ -41,7 +40,6 @@ auto ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> D auto ApiDownload::makeByteArray(QUrl url, std::shared_ptr output, Options options) -> Download::Ptr { auto dl = makeShared(); - dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("BYTES:") + url.toString()); dl->m_options = options; @@ -52,7 +50,6 @@ auto ApiDownload::makeByteArray(QUrl url, std::shared_ptr output, Op auto ApiDownload::makeFile(QUrl url, QString path, Options options) -> Download::Ptr { auto dl = makeShared(); - dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("FILE:") + url.toString()); dl->m_options = options; diff --git a/launcher/net/ApiUpload.cpp b/launcher/net/ApiUpload.cpp index ec4f14af7..c1221b764 100644 --- a/launcher/net/ApiUpload.cpp +++ b/launcher/net/ApiUpload.cpp @@ -28,7 +28,6 @@ namespace Net { Upload::Ptr ApiUpload::makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data) { auto up = makeShared(); - up->logCat = taskUploadLogC; up->m_url = std::move(url); up->m_sink.reset(new ByteArraySink(output)); up->m_post_data = std::move(m_post_data); diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index dc3168788..d25447b2d 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -47,25 +47,14 @@ #include "ChecksumValidator.h" #include "MetaCacheSink.h" -#if defined(LAUNCHER_APPLICATION) -#include "Application.h" -#endif - -#include "BuildConfig.h" - -#include "net/Logging.h" #include "net/NetAction.h" -#include "MMCTime.h" -#include "StringUtils.h" - namespace Net { #if defined(LAUNCHER_APPLICATION) auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr { auto dl = makeShared(); - dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("CACHE:") + url.toString()); dl->m_options = options; @@ -79,7 +68,6 @@ auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Down auto Download::makeByteArray(QUrl url, std::shared_ptr output, Options options) -> Download::Ptr { auto dl = makeShared(); - dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("BYTES:") + url.toString()); dl->m_options = options; @@ -90,7 +78,6 @@ auto Download::makeByteArray(QUrl url, std::shared_ptr output, Optio auto Download::makeFile(QUrl url, QString path, Options options) -> Download::Ptr { auto dl = makeShared(); - dl->logCat = taskDownloadLogC; dl->m_url = url; dl->setObjectName(QString("FILE:") + url.toString()); dl->m_options = options; diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 113875ee7..dc3ccacf0 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -38,12 +38,7 @@ #pragma once -#include - #include "HttpMetaCache.h" -#include "NetAction.h" -#include "Sink.h" -#include "Validator.h" #include "QObjectPtr.h" #include "net/NetRequest.h" @@ -51,12 +46,9 @@ namespace Net { class Download : public NetRequest { Q_OBJECT - public: using Ptr = shared_qobject_ptr; - - public: - ~Download() override = default; + explicit Download() : NetRequest() { logCat = taskDownloadLogC; }; #if defined(LAUNCHER_APPLICATION) static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; @@ -65,8 +57,6 @@ class Download : public NetRequest { static auto makeByteArray(QUrl url, std::shared_ptr output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; - void init() override{}; - protected: virtual QNetworkReply* getReply(QNetworkRequest&) override; }; diff --git a/launcher/net/NetRequest.cpp b/launcher/net/NetRequest.cpp index 3f7cdbaa8..304577121 100644 --- a/launcher/net/NetRequest.cpp +++ b/launcher/net/NetRequest.cpp @@ -43,17 +43,10 @@ #include #include -#include "ByteArraySink.h" -#include "ChecksumValidator.h" -#include "MetaCacheSink.h" - #if defined(LAUNCHER_APPLICATION) #include "Application.h" #endif -#include "BuildConfig.h" - -#include "net/Logging.h" #include "net/NetAction.h" #include "MMCTime.h" @@ -70,7 +63,7 @@ void NetRequest::executeTask() { init(); - setStatus(tr("Downloading %1").arg(StringUtils::truncateUrlHumanFriendly(m_url, 80))); + setStatus(tr("Requesting %1").arg(StringUtils::truncateUrlHumanFriendly(m_url, 80))); if (getState() == Task::State::AbortedByUser) { qCWarning(logCat) << getUid().toString() << "Attempt to start an aborted Request:" << m_url.toString(); @@ -314,9 +307,7 @@ void NetRequest::downloadReadyRead() } } -} // namespace Net - -auto Net::NetRequest::abort() -> bool +auto NetRequest::abort() -> bool { if (m_reply) { m_reply->abort(); @@ -325,3 +316,5 @@ auto Net::NetRequest::abort() -> bool } return true; } + +} // namespace Net diff --git a/launcher/net/NetRequest.h b/launcher/net/NetRequest.h index 0105a60c3..6ebdcab05 100644 --- a/launcher/net/NetRequest.h +++ b/launcher/net/NetRequest.h @@ -51,6 +51,8 @@ namespace Net { class NetRequest : public NetAction { Q_OBJECT + protected: + explicit NetRequest() : NetAction(){}; public: using Ptr = shared_qobject_ptr; diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index 245a52aea..726572e52 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -42,8 +42,6 @@ #include #include "ByteArraySink.h" -#include "net/Logging.h" - namespace Net { QNetworkReply* Upload::getReply(QNetworkRequest& request) @@ -55,7 +53,6 @@ QNetworkReply* Upload::getReply(QNetworkRequest& request) Upload::Ptr Upload::makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data) { auto up = makeShared(); - up->logCat = taskUploadLogC; up->m_url = std::move(url); up->m_sink.reset(new ByteArraySink(output)); up->m_post_data = std::move(m_post_data); diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h index 51ce410bb..f920e5561 100644 --- a/launcher/net/Upload.h +++ b/launcher/net/Upload.h @@ -43,9 +43,9 @@ namespace Net { class Upload : public NetRequest { Q_OBJECT - public: using Ptr = shared_qobject_ptr; + explicit Upload() : NetRequest() { logCat = taskUploadLogC; }; static Upload::Ptr makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data); From 6f7454243ef8d6c9b317ee7e83cf0c361f863c14 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 26 Jun 2023 23:24:46 -0700 Subject: [PATCH 100/398] fix: prep for changes in #1276 - sign updater Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 9 +- CMakeLists.txt | 10 +- buildconfig/BuildConfig.cpp.in | 22 ++ buildconfig/BuildConfig.h | 36 ++- launcher/Application.cpp | 229 +++++++++--------- .../updater/prismupdater/PrismUpdater.cpp | 16 +- 6 files changed, 197 insertions(+), 125 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 777e7a79b..5a1554fc6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -283,12 +283,12 @@ jobs: if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_UPDATER_GITHUB_REPO=https://github.com/${{ github.repository }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }} -G Ninja - name: Configure CMake (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_UPDATER_GITHUB_REPO=https://github.com/${{ github.repository }} + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }} # https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix) if ("${{ env.CCACHE_VAR }}") { @@ -303,7 +303,7 @@ jobs: - name: Configure CMake (Linux) if: runner.os == 'Linux' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_UPDATER_GITHUB_REPO=https://github.com/${{ github.repository }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=${{ matrix.name }} -G Ninja ## # BUILD @@ -391,7 +391,6 @@ jobs: if: runner.os == 'Windows' && matrix.msystem == '' run: | cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }} - Get-Content ${{ env.BUILD_DIR }}/install_manifest.txt | %{ $_.TrimStart("$pwd/") } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('./') } | Out-File -Append -FilePath ${{ env.INSTALL_DIR }}/manifest.txt cd ${{ env.INSTALL_DIR }} if ("${{ matrix.qt_ver }}" -eq "5") @@ -416,7 +415,7 @@ jobs: if (Get-Content ./codesign.pfx){ cd ${{ env.INSTALL_DIR }} # We ship the exact same executable for portable and non-portable editions, so signing just once is fine - SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_filelink.exe + SignTool sign /fd sha256 /td sha256 /f ../codesign.pfx /p '${{ secrets.WINDOWS_CODESIGN_PASSWORD }}' /tr http://timestamp.digicert.com prismlauncher.exe prismlauncher_updater.exe prismlauncher_filelink.exe } else { ":warning: Skipped code signing for Windows, as certificate was not present." >> $env:GITHUB_STEP_SUMMARY } diff --git a/CMakeLists.txt b/CMakeLists.txt index cb75f769c..bbe8bfbbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,7 +149,10 @@ set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_M set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used to display in the about dialog.") # Github repo URL with releases for updater -set(Launcher_UPDATER_GITHUB_REPO "" CACHE STRING "Base URL for the updater.") +set(Launcher_UPDATER_GITHUB_REPO "https://github.com/PrismLauncher/PrismLauncher" CACHE STRING "Base github URL for the updater.") + +# Name to help updater identify valid artifacts +set(Launcher_BUILD_ARTIFACT "" CACHE STRING "Artifact name to help the updater identify valid artifacts.") # The metadata server set(Launcher_META_URL "https://meta.prismlauncher.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.") @@ -193,6 +196,11 @@ set(Launcher_MSA_CLIENT_ID "c36a9fb6-4f2a-41ff-90bd-ae7cc92031eb" CACHE STRING " # This key was issued specifically for Prism Launcher set(Launcher_CURSEFORGE_API_KEY "$2a$10$wuAJuNZuted3NORVmpgUC.m8sI.pv1tOPKZyBgLFGjxFp/br0lZCC" CACHE STRING "API key for the CurseForge platform") +set(Launcher_COMPILER_NAME ${CMAKE_CXX_COMPILER_ID}) +set(Launcher_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}) +set(Launcher_COMPILER_TARGET_SYSTEM ${CMAKE_SYSTEM_NAME}) +set(Launcher_COMPILER_TARGET_SYSTEM_VERSION ${CMAKE_SYSTEM_VERSION}) +set(Launcher_COMPILER_TARGET_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}) #### Check the current Git commit and branch include(GetGitRevisionDescription) diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index b03867c3c..e8e8a4ef8 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -33,6 +33,7 @@ * limitations under the License. */ +#include #include "BuildConfig.h" #include @@ -59,9 +60,17 @@ Config::Config() VERSION_MINOR = @Launcher_VERSION_MINOR@; BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@"; + BUILD_ARTIFACT = "@Launcher_BUILD_ARTIFACT@"; BUILD_DATE = "@Launcher_BUILD_TIMESTAMP@"; UPDATER_GITHUB_REPO = "@Launcher_UPDATER_GITHUB_REPO@"; + COMPILER_NAME = "@Launcher_COMPILER_NAME@"; + COMPILER_VERSION = "@Launcher_COMPILER_VERSION@"; + + COMPILER_TARGET_SYSTEM = "@Launcher_COMPILER_TARGET_SYSTEM@"; + COMPILER_TARGET_SYSTEM_VERSION = "@Launcher_COMPILER_TARGET_SYSTEM_VERSION@"; + COMPILER_TARGET_SYSTEM_PROCESSOR = "@Launcher_COMPILER_TARGET_PROCESSOR@"; + MAC_SPARKLE_PUB_KEY = "@MACOSX_SPARKLE_UPDATE_PUBLIC_KEY@"; MAC_SPARKLE_APPCAST_URL = "@MACOSX_SPARKLE_UPDATE_FEED_URL@"; @@ -133,3 +142,16 @@ QString Config::printableVersionString() const } return vstr; } + +QString Config::compilerID() const +{ + if (COMPILER_VERSION.isEmpty()) + return COMPILER_NAME; + return QStringLiteral("%1 - %2").arg(COMPILER_NAME).arg(COMPILER_VERSION); +} + +QString Config::systemID() const +{ + return QStringLiteral("%1 %2 %3").arg(COMPILER_TARGET_SYSTEM, COMPILER_TARGET_SYSTEM_VERSION, COMPILER_TARGET_SYSTEM_PROCESSOR); +} + diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index b6ae6e6d8..723b2e714 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -36,8 +36,8 @@ */ #pragma once -#include #include +#include /** * \brief The Config class holds all the build-time information passed from the build system. @@ -71,9 +71,27 @@ class Config { /// A short string identifying this build's platform. For example, "lin64" or "win32". QString BUILD_PLATFORM; + /// A short string identifying this build's valid artifacts int he updater. For example, "lin64" or "win32". + QString BUILD_ARTIFACT; + /// A string containing the build timestamp QString BUILD_DATE; + /// A string identifying the compiler use to build + QString COMPILER_NAME; + + /// A string identifying the compiler version used to build + QString COMPILER_VERSION; + + /// A string identifying the compiler target system os + QString COMPILER_TARGET_SYSTEM; + + /// A String identifying the compiler target system version + QString COMPILER_TARGET_SYSTEM_VERSION; + + /// A String identifying the compiler target processor + QString COMPILER_TARGET_SYSTEM_PROCESSOR; + /// URL for the updater's channel QString UPDATER_GITHUB_REPO; @@ -145,7 +163,7 @@ class Config { QString AUTH_BASE = "https://authserver.mojang.com/"; QString IMGUR_BASE_URL = "https://api.imgur.com/3/"; QString FMLLIBS_BASE_URL = "https://files.prismlauncher.org/fmllibs/"; // FIXME: move into CMakeLists - QString TRANSLATIONS_BASE_URL = "https://i18n.prismlauncher.org/"; // FIXME: move into CMakeLists + QString TRANSLATIONS_BASE_URL = "https://i18n.prismlauncher.org/"; // FIXME: move into CMakeLists QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/"; @@ -162,7 +180,7 @@ class Config { QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2"; QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2"; - QStringList MODRINTH_MRPACK_HOSTS{"cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com"}; + QStringList MODRINTH_MRPACK_HOSTS{ "cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com" }; QString FLAME_BASE_URL = "https://api.curseforge.com/v1"; @@ -172,6 +190,18 @@ class Config { * \return The version number in string format (major.minor.revision.build). */ QString printableVersionString() const; + + /** + * \brief Compiler ID String + * \return a string of the form "Name - Version" of just "Name" if the version is empty + */ + QString compilerID() const; + + /** + * \brief System ID String + * \return a string of the form "OS Verison Processor" + */ + QString systemID() const; }; extern const Config BuildConfig; diff --git a/launcher/Application.cpp b/launcher/Application.cpp index e172472a1..a8b26ed74 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -175,6 +175,34 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt } // namespace +std::tuple read_lock_File(const QString& path) +{ + auto contents = QString(FS::read(path)); + auto lines = contents.split('\n'); + + QDateTime timestamp; + QString from, to, target, data_path; + for (auto line : lines) { + auto index = line.indexOf("="); + if (index < 0) + continue; + auto left = line.left(index); + auto right = line.mid(index + 1); + if (left.toLower() == "timestamp") { + timestamp = QDateTime::fromString(right, Qt::ISODate); + } else if (left.toLower() == "from") { + from = right; + } else if (left.toLower() == "to") { + to = right; + } else if (left.toLower() == "target") { + target = right; + } else if (left.toLower() == "data_path") { + data_path = right; + } + } + return std::make_tuple(timestamp, from, to, target, data_path); +} + #if defined Q_OS_WIN32 // taken from https://stackoverflow.com/a/25927081 @@ -554,6 +582,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qDebug() << "Version : " << BuildConfig.printableVersionString(); qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; + qDebug() << "Compiled for : " << BuildConfig.systemID(); + qDebug() << "Compiled by : " << BuildConfig.compilerID(); if (adjustedBy.size()) { qDebug() << "Work dir before adjustment : " << origcwdPath; qDebug() << "Work dir after adjustment : " << QDir::currentPath(); @@ -942,6 +972,95 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) applyCurrentlySelectedTheme(true); + // check update locks + { + auto update_log_path = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); + + auto update_lock = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.lock")); + if (update_lock.exists()) { + auto [timestamp, from, to, target, data_path] = read_lock_File(update_lock.absoluteFilePath()); + auto infoMsg = tr("This installation has a update lock file present at: %1\n" + "\n" + "Timestamp: %2\n" + "Updating from version %3 to %4\n" + "Target install path: %5\n" + "Data Path: %6" + "\n" + "This likely means that a update attempt failed. Please ensure your installation is in working order before " + "proceeding.\n" + "Check the Prism Launcher updater log at: \n" + "%7\n" + "for details on the last update attempt.\n" + "\n" + "To delete this lock and proceed select \"Ignore\" below.") + .arg(update_lock.absoluteFilePath()) + .arg(timestamp.toString(Qt::ISODate), from, to, target, data_path) + .arg(update_log_path); + auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update In Progress"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); + msgBox.setDefaultButton(QMessageBox::Abort); + msgBox.setModal(true); + auto res = msgBox.exec(); + switch (res) { + case QMessageBox::Ignore: { + FS::deletePath(update_lock.absoluteFilePath()); + break; + } + case QMessageBox::Abort: + [[fallthrough]]; + default: { + qDebug() << "Exiting because update lockfile is present"; + QMetaObject::invokeMethod(this, [](){ exit(1); }, Qt::QueuedConnection); + return; + } + } + } + + auto update_fail_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.fail")); + if (update_fail_marker.exists()) { + auto infoMsg = tr("An update attempt failed\n" + "\n" + "Please ensure your installation is in working order before " + "proceeding.\n" + "Check the Prism Launcher updater log at: \n" + "%1\n" + "for details on the last update attempt.") + .arg(update_log_path); + auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Failed"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); + msgBox.setDefaultButton(QMessageBox::Abort); + msgBox.setModal(true); + auto res = msgBox.exec(); + switch (res) { + case QMessageBox::Ignore: { + FS::deletePath(update_fail_marker.absoluteFilePath()); + break; + } + case QMessageBox::Abort: + [[fallthrough]]; + default: { + qDebug() << "Exiting because update lockfile is present"; + QMetaObject::invokeMethod(this, [](){ exit(1); }, Qt::QueuedConnection); + return; + } + } + } + + auto update_success_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.success")); + if (update_success_marker.exists()) { + auto infoMsg = tr("Update succeeded\n" + "\n" + "You are now running %1 .\n" + "Check the Prism Launcher updater log at: \n" + "%1\n" + "for details.") + .arg(BuildConfig.printableVersionString()) + .arg(update_log_path); + auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.open(); + FS::deletePath(update_success_marker.absoluteFilePath()); + } + } + updateCapabilities(); if (createSetupWizard()) { @@ -1032,119 +1151,11 @@ void Application::setupWizardFinished(int status) performMainStartupAction(); } -std::tuple read_lock_File(const QString& path) -{ - auto contents = QString(FS::read(path)); - auto lines = contents.split('\n'); - - QDateTime timestamp; - QString from, to, target, data_path; - for (auto line : lines) { - auto index = line.indexOf("="); - if (index < 0) - continue; - auto left = line.left(index); - auto right = line.mid(index + 1); - if (left.toLower() == "timestamp") { - timestamp = QDateTime::fromString(right, Qt::ISODate); - } else if (left.toLower() == "from") { - from = right; - } else if (left.toLower() == "to") { - to = right; - } else if (left.toLower() == "target") { - target = right; - } else if (left.toLower() == "data_path") { - data_path = right; - } - } - return std::make_tuple(timestamp, from, to, target, data_path); -} - void Application::performMainStartupAction() { m_status = Application::Initialized; - auto update_log_path = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); - - auto update_lock = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.lock")); - if (update_lock.exists()) { - auto [timestamp, from, to, target, data_path] = read_lock_File(update_lock.absoluteFilePath()); - auto infoMsg = tr("This installation has a update lock file present at: %1\n" - "\n" - "Timestamp: %2\n" - "Updating from version %3 to %4\n" - "Target install path: %5\n" - "Data Path: %6" - "\n" - "This likely means that a update attempt failed. Please ensure your installation is in working order before " - "proceeding.\n" - "Check the Prism Launcher updater log at: \n" - "%7\n" - "for details on the last update attempt.\n" - "\n" - "To delete this lock and proceed select \"Ignore\" below.") - .arg(update_lock.absoluteFilePath()) - .arg(timestamp.toString(Qt::ISODate), from, to, target, data_path) - .arg(update_log_path); - auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update In Progress"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); - msgBox.setDefaultButton(QMessageBox::Abort); - msgBox.setModal(true); - switch (msgBox.exec()) { - case QMessageBox::AcceptRole: { - FS::deletePath(update_lock.absoluteFilePath()); - break; - } - case QMessageBox::RejectRole: - [[fallthrough]]; - default: { - qDebug() << "Exiting because update lockfile is present"; - exit(1); - } - } - } - - auto update_fail_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.fail")); - if (update_fail_marker.exists()) { - auto infoMsg = tr("An update attempt failed\n" - "\n" - "Please ensure your installation is in working order before " - "proceeding.\n" - "Check the Prism Launcher updater log at: \n" - "%1\n" - "for details on the last update attempt.") - .arg(update_log_path); - auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Failed"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); - msgBox.setDefaultButton(QMessageBox::Abort); - msgBox.setModal(true); - switch (msgBox.exec()) { - case QMessageBox::AcceptRole: { - FS::deletePath(update_fail_marker.absoluteFilePath()); - break; - } - case QMessageBox::RejectRole: - [[fallthrough]]; - default: { - qDebug() << "Exiting because update lockfile is present"; - exit(1); - } - } - } - - auto update_success_marker = QFileInfo(FS::PathCombine(m_dataPath, ".prism_launcher_update.success")); - if (update_success_marker.exists()) { - auto infoMsg = tr("Update succeeded\n" - "\n" - "You are now running %1 .\n" - "Check the Prism Launcher updater log at: \n" - "%1\n" - "for details.") - .arg(BuildConfig.printableVersionString()) - .arg(update_log_path); - auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.open(); - FS::deletePath(update_success_marker.absoluteFilePath()); - } + if (!m_instanceIdToLaunch.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToLaunch); diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 439457bae..3fd832b24 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -244,7 +244,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar auto updater_executable = QCoreApplication::applicationFilePath(); - if (BuildConfig.BUILD_PLATFORM.toLower() == "macos") + if (BuildConfig.BUILD_ARTIFACT.toLower() == "macos") showFatalErrorMessage(tr("MacOS Not Supported"), tr("The updater does not support installations on MacOS")); if (updater_executable.startsWith("/tmp/.mount_")) { @@ -435,6 +435,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "Version : " << BuildConfig.printableVersionString(); qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; + qDebug() << "Compiled for : " << BuildConfig.systemID(); + qDebug() << "Compiled by : " << BuildConfig.compilerID(); if (adjustedBy.size()) { qDebug() << "Data dir before adjustment : " << origCwdPath; qDebug() << "Data dir after adjustment : " << m_dataPath; @@ -576,7 +578,7 @@ void PrismUpdaterApp::run() return exit(result ? 0 : 1); } - if (BuildConfig.BUILD_PLATFORM.toLower() == "linux" && !m_isPortable) { + if (BuildConfig.BUILD_ARTIFACT.toLower() == "linux" && !m_isPortable) { showFatalErrorMessage(tr("Updating Not Supported"), tr("Updating non-portable linux installations is not supported. Please use your system package manager")); return; @@ -751,9 +753,9 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel { QList valid; - qDebug() << "Selecting best asset from" << release.tag_name << "for platform" << BuildConfig.BUILD_PLATFORM + qDebug() << "Selecting best asset from" << release.tag_name << "for platform" << BuildConfig.BUILD_ARTIFACT << "portable:" << m_isPortable; - if (BuildConfig.BUILD_PLATFORM.isEmpty()) + if (BuildConfig.BUILD_ARTIFACT.isEmpty()) qWarning() << "Build platform is not set!"; for (auto asset : release.assets) { if (!m_isAppimage && asset.name.toLower().endsWith("appimage")) @@ -761,7 +763,7 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel else if (m_isAppimage && !asset.name.toLower().endsWith("appimage")) continue; auto asset_name = asset.name.toLower(); - auto platform = BuildConfig.BUILD_PLATFORM.toLower(); + auto platform = BuildConfig.BUILD_ARTIFACT.toLower(); auto system_is_arm = QSysInfo::buildCpuArchitecture().contains("arm64"); auto asset_is_arm = asset_name.contains("arm64"); auto asset_is_archive = asset_name.endsWith(".zip") || asset_name.endsWith(".tar.gz"); @@ -808,7 +810,7 @@ void PrismUpdaterApp::performUpdate(const GitHubRelease& release) tr("No Valid Release Assets"), tr("Github release %1 has no valid assets for this platform: %2") .arg(release.tag_name) - .arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_PLATFORM).arg(m_isPortable ? tr("yes") : tr("no")))); + .arg(tr("%1 portable: %2").arg(BuildConfig.BUILD_ARTIFACT).arg(m_isPortable ? tr("yes") : tr("no")))); } else if (valid_assets.length() > 1) { selected_asset = selectAsset(valid_assets); } else { @@ -1020,7 +1022,7 @@ void PrismUpdaterApp::backupAppDir() if (file_list.isEmpty()) { // best guess - if (BuildConfig.BUILD_PLATFORM.toLower() == "linux") { + if (BuildConfig.BUILD_ARTIFACT.toLower() == "linux") { file_list.append({ "PrismLauncher", "bin", "share", "lib" }); } else { // windows by process of elimination file_list.append({ From cb35fb8d0ed9836c49d0f50f78fdd3f449244035 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 27 Jun 2023 19:56:02 -0700 Subject: [PATCH 101/398] add optional pre-release tag Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 3 ++- buildconfig/BuildConfig.cpp.in | 3 ++- buildconfig/BuildConfig.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bbe8bfbbc..c67febdb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,8 +140,9 @@ set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRIN ######## Set version numbers ######## set(Launcher_VERSION_MAJOR 8) set(Launcher_VERSION_MINOR 0) +set(Launcher_VERSION_PRERELEASE "") -set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}") +set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}${Launcher_VERSION_PRERELEASE}") set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0") set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},0,0") diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index e8e8a4ef8..3e0547046 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -58,6 +58,7 @@ Config::Config() // Version information VERSION_MAJOR = @Launcher_VERSION_MAJOR@; VERSION_MINOR = @Launcher_VERSION_MINOR@; + VERSION_PRERELEASE = "@Launcher_VERSION_PRERELEASE@"; BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@"; BUILD_ARTIFACT = "@Launcher_BUILD_ARTIFACT@"; @@ -128,7 +129,7 @@ Config::Config() QString Config::versionString() const { - return QString("%1.%2").arg(VERSION_MAJOR).arg(VERSION_MINOR); + return QString("%1.%2%3").arg(VERSION_MAJOR).arg(VERSION_MINOR).arg(VERSION_PRERELEASE); } QString Config::printableVersionString() const diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 723b2e714..f8835f1b3 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -60,6 +60,8 @@ class Config { /// The minor version number. int VERSION_MINOR; + QString VERSION_PRERELEASE; + /** * The version channel * This is used by the updater to determine what channel the current version came from. From 4123343130a1b5e6f443a465b719775f2520c045 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 28 Jun 2023 00:25:09 -0700 Subject: [PATCH 102/398] no need for pre release tag Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 3 +- buildconfig/BuildConfig.cpp.in | 3 +- buildconfig/BuildConfig.h | 2 - launcher/filelink/FileLink.cpp | 121 +++++++++++++++--- .../updater/prismupdater/PrismUpdater.cpp | 21 ++- 5 files changed, 117 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c67febdb2..bbe8bfbbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,9 +140,8 @@ set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRIN ######## Set version numbers ######## set(Launcher_VERSION_MAJOR 8) set(Launcher_VERSION_MINOR 0) -set(Launcher_VERSION_PRERELEASE "") -set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}${Launcher_VERSION_PRERELEASE}") +set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}") set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0") set(Launcher_VERSION_NAME4_COMMA "${Launcher_VERSION_MAJOR},${Launcher_VERSION_MINOR},0,0") diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index 3e0547046..e8e8a4ef8 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -58,7 +58,6 @@ Config::Config() // Version information VERSION_MAJOR = @Launcher_VERSION_MAJOR@; VERSION_MINOR = @Launcher_VERSION_MINOR@; - VERSION_PRERELEASE = "@Launcher_VERSION_PRERELEASE@"; BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@"; BUILD_ARTIFACT = "@Launcher_BUILD_ARTIFACT@"; @@ -129,7 +128,7 @@ Config::Config() QString Config::versionString() const { - return QString("%1.%2%3").arg(VERSION_MAJOR).arg(VERSION_MINOR).arg(VERSION_PRERELEASE); + return QString("%1.%2").arg(VERSION_MAJOR).arg(VERSION_MINOR); } QString Config::printableVersionString() const diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index f8835f1b3..723b2e714 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -60,8 +60,6 @@ class Config { /// The minor version number. int VERSION_MINOR; - QString VERSION_PRERELEASE; - /** * The version channel * This is used by the updater to determine what channel the current version came from. diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index 79b30c665..be69de007 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -40,8 +40,11 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include +#include #include #include +#include #endif // Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header @@ -63,26 +66,112 @@ namespace fs = std::filesystem; namespace fs = ghc::filesystem; #endif +#if defined Q_OS_WIN32 + +// taken from https://stackoverflow.com/a/25927081 +// getting a proper output to console with redirection support on windows is apparently hell +void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) +{ + // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been + // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 + // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our + // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value + // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to + // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target + // using the "_dup2" function. + if (bindStdIn) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "r", stdin); + } + if (bindStdOut) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stdout); + } + if (bindStdErr) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stderr); + } + + // Redirect unbuffered stdin from the current standard input handle + if (bindStdIn) { + HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "r"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdin)); + if (dup2Result == 0) { + setvbuf(stdin, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stdout to the current standard output handle + if (bindStdOut) { + HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdout)); + if (dup2Result == 0) { + setvbuf(stdout, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stderr to the current standard error handle + if (bindStdErr) { + HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stderr)); + if (dup2Result == 0) { + setvbuf(stderr, NULL, _IONBF, 0); + } + } + } + } + } + + // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the + // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In + // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything + // has been read from or written to the targets or not. + if (bindStdIn) { + std::wcin.clear(); + std::cin.clear(); + } + if (bindStdOut) { + std::wcout.clear(); + std::cout.clear(); + } + if (bindStdErr) { + std::wcerr.clear(); + std::cerr.clear(); + } +} +#endif + FileLinkApp::FileLinkApp(int& argc, char** argv) : QCoreApplication(argc, argv), socket(new QLocalSocket(this)) { #if defined Q_OS_WIN32 - // attach the parent console - if (AttachConsole(ATTACH_PARENT_PROCESS)) { - // if attach succeeds, reopen and sync all the i/o - if (freopen("CON", "w", stdout)) { - std::cout.sync_with_stdio(); + // attach the parent console if stdout not already captured + auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + BindCrtHandlesToStdHandles(true, true, true); + consoleAttached = true; } - if (freopen("CON", "w", stderr)) { - std::cerr.sync_with_stdio(); - } - if (freopen("CON", "r", stdin)) { - std::cin.sync_with_stdio(); - } - auto out = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD written; - const char* endline = "\n"; - WriteConsole(out, endline, strlen(endline), &written, NULL); - consoleAttached = true; } #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 3fd832b24..614174446 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -39,8 +39,8 @@ #include #include -#include #include +#include #if defined Q_OS_WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -209,7 +209,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar BindCrtHandlesToStdHandles(true, true, true); consoleAttached = true; } - } + } #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN); @@ -272,8 +272,6 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar auto prism_update_url = parser.value("update-url"); if (prism_update_url.isEmpty()) prism_update_url = BuildConfig.UPDATER_GITHUB_REPO; - if (prism_update_url.isEmpty()) - prism_update_url = "https://github.com/PrismLauncher/PrismLauncher"; m_prismRepoUrl = QUrl::fromUserInput(prism_update_url); @@ -354,18 +352,20 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar QFile::remove(oldName); }; - moveFile(logBase.arg(1), logBase.arg(2)); - moveFile(logBase.arg(0), logBase.arg(1)); + if (FS::ensureFolderPathExists("logs")) { + moveFile(logBase.arg(1), logBase.arg(2)); + moveFile(logBase.arg(0), logBase.arg(1)); + } logFile = std::unique_ptr(new QFile(logBase.arg(0))); if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { showFatalErrorMessage(tr("The launcher data folder is not writable!"), - tr("The launcher couldn't create a log file - the data folder is not writable.\n" + tr("The updater couldn't create a log file - the data folder is not writable.\n" "\n" "Make sure you have write permissions to the data folder.\n" "(%1)\n" "\n" - "The launcher cannot continue until you fix this problem.") + "The updater cannot continue until you fix this problem.") .arg(m_dataPath)); return; } @@ -560,8 +560,7 @@ void PrismUpdaterApp::run() stdOutStream.flush(); return exit(100); - } - else { + } else { return exit(0); } } @@ -1155,7 +1154,7 @@ bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) if (first_parts.length() < 2) return false; m_prismBinaryName = first_parts.takeFirst(); - auto version = first_parts.takeFirst(); + auto version = first_parts.takeFirst().trimmed(); m_prismVersion = version; if (version.contains('-')) { auto index = version.indexOf('-'); From 5f1074471d254ff82af1980e15a53b71ae121186 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 28 Jun 2023 13:35:42 +0300 Subject: [PATCH 103/398] Corected variable name Signed-off-by: Trial97 --- .../minecraft/auth/steps/XboxUserStep.cpp | 2 +- launcher/modplatform/CheckUpdateTask.h | 4 ++-- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/flame/FlameAPI.cpp | 2 +- .../modplatform/flame/FlameCheckUpdate.cpp | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 4 ++-- .../modrinth/ModrinthCheckUpdate.cpp | 2 +- .../modrinth/ModrinthPackIndex.cpp | 4 ++-- launcher/ui/dialogs/ModUpdateDialog.cpp | 20 ++++++++++--------- launcher/ui/pages/modplatform/ModPage.cpp | 2 +- .../ui/pages/modplatform/ResourcePage.cpp | 4 ++-- .../ui/pages/modplatform/flame/FlamePage.cpp | 11 ++++------ .../modplatform/modrinth/ModrinthPage.cpp | 5 +++-- 13 files changed, 32 insertions(+), 32 deletions(-) diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index 842eb60ff..06b67e81f 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -38,7 +38,7 @@ void XboxUserStep::perform() { QNetworkRequest request = QNetworkRequest(QUrl("https://user.auth.xboxlive.com/user/authenticate")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json"); - // set contract-verison header (prevent err 400 bad-request?) + // set contract-version header (prevent err 400 bad-request?) // https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/reference/live/rest/additional/httpstandardheaders request.setRawHeader("x-xbl-contract-version", "1"); diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index fbafedd77..65c80d268 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -23,7 +23,7 @@ class CheckUpdateTask : public Task { QString old_hash; QString old_version; QString new_version; - std::optional new_verison_type; + std::optional new_version_type; QString changelog; ModPlatform::ResourceProvider provider; shared_qobject_ptr download; @@ -41,7 +41,7 @@ class CheckUpdateTask : public Task { , old_hash(old_h) , old_version(old_v) , new_version(new_v) - , new_verison_type(new_v_type) + , new_version_type(new_v_type) , changelog(changelog) , provider(p) , download(t) diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index b47d09487..4ed9e7ebe 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -96,7 +96,7 @@ struct IndexedVersion { QVariant fileId; QString version; QString version_number = {}; - IndexedVersionType verison_type; + IndexedVersionType version_type; QStringList mcVersion; QString downloadUrl; QString date; diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 434703009..885c46873 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -135,7 +135,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - bool better_release = file_tmp.verison_type <= ver_tmp.verison_type; + bool better_release = file_tmp.version_type <= ver_tmp.version_type; if (file_tmp.date > ver_tmp.date && better_release) { ver_tmp = file_tmp; latest_file_obj = file_obj; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index cf159cad7..5ff833cfa 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -173,7 +173,7 @@ void FlameCheckUpdate::executeTask() } auto download_task = makeShared(pack, latest_ver, m_mods_folder); - m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version, latest_ver.verison_type, + m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version, latest_ver.version_type, api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), ModPlatform::ResourceProvider::FLAME, download_task); } diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 108d8b37f..5a44d4db7 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -94,7 +94,7 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = a.verison_type <= b.verison_type; + bool a_better_release = a.version_type <= b.version_type; // dates are in RFC 3339 format return a.date > b.date && a_better_release; }; @@ -124,7 +124,7 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> file.version = Json::requireString(obj, "displayName"); file.downloadUrl = Json::ensureString(obj, "downloadUrl"); file.fileName = Json::requireString(obj, "fileName"); - file.verison_type = ModPlatform::IndexedVersionType(Json::requireInteger(obj, "releaseType")); + file.version_type = ModPlatform::IndexedVersionType(Json::requireInteger(obj, "releaseType")); auto hash_list = Json::ensureArray(obj, "hashes"); for (auto h : hash_list) { diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 3ee22818a..845e0c61e 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -162,7 +162,7 @@ void ModrinthCheckUpdate::executeTask() auto download_task = makeShared(pack, project_ver, m_mods_folder); - m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.verison_type, + m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.version_type, project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task); } } diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 4d0882f64..d93d870cf 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -109,7 +109,7 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = a.verison_type <= b.verison_type; + bool a_better_release = a.version_type <= b.version_type; // dates are in RFC 3339 format return a.date > b.date && a_better_release; }; @@ -139,7 +139,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t } file.version = Json::requireString(obj, "name"); file.version_number = Json::requireString(obj, "version_number"); - file.verison_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type")); + file.version_type = ModPlatform::IndexedVersionType(Json::requireString(obj, "version_type")); file.changelog = Json::requireString(obj, "changelog"); diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 9e010444c..79622ff74 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -89,15 +89,17 @@ void ModUpdateDialog::checkCandidates() if (!m_modrinth_to_update.empty()) { m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, m_mod_model)); - connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_modrinth_check_task); } if (!m_flame_to_update.empty()) { m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loaders, m_mod_model)); - connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_flame_check_task); } @@ -162,7 +164,7 @@ void ModUpdateDialog::checkCandidates() if (!recover_url.isEmpty()) //: %1 is the link to download it manually text += tr("Possible solution: Getting the latest version manually:
%1
") - .arg(QString("%1").arg(recover_url.toString())); + .arg(QString("%1").arg(recover_url.toString())); text += "
"; } @@ -342,7 +344,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R } else { QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") }; - m_failed_metadata.append({mod, reason}); + m_failed_metadata.append({ mod, reason }); } } @@ -362,11 +364,11 @@ void ModUpdateDialog::appendMod(CheckUpdateTask::UpdatableMod const& info) auto new_version_item = new QTreeWidgetItem(item_top); new_version_item->setText(0, tr("New version: %1").arg(info.new_version)); - if (info.new_verison_type.has_value()) { + if (info.new_version_type.has_value()) { auto new_version_type_itme = new QTreeWidgetItem(item_top); - new_version_type_itme->setText(0, tr("New Version Type: %1").arg(info.new_verison_type.value().toString())); + new_version_type_itme->setText(0, tr("New Version Type: %1").arg(info.new_version_type.value().toString())); } - + auto changelog_item = new QTreeWidgetItem(item_top); changelog_item->setText(0, tr("Changelog of the latest version")); diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 9c9954a44..9b178048f 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -133,7 +133,7 @@ void ModPage::updateVersionList() // Only add the version if it's valid or using the 'Any' filter, but never if the version is opted out if ((valid || m_filter->versions.empty()) && !optedOut(version)) { - auto release_type = version.verison_type.isValid() ? QString(" : %1").arg(version.verison_type.toString()) : ""; + auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : ""; m_ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(i)); } } diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 5c8f23d22..3619c51a4 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -268,8 +268,8 @@ void ResourcePage::updateVersionList() if (optedOut(version)) continue; - auto release_type = current_pack->versions[i].verison_type.isValid() - ? QString(" : %1").arg(current_pack->versions[i].verison_type.toString()) + auto release_type = current_pack->versions[i].version_type.isValid() + ? QString(" [%1]").arg(current_pack->versions[i].version_type.toString()) : ""; m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i)); } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 575211515..aad376942 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -42,9 +42,9 @@ #include "FlameModel.h" #include "InstanceImportTask.h" #include "Json.h" +#include "modplatform/flame/FlameAPI.h" #include "ui/dialogs/NewInstanceDialog.h" #include "ui/widgets/ProjectItem.h" -#include "modplatform/flame/FlameAPI.h" static FlameAPI api; @@ -155,7 +155,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) } for (auto version : current.versions) { - auto release_type = version.version_type.isValid() ? QString(" : %1").arg(version.version_type.toString()) : ""; + auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : ""; ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(version.downloadUrl)); } @@ -253,10 +253,8 @@ void FlamePage::updateUi() text += "
" + tr(" by ") + authorStrs.join(", "); } - if(current.extraInfoLoaded) { - if (!current.extra.issuesUrl.isEmpty() - || !current.extra.sourceUrl.isEmpty() - || !current.extra.wikiUrl.isEmpty()) { + if (current.extraInfoLoaded) { + if (!current.extra.issuesUrl.isEmpty() || !current.extra.sourceUrl.isEmpty() || !current.extra.wikiUrl.isEmpty()) { text += "

" + tr("External links:") + "
"; } @@ -268,7 +266,6 @@ void FlamePage::updateUi() text += "- " + tr("Source code: %1").arg(current.extra.sourceUrl) + "
"; } - text += "
"; text += api.getModDescription(current.addonId).toUtf8(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 9ca26ea9a..c41f118a6 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -199,9 +199,10 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) qWarning() << "Error while reading modrinth modpack version: " << e.cause(); } for (auto version : current.versions) { - auto release_type = version.version_type.isValid() ? QString(" : %1").arg(version.version_type.toString()) : ""; + auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : ""; if (!version.name.contains(version.version)) - ui->versionSelectionBox->addItem(QString("%1 — %2%3").arg(version.name, version.version, release_type), QVariant(version.id)); + ui->versionSelectionBox->addItem(QString("%1 — %2%3").arg(version.name, version.version, release_type), + QVariant(version.id)); else ui->versionSelectionBox->addItem(QString("%1%2").arg(version.name, release_type), QVariant(version.id)); } From 3ad559ab22b6b20264eebb826efc4227374a64cc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 28 Jun 2023 17:43:09 +0300 Subject: [PATCH 104/398] Added version type to review message dialog Signed-off-by: Trial97 --- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 3 ++- launcher/ui/dialogs/ReviewMessageBox.cpp | 4 ++++ launcher/ui/dialogs/ReviewMessageBox.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 4f59f5605..4b29df0ad 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -187,7 +187,8 @@ void ResourceDownloadDialog::confirm() }); for (auto& task : selected) { confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(), - ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task) }); + ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task), + task->getVersion().version_type.toString() }); } if (confirm_dialog->exec()) { diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp index 7b33765fd..d1b7bd156 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.cpp +++ b/launcher/ui/dialogs/ReviewMessageBox.cpp @@ -77,6 +77,10 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info) itemTop->insertChildren(childIndx++, { requiredByItem }); } + auto versionTypeItem = new QTreeWidgetItem(itemTop); + versionTypeItem->setText(0, tr("Version Type: %1").arg(info.version_type)); + itemTop->insertChildren(childIndx++, { versionTypeItem }); + ui->modTreeWidget->addTopLevelItem(itemTop); } diff --git a/launcher/ui/dialogs/ReviewMessageBox.h b/launcher/ui/dialogs/ReviewMessageBox.h index a520cc2a6..596f39c8e 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.h +++ b/launcher/ui/dialogs/ReviewMessageBox.h @@ -18,6 +18,7 @@ class ReviewMessageBox : public QDialog { QString custom_file_path{}; QString provider; QStringList required_by; + QString version_type; }; void appendResource(ResourceInformation&& info); From 46e840fdf12a039e4e7f5e4ee49f834099e3d774 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:18:07 -0700 Subject: [PATCH 105/398] fix: add thread sleep to wait for resources - add detail text from logs Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 5 ++++- launcher/updater/PrismExternalUpdater.cpp | 18 +++++++++++------- launcher/updater/prismupdater/PrismUpdater.cpp | 4 ++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a8b26ed74..4c3e36d64 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -999,6 +999,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update In Progress"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); msgBox.setDefaultButton(QMessageBox::Abort); msgBox.setModal(true); + msgBox.setDetailedText(FS::read(update_log_path)); auto res = msgBox.exec(); switch (res) { case QMessageBox::Ignore: { @@ -1028,6 +1029,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Failed"), infoMsg, QMessageBox::Ignore | QMessageBox::Abort); msgBox.setDefaultButton(QMessageBox::Abort); msgBox.setModal(true); + msgBox.setDetailedText(FS::read(update_log_path)); auto res = msgBox.exec(); switch (res) { case QMessageBox::Ignore: { @@ -1056,7 +1058,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) .arg(update_log_path); auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.open(); + msgBox.setDetailedText(FS::read(update_log_path)); + msgBox.exec(); FS::deletePath(update_success_marker.absoluteFilePath()); } } diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index f2c88cf6a..42515332e 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -23,13 +23,14 @@ #include "PrismExternalUpdater.h" #include #include +#include #include +#include #include #include #include #include #include -#include #include "StringUtils.h" @@ -117,9 +118,6 @@ void PrismExternalUpdater::checkForUpdates() auto std_output = proc.readAllStandardOutput(); auto std_error = proc.readAllStandardError(); - qDebug() << "captured output:" << std_output; - qDebug() << "captured error:" << std_error; - progress.hide(); QCoreApplication::processEvents(); @@ -128,12 +126,17 @@ void PrismExternalUpdater::checkForUpdates() // no update available { qDebug() << "No update available"; + auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("You are running the latest version.")); + msgBox.exec(); } break; case 1: // there was an error { - qDebug() << "Updater subprocess error" << std_error; + qDebug() << "Updater subprocess error" << qPrintable(std_error); + auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check.")); + msgBox.setDetailedText(std_error); + msgBox.exec(); } break; case 100: @@ -264,14 +267,15 @@ void PrismExternalUpdater::offerUpdate(const QString& version_name, const QStrin } } -void PrismExternalUpdater::performUpdate(const QString& version_tag) { +void PrismExternalUpdater::performUpdate(const QString& version_tag) +{ QProcess proc; auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 exe_name.append(".exe"); #endif - QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", version_tag }; + QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", version_tag }; if (priv->allowBeta) args.append("--pre-release"); diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 614174446..4df103517 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -617,6 +617,10 @@ void PrismUpdaterApp::run() void PrismUpdaterApp::moveAndFinishUpdate(QDir target) { logUpdate("Finishing update process"); + + logUpdate("Waiting 2 seconds for resources to free"); + this->thread()->sleep(2); + auto manifest_path = FS::PathCombine(applicationDirPath(), "manifest.txt"); QFileInfo manifest(manifest_path); From e29126ca26a6817d2f5060aacd6a9f1eb5a0eb6d Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 28 Jun 2023 10:56:16 -0700 Subject: [PATCH 106/398] fix: add split markdown source Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 9534c3a3f..9ac496361 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -600,6 +600,7 @@ set(PRISMUPDATER_SOURCES Version.h Version.cpp Markdown.h + Markdown.cpp # Zip MMCZip.h From f287d9deaca3970592edf5ae99f190dc12f11a36 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:09:59 -0700 Subject: [PATCH 107/398] fix add NetRequest source Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 080882c6e..4b0e98f83 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -623,6 +623,8 @@ set(PRISMUPDATER_SOURCES net/Logging.h net/Logging.cpp net/NetAction.h + net/NetRequest.cpp + net/NetRequest.h net/NetJob.cpp net/NetJob.h net/NetUtils.h From c1235583146e6f1f6fae997b8ea2808687dbb372 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:25:59 -0700 Subject: [PATCH 108/398] fix: add build config header & trimlines form stdout Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/net/NetRequest.cpp | 1 + launcher/updater/PrismExternalUpdater.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/net/NetRequest.cpp b/launcher/net/NetRequest.cpp index 304577121..66307099c 100644 --- a/launcher/net/NetRequest.cpp +++ b/launcher/net/NetRequest.cpp @@ -46,6 +46,7 @@ #if defined(LAUNCHER_APPLICATION) #include "Application.h" #endif +#include "BuildConfig.h" #include "net/NetAction.h" diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 42515332e..9b99b2008 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -145,9 +145,9 @@ void PrismExternalUpdater::checkForUpdates() auto [first_line, remainder1] = StringUtils::splitFirst(std_output, '\n'); auto [second_line, remainder2] = StringUtils::splitFirst(remainder1, '\n'); auto [third_line, release_notes] = StringUtils::splitFirst(remainder2, '\n'); - auto version_name = StringUtils::splitFirst(first_line, ": ").second; - auto version_tag = StringUtils::splitFirst(second_line, ": ").second; - auto release_timestamp = QDateTime::fromString(StringUtils::splitFirst(third_line, ": ").second, Qt::ISODate); + auto version_name = StringUtils::splitFirst(first_line, ": ").second.trimmed(); + auto version_tag = StringUtils::splitFirst(second_line, ": ").second.trimmed(); + auto release_timestamp = QDateTime::fromString(StringUtils::splitFirst(third_line, ": ").second.trimmed(), Qt::ISODate); qDebug() << "Update available:" << version_name << version_tag << release_timestamp; qDebug() << "Update release notes:" << release_notes; From 400a2f7201ecb05af769dff5ea8738dde19205ed Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:46:28 -0700 Subject: [PATCH 109/398] fix: final fixes - use `done(code)` for offer dialog Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/UpdateAvailableDialog.cpp | 12 ++++++------ launcher/ui/dialogs/UpdateAvailableDialog.h | 8 ++++---- launcher/updater/PrismExternalUpdater.cpp | 10 ++++++++-- launcher/updater/prismupdater/PrismUpdater.cpp | 9 +++++++-- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.cpp b/launcher/ui/dialogs/UpdateAvailableDialog.cpp index 9f7308cba..28f7167cb 100644 --- a/launcher/ui/dialogs/UpdateAvailableDialog.cpp +++ b/launcher/ui/dialogs/UpdateAvailableDialog.cpp @@ -47,17 +47,17 @@ UpdateAvailableDialog::UpdateAvailableDialog(const QString& currentVersion, ui->releaseNotes->setOpenExternalLinks(true); connect(ui->skipButton, &QPushButton::clicked, this, [this](){ - this->setResult(DialogCode::Skip); - this->close(); + setResult(ResultCode::Skip); + done(ResultCode::Skip); }); connect(ui->delayButton, &QPushButton::clicked, this, [this](){ - this->setResult(DialogCode::DontInstall); - this->close(); + setResult(ResultCode::DontInstall); + done(ResultCode::DontInstall); }); connect(ui->installButton, &QPushButton::clicked, this, [this](){ - this->setResult(DialogCode::Install); - this->close(); + setResult(ResultCode::Install); + done(ResultCode::Install); }); } diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.h b/launcher/ui/dialogs/UpdateAvailableDialog.h index 7a14c01da..f3ea5cbb1 100644 --- a/launcher/ui/dialogs/UpdateAvailableDialog.h +++ b/launcher/ui/dialogs/UpdateAvailableDialog.h @@ -32,10 +32,10 @@ class UpdateAvailableDialog : public QDialog { public: - enum DialogCode { - Install, - DontInstall, - Skip, + enum ResultCode { + Install = 10, + DontInstall = 11, + Skip = 12, }; explicit UpdateAvailableDialog(const QString& currentVersion, diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 9b99b2008..969897405 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -134,7 +134,8 @@ void PrismExternalUpdater::checkForUpdates() // there was an error { qDebug() << "Updater subprocess error" << qPrintable(std_error); - auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check.")); + auto msgBox = + QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check.")); msgBox.setDetailedText(std_error); msgBox.exec(); } @@ -244,15 +245,20 @@ void PrismExternalUpdater::offerUpdate(const QString& version_name, const QStrin auto should_skip = priv->settings->value(version_tag, false).toBool(); priv->settings->endGroup(); - if (should_skip) + if (should_skip) { + auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("There are no new updates available.")); + msgBox.exec(); return; + } UpdateAvailableDialog dlg(BuildConfig.printableVersionString(), version_name, release_notes); auto result = dlg.exec(); + qDebug() << "offer dlg result" << result; switch (result) { case UpdateAvailableDialog::Install: { performUpdate(version_tag); + return; } case UpdateAvailableDialog::Skip: { priv->settings->beginGroup("skip"); diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 4df103517..f8819d940 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -327,6 +327,11 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar // on command line adjustedBy = "Command line"; m_dataPath = dirParam; +#ifndef Q_OS_MACOS + if (QFile::exists(FS::PathCombine(m_rootPath, "portable.txt"))) { + m_isPortable = true; + } +#endif } else { QDir foo(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); m_dataPath = foo.absolutePath(); @@ -958,8 +963,6 @@ void PrismUpdaterApp::performInstall(QFileInfo file) return showFatalErrorMessage(tr("Update Aborted"), tr("The update attempt was aborted")); } } - write_lock_file(update_lock_path, QDateTime::currentDateTime(), m_prismVersion, m_install_release.tag_name, applicationDirPath(), - m_dataPath); clearUpdateLog(); auto changelog_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.changelog"); @@ -967,6 +970,8 @@ void PrismUpdaterApp::performInstall(QFileInfo file) logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name)); if (m_isPortable || file.suffix().toLower() == "zip") { + write_lock_file(update_lock_path, QDateTime::currentDateTime(), m_prismVersion, m_install_release.tag_name, applicationDirPath(), + m_dataPath); logUpdate(tr("Updating portable install at %1").arg(applicationDirPath())); unpackAndInstall(file); } else { From cb7ff81ade4bdc125d19b85aa48a67a493994305 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 28 Jun 2023 13:51:58 -0700 Subject: [PATCH 110/398] fix: copy needs to overwrite Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/FileSystem.cpp | 3 +++ launcher/FileSystem.h | 6 ++++++ launcher/updater/prismupdater/PrismUpdater.cpp | 8 ++++---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index eff4884db..6dfb69bfa 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -297,6 +297,9 @@ bool copy::operator()(const QString& offset, bool dryRun) if (!m_followSymlinks) opt |= copy_opts::copy_symlinks; + if (m_overwrite) + opt |= copy_opts::overwrite_existing; + // Function that'll do the actual copying auto copy_file = [&](QString src_path, QString relative_dst_path) { if (m_matcher && (m_matcher->matches(relative_dst_path) != m_whitelist)) diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index ca26c1ee7..ab29cf936 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -120,6 +120,11 @@ class copy : public QObject { m_whitelist = whitelist; return *this; } + copy& overwrite(const bool overwrite) + { + m_overwrite = overwrite; + return *this; + } bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); } @@ -136,6 +141,7 @@ class copy : public QObject { bool m_followSymlinks = true; const IPathMatcher* m_matcher = nullptr; bool m_whitelist = false; + bool m_overwrite = false; QDir m_src; QDir m_dst; int m_copied; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index f8819d940..ef7e505b9 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -672,7 +672,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) auto install_path = FS::PathCombine(target.absolutePath(), rel_path); logUpdate(tr("Installing %1 from %2").arg(install_path).arg(to_install_file)); FS::ensureFilePathExists(install_path); - auto result = FS::copy(to_install_file, install_path)(); + auto result = FS::copy(to_install_file, install_path).overwrite(true)(); if (!result) { error = true; logUpdate(tr("Failed copy %1 to %2").arg(to_install_file).arg(install_path)); @@ -686,11 +686,11 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) if (error) { logUpdate(tr("There were errors installing the update.")); auto fail_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.fail"); - FS::copy(m_updateLogPath, fail_marker)(); + FS::copy(m_updateLogPath, fail_marker).overwrite(true)(); } else { logUpdate(tr("Update succeed.")); auto success_marker = FS::PathCombine(m_dataPath, ".prism_launcher_update.success"); - FS::copy(m_updateLogPath, success_marker)(); + FS::copy(m_updateLogPath, success_marker).overwrite(true)(); } auto update_lock_path = FS::PathCombine(m_dataPath, ".prism_launcher_update.lock"); FS::deletePath(update_lock_path); @@ -1078,7 +1078,7 @@ void PrismUpdaterApp::backupAppDir() auto bak_path = FS::PathCombine(backup_dir, rel_path); logUpdate(tr("Backing up and then removing %1").arg(to_bak_file)); FS::ensureFilePathExists(bak_path); - auto result = FS::copy(to_bak_file, bak_path)(); + auto result = FS::copy(to_bak_file, bak_path).overwrite(true)(); if (!result) { logUpdate(tr("Failed to backup %1 to %2").arg(to_bak_file).arg(bak_path)); } else { From e38adf6006e36928af92b317a1605eee063d70ed Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 14:01:11 -0700 Subject: [PATCH 111/398] fix(updater) fixes form first round of testing - reset update time after check Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- buildconfig/BuildConfig.cpp.in | 7 ++- launcher/Application.cpp | 40 +++++++++++----- launcher/Application.h | 3 ++ launcher/ui/MainWindow.cpp | 8 ++-- launcher/updater/PrismExternalUpdater.cpp | 46 +++++++++++++++++-- .../updater/prismupdater/PrismUpdater.cpp | 21 +++++++-- 6 files changed, 95 insertions(+), 30 deletions(-) diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index e8e8a4ef8..b1c9b5bef 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -77,6 +77,8 @@ Config::Config() if (BUILD_PLATFORM == "macOS" && !MAC_SPARKLE_PUB_KEY.isEmpty() && !MAC_SPARKLE_APPCAST_URL.isEmpty()) { UPDATER_ENABLED = true; + } else if(!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_ARTIFACT.isEmpty()) { + UPDATER_ENABLED = true; } GIT_COMMIT = "@Launcher_GIT_COMMIT@"; @@ -97,10 +99,7 @@ Config::Config() if (GIT_REFSPEC.startsWith("refs/heads/")) { VERSION_CHANNEL = GIT_REFSPEC; - VERSION_CHANNEL.remove("refs/heads/"); - if(!UPDATER_GITHUB_REPO.isEmpty() && !BUILD_PLATFORM.isEmpty()) { - UPDATER_ENABLED = true; - } + VERSION_CHANNEL.remove("refs/heads/"); } else if (!GIT_COMMIT.isEmpty()) { diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1a381a045..c59bea8d6 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -584,6 +584,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; qDebug() << "Compiled for : " << BuildConfig.systemID(); qDebug() << "Compiled by : " << BuildConfig.compilerID(); + qDebug() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT; + qDebug() << "Updates Enabeled : " << (updaterEnabled() ? "Yes" : "No"); if (adjustedBy.size()) { qDebug() << "Work dir before adjustment : " << origcwdPath; qDebug() << "Work dir after adjustment : " << QDir::currentPath(); @@ -856,18 +858,12 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } // initialize the updater - if (BuildConfig.UPDATER_ENABLED) { + if (updaterEnabled()) { qDebug() << "Initializing updater"; #ifdef Q_OS_MAC m_updater.reset(new MacSparkleUpdater()); #else - auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); -#if defined Q_OS_WIN32 - exe_name.append(".exe"); -#endif - auto updater_binary = QFileInfo(QDir(m_rootPath).absoluteFilePath(exe_name)); - if (updater_binary.isFile()) - m_updater.reset(new PrismExternalUpdater(m_rootPath, m_dataPath)); + m_updater.reset(new PrismExternalUpdater(applicationDirPath(), m_dataPath)); #endif qDebug() << "<> Updater started."; } @@ -1000,6 +996,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) msgBox.setDefaultButton(QMessageBox::Abort); msgBox.setModal(true); msgBox.setDetailedText(FS::read(update_log_path)); + msgBox.adjustSize(); auto res = msgBox.exec(); switch (res) { case QMessageBox::Ignore: { @@ -1030,6 +1027,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) msgBox.setDefaultButton(QMessageBox::Abort); msgBox.setModal(true); msgBox.setDetailedText(FS::read(update_log_path)); + msgBox.adjustSize(); auto res = msgBox.exec(); switch (res) { case QMessageBox::Ignore: { @@ -1056,10 +1054,12 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) "for details.") .arg(BuildConfig.printableVersionString()) .arg(update_log_path); - auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.setDetailedText(FS::read(update_log_path)); - msgBox.exec(); + auto msgBox = new QMessageBox(QMessageBox::Information, tr("Update Succeeded"), infoMsg, QMessageBox::Ok); + msgBox->setDefaultButton(QMessageBox::Ok); + msgBox->setDetailedText(FS::read(update_log_path)); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->adjustSize(); + msgBox->open(); FS::deletePath(update_success_marker.absoluteFilePath()); } } @@ -1127,6 +1127,22 @@ bool Application::createSetupWizard() return false; } +bool Application::updaterEnabled() { +#if defined(Q_OS_MAC) + return BuildConfig.UPDATER_ENABLED; +#else + return BuildConfig.UPDATER_ENABLED && QFileInfo(updaterBinaryName()).isFile(); +#endif +} + +QString Application::updaterBinaryName() { + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); +#if defined Q_OS_WIN32 + exe_name.append(".exe"); +#endif + return exe_name; +} + bool Application::event(QEvent* event) { #ifdef Q_OS_MACOS diff --git a/launcher/Application.h b/launcher/Application.h index baf64575d..c87ee2652 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -216,6 +216,9 @@ public: int suitableMaxMem(); + bool updaterEnabled(); + QString updaterBinaryName(); + signals: void updateAllowedChanged(bool status); void globalSettingsAboutToOpen(); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 496738e32..16d696dc8 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -215,7 +215,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi ui->actionDISCORD->setVisible(!BuildConfig.DISCORD_URL.isEmpty()); ui->actionREDDIT->setVisible(!BuildConfig.SUBREDDIT_URL.isEmpty()); - ui->actionCheckUpdate->setVisible(BuildConfig.UPDATER_ENABLED); + ui->actionCheckUpdate->setVisible(APPLICATION->updaterEnabled()); #ifndef Q_OS_MAC ui->actionAddToPATH->setVisible(false); @@ -388,7 +388,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi updateNewsLabel(); } - if (BuildConfig.UPDATER_ENABLED) { + if (APPLICATION->updaterEnabled()) { bool updatesAllowed = APPLICATION->updatesAreAllowed(); updatesAllowedChanged(updatesAllowed); @@ -781,7 +781,7 @@ void MainWindow::repopulateAccountsMenu() void MainWindow::updatesAllowedChanged(bool allowed) { - if(!BuildConfig.UPDATER_ENABLED) + if(!APPLICATION->updaterEnabled()) { return; } @@ -1259,7 +1259,7 @@ void MainWindow::on_actionViewCentralModsFolder_triggered() void MainWindow::checkForUpdates() { - if(BuildConfig.UPDATER_ENABLED) + if(APPLICATION->updaterEnabled()) { APPLICATION->triggerUpdateCheck(); } diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 969897405..7f987204a 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -40,7 +40,7 @@ class PrismExternalUpdater::Private { public: - QDir appDir; + QDir binDir; QDir dataDir; QTimer updateTimer; bool allowBeta; @@ -50,10 +50,10 @@ class PrismExternalUpdater::Private { std::unique_ptr settings; }; -PrismExternalUpdater::PrismExternalUpdater(const QString& appDir, const QString& dataDir) +PrismExternalUpdater::PrismExternalUpdater(const QString& binDir, const QString& dataDir) { priv = new PrismExternalUpdater::Private(); - priv->appDir = QDir(appDir); + priv->binDir = QDir(binDir); priv->dataDir = QDir(dataDir); auto settings_file = priv->dataDir.absoluteFilePath("prismlauncher_update.cfg"); priv->settings = std::make_unique(settings_file, QSettings::Format::IniFormat); @@ -97,20 +97,42 @@ void PrismExternalUpdater::checkForUpdates() if (priv->allowBeta) args.append("--pre-release"); - proc.start(priv->appDir.absoluteFilePath(exe_name), args); + proc.start(priv->binDir.absoluteFilePath(exe_name), args); auto result_start = proc.waitForStarted(5000); if (!result_start) { auto err = proc.error(); qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString(); + auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Check Failed"), + tr("Failed to start after 5 seconds\nReason: %1.").arg(proc.errorString())); + + msgBox.adjustSize(); + msgBox.exec(); + priv->lastCheck = QDateTime::currentDateTime(); + priv->settings->setValue("last_check", priv->lastCheck.toString(Qt::ISODate)); + priv->settings->sync(); + resetAutoCheckTimer(); + return; } QCoreApplication::processEvents(); auto result_finished = proc.waitForFinished(60000); if (!result_finished) { + proc.kill(); auto err = proc.error(); + auto output = proc.readAll(); qDebug() << "Updater failed to close after 60 seconds." << "reason:" << err << proc.errorString(); + auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Check Failed"), + tr("Updater failed to close 60 seconds\nReason: %1.").arg(proc.errorString())); + msgBox.setDetailedText(output); + msgBox.adjustSize(); + msgBox.exec(); + priv->lastCheck = QDateTime::currentDateTime(); + priv->settings->setValue("last_check", priv->lastCheck.toString(Qt::ISODate)); + priv->settings->sync(); + resetAutoCheckTimer(); + return; } auto exit_code = proc.exitCode(); @@ -127,6 +149,8 @@ void PrismExternalUpdater::checkForUpdates() { qDebug() << "No update available"; auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("You are running the latest version.")); + + msgBox.adjustSize(); msgBox.exec(); } break; @@ -137,6 +161,8 @@ void PrismExternalUpdater::checkForUpdates() auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check.")); msgBox.setDetailedText(std_error); + + msgBox.adjustSize(); msgBox.exec(); } break; @@ -159,11 +185,19 @@ void PrismExternalUpdater::checkForUpdates() // unknown error code { qDebug() << "Updater exited with unknown code" << exit_code; + auto msgBox = QMessageBox(QMessageBox::Information, tr("Unknown Update Error"), + tr("The updater exited with an unknown condition.\nExit Code: %1").arg(exit_code)); + auto detail_txt = tr("StdOut: %1\nStdErr: %2").arg(std_output).arg(std_error); + msgBox.setDetailedText(detail_txt); + + msgBox.adjustSize(); + msgBox.exec(); } } priv->lastCheck = QDateTime::currentDateTime(); priv->settings->setValue("last_check", priv->lastCheck.toString(Qt::ISODate)); priv->settings->sync(); + resetAutoCheckTimer(); } bool PrismExternalUpdater::getAutomaticallyChecksForUpdates() @@ -247,6 +281,8 @@ void PrismExternalUpdater::offerUpdate(const QString& version_name, const QStrin if (should_skip) { auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("There are no new updates available.")); + + msgBox.adjustSize(); msgBox.exec(); return; } @@ -285,7 +321,7 @@ void PrismExternalUpdater::performUpdate(const QString& version_tag) if (priv->allowBeta) args.append("--pre-release"); - auto result = proc.startDetached(priv->appDir.absoluteFilePath(exe_name), args); + auto result = proc.startDetached(priv->binDir.absoluteFilePath(exe_name), args); if (!result) { qDebug() << "Failed to start updater:" << proc.error() << proc.errorString(); } diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index ef7e505b9..1859d5262 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -350,14 +350,14 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar { // setup logging static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; - static const QString logBase = FS::PathCombine("logs", baseLogFile); + static const QString logBase = FS::PathCombine(m_dataPath, "logs", baseLogFile); auto moveFile = [](const QString& oldName, const QString& newName) { QFile::remove(newName); QFile::copy(oldName, newName); QFile::remove(oldName); }; - if (FS::ensureFolderPathExists("logs")) { + if (FS::ensureFolderPathExists("logs")) { // enough history to track both launches of the updater during a portable install moveFile(logBase.arg(1), logBase.arg(2)); moveFile(logBase.arg(0), logBase.arg(1)); } @@ -442,6 +442,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; qDebug() << "Compiled for : " << BuildConfig.systemID(); qDebug() << "Compiled by : " << BuildConfig.compilerID(); + qDebug() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT; if (adjustedBy.size()) { qDebug() << "Data dir before adjustment : " << origCwdPath; qDebug() << "Data dir after adjustment : " << m_dataPath; @@ -521,6 +522,7 @@ void PrismUpdaterApp::showFatalErrorMessage(const QString& title, const QString& msgBox->setDefaultButton(QMessageBox::Ok); msgBox->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction); msgBox->setIcon(QMessageBox::Critical); + msgBox->adjustSize(); msgBox->exec(); exit(1); } @@ -658,6 +660,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); progress.setCancelButton(nullptr); + progress.adjustSize(); progress.show(); QCoreApplication::processEvents(); @@ -766,10 +769,13 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel if (BuildConfig.BUILD_ARTIFACT.isEmpty()) qWarning() << "Build platform is not set!"; for (auto asset : release.assets) { - if (!m_isAppimage && asset.name.toLower().endsWith("appimage")) + if (!m_isAppimage && asset.name.toLower().endsWith("appimage")) { + qDebug() << "Rejecting" << asset.name << "because it is an AppImage"; continue; - else if (m_isAppimage && !asset.name.toLower().endsWith("appimage")) + } else if (m_isAppimage && !asset.name.toLower().endsWith("appimage")) { + qDebug() << "Rejecting" << asset.name << "because it is not an AppImage"; continue; + } auto asset_name = asset.name.toLower(); auto platform = BuildConfig.BUILD_ARTIFACT.toLower(); auto system_is_arm = QSysInfo::buildCpuArchitecture().contains("arm64"); @@ -786,6 +792,8 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel for_platform = false; if (((m_isPortable && for_portable) || (!m_isPortable && !for_portable)) && for_platform) { + qDebug() << "Rejecting" << asset.name << "|" + << "For Platform:" << (for_platform ? "Yes" : "No") << "For Portable:" << (for_portable ? "Yes" : "No"); valid.append(asset); } } @@ -849,6 +857,7 @@ QFileInfo PrismUpdaterApp::downloadAsset(const GitHubReleaseAsset& asset) auto download = Net::Download::makeFile(file_url, out_file_path); download->setNetwork(m_network); auto progress_dialog = ProgressDialog(); + progress_dialog.adjustSize(); if (progress_dialog.execWithTask(download.get()) == QDialog::Rejected) showFatalErrorMessage(tr("Download Aborted"), tr("Download of %1 aborted by user").arg(file_url.toString())); @@ -954,6 +963,7 @@ void PrismUpdaterApp::performInstall(QFileInfo file) msgBox.setInformativeText(infoMsg); msgBox.setStandardButtons(QMessageBox::Ignore | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); + msgBox.adjustSize(); switch (msgBox.exec()) { case QMessageBox::AcceptRole: break; @@ -971,7 +981,7 @@ void PrismUpdaterApp::performInstall(QFileInfo file) logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name)); if (m_isPortable || file.suffix().toLower() == "zip") { write_lock_file(update_lock_path, QDateTime::currentDateTime(), m_prismVersion, m_install_release.tag_name, applicationDirPath(), - m_dataPath); + m_dataPath); logUpdate(tr("Updating portable install at %1").arg(applicationDirPath())); unpackAndInstall(file); } else { @@ -1065,6 +1075,7 @@ void PrismUpdaterApp::backupAppDir() QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); progress.setCancelButton(nullptr); + progress.adjustSize(); progress.show(); QCoreApplication::processEvents(); int i = 0; From a6c8a37a5deca0fcdb14f53a5f91aa83c3d558b5 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 14:06:14 -0700 Subject: [PATCH 112/398] fixa(updater): better update timer logs Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/PrismExternalUpdater.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 7f987204a..d51ad690e 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -60,6 +60,7 @@ PrismExternalUpdater::PrismExternalUpdater(const QString& binDir, const QString& priv->allowBeta = priv->settings->value("allow_beta", false).toBool(); priv->autoCheck = priv->settings->value("auto_check", false).toBool(); bool interval_ok; + // default once per day priv->updateInterval = priv->settings->value("update_interval", 86400).toInt(&interval_ok); if (!interval_ok) priv->updateInterval = 86400; @@ -240,9 +241,9 @@ void PrismExternalUpdater::setBetaAllowed(bool allowed) void PrismExternalUpdater::resetAutoCheckTimer() { - int timeoutDuration = 0; - auto now = QDateTime::currentDateTime(); if (priv->autoCheck) { + int timeoutDuration = 0; + auto now = QDateTime::currentDateTime(); if (priv->lastCheck.isValid()) { auto diff = priv->lastCheck.secsTo(now); auto secs_left = priv->updateInterval - diff; @@ -270,6 +271,7 @@ void PrismExternalUpdater::disconnectTimer() void PrismExternalUpdater::autoCheckTimerFired() { + qDebug() << "Auto update Timer fired"; checkForUpdates(); } From 494483fd2b8b3ecc8c7ad19d493a8f7552cc95e2 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 29 Jun 2023 19:09:52 -0300 Subject: [PATCH 113/398] fix(updater): add parent to dialog to fix issues in tilling WMs QProgressDialog without parents in Qt tend to cause graphical issues on some systems, so we add the main window as a parent here! Signed-off-by: flow --- launcher/Application.cpp | 38 +++++++++++------------ launcher/updater/PrismExternalUpdater.cpp | 7 +++-- launcher/updater/PrismExternalUpdater.h | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index c59bea8d6..8007f26a9 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -857,17 +857,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qDebug() << "<> Translations loaded."; } - // initialize the updater - if (updaterEnabled()) { - qDebug() << "Initializing updater"; -#ifdef Q_OS_MAC - m_updater.reset(new MacSparkleUpdater()); -#else - m_updater.reset(new PrismExternalUpdater(applicationDirPath(), m_dataPath)); -#endif - qDebug() << "<> Updater started."; - } - // Instance icons { auto setting = APPLICATION->settings()->getSetting("IconsDir"); @@ -968,6 +957,25 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) applyCurrentlySelectedTheme(true); + updateCapabilities(); + + if (createSetupWizard()) { + return; + } + + performMainStartupAction(); + + // initialize the updater + if (updaterEnabled()) { + qDebug() << "Initializing updater"; +#ifdef Q_OS_MAC + m_updater.reset(new MacSparkleUpdater()); +#else + m_updater.reset(new PrismExternalUpdater(m_mainWindow, applicationDirPath(), m_dataPath)); +#endif + qDebug() << "<> Updater started."; + } + // check update locks { auto update_log_path = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); @@ -1063,14 +1071,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) FS::deletePath(update_success_marker.absoluteFilePath()); } } - - updateCapabilities(); - - if (createSetupWizard()) { - return; - } - - performMainStartupAction(); } bool Application::createSetupWizard() diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index d51ad690e..792dd2a52 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -48,9 +48,11 @@ class PrismExternalUpdater::Private { double updateInterval; QDateTime lastCheck; std::unique_ptr settings; + + QWidget* parent; }; -PrismExternalUpdater::PrismExternalUpdater(const QString& binDir, const QString& dataDir) +PrismExternalUpdater::PrismExternalUpdater(QWidget* parent, const QString& binDir, const QString& dataDir) { priv = new PrismExternalUpdater::Private(); priv->binDir = QDir(binDir); @@ -68,6 +70,7 @@ PrismExternalUpdater::PrismExternalUpdater(const QString& binDir, const QString& if (!last_check.isNull() && last_check.isValid()) { priv->lastCheck = QDateTime::fromString(last_check.toString(), Qt::ISODate); } + priv->parent = parent; connectTimer(); resetAutoCheckTimer(); } @@ -83,7 +86,7 @@ PrismExternalUpdater::~PrismExternalUpdater() void PrismExternalUpdater::checkForUpdates() { - QProgressDialog progress(tr("Checking for updates..."), "", 0, 0); + QProgressDialog progress(tr("Checking for updates..."), "", 0, 0, priv->parent); progress.setCancelButton(nullptr); progress.show(); QCoreApplication::processEvents(); diff --git a/launcher/updater/PrismExternalUpdater.h b/launcher/updater/PrismExternalUpdater.h index f8ed29ccc..bfe94c149 100644 --- a/launcher/updater/PrismExternalUpdater.h +++ b/launcher/updater/PrismExternalUpdater.h @@ -34,7 +34,7 @@ class PrismExternalUpdater : public ExternalUpdater { Q_OBJECT public: - PrismExternalUpdater(const QString& appDir, const QString& dataDir); + PrismExternalUpdater(QWidget* parent, const QString& appDir, const QString& dataDir); ~PrismExternalUpdater() override; /*! From 41cb8d7ec609b91e191e2c89ef651d2f141140cf Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 15:24:23 -0700 Subject: [PATCH 114/398] fix: adjust dialog size, add parent to msgboxes Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/PrismExternalUpdater.cpp | 24 ++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 792dd2a52..c3b3bcfee 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -88,6 +88,7 @@ void PrismExternalUpdater::checkForUpdates() { QProgressDialog progress(tr("Checking for updates..."), "", 0, 0, priv->parent); progress.setCancelButton(nullptr); + progress.adjustSize(); progress.show(); QCoreApplication::processEvents(); @@ -107,8 +108,9 @@ void PrismExternalUpdater::checkForUpdates() auto err = proc.error(); qDebug() << "Failed to start updater after 5 seconds." << "reason:" << err << proc.errorString(); - auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Check Failed"), - tr("Failed to start after 5 seconds\nReason: %1.").arg(proc.errorString())); + auto msgBox = + QMessageBox(QMessageBox::Information, tr("Update Check Failed"), + tr("Failed to start after 5 seconds\nReason: %1.").arg(proc.errorString()), QMessageBox::Ok, priv->parent); msgBox.adjustSize(); msgBox.exec(); @@ -127,8 +129,9 @@ void PrismExternalUpdater::checkForUpdates() auto output = proc.readAll(); qDebug() << "Updater failed to close after 60 seconds." << "reason:" << err << proc.errorString(); - auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Check Failed"), - tr("Updater failed to close 60 seconds\nReason: %1.").arg(proc.errorString())); + auto msgBox = + QMessageBox(QMessageBox::Information, tr("Update Check Failed"), + tr("Updater failed to close 60 seconds\nReason: %1.").arg(proc.errorString()), QMessageBox::Ok, priv->parent); msgBox.setDetailedText(output); msgBox.adjustSize(); msgBox.exec(); @@ -152,7 +155,8 @@ void PrismExternalUpdater::checkForUpdates() // no update available { qDebug() << "No update available"; - auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("You are running the latest version.")); + auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("You are running the latest version."), + QMessageBox::Ok, priv->parent); msgBox.adjustSize(); msgBox.exec(); @@ -162,8 +166,8 @@ void PrismExternalUpdater::checkForUpdates() // there was an error { qDebug() << "Updater subprocess error" << qPrintable(std_error); - auto msgBox = - QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check.")); + auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Check Error"), + tr("There was an error running the update check."), QMessageBox::Ok, priv->parent); msgBox.setDetailedText(std_error); msgBox.adjustSize(); @@ -190,7 +194,8 @@ void PrismExternalUpdater::checkForUpdates() { qDebug() << "Updater exited with unknown code" << exit_code; auto msgBox = QMessageBox(QMessageBox::Information, tr("Unknown Update Error"), - tr("The updater exited with an unknown condition.\nExit Code: %1").arg(exit_code)); + tr("The updater exited with an unknown condition.\nExit Code: %1").arg(exit_code), + QMessageBox::Ok, priv->parent); auto detail_txt = tr("StdOut: %1\nStdErr: %2").arg(std_output).arg(std_error); msgBox.setDetailedText(detail_txt); @@ -285,7 +290,8 @@ void PrismExternalUpdater::offerUpdate(const QString& version_name, const QStrin priv->settings->endGroup(); if (should_skip) { - auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("There are no new updates available.")); + auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("There are no new updates available."), + QMessageBox::Ok, priv->parent); msgBox.adjustSize(); msgBox.exec(); From 109ae5bae0f487e8218d3e4c12b610399541205a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 15:42:36 -0700 Subject: [PATCH 115/398] fix(updater): convert int to string Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/PrismExternalUpdater.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index c3b3bcfee..585d8f8bf 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -193,9 +193,10 @@ void PrismExternalUpdater::checkForUpdates() // unknown error code { qDebug() << "Updater exited with unknown code" << exit_code; - auto msgBox = QMessageBox(QMessageBox::Information, tr("Unknown Update Error"), - tr("The updater exited with an unknown condition.\nExit Code: %1").arg(exit_code), - QMessageBox::Ok, priv->parent); + auto msgBox = + QMessageBox(QMessageBox::Information, tr("Unknown Update Error"), + tr("The updater exited with an unknown condition.\nExit Code: %1").arg(QString::number(exit_code)), + QMessageBox::Ok, priv->parent); auto detail_txt = tr("StdOut: %1\nStdErr: %2").arg(std_output).arg(std_error); msgBox.setDetailedText(detail_txt); From 603e3e7e2edb53ee2cf7f15846b04c4acd29e9df Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 15:56:44 -0700 Subject: [PATCH 116/398] fix(updater): set minimum dialog / msgbox sizes Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 17 +++++++++++------ launcher/updater/PrismExternalUpdater.cpp | 11 ++++++----- launcher/updater/prismupdater/PrismUpdater.cpp | 4 ++++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 8007f26a9..1993a1491 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1004,6 +1004,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) msgBox.setDefaultButton(QMessageBox::Abort); msgBox.setModal(true); msgBox.setDetailedText(FS::read(update_log_path)); + msgBox.setMinimumWidth(460); msgBox.adjustSize(); auto res = msgBox.exec(); switch (res) { @@ -1015,7 +1016,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) [[fallthrough]]; default: { qDebug() << "Exiting because update lockfile is present"; - QMetaObject::invokeMethod(this, [](){ exit(1); }, Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, []() { exit(1); }, Qt::QueuedConnection); return; } } @@ -1035,6 +1037,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) msgBox.setDefaultButton(QMessageBox::Abort); msgBox.setModal(true); msgBox.setDetailedText(FS::read(update_log_path)); + msgBox.setMinimumWidth(460); msgBox.adjustSize(); auto res = msgBox.exec(); switch (res) { @@ -1046,7 +1049,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) [[fallthrough]]; default: { qDebug() << "Exiting because update lockfile is present"; - QMetaObject::invokeMethod(this, [](){ exit(1); }, Qt::QueuedConnection); + QMetaObject::invokeMethod( + this, []() { exit(1); }, Qt::QueuedConnection); return; } } @@ -1066,6 +1070,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) msgBox->setDefaultButton(QMessageBox::Ok); msgBox->setDetailedText(FS::read(update_log_path)); msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setMinimumWidth(460); msgBox->adjustSize(); msgBox->open(); FS::deletePath(update_success_marker.absoluteFilePath()); @@ -1127,7 +1132,8 @@ bool Application::createSetupWizard() return false; } -bool Application::updaterEnabled() { +bool Application::updaterEnabled() +{ #if defined(Q_OS_MAC) return BuildConfig.UPDATER_ENABLED; #else @@ -1135,7 +1141,8 @@ bool Application::updaterEnabled() { #endif } -QString Application::updaterBinaryName() { +QString Application::updaterBinaryName() +{ auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 exe_name.append(".exe"); @@ -1174,8 +1181,6 @@ void Application::performMainStartupAction() { m_status = Application::Initialized; - - if (!m_instanceIdToLaunch.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToLaunch); if (inst) { diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 585d8f8bf..29d411a1e 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -111,7 +111,7 @@ void PrismExternalUpdater::checkForUpdates() auto msgBox = QMessageBox(QMessageBox::Information, tr("Update Check Failed"), tr("Failed to start after 5 seconds\nReason: %1.").arg(proc.errorString()), QMessageBox::Ok, priv->parent); - + msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); priv->lastCheck = QDateTime::currentDateTime(); @@ -133,6 +133,7 @@ void PrismExternalUpdater::checkForUpdates() QMessageBox(QMessageBox::Information, tr("Update Check Failed"), tr("Updater failed to close 60 seconds\nReason: %1.").arg(proc.errorString()), QMessageBox::Ok, priv->parent); msgBox.setDetailedText(output); + msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); priv->lastCheck = QDateTime::currentDateTime(); @@ -157,7 +158,7 @@ void PrismExternalUpdater::checkForUpdates() qDebug() << "No update available"; auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("You are running the latest version."), QMessageBox::Ok, priv->parent); - + msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); } @@ -169,7 +170,7 @@ void PrismExternalUpdater::checkForUpdates() auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check."), QMessageBox::Ok, priv->parent); msgBox.setDetailedText(std_error); - + msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); } @@ -199,7 +200,7 @@ void PrismExternalUpdater::checkForUpdates() QMessageBox::Ok, priv->parent); auto detail_txt = tr("StdOut: %1\nStdErr: %2").arg(std_output).arg(std_error); msgBox.setDetailedText(detail_txt); - + msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); } @@ -293,7 +294,7 @@ void PrismExternalUpdater::offerUpdate(const QString& version_name, const QStrin if (should_skip) { auto msgBox = QMessageBox(QMessageBox::Information, tr("No Update Available"), tr("There are no new updates available."), QMessageBox::Ok, priv->parent); - + msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); return; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 1859d5262..91cc87ec8 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -522,6 +522,7 @@ void PrismUpdaterApp::showFatalErrorMessage(const QString& title, const QString& msgBox->setDefaultButton(QMessageBox::Ok); msgBox->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction); msgBox->setIcon(QMessageBox::Critical); + msgBox->setMinimumWidth(460); msgBox->adjustSize(); msgBox->exec(); exit(1); @@ -660,6 +661,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); progress.setCancelButton(nullptr); + progress.setMinimumWidth(400); progress.adjustSize(); progress.show(); QCoreApplication::processEvents(); @@ -963,6 +965,7 @@ void PrismUpdaterApp::performInstall(QFileInfo file) msgBox.setInformativeText(infoMsg); msgBox.setStandardButtons(QMessageBox::Ignore | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); + msgBox.setMinimumWidth(460); msgBox.adjustSize(); switch (msgBox.exec()) { case QMessageBox::AcceptRole: @@ -1075,6 +1078,7 @@ void PrismUpdaterApp::backupAppDir() QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); progress.setCancelButton(nullptr); + progress.setMinimumWidth(400); progress.adjustSize(); progress.show(); QCoreApplication::processEvents(); From 4320830a861d16c8fe0b1593e1ee6d022b2d1404 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 17:59:14 -0700 Subject: [PATCH 117/398] fix(updater): Explicit conversion to string for QByteArray Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/PrismExternalUpdater.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 29d411a1e..02e3a3dec 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -169,7 +169,7 @@ void PrismExternalUpdater::checkForUpdates() qDebug() << "Updater subprocess error" << qPrintable(std_error); auto msgBox = QMessageBox(QMessageBox::Warning, tr("Update Check Error"), tr("There was an error running the update check."), QMessageBox::Ok, priv->parent); - msgBox.setDetailedText(std_error); + msgBox.setDetailedText(QString(std_error)); msgBox.setMinimumWidth(460); msgBox.adjustSize(); msgBox.exec(); @@ -198,7 +198,7 @@ void PrismExternalUpdater::checkForUpdates() QMessageBox(QMessageBox::Information, tr("Unknown Update Error"), tr("The updater exited with an unknown condition.\nExit Code: %1").arg(QString::number(exit_code)), QMessageBox::Ok, priv->parent); - auto detail_txt = tr("StdOut: %1\nStdErr: %2").arg(std_output).arg(std_error); + auto detail_txt = tr("StdOut: %1\nStdErr: %2").arg(QString(std_output)).arg(QString(std_error)); msgBox.setDetailedText(detail_txt); msgBox.setMinimumWidth(460); msgBox.adjustSize(); From 3db83a189c4c52437bbab94f80d8e0d663d21e75 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 22:38:16 -0700 Subject: [PATCH 118/398] fix(updater): include updater in setup.exe Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- program_info/win_install.nsi.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index d3b5c256f..1e4c29ad7 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -350,6 +350,7 @@ Section "@Launcher_DisplayName@" File "@Launcher_APP_BINARY_NAME@.exe" File "@Launcher_APP_BINARY_NAME@_filelink.exe" + File "@Launcher_APP_BINARY_NAME@_updater.exe" File "qt.conf" File "qtlogging.ini" File *.dll @@ -431,6 +432,7 @@ Section "Uninstall" Delete $INSTDIR\@Launcher_APP_BINARY_NAME@.exe Delete $INSTDIR\@Launcher_APP_BINARY_NAME@_filelink.exe + Delete $INSTDIR\@Launcher_APP_BINARY_NAME@_updater.exe Delete $INSTDIR\qt.conf Delete $INSTDIR\*.dll From 8dd3a02747ab49a205903b362bf3519ce79205bd Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 29 Jun 2023 23:49:31 -0700 Subject: [PATCH 119/398] Update launcher/Application.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1993a1491..e98cc0081 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -585,7 +585,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qDebug() << "Compiled for : " << BuildConfig.systemID(); qDebug() << "Compiled by : " << BuildConfig.compilerID(); qDebug() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT; - qDebug() << "Updates Enabeled : " << (updaterEnabled() ? "Yes" : "No"); + qDebug() << "Updates Enabled : " << (updaterEnabled() ? "Yes" : "No"); if (adjustedBy.size()) { qDebug() << "Work dir before adjustment : " << origcwdPath; qDebug() << "Work dir after adjustment : " << QDir::currentPath(); From 00f75e2d5425edec250134de96f83e0a53cd6500 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 00:54:29 -0700 Subject: [PATCH 120/398] fix(updater): avoid windows installer detection with "asInvoker" in xml exe.manifest Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 1 + .../updater/prismupdater/updater.exe.manifest | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 launcher/updater/prismupdater/updater.exe.manifest diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 4b0e98f83..da4d66b34 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1285,6 +1285,7 @@ if(NOT APPLE OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER)) ) add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp) + target_sources("${Launcher_Name}_updater" PRIVATE updater/prismupdater/updater.exe.manifest) target_link_libraries("${Launcher_Name}_updater" prism_updater_logic) if(DEFINED Launcher_APP_BINARY_NAME) diff --git a/launcher/updater/prismupdater/updater.exe.manifest b/launcher/updater/prismupdater/updater.exe.manifest new file mode 100644 index 000000000..2bce76b77 --- /dev/null +++ b/launcher/updater/prismupdater/updater.exe.manifest @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + From a01a48793c6670743452038f9851c533c1734b0a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 03:00:26 -0700 Subject: [PATCH 121/398] fix(updater): force `asInvoker` for updater on windows - use `__COMPAT_LAYER` env var in windows to bypass Installer Detection and run as a normal user anyway - set up updater directly after main windows is created - check update locks before main window Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 35 ++++++++++--------- launcher/updater/PrismExternalUpdater.cpp | 8 +++++ .../updater/prismupdater/PrismUpdater.cpp | 19 +++++++++- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index e98cc0081..c1d78c5da 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -959,23 +959,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) updateCapabilities(); - if (createSetupWizard()) { - return; - } - - performMainStartupAction(); - - // initialize the updater - if (updaterEnabled()) { - qDebug() << "Initializing updater"; -#ifdef Q_OS_MAC - m_updater.reset(new MacSparkleUpdater()); -#else - m_updater.reset(new PrismExternalUpdater(m_mainWindow, applicationDirPath(), m_dataPath)); -#endif - qDebug() << "<> Updater started."; - } - // check update locks { auto update_log_path = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); @@ -1076,6 +1059,12 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) FS::deletePath(update_success_marker.absoluteFilePath()); } } + + if (createSetupWizard()) { + return; + } + + performMainStartupAction(); } bool Application::createSetupWizard() @@ -1219,6 +1208,18 @@ void Application::performMainStartupAction() showMainWindow(false); qDebug() << "<> Main window shown."; } + + // initialize the updater + if (updaterEnabled()) { + qDebug() << "Initializing updater"; +#ifdef Q_OS_MAC + m_updater.reset(new MacSparkleUpdater()); +#else + m_updater.reset(new PrismExternalUpdater(m_mainWindow, applicationDirPath(), m_dataPath)); +#endif + qDebug() << "<> Updater started."; + } + if (!m_zipsToImport.isEmpty()) { qDebug() << "<> Importing from zip:" << m_zipsToImport; m_mainWindow->processURLs(m_zipsToImport); diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 02e3a3dec..8de2a8119 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -96,6 +96,10 @@ void PrismExternalUpdater::checkForUpdates() auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 exe_name.append(".exe"); + + auto env = QProcessEnvironment::systemEnvironment(); + env.insert("__COMPAT_LAYER", "RUNASINVOKER"); + proc.setProcessEnvironment(env); #endif QStringList args = { "--check-only", "--dir", priv->dataDir.absolutePath(), "--debug" }; @@ -328,6 +332,10 @@ void PrismExternalUpdater::performUpdate(const QString& version_tag) auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 exe_name.append(".exe"); + + auto env = QProcessEnvironment::systemEnvironment(); + env.insert("__COMPAT_LAYER", "RUNASINVOKER"); + proc.setProcessEnvironment(env); #endif QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", version_tag }; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 91cc87ec8..771c6f754 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -704,7 +704,12 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) auto app_exe_name = BuildConfig.LAUNCHER_APP_BINARY_NAME; #if defined Q_OS_WIN32 app_exe_name.append(".exe"); + + auto env = QProcessEnvironment::systemEnvironment(); + env.insert("__COMPAT_LAYER", "RUNASINVOKER"); + proc.setProcessEnvironment(env); #endif + auto app_exe_path = target.absoluteFilePath(app_exe_name); proc.startDetached(app_exe_path); @@ -990,6 +995,11 @@ void PrismUpdaterApp::performInstall(QFileInfo file) } else { logUpdate(tr("Running installer file at %1").arg(file.absoluteFilePath())); QProcess proc = QProcess(); +#if defined Q_OS_WIN + auto env = QProcessEnvironment::systemEnvironment(); + env.insert("__COMPAT_LAYER", "RUNASINVOKER"); + proc.setProcessEnvironment(env); +#endif proc.setProgram(file.absoluteFilePath()); bool result = proc.startDetached(); logUpdate(tr("Process start result: %1").arg(result ? tr("yes") : tr("no"))); @@ -1005,13 +1015,20 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) if (auto loc = unpackArchive(archive)) { auto marker_file_path = loc.value().absoluteFilePath(".prism_launcher_updater_unpack.marker"); FS::write(marker_file_path, applicationDirPath().toUtf8()); + + QProcess proc = QProcess(); + auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 exe_name.append(".exe"); + + auto env = QProcessEnvironment::systemEnvironment(); + env.insert("__COMPAT_LAYER", "RUNASINVOKER"); + proc.setProcessEnvironment(env); #endif + auto new_updater_path = loc.value().absoluteFilePath(exe_name); logUpdate(tr("Starting new updater at '%1'").arg(new_updater_path)); - QProcess proc = QProcess(); if (!proc.startDetached(new_updater_path, { "-d", m_dataPath }, loc.value().absolutePath())) { logUpdate(tr("Failed to launch '%1' %2").arg(new_updater_path).arg(proc.errorString())); return exit(10); From 6476023cf7041340c4e05b020e5c08065578b2d1 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 10:57:53 -0700 Subject: [PATCH 122/398] fix(updater): check the app root dir for binary Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index c1d78c5da..69cd34abc 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1126,7 +1126,7 @@ bool Application::updaterEnabled() #if defined(Q_OS_MAC) return BuildConfig.UPDATER_ENABLED; #else - return BuildConfig.UPDATER_ENABLED && QFileInfo(updaterBinaryName()).isFile(); + return BuildConfig.UPDATER_ENABLED && QFileInfo(FS::PathCombine(applicationDirPath(), updaterBinaryName())).isFile(); #endif } From cd527c44a431e337b58e6888225842b9eb99ff12 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 18:17:06 -0700 Subject: [PATCH 123/398] fix(updater): build atrifact fix on linux ci + add qt-ver to artifact name Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 6 ++-- launcher/StringUtils.cpp | 20 ++++++----- .../updater/prismupdater/PrismUpdater.cpp | 33 ++++++++++++++----- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a1554fc6..de908d335 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -283,12 +283,12 @@ jobs: if: runner.os == 'Windows' && matrix.msystem != '' shell: msys2 {0} run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} -G Ninja - name: Configure CMake (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }} + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON -DLauncher_BUILD_ARTIFACT=${{ matrix.name }}-Qt${{ matrix.qt_ver }} # https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix) if ("${{ env.CCACHE_VAR }}") { @@ -303,7 +303,7 @@ jobs: - name: Configure CMake (Linux) if: runner.os == 'Linux' run: | - cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=${{ matrix.name }} -G Ninja + cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=Linux -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DLauncher_BUILD_ARTIFACT=Linux-Qt${{ matrix.qt_ver }} -G Ninja ## # BUILD diff --git a/launcher/StringUtils.cpp b/launcher/StringUtils.cpp index b54299721..72ccdfbff 100644 --- a/launcher/StringUtils.cpp +++ b/launcher/StringUtils.cpp @@ -184,27 +184,31 @@ QString StringUtils::getRandomAlphaNumeric() return QUuid::createUuid().toString(QUuid::Id128); } -QPair StringUtils::splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs) { +QPair StringUtils::splitFirst(const QString& s, const QString& sep, Qt::CaseSensitivity cs) +{ QString left, right; auto index = s.indexOf(sep, 0, cs); left = s.mid(0, index); - right = s.mid(index + 1); + right = s.mid(index + sep.length()); return qMakePair(left, right); } -QPair StringUtils::splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs) { +QPair StringUtils::splitFirst(const QString& s, QChar sep, Qt::CaseSensitivity cs) +{ QString left, right; auto index = s.indexOf(sep, 0, cs); left = s.mid(0, index); - right = s.mid(index + 1); + right = s.mid(left.length() + 1); return qMakePair(left, right); } -QPair StringUtils::splitFirst(const QString& s, const QRegularExpression& re) { +QPair StringUtils::splitFirst(const QString& s, const QRegularExpression& re) +{ QString left, right; - auto index = s.indexOf(re); + QRegularExpressionMatch match; + auto index = s.indexOf(re, 0, &match); left = s.mid(0, index); - right = s.mid(index + 1); + auto end = match.hasMatch() ? left.length() + match.capturedLength() : left.length() + 1; + right = s.mid(end); return qMakePair(left, right); } - diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 771c6f754..3683286d8 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -784,23 +784,41 @@ QList PrismUpdaterApp::validReleaseArtifacts(const GitHubRel continue; } auto asset_name = asset.name.toLower(); - auto platform = BuildConfig.BUILD_ARTIFACT.toLower(); + auto [platform, platform_qt_ver] = StringUtils::splitFirst(BuildConfig.BUILD_ARTIFACT.toLower(), "-qt"); auto system_is_arm = QSysInfo::buildCpuArchitecture().contains("arm64"); auto asset_is_arm = asset_name.contains("arm64"); auto asset_is_archive = asset_name.endsWith(".zip") || asset_name.endsWith(".tar.gz"); bool for_platform = !platform.isEmpty() && asset_name.contains(platform); + if (!for_platform) { + qDebug() << "Rejecting" << asset.name << "because platforms do not match"; + } bool for_portable = asset_name.contains("portable"); - if (for_platform && asset_name.contains("legacy") && !platform.contains("legacy")) + if (for_platform && asset_name.contains("legacy") && !platform.contains("legacy")) { + qDebug() << "Rejecting" << asset.name << "because platforms do not match"; for_platform = false; - if (for_platform && ((asset_is_arm && !system_is_arm) || (!asset_is_arm && system_is_arm))) + } + if (for_platform && ((asset_is_arm && !system_is_arm) || (!asset_is_arm && system_is_arm))) { + qDebug() << "Rejecting" << asset.name << "because architecture does not match"; for_platform = false; - if (for_platform && platform.contains("windows") && !m_isPortable && asset_is_archive) + } + if (for_platform && platform.contains("windows") && !m_isPortable && asset_is_archive) { + qDebug() << "Rejecting" << asset.name << "because it is not an installer"; for_platform = false; + } + + auto qt_pattern = QRegularExpression("-qt(\\d+)"); + auto qt_match = qt_pattern.match(asset_name); + if (for_platform && qt_match.hasMatch()) { + if (platform_qt_ver.isEmpty() || platform_qt_ver.toInt() != qt_match.captured(1).toInt()) { + qDebug() << "Rejecting" << asset.name << "because it is not for the correct qt version" << platform_qt_ver.toInt() << "vs" + << qt_match.captured(1).toInt(); + for_platform = false; + } + } if (((m_isPortable && for_portable) || (!m_isPortable && !for_portable)) && for_platform) { - qDebug() << "Rejecting" << asset.name << "|" - << "For Platform:" << (for_platform ? "Yes" : "No") << "For Portable:" << (for_portable ? "Yes" : "No"); + qDebug() << "Accepting" << asset.name; valid.append(asset); } } @@ -866,8 +884,7 @@ QFileInfo PrismUpdaterApp::downloadAsset(const GitHubReleaseAsset& asset) auto progress_dialog = ProgressDialog(); progress_dialog.adjustSize(); - if (progress_dialog.execWithTask(download.get()) == QDialog::Rejected) - showFatalErrorMessage(tr("Download Aborted"), tr("Download of %1 aborted by user").arg(file_url.toString())); + progress_dialog.execWithTask(download.get()); qDebug() << "download complete"; From 1fd90e9dd03aa087fd7b8fa2178018812466d80e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 21:24:30 -0700 Subject: [PATCH 124/398] fix(updater): ensure updater knows binaries are in `./bin/` on linux and can find them Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 6 ++- launcher/updater/PrismExternalUpdater.cpp | 12 +++-- .../updater/prismupdater/PrismUpdater.cpp | 48 +++++++++++-------- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 69cd34abc..7eec45bfd 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1126,7 +1126,7 @@ bool Application::updaterEnabled() #if defined(Q_OS_MAC) return BuildConfig.UPDATER_ENABLED; #else - return BuildConfig.UPDATER_ENABLED && QFileInfo(FS::PathCombine(applicationDirPath(), updaterBinaryName())).isFile(); + return BuildConfig.UPDATER_ENABLED && QFileInfo(FS::PathCombine(m_rootPath, updaterBinaryName())).isFile(); #endif } @@ -1135,6 +1135,8 @@ QString Application::updaterBinaryName() auto exe_name = QStringLiteral("%1_updater").arg(BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 exe_name.append(".exe"); +#else + exe_name.prepend("bin/"); #endif return exe_name; } @@ -1215,7 +1217,7 @@ void Application::performMainStartupAction() #ifdef Q_OS_MAC m_updater.reset(new MacSparkleUpdater()); #else - m_updater.reset(new PrismExternalUpdater(m_mainWindow, applicationDirPath(), m_dataPath)); + m_updater.reset(new PrismExternalUpdater(m_mainWindow, m_rootPath, m_dataPath)); #endif qDebug() << "<> Updater started."; } diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 8de2a8119..3595042d6 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -40,7 +40,7 @@ class PrismExternalUpdater::Private { public: - QDir binDir; + QDir appDir; QDir dataDir; QTimer updateTimer; bool allowBeta; @@ -52,10 +52,10 @@ class PrismExternalUpdater::Private { QWidget* parent; }; -PrismExternalUpdater::PrismExternalUpdater(QWidget* parent, const QString& binDir, const QString& dataDir) +PrismExternalUpdater::PrismExternalUpdater(QWidget* parent, const QString& appDir, const QString& dataDir) { priv = new PrismExternalUpdater::Private(); - priv->binDir = QDir(binDir); + priv->appDir = QDir(appDir); priv->dataDir = QDir(dataDir); auto settings_file = priv->dataDir.absoluteFilePath("prismlauncher_update.cfg"); priv->settings = std::make_unique(settings_file, QSettings::Format::IniFormat); @@ -100,13 +100,15 @@ void PrismExternalUpdater::checkForUpdates() auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); +#else + exe_name = QString("bin/%1").arg(exe_name); #endif QStringList args = { "--check-only", "--dir", priv->dataDir.absolutePath(), "--debug" }; if (priv->allowBeta) args.append("--pre-release"); - proc.start(priv->binDir.absoluteFilePath(exe_name), args); + proc.start(priv->appDir.absoluteFilePath(exe_name), args); auto result_start = proc.waitForStarted(5000); if (!result_start) { auto err = proc.error(); @@ -342,7 +344,7 @@ void PrismExternalUpdater::performUpdate(const QString& version_tag) if (priv->allowBeta) args.append("--pre-release"); - auto result = proc.startDetached(priv->binDir.absoluteFilePath(exe_name), args); + auto result = proc.startDetached(priv->appDir.absoluteFilePath(exe_name), args); if (!result) { qDebug() << "Failed to start updater:" << proc.error() << proc.errorString(); } diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 3683286d8..8af65d3c6 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -258,9 +258,9 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_isFlatpak = DesktopServices::isFlatpak(); - QString prism_executable = QCoreApplication::applicationDirPath() + "/" + BuildConfig.LAUNCHER_APP_BINARY_NAME; + QString prism_executable = FS::PathCombine(applicationDirPath(), BuildConfig.LAUNCHER_APP_BINARY_NAME); #if defined Q_OS_WIN32 - prism_executable += ".exe"; + prism_executable.append(".exe"); #endif if (!QFileInfo(prism_executable).isFile()) { @@ -349,6 +349,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_updateLogPath = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); { // setup logging + FS::ensureFolderPathExists(FS::PathCombine(m_dataPath, "logs")); static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; static const QString logBase = FS::PathCombine(m_dataPath, "logs", baseLogFile); auto moveFile = [](const QString& oldName, const QString& newName) { @@ -464,13 +465,13 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar m_network->setProxy(proxy); } - auto marker_file_path = QDir(applicationDirPath()).absoluteFilePath(".prism_launcher_updater_unpack.marker"); + auto marker_file_path = QDir(m_rootPath).absoluteFilePath(".prism_launcher_updater_unpack.marker"); auto marker_file = QFileInfo(marker_file_path); if (marker_file.exists()) { auto target_dir = QString(FS::read(marker_file_path)).trimmed(); if (target_dir.isEmpty()) { qWarning() << "Empty updater marker file contains no install target. making best guess of parent dir"; - target_dir = QDir(applicationDirPath()).absoluteFilePath(".."); + target_dir = QDir(m_rootPath).absoluteFilePath(".."); } QMetaObject::invokeMethod( @@ -629,10 +630,10 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) logUpdate("Waiting 2 seconds for resources to free"); this->thread()->sleep(2); - auto manifest_path = FS::PathCombine(applicationDirPath(), "manifest.txt"); + auto manifest_path = FS::PathCombine(m_rootPath, "manifest.txt"); QFileInfo manifest(manifest_path); - auto app_dir = QDir(applicationDirPath()); + auto app_dir = QDir(m_rootPath); QStringList file_list; if (manifest.isFile()) { @@ -649,7 +650,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) } if (file_list.isEmpty()) { - logUpdate(tr("Manifest empty, making best guess of the directory contents of %1").arg(applicationDirPath())); + logUpdate(tr("Manifest empty, making best guess of the directory contents of %1").arg(m_rootPath)); auto entries = target.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); for (auto entry : entries) { file_list.append(entry.fileName()); @@ -659,7 +660,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) bool error = false; - QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); + QProgressDialog progress(tr("Backing up install at %1").arg(m_rootPath), "", 0, file_list.length()); progress.setCancelButton(nullptr); progress.setMinimumWidth(400); progress.adjustSize(); @@ -668,7 +669,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) int i = 0; for (auto glob : file_list) { - QDirIterator iter(applicationDirPath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); + QDirIterator iter(m_rootPath, QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); progress.setValue(i); QCoreApplication::processEvents(); while (iter.hasNext()) { @@ -708,6 +709,8 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); +#else + exe_name.prepend("bin/"); #endif auto app_exe_path = target.absoluteFilePath(app_exe_name); @@ -894,10 +897,15 @@ QFileInfo PrismUpdaterApp::downloadAsset(const GitHubReleaseAsset& asset) bool PrismUpdaterApp::callAppImageUpdate() { + auto appimage_path = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); QProcess proc = QProcess(); + qDebug() << "Calling: AppImageUpdate" << appimage_path; proc.setProgram("AppImageUpdate"); - proc.setArguments({ QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")) }); - return proc.startDetached(); + proc.setArguments({ appimage_path }); + auto result = proc.startDetached(); + if (!result) + qDebug() << "Failed to start AppImageUpdate reason:" << proc.errorString(); + return result; } void PrismUpdaterApp::clearUpdateLog() @@ -1005,9 +1013,8 @@ void PrismUpdaterApp::performInstall(QFileInfo file) logUpdate(tr("Updating from %1 to %2").arg(m_prismVersion).arg(m_install_release.tag_name)); if (m_isPortable || file.suffix().toLower() == "zip") { - write_lock_file(update_lock_path, QDateTime::currentDateTime(), m_prismVersion, m_install_release.tag_name, applicationDirPath(), - m_dataPath); - logUpdate(tr("Updating portable install at %1").arg(applicationDirPath())); + write_lock_file(update_lock_path, QDateTime::currentDateTime(), m_prismVersion, m_install_release.tag_name, m_rootPath, m_dataPath); + logUpdate(tr("Updating portable install at %1").arg(m_rootPath)); unpackAndInstall(file); } else { logUpdate(tr("Running installer file at %1").arg(file.absoluteFilePath())); @@ -1016,6 +1023,8 @@ void PrismUpdaterApp::performInstall(QFileInfo file) auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); +#else + exe_name.prepend("bin/"); #endif proc.setProgram(file.absoluteFilePath()); bool result = proc.startDetached(); @@ -1031,7 +1040,7 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) if (auto loc = unpackArchive(archive)) { auto marker_file_path = loc.value().absoluteFilePath(".prism_launcher_updater_unpack.marker"); - FS::write(marker_file_path, applicationDirPath().toUtf8()); + FS::write(marker_file_path, m_rootPath.toUtf8()); QProcess proc = QProcess(); @@ -1042,6 +1051,8 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); +#else + exe_name.prepend("bin/"); #endif auto new_updater_path = loc.value().absoluteFilePath(exe_name); @@ -1057,7 +1068,7 @@ void PrismUpdaterApp::unpackAndInstall(QFileInfo archive) void PrismUpdaterApp::backupAppDir() { - auto manifest_path = FS::PathCombine(applicationDirPath(), "manifest.txt"); + auto manifest_path = FS::PathCombine(m_rootPath, "manifest.txt"); QFileInfo manifest(manifest_path); QStringList file_list; @@ -1099,8 +1110,7 @@ void PrismUpdaterApp::backupAppDir() logUpdate("manifest.txt empty or missing. making best guess at files to back up."); } logUpdate(tr("Backing up:\n %1").arg(file_list.join(",\n "))); - - QDir app_dir = QCoreApplication::applicationDirPath(); + auto app_dir = QDir(m_rootPath); auto backup_dir = FS::PathCombine( app_dir.absolutePath(), QStringLiteral("backup_") + @@ -1110,7 +1120,7 @@ void PrismUpdaterApp::backupAppDir() auto backup_marker_path = FS::PathCombine(m_dataPath, ".prism_launcher_update_backup_path.txt"); FS::write(backup_marker_path, backup_dir.toUtf8()); - QProgressDialog progress(tr("Backing up install at %1").arg(applicationDirPath()), "", 0, file_list.length()); + QProgressDialog progress(tr("Backing up install at %1").arg(m_rootPath), "", 0, file_list.length()); progress.setCancelButton(nullptr); progress.setMinimumWidth(400); progress.adjustSize(); From cea285f5f5b678bed0786ff78586e2e921a77392 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 21:33:22 -0700 Subject: [PATCH 125/398] fix(updater): fix bad exe_name on linux Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/updater/prismupdater/PrismUpdater.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 8af65d3c6..2604d2e0b 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -710,7 +710,7 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); #else - exe_name.prepend("bin/"); + app_exe_name.prepend("bin/"); #endif auto app_exe_path = target.absoluteFilePath(app_exe_name); @@ -1023,8 +1023,6 @@ void PrismUpdaterApp::performInstall(QFileInfo file) auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); -#else - exe_name.prepend("bin/"); #endif proc.setProgram(file.absoluteFilePath()); bool result = proc.startDetached(); From b67844e74c1125bde0111606b06aee5a4686c94b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 23:04:55 -0700 Subject: [PATCH 126/398] fix(windows installer): old installers didn't uninstall first. now they do so ensure shortcuts stay selected by default Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- program_info/win_install.nsi.in | 1 - 1 file changed, 1 deletion(-) diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index 1e4c29ad7..fa8615e94 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -470,7 +470,6 @@ Function .onInit ${GetParameters} $R0 ${GetOptions} $R0 "/NoShortcuts" $R1 ${IfNot} ${Errors} -${OrIf} ${FileExists} "$InstDir\@Launcher_APP_BINARY_NAME@.exe" !insertmacro UnselectSection ${SM_SHORTCUTS} !insertmacro UnselectSection ${DESKTOP_SHORTCUTS} ${EndIf} From 4332b62a6268e3093c957dfcbd652c5275228546 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 16:39:21 +0100 Subject: [PATCH 127/398] Fix search focusing Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 22 ++++++++++----------- launcher/ui/dialogs/VersionSelectDialog.cpp | 3 ++- launcher/ui/widgets/JavaSettingsWidget.cpp | 3 ++- launcher/ui/widgets/VersionSelectWidget.cpp | 14 ++++++------- launcher/ui/widgets/VersionSelectWidget.h | 4 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 6e1ad1c04..f62fb8c47 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -30,9 +30,9 @@ #include "ui/widgets/PageContainer.h" #include "ui/widgets/VersionSelectWidget.h" -class LoaderPage : public VersionSelectWidget, public BasePage { +class InstallLoaderPage : public VersionSelectWidget, public BasePage { public: - LoaderPage(const QString& id, + InstallLoaderPage(const QString& id, const QString& icon, const QString& name, // "lightweight" loaders are independent to any game version @@ -86,9 +86,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q auto refreshButton = new QPushButton(tr("&Refresh"), this); connect(refreshButton, &QPushButton::pressed, this, [this] { - LoaderPage* page = dynamic_cast(m_container->selectedPage()); - Q_ASSERT(page != nullptr); - page->loadList(); + dynamic_cast(m_container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); @@ -106,18 +104,20 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q connect(m_container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); updateAcceptButton(m_container->selectedPage()); + + dynamic_cast(m_container->selectedPage())->selectSearch(); } QList InstallLoaderDialog::getPages() { return { // Forge - new LoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), // Fabric - new LoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), // Quilt - new LoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), // LiteLoader - new LoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) }; } @@ -135,9 +135,7 @@ void InstallLoaderDialog::updateAcceptButton(const BasePage* page) void InstallLoaderDialog::done(int result) { if (result == Accepted) { - LoaderPage* page = dynamic_cast(m_container->selectedPage()); - Q_ASSERT(page != nullptr); - + auto* page = dynamic_cast(m_container->selectedPage()); if (page->selectedVersion()) { m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); m_profile->resolve(Net::Mode::Online); diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index 5feb70d20..dec85550f 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -55,7 +55,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, m_verticalLayout = new QVBoxLayout(this); m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - m_versionWidget = new VersionSelectWidget(true, parent); + m_versionWidget = new VersionSelectWidget(parent); m_verticalLayout->addWidget(m_versionWidget); m_horizontalLayout = new QHBoxLayout(); @@ -123,6 +123,7 @@ int VersionSelectDialog::exec() { QDialog::open(); m_versionWidget->initialize(m_vlist); + m_versionWidget->selectSearch(); if(resizeOnColumn != -1) { m_versionWidget->setResizeOn(resizeOnColumn); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index c94fdd8d5..d77e0fa00 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -46,7 +46,7 @@ void JavaSettingsWidget::setupUi() m_verticalLayout = new QVBoxLayout(this); m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - m_versionWidget = new VersionSelectWidget(true, this); + m_versionWidget = new VersionSelectWidget(this); m_verticalLayout->addWidget(m_versionWidget); m_horizontalLayout = new QHBoxLayout(); @@ -126,6 +126,7 @@ void JavaSettingsWidget::setupUi() void JavaSettingsWidget::initialize() { m_versionWidget->initialize(APPLICATION->javalist().get()); + m_versionWidget->selectSearch(); m_versionWidget->setResizeOn(2); auto s = APPLICATION->settings(); // Memory diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index a956ddb3c..efc9c4124 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -11,10 +11,8 @@ #include "ui/dialogs/CustomMessageBox.h" -VersionSelectWidget::VersionSelectWidget(QWidget* parent) : VersionSelectWidget(false, parent) {} - -VersionSelectWidget::VersionSelectWidget(bool focusSearch, QWidget* parent) - : QWidget(parent), focusSearch(focusSearch) +VersionSelectWidget::VersionSelectWidget(QWidget* parent) + : QWidget(parent) { setObjectName(QStringLiteral("VersionSelectWidget")); verticalLayout = new QVBoxLayout(this); @@ -116,9 +114,6 @@ void VersionSelectWidget::initialize(BaseVersionList *vlist) listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); - if (focusSearch) - search->setFocus(); - if (!m_vlist->isLoaded()) { loadList(); @@ -210,6 +205,11 @@ void VersionSelectWidget::selectCurrent() } } +void VersionSelectWidget::selectSearch() +{ + search->setFocus(); +} + void VersionSelectWidget::selectRecommended() { auto idx = m_proxyModel->getRecommended(); diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index be4ba768d..a1b60d359 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -52,7 +52,6 @@ class VersionSelectWidget: public QWidget Q_OBJECT public: explicit VersionSelectWidget(QWidget *parent); - explicit VersionSelectWidget(bool focusSearch = false, QWidget *parent = 0); ~VersionSelectWidget(); //! loads the list if needed. @@ -65,6 +64,7 @@ public: BaseVersion::Ptr selectedVersion() const; void selectRecommended(); void selectCurrent(); + void selectSearch(); void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); @@ -74,6 +74,7 @@ public: void setEmptyErrorString(QString emptyErrorString); void setEmptyMode(VersionListView::EmptyMode mode); void setResizeOn(int column); + bool eventFilter(QObject* watched, QEvent* event) override; signals: @@ -98,7 +99,6 @@ private: int resizeOnColumn = 0; Task * loadTask; bool preselectedAlready = false; - bool focusSearch; QVBoxLayout *verticalLayout = nullptr; VersionListView *listView = nullptr; From 4cdf669154327b764ea2f7371e3d29f71d06daa7 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 17:02:39 +0100 Subject: [PATCH 128/398] Modify "Change Version" to use "Install Loader" dialog Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 18 ++++++++++++++---- launcher/ui/dialogs/InstallLoaderDialog.h | 4 ++-- launcher/ui/pages/instance/VersionPage.cpp | 12 +++++++++++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index f62fb8c47..74b3ea92b 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -74,7 +74,14 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { bool m_loaded = false; }; -InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, QWidget* parent) +InstallLoaderPage* pageCast(BasePage* page) +{ + auto result = dynamic_cast(page); + Q_ASSERT(result != nullptr); + return result; +} + +InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, const QString& uid, QWidget* parent) : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)), m_buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); @@ -86,7 +93,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q auto refreshButton = new QPushButton(tr("&Refresh"), this); connect(refreshButton, &QPushButton::pressed, this, [this] { - dynamic_cast(m_container->selectedPage())->loadList(); + pageCast(m_container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); @@ -105,7 +112,10 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, Q [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); updateAcceptButton(m_container->selectedPage()); - dynamic_cast(m_container->selectedPage())->selectSearch(); + pageCast(m_container->selectedPage())->selectSearch(); + for (BasePage* page : m_container->getPages()) + if (page->id() == uid) + m_container->selectPage(page->id()); } QList InstallLoaderDialog::getPages() @@ -135,7 +145,7 @@ void InstallLoaderDialog::updateAcceptButton(const BasePage* page) void InstallLoaderDialog::done(int result) { if (result == Accepted) { - auto* page = dynamic_cast(m_container->selectedPage()); + auto* page = pageCast(m_container->selectedPage()); if (page->selectedVersion()) { m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); m_profile->resolve(Net::Mode::Online); diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 6c8762dc0..24064eaa0 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -26,11 +26,11 @@ class PageContainer; class PackProfile; class QDialogButtonBox; -class InstallLoaderDialog : public QDialog, public BasePageProvider { +class InstallLoaderDialog final : public QDialog, public BasePageProvider { Q_OBJECT public: - explicit InstallLoaderDialog(std::shared_ptr instance, QWidget* parent = nullptr); + explicit InstallLoaderDialog(std::shared_ptr instance, const QString& uid = QString(), QWidget* parent = nullptr); QList getPages() override; QString dialogTitle() override; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 53a710083..86ba5c276 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -432,6 +432,16 @@ void VersionPage::on_actionChange_version_triggered() return; } auto uid = list->uid(); + + // FIXME: this is still a horrible HACK. + if (uid == "net.minecraftforge" || uid == "com.mumfrey.liteloader" || uid == "net.fabricmc.fabric-loader" || + uid == "org.quiltmc.quilt-loader") { + InstallLoaderDialog dialog(m_inst->getPackProfile(), uid, this); + dialog.exec(); + m_container->refreshContainer(); + return; + } + VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { @@ -485,7 +495,7 @@ void VersionPage::on_actionDownload_All_triggered() void VersionPage::on_actionInstall_Loader_triggered() { - InstallLoaderDialog dialog(m_inst->getPackProfile(), this); + InstallLoaderDialog dialog(m_inst->getPackProfile(), QString(), this); dialog.exec(); m_container->refreshContainer(); } From 284e374ae858d6784b6df48c83534dc6dc973747 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 17:20:43 +0100 Subject: [PATCH 129/398] Nop Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 10 ---------- launcher/ui/dialogs/InstallLoaderDialog.h | 1 - 2 files changed, 11 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 74b3ea92b..31307ee15 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -108,10 +108,6 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c setWindowTitle(dialogTitle()); resize(650, 400); - connect(m_container, &PageContainer::selectedPageChanged, this, - [this](BasePage* previous, BasePage* selected) { updateAcceptButton(selected); }); - updateAcceptButton(m_container->selectedPage()); - pageCast(m_container->selectedPage())->selectSearch(); for (BasePage* page : m_container->getPages()) if (page->id() == uid) @@ -136,12 +132,6 @@ QString InstallLoaderDialog::dialogTitle() return tr("Install Loader"); } -void InstallLoaderDialog::updateAcceptButton(const BasePage* page) -{ - auto installed = !m_profile->getComponentVersion(page->id()).isNull(); - m_buttons->button(QDialogButtonBox::Ok)->setText(installed ? tr("&Update") : tr("&Install")); -} - void InstallLoaderDialog::done(int result) { if (result == Accepted) { diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 24064eaa0..09d847778 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -35,7 +35,6 @@ class InstallLoaderDialog final : public QDialog, public BasePageProvider { QList getPages() override; QString dialogTitle() override; - void updateAcceptButton(const BasePage* page); void done(int result) override; private: From 9f9b5254a239d6359d199c33fa5d966e1f4d6e63 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 19:32:04 +0100 Subject: [PATCH 130/398] Double-click to install/change version Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 33 +++++++++++---------- launcher/ui/dialogs/VersionSelectDialog.cpp | 5 ++-- launcher/ui/widgets/VersionSelectWidget.cpp | 5 ++++ launcher/ui/widgets/VersionSelectWidget.h | 1 + 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 31307ee15..acef60c69 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -33,13 +33,12 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { public: InstallLoaderPage(const QString& id, - const QString& icon, - const QString& name, - // "lightweight" loaders are independent to any game version - const bool lightweight, - const std::shared_ptr profile, - QWidget* parent = nullptr) - : VersionSelectWidget(parent), m_id(id), m_icon(icon), m_name(name) + const QString& icon, + const QString& name, + // "lightweight" loaders are independent to any game version + const bool lightweight, + const std::shared_ptr profile) + : VersionSelectWidget(nullptr), m_id(id), m_icon(icon), m_name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); @@ -67,6 +66,12 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { m_loaded = true; } + void setParentContainer(BasePageContainer* container) override + { + auto dialog = dynamic_cast(dynamic_cast(container)->parent()); + connect(view(), &QAbstractItemView::doubleClicked, dialog, &QDialog::accept); + } + private: const QString m_id; const QString m_icon; @@ -82,7 +87,7 @@ InstallLoaderPage* pageCast(BasePage* page) } InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, const QString& uid, QWidget* parent) - : QDialog(parent), m_profile(profile), m_container(new PageContainer(this)), m_buttons(new QDialogButtonBox(this)) + : QDialog(parent), m_profile(profile), m_container(new PageContainer(this, QString(), this)), m_buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); @@ -92,9 +97,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c auto buttonLayout = new QHBoxLayout(this); auto refreshButton = new QPushButton(tr("&Refresh"), this); - connect(refreshButton, &QPushButton::pressed, this, [this] { - pageCast(m_container->selectedPage())->loadList(); - }); + connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(m_container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); m_buttons->setOrientation(Qt::Horizontal); @@ -117,13 +120,13 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c QList InstallLoaderDialog::getPages() { return { // Forge - new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile, this), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile, this), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile), // Quilt - new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile, this), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile), // LiteLoader - new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile, this) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile) }; } diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index dec85550f..e45787e4a 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -75,8 +75,9 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, retranslate(); - QObject::connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - QObject::connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_versionWidget->view(), &QAbstractItemView::doubleClicked, this, &QDialog::accept); + connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); QMetaObject::connectSlotsByName(this); setWindowModality(Qt::WindowModal); diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index efc9c4124..f20dad711 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -210,6 +210,11 @@ void VersionSelectWidget::selectSearch() search->setFocus(); } +VersionListView* VersionSelectWidget::view() +{ + return listView; +} + void VersionSelectWidget::selectRecommended() { auto idx = m_proxyModel->getRecommended(); diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index a1b60d359..624d9a232 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -65,6 +65,7 @@ public: void selectRecommended(); void selectCurrent(); void selectSearch(); + VersionListView* view(); void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); From 6cc3587da2a87c87d37f205fd39a31a5a136814a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 1 Jul 2023 20:10:38 +0100 Subject: [PATCH 131/398] Disable as intended Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/VersionPage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 86ba5c276..31e0b9b37 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -274,8 +274,9 @@ void VersionPage::updateButtons(int row) ui->actionAdd_Empty->setEnabled(controlsEnabled); ui->actionImport_Components->setEnabled(controlsEnabled); ui->actionReload->setEnabled(controlsEnabled); - ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); + ui->actionInstall_Loader->setEnabled(controlsEnabled); ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); + ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_Agents->setEnabled(controlsEnabled); } From e2a65a70779a66471d98a98a1cc611fcb9bb0d5b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 1 Jul 2023 13:45:53 -0700 Subject: [PATCH 132/398] feat: ensure MSVC using stack unwind semantics Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70a553190..b1e635859 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,13 @@ if(MSVC) # Use /W4 as /Wall includes unnesserey warnings such as added padding to structs set(CMAKE_CXX_FLAGS "/GS /permissive- /W4 ${CMAKE_CXX_FLAGS}") + # /EHs Enables stack unwind semantics for standard C++ exceptions to ensure stackframes are unwound + # and object deconstructors are called when an exception is caught. + # without it memory leaks and a warning is printed + # /EHc tells the compiler to assume that functions declared as extern "C" never throw a C++ exception + # This appears to not always be a defualt compiler option in CMAKE + set(CMAKE_CXX_FLAGS "/EHsc ${CMAKE_CXX_FLAGS}") + # LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs # This implicitly selects an entrypoint specific to the subsystem selected # qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs From 2a5d291bd940ea61b8254eb78b478ae86ed17f59 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 1 Jul 2023 13:38:32 -0700 Subject: [PATCH 133/398] fix: toml without exceptions usage Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/tasks/LocalModParseTask.cpp | 7 ++++--- launcher/modplatform/packwiz/Packwiz.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index 264019f84..f8d454cf6 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -104,14 +104,15 @@ ModDetails ReadMCModTOML(QByteArray contents) #if TOML_EXCEPTIONS try { tomlData = toml::parse(contents.toStdString()); - } catch (const toml::parse_error& err) { + } catch ([[maybe_unused]] const toml::parse_error& err) { return {}; } #else - tomlData = toml::parse(contents.toStdString()); - if (!tomlData) { + toml::parse_result result = toml::parse(contents.toStdString()); + if (!result) { return {}; } + tomlData = result.table(); #endif // array defined by [[mods]] diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 510c7309d..967b8870c 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -241,12 +241,13 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod return {}; } #else - table = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname))); - if (!table) { + toml::parse_result result = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname))); + if (!result) { qWarning() << QString("Could not open file %1!").arg(normalized_fname); - qWarning() << "Reason: " << QString(table.error().what()); + qWarning() << "Reason: " << result.error().description(); return {}; } + table = result.table(); #endif // index_file.close(); From d7d2d9f6123618273f753fd07263c807112031d2 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 23:17:18 -0700 Subject: [PATCH 134/398] chore: remove WARNINGS_AS_ERRORS Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- cmake/CompilerWarnings.cmake | 9 --------- launcher/CMakeLists.txt | 2 -- 2 files changed, 11 deletions(-) diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index b03664016..635e54289 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -39,7 +39,6 @@ endfunction() function( set_project_warnings _project_name - WARNINGS_AS_ERRORS MSVC_WARNINGS CLANG_WARNINGS GCC_WARNINGS @@ -105,14 +104,6 @@ function( ) endif() - - if(WARNINGS_AS_ERRORS) - message(TRACE "Warnings are treated as errors") - list(APPEND CLANG_WARNINGS -Werror) - list(APPEND GCC_WARNINGS -Werror) - list(APPEND MSVC_WARNINGS /WX) - endif() - if(MSVC) set(PROJECT_WARNINGS_CXX ${MSVC_WARNINGS}) elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 9bb465721..b3071ae24 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1095,7 +1095,6 @@ include(CompilerWarnings) # Add executable add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) set_project_warnings(Launcher_logic - "${WARNINGS_AS_ERRORS}" "${Launcher_MSVC_WARNINGS}" "${Launcher_CLANG_WARNINGS}" "${Launcher_GCC_WARNINGS}") @@ -1178,7 +1177,6 @@ install(TARGETS ${Launcher_Name} if(WIN32) add_library(filelink_logic STATIC ${LINKEXE_SOURCES}) set_project_warnings(filelink_logic - "${WARNINGS_AS_ERRORS}" "${Launcher_MSVC_WARNINGS}" "${Launcher_CLANG_WARNINGS}" "${Launcher_GCC_WARNINGS}") From 98d6904e4a84836c1b9ec662b0b8a49d5282e27b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 23:50:13 -0700 Subject: [PATCH 135/398] chore: fix propagate mispelling Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/InstanceImportTask.cpp | 6 +++--- launcher/InstanceList.cpp | 13 +++++++++---- launcher/ResourceDownloadTask.cpp | 2 +- launcher/launch/steps/Update.cpp | 2 +- launcher/minecraft/MinecraftLoadAndCheck.cpp | 2 +- launcher/minecraft/MinecraftUpdate.cpp | 4 ++-- launcher/minecraft/update/AssetUpdateTask.cpp | 4 ++-- launcher/minecraft/update/FMLLibrariesTask.cpp | 2 +- launcher/minecraft/update/LibrariesTask.cpp | 2 +- .../modplatform/atlauncher/ATLPackInstallTask.cpp | 4 ++-- launcher/modplatform/flame/FileResolvingTask.cpp | 6 +++--- .../modplatform/flame/FlameInstanceCreationTask.cpp | 4 ++-- launcher/modplatform/legacy_ftb/PackInstallTask.cpp | 2 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 2 +- .../technic/SingleZipPackInstallTask.cpp | 2 +- .../modplatform/technic/SolderPackInstallTask.cpp | 2 +- launcher/tasks/Task.cpp | 2 +- launcher/tasks/Task.h | 2 +- 18 files changed, 34 insertions(+), 29 deletions(-) diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 352848f02..d6a96deb1 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -99,7 +99,7 @@ void InstanceImportTask::executeTask() connect(m_filesNetJob.get(), &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged); - connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &InstanceImportTask::propagateStepProgress); connect(m_filesNetJob.get(), &NetJob::failed, this, &InstanceImportTask::downloadFailed); connect(m_filesNetJob.get(), &NetJob::aborted, this, &InstanceImportTask::downloadAborted); @@ -293,7 +293,7 @@ void InstanceImportTask::processFlame() }); connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed); connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress); - connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress); connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus); connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails); @@ -385,7 +385,7 @@ void InstanceImportTask::processModrinth() }); connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed); connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress); - connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propagateStepProgress); connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus); connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails); connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater); diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index b4c520cd9..b361b286b 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -787,20 +787,25 @@ class InstanceStaging : public Task { Q_OBJECT const unsigned minBackoff = 1; const unsigned maxBackoff = 16; + public: InstanceStaging(InstanceList* parent, InstanceTask* child, QString stagingPath, InstanceName const& instanceName, QString groupName) - : m_parent(parent), backoff(minBackoff, maxBackoff), m_stagingPath(std::move(stagingPath)), m_instance_name(std::move(instanceName)), m_groupName(std::move(groupName)) + : m_parent(parent) + , backoff(minBackoff, maxBackoff) + , m_stagingPath(std::move(stagingPath)) + , m_instance_name(std::move(instanceName)) + , m_groupName(std::move(groupName)) { m_child.reset(child); - connect(child, &Task::succeeded, this, &InstanceStaging::childSucceded); + connect(child, &Task::succeeded, this, &InstanceStaging::childSucceeded); connect(child, &Task::failed, this, &InstanceStaging::childFailed); connect(child, &Task::aborted, this, &InstanceStaging::childAborted); connect(child, &Task::abortStatusChanged, this, &InstanceStaging::setAbortable); connect(child, &Task::status, this, &InstanceStaging::setStatus); connect(child, &Task::details, this, &InstanceStaging::setDetails); connect(child, &Task::progress, this, &InstanceStaging::setProgress); - connect(child, &Task::stepProgress, this, &InstanceStaging::propogateStepProgress); - connect(&m_backoffTimer, &QTimer::timeout, this, &InstanceStaging::childSucceded); + connect(child, &Task::stepProgress, this, &InstanceStaging::propagateStepProgress); + connect(&m_backoffTimer, &QTimer::timeout, this, &InstanceStaging::childSucceeded); } virtual ~InstanceStaging(){}; diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp index 06c03c779..8bb9b64e9 100644 --- a/launcher/ResourceDownloadTask.cpp +++ b/launcher/ResourceDownloadTask.cpp @@ -54,7 +54,7 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, m_filesNetJob->addNetAction(Net::Download::makeFile(m_pack_version.downloadUrl, dir.absoluteFilePath(getFilename()))); connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ResourceDownloadTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &ResourceDownloadTask::downloadProgressChanged); - connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propogateStepProgress); + connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &ResourceDownloadTask::propagateStepProgress); connect(m_filesNetJob.get(), &NetJob::failed, this, &ResourceDownloadTask::downloadFailed); addTask(m_filesNetJob); diff --git a/launcher/launch/steps/Update.cpp b/launcher/launch/steps/Update.cpp index 77c8a18ea..8df2bc67c 100644 --- a/launcher/launch/steps/Update.cpp +++ b/launcher/launch/steps/Update.cpp @@ -28,7 +28,7 @@ void Update::executeTask() { connect(m_updateTask.get(), &Task::finished, this, &Update::updateFinished); connect(m_updateTask.get(), &Task::progress, this, &Update::setProgress); - connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propogateStepProgress); + connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propagateStepProgress); connect(m_updateTask.get(), &Task::status, this, &Update::setStatus); connect(m_updateTask.get(), &Task::details, this, &Update::setDetails); emit progressReportingRequest(); diff --git a/launcher/minecraft/MinecraftLoadAndCheck.cpp b/launcher/minecraft/MinecraftLoadAndCheck.cpp index 1c3f6fb71..2a3698798 100644 --- a/launcher/minecraft/MinecraftLoadAndCheck.cpp +++ b/launcher/minecraft/MinecraftLoadAndCheck.cpp @@ -22,7 +22,7 @@ void MinecraftLoadAndCheck::executeTask() connect(m_task.get(), &Task::failed, this, &MinecraftLoadAndCheck::subtaskFailed); connect(m_task.get(), &Task::aborted, this, [this]{ subtaskFailed(tr("Aborted")); }); connect(m_task.get(), &Task::progress, this, &MinecraftLoadAndCheck::progress); - connect(m_task.get(), &Task::stepProgress, this, &MinecraftLoadAndCheck::propogateStepProgress); + connect(m_task.get(), &Task::stepProgress, this, &MinecraftLoadAndCheck::propagateStepProgress); connect(m_task.get(), &Task::status, this, &MinecraftLoadAndCheck::setStatus); } diff --git a/launcher/minecraft/MinecraftUpdate.cpp b/launcher/minecraft/MinecraftUpdate.cpp index 35430bb0f..236d0224b 100644 --- a/launcher/minecraft/MinecraftUpdate.cpp +++ b/launcher/minecraft/MinecraftUpdate.cpp @@ -100,7 +100,7 @@ void MinecraftUpdate::next() disconnect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); disconnect(task.get(), &Task::aborted, this, &Task::abort); disconnect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress); + disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); } @@ -120,7 +120,7 @@ void MinecraftUpdate::next() connect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); connect(task.get(), &Task::aborted, this, &Task::abort); connect(task.get(), &Task::progress, this, &MinecraftUpdate::progress); - connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propogateStepProgress); + connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress); connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); // if the task is already running, do not start it again diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index 31fd5eb11..fda85ba8a 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -45,7 +45,7 @@ void AssetUpdateTask::executeTask() connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetIndexFailed); connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); - connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propogateStepProgress); + connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); qDebug() << m_inst->name() << ": Starting asset index download"; downloadJob->start(); @@ -84,7 +84,7 @@ void AssetUpdateTask::assetIndexFinished() connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed); connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); - connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propogateStepProgress); + connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); downloadJob->start(); return; } diff --git a/launcher/minecraft/update/FMLLibrariesTask.cpp b/launcher/minecraft/update/FMLLibrariesTask.cpp index 75e5c5720..d9fa0595d 100644 --- a/launcher/minecraft/update/FMLLibrariesTask.cpp +++ b/launcher/minecraft/update/FMLLibrariesTask.cpp @@ -75,7 +75,7 @@ void FMLLibrariesTask::executeTask() connect(dljob.get(), &NetJob::failed, this, &FMLLibrariesTask::fmllibsFailed); connect(dljob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(dljob.get(), &NetJob::progress, this, &FMLLibrariesTask::progress); - connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propogateStepProgress); + connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propagateStepProgress); downloadJob.reset(dljob); downloadJob->start(); } diff --git a/launcher/minecraft/update/LibrariesTask.cpp b/launcher/minecraft/update/LibrariesTask.cpp index 415b9a660..9d1c02957 100644 --- a/launcher/minecraft/update/LibrariesTask.cpp +++ b/launcher/minecraft/update/LibrariesTask.cpp @@ -70,7 +70,7 @@ void LibrariesTask::executeTask() connect(downloadJob.get(), &NetJob::failed, this, &LibrariesTask::jarlibFailed); connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &LibrariesTask::progress); - connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propogateStepProgress); + connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propagateStepProgress); downloadJob->start(); } diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 22ea02da2..82a51c274 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -684,7 +684,7 @@ void PackInstallTask::installConfigs() abortable = true; setProgress(current, total); }); - connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress); + connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); connect(jobPtr.get(), &NetJob::aborted, [&]{ abortable = false; jobPtr.reset(); @@ -852,7 +852,7 @@ void PackInstallTask::downloadMods() abortable = true; setProgress(current, total); }); - connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress); + connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); connect(jobPtr.get(), &NetJob::aborted, [&] { abortable = false; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index ce7a60551..84455e58a 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -48,7 +48,7 @@ void Flame::FileResolvingTask::executeTask() stepProgress(*step_progress); emitFailed(reason); }); - connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress); connect(m_dljob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { qDebug() << "Resolve slug progress" << current << total; step_progress->update(current, total); @@ -114,7 +114,7 @@ void Flame::FileResolvingTask::netJobFinished() stepProgress(*step_progress); emitFailed(reason); }); - connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress); connect(m_checkJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { qDebug() << "Resolve slug progress" << current << total; step_progress->update(current, total); @@ -192,7 +192,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { stepProgress(*step_progress); emitFailed(reason); }); - connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propagateStepProgress); connect(m_slugJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { qDebug() << "Resolve slug progress" << current << total; step_progress->update(current, total); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index f003ada9d..ccf46d5d3 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -386,7 +386,7 @@ bool FlameCreationTask::createInstance() }); connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress); connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus); - connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propogateStepProgress); + connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propagateStepProgress); connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::details, this, &FlameCreationTask::setDetails); m_mod_id_resolver->start(); @@ -505,7 +505,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); setProgress(current, total); }); - connect(m_files_job.get(), &NetJob::stepProgress, this, &FlameCreationTask::propogateStepProgress); + connect(m_files_job.get(), &NetJob::stepProgress, this, &FlameCreationTask::propagateStepProgress); connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit); setStatus(tr("Downloading mods...")); diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index 36c142acb..62ffd6abe 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -81,7 +81,7 @@ void PackInstallTask::downloadPack() connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); connect(netJobContainer.get(), &NetJob::progress, this, &PackInstallTask::onDownloadProgress); - connect(netJobContainer.get(), &NetJob::stepProgress, this, &PackInstallTask::propogateStepProgress); + connect(netJobContainer.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); connect(netJobContainer.get(), &NetJob::aborted, this, &PackInstallTask::onDownloadAborted); netJobContainer->start(); diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 76f072773..bd0b828c6 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -267,7 +267,7 @@ bool ModrinthCreationTask::createInstance() setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); setProgress(current, total); }); - connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propogateStepProgress); + connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propagateStepProgress); setStatus(tr("Downloading mods...")); m_files_job->start(); diff --git a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp index f07ca24af..ab91c4668 100644 --- a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp +++ b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp @@ -50,7 +50,7 @@ void Technic::SingleZipPackInstallTask::executeTask() auto job = m_filesNetJob.get(); connect(job, &NetJob::succeeded, this, &Technic::SingleZipPackInstallTask::downloadSucceeded); connect(job, &NetJob::progress, this, &Technic::SingleZipPackInstallTask::downloadProgressChanged); - connect(job, &NetJob::stepProgress, this, &Technic::SingleZipPackInstallTask::propogateStepProgress); + connect(job, &NetJob::stepProgress, this, &Technic::SingleZipPackInstallTask::propagateStepProgress); connect(job, &NetJob::failed, this, &Technic::SingleZipPackInstallTask::downloadFailed); m_filesNetJob->start(); } diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index 6a05d17ae..cc1d261e2 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -126,7 +126,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded() connect(m_filesNetJob.get(), &NetJob::succeeded, this, &Technic::SolderPackInstallTask::downloadSucceeded); connect(m_filesNetJob.get(), &NetJob::progress, this, &Technic::SolderPackInstallTask::downloadProgressChanged); - connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &Technic::SolderPackInstallTask::propogateStepProgress); + connect(m_filesNetJob.get(), &NetJob::stepProgress, this, &Technic::SolderPackInstallTask::propagateStepProgress); connect(m_filesNetJob.get(), &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed); connect(m_filesNetJob.get(), &NetJob::aborted, this, &Technic::SolderPackInstallTask::downloadAborted); m_filesNetJob->start(); diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index 29c55cd48..fd82ec001 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -161,7 +161,7 @@ void Task::emitSucceeded() emit finished(); } -void Task::propogateStepProgress(TaskStepProgress const& task_progress) +void Task::propagateStepProgress(TaskStepProgress const& task_progress) { emit stepProgress(task_progress); } diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index d3bcc84f7..de0884c59 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -167,7 +167,7 @@ class Task : public QObject, public QRunnable { virtual void emitAborted(); virtual void emitFailed(QString reason = ""); - virtual void propogateStepProgress(TaskStepProgress const& task_progress); + virtual void propagateStepProgress(TaskStepProgress const& task_progress); public slots: void setStatus(const QString& status); From 8d7dcdfc5b2a231a1304878e25929e6f4ff4e338 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 30 Jun 2023 23:51:15 -0700 Subject: [PATCH 136/398] chore: fix shadowed member and signed/unsigned mismatch Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: supress unused with [[maybe_unused]] Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: unshadow ^&^& static_cast implicit return Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: deshadow and mark unused in parse task Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: mark unused in folder models Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: deshadow and mark unused with instances Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: more deshadow and unused Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: remove uneeded simicolons Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: mark unused Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> chore: prevent shadow Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/DesktopServices.cpp | 2 +- launcher/InstanceList.cpp | 128 +++++++++--------- launcher/NullInstance.h | 2 +- launcher/RecursiveFileSystemWatcher.cpp | 2 +- launcher/VersionProxyModel.cpp | 36 ++--- launcher/filelink/FileLink.cpp | 2 +- launcher/icons/IconUtils.cpp | 4 +- launcher/meta/BaseEntity.cpp | 6 +- launcher/minecraft/MinecraftInstance.cpp | 6 +- launcher/minecraft/MojangDownloadInfo.h | 10 +- launcher/minecraft/OneSixVersionFormat.cpp | 2 +- launcher/minecraft/PackProfile.cpp | 18 +-- launcher/minecraft/PackProfile.h | 2 +- launcher/minecraft/ProfileUtils.cpp | 2 +- launcher/minecraft/World.cpp | 12 +- launcher/minecraft/WorldList.cpp | 11 +- launcher/minecraft/auth/AccountData.cpp | 4 +- launcher/minecraft/auth/AccountList.cpp | 2 +- launcher/minecraft/auth/Parsers.cpp | 8 +- .../minecraft/auth/steps/EntitlementsStep.cpp | 4 +- .../minecraft/gameoptions/GameOptions.cpp | 3 +- .../minecraft/launch/LauncherPartLaunch.cpp | 2 +- launcher/minecraft/mod/Mod.h | 2 +- launcher/minecraft/mod/ModDetails.h | 19 ++- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- .../minecraft/mod/ResourceFolderModel.cpp | 6 +- launcher/minecraft/mod/ResourceFolderModel.h | 4 +- .../minecraft/mod/ResourcePackFolderModel.cpp | 3 +- .../minecraft/mod/TexturePackFolderModel.cpp | 2 +- .../mod/tasks/GetModDependenciesTask.cpp | 20 +-- .../minecraft/mod/tasks/LocalModParseTask.cpp | 26 ++-- launcher/minecraft/services/CapeChange.cpp | 2 +- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/ResourceAPI.h | 4 +- .../modplatform/flame/FileResolvingTask.cpp | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 7 +- .../helpers/NetworkResourceAPI.cpp | 3 +- .../modrinth/ModrinthPackExportTask.cpp | 12 +- .../modrinth/ModrinthPackIndex.cpp | 6 +- launcher/modplatform/packwiz/Packwiz.cpp | 5 +- .../technic/TechnicPackProcessor.cpp | 16 ++- launcher/news/NewsEntry.cpp | 7 +- launcher/screenshots/ImgurAlbumCreation.cpp | 2 +- launcher/screenshots/ImgurUpload.cpp | 2 +- launcher/tasks/ConcurrentTask.cpp | 2 +- launcher/tasks/Task.h | 7 +- launcher/tools/JProfiler.cpp | 2 +- launcher/tools/JVisualVM.cpp | 2 +- launcher/translations/POTranslator.cpp | 2 +- launcher/translations/TranslationsModel.cpp | 12 +- launcher/ui/MainWindow.cpp | 27 ++-- launcher/ui/dialogs/CopyInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ExportInstanceDialog.cpp | 8 +- launcher/ui/dialogs/NewInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ProfileSetupDialog.cpp | 16 +-- launcher/ui/dialogs/ProgressDialog.cpp | 20 +-- launcher/ui/dialogs/ProgressDialog.h | 2 +- .../ui/dialogs/ResourceDownloadDialog.cpp | 2 +- launcher/ui/dialogs/ReviewMessageBox.cpp | 2 +- launcher/ui/dialogs/SkinUploadDialog.cpp | 6 +- launcher/ui/instanceview/InstanceDelegate.cpp | 22 +-- launcher/ui/instanceview/InstanceView.cpp | 82 +++++------ launcher/ui/instanceview/VisualGroup.cpp | 6 +- launcher/ui/pages/global/AccountListPage.cpp | 5 +- launcher/ui/pages/global/JavaPage.cpp | 2 +- launcher/ui/pages/global/ProxyPage.cpp | 2 +- .../pages/instance/ExternalResourcesPage.cpp | 2 +- .../pages/instance/InstanceSettingsPage.cpp | 2 +- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- launcher/ui/pages/instance/OtherLogsPage.cpp | 22 +-- .../ui/pages/instance/ResourcePackPage.cpp | 2 +- launcher/ui/pages/instance/ServersPage.cpp | 4 +- .../ui/pages/instance/TexturePackPage.cpp | 2 +- launcher/ui/pages/instance/VersionPage.cpp | 4 +- launcher/ui/pages/instance/WorldListPage.cpp | 2 +- launcher/ui/pages/modplatform/ImportPage.cpp | 6 +- .../ui/pages/modplatform/ResourceModel.cpp | 6 +- .../pages/modplatform/ResourcePackModel.cpp | 3 +- .../ui/pages/modplatform/ResourcePage.cpp | 6 +- launcher/ui/pages/modplatform/ResourcePage.h | 5 +- .../ui/pages/modplatform/ShaderPackModel.cpp | 3 +- .../atlauncher/AtlOptionalModDialog.cpp | 16 +-- .../atlauncher/AtlOptionalModDialog.h | 2 +- .../pages/modplatform/atlauncher/AtlPage.cpp | 12 +- .../ui/pages/modplatform/flame/FlameModel.cpp | 4 +- .../ui/pages/modplatform/flame/FlamePage.cpp | 6 +- .../modplatform/flame/FlameResourceModels.cpp | 2 +- .../modplatform/legacy_ftb/ListModel.cpp | 6 +- .../ui/pages/modplatform/legacy_ftb/Page.cpp | 18 +-- .../modplatform/modrinth/ModrinthModel.cpp | 4 +- .../modplatform/modrinth/ModrinthPage.cpp | 6 +- .../modrinth/ModrinthResourceModels.cpp | 2 +- .../pages/modplatform/technic/TechnicPage.cpp | 8 +- launcher/ui/themes/CustomTheme.cpp | 2 +- launcher/ui/widgets/InfoFrame.cpp | 6 +- launcher/ui/widgets/SubTaskProgressBar.cpp | 2 +- 96 files changed, 409 insertions(+), 413 deletions(-) diff --git a/launcher/DesktopServices.cpp b/launcher/DesktopServices.cpp index 2984a1b4f..c20021269 100644 --- a/launcher/DesktopServices.cpp +++ b/launcher/DesktopServices.cpp @@ -104,7 +104,7 @@ bool IndirectOpen(T callable, qint64 *pid_forked = nullptr) #endif namespace DesktopServices { -bool openDirectory(const QString &path, bool ensureExists) +bool openDirectory(const QString &path, [[maybe_unused]] bool ensureExists) { qDebug() << "Opening directory" << path; QDir parentPath; diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index b361b286b..a5950659a 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -41,9 +41,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -96,7 +96,11 @@ Qt::DropActions InstanceList::supportedDropActions() const return Qt::MoveAction; } -bool InstanceList::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const +bool InstanceList::canDropMimeData(const QMimeData* data, + [[maybe_unused]] Qt::DropAction action, + [[maybe_unused]] int row, + [[maybe_unused]] int column, + [[maybe_unused]] const QModelIndex& parent) const { if (data && data->hasFormat("application/x-instanceid")) { return true; @@ -104,7 +108,11 @@ bool InstanceList::canDropMimeData(const QMimeData* data, Qt::DropAction action, return false; } -bool InstanceList::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) +bool InstanceList::dropMimeData(const QMimeData* data, + [[maybe_unused]] Qt::DropAction action, + [[maybe_unused]] int row, + [[maybe_unused]] int column, + [[maybe_unused]] const QModelIndex& parent) { if (data && data->hasFormat("application/x-instanceid")) { return true; @@ -129,7 +137,7 @@ QMimeData* InstanceList::mimeData(const QModelIndexList& indexes) const return mimeData; } -QStringList InstanceList::getLinkedInstancesById(const QString &id) const +QStringList InstanceList::getLinkedInstancesById(const QString& id) const { QStringList linkedInstances; for (auto inst : m_instances) { @@ -158,42 +166,34 @@ QVariant InstanceList::data(const QModelIndex& index, int role) const if (!index.isValid()) { return QVariant(); } - BaseInstance *pdata = static_cast(index.internalPointer()); - switch (role) - { - case InstancePointerRole: - { - QVariant v = QVariant::fromValue((void *)pdata); - return v; - } - case InstanceIDRole: - { - return pdata->id(); - } - case Qt::EditRole: - case Qt::DisplayRole: - { - return pdata->name(); - } - case Qt::AccessibleTextRole: - { - return tr("%1 Instance").arg(pdata->name()); - } - case Qt::ToolTipRole: - { - return pdata->instanceRoot(); - } - case Qt::DecorationRole: - { - return pdata->iconKey(); - } - // HACK: see InstanceView.h in gui! - case GroupRole: - { - return getInstanceGroup(pdata->id()); - } - default: - break; + BaseInstance* pdata = static_cast(index.internalPointer()); + switch (role) { + case InstancePointerRole: { + QVariant v = QVariant::fromValue((void*)pdata); + return v; + } + case InstanceIDRole: { + return pdata->id(); + } + case Qt::EditRole: + case Qt::DisplayRole: { + return pdata->name(); + } + case Qt::AccessibleTextRole: { + return tr("%1 Instance").arg(pdata->name()); + } + case Qt::ToolTipRole: { + return pdata->instanceRoot(); + } + case Qt::DecorationRole: { + return pdata->iconKey(); + } + // HACK: see InstanceView.h in gui! + case GroupRole: { + return getInstanceGroup(pdata->id()); + } + default: + break; } return QVariant(); } @@ -320,16 +320,18 @@ bool InstanceList::trashInstance(const InstanceId& id) } qDebug() << "Instance" << id << "has been trashed by the launcher."; - m_trashHistory.push({id, inst->instanceRoot(), trashedLoc, cachedGroupId}); - + m_trashHistory.push({ id, inst->instanceRoot(), trashedLoc, cachedGroupId }); + return true; } -bool InstanceList::trashedSomething() { +bool InstanceList::trashedSomething() +{ return !m_trashHistory.empty(); } -void InstanceList::undoTrashInstance() { +void InstanceList::undoTrashInstance() +{ if (m_trashHistory.empty()) { qWarning() << "Nothing to recover from trash."; return; @@ -558,7 +560,7 @@ InstancePtr InstanceList::getInstanceByManagedName(const QString& managed_name) return {}; } -QModelIndex InstanceList::getInstanceIndexById(const QString &id) const +QModelIndex InstanceList::getInstanceIndexById(const QString& id) const { return index(getInstIndex(getInstanceById(id).get())); } @@ -597,13 +599,11 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id) QString inst_type = instanceSettings->get("InstanceType").toString(); - // NOTE: Some PolyMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a OneSix instance - if (inst_type == "OneSix" || inst_type.isEmpty()) - { + // NOTE: Some PolyMC versions didn't save the InstanceType properly. We will just bank on the probability that this is probably a OneSix + // instance + if (inst_type == "OneSix" || inst_type.isEmpty()) { inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot)); - } - else - { + } else { inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot)); } qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot(); @@ -759,7 +759,7 @@ void InstanceList::instanceDirContentsChanged(const QString& path) emit instancesChanged(); } -void InstanceList::on_InstFolderChanged(const Setting& setting, QVariant value) +void InstanceList::on_InstFolderChanged( [[maybe_unused]] const Setting& setting, QVariant value) { QString newInstDir = QDir(value.toString()).canonicalPath(); if (newInstDir != m_instDir) { @@ -820,21 +820,17 @@ class InstanceStaging : public Task { return Task::abort(); } - bool canAbort() const override - { - return (m_child && m_child->canAbort()); - } + bool canAbort() const override { return (m_child && m_child->canAbort()); } protected: virtual void executeTask() override { m_child->start(); } QStringList warnings() const override { return m_child->warnings(); } private slots: - void childSucceded() + void childSucceeded() { unsigned sleepTime = backoff(); - if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get())) - { + if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get())) { emitSucceeded(); return; } @@ -852,13 +848,10 @@ class InstanceStaging : public Task { emitFailed(reason); } - void childAborted() - { - emitAborted(); - } + void childAborted() { emitAborted(); } -private: - InstanceList * m_parent; + private: + InstanceList* m_parent; /* * WHY: the whole reason why this uses an exponential backoff retry scheme is antivirus on Windows. * Basically, it starts messing things up while the launcher is extracting/creating instances @@ -897,7 +890,10 @@ QString InstanceList::getStagedInstancePath() return path; } -bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, InstanceTask const& commiting) +bool InstanceList::commitStagedInstance(const QString& path, + InstanceName const& instanceName, + const QString& groupName, + InstanceTask const& commiting) { QDir dir; QString instID; diff --git a/launcher/NullInstance.h b/launcher/NullInstance.h index 53edfa0b8..0f7434bb1 100644 --- a/launcher/NullInstance.h +++ b/launcher/NullInstance.h @@ -70,7 +70,7 @@ public: { return nullptr; } - shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override + shared_qobject_ptr< Task > createUpdateTask([[maybe_unused]] Net::Mode mode) override { return nullptr; } diff --git a/launcher/RecursiveFileSystemWatcher.cpp b/launcher/RecursiveFileSystemWatcher.cpp index b7417cdfe..be4d1fde6 100644 --- a/launcher/RecursiveFileSystemWatcher.cpp +++ b/launcher/RecursiveFileSystemWatcher.cpp @@ -105,7 +105,7 @@ void RecursiveFileSystemWatcher::fileChange(const QString &path) { emit fileChanged(path); } -void RecursiveFileSystemWatcher::directoryChange(const QString &path) +void RecursiveFileSystemWatcher::directoryChange([[maybe_unused]] const QString& path) { setFiles(scanRecursive(m_root)); } diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index e5c665662..ce3abe38f 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -199,16 +199,12 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const { if(hasRecommended) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { + auto recommended = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if (recommended.toBool()) { return tr("Recommended"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { + } else if (hasLatest) { + auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if (latest.toBool()) { return tr("Latest"); } } @@ -228,16 +224,12 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const { if(hasRecommended) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { + auto recommenced = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if (recommenced.toBool()) { return APPLICATION->getThemedIcon("star"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { + } else if (hasLatest) { + auto latest = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if (latest.toBool()) { return APPLICATION->getThemedIcon("bug"); } } @@ -270,7 +262,7 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } } -QModelIndex VersionProxyModel::parent(const QModelIndex &child) const +QModelIndex VersionProxyModel::parent([[maybe_unused]] const QModelIndex& child) const { return QModelIndex(); } @@ -469,7 +461,9 @@ void VersionProxyModel::sourceRowsAboutToBeInserted(const QModelIndex& parent, i beginInsertRows(parent, first, last); } -void VersionProxyModel::sourceRowsInserted(const QModelIndex& parent, int first, int last) +void VersionProxyModel::sourceRowsInserted([[maybe_unused]] const QModelIndex& parent, + [[maybe_unused]] int first, + [[maybe_unused]] int last) { endInsertRows(); } @@ -479,7 +473,7 @@ void VersionProxyModel::sourceRowsAboutToBeRemoved(const QModelIndex& parent, in beginRemoveRows(parent, first, last); } -void VersionProxyModel::sourceRowsRemoved(const QModelIndex& parent, int first, int last) +void VersionProxyModel::sourceRowsRemoved([[maybe_unused]] const QModelIndex& parent, [[maybe_unused]] int first, [[maybe_unused]] int last) { endRemoveRows(); } diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index c9599b820..2650bb038 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -248,7 +248,7 @@ void FileLinkApp::readPathPairs() in >> numLinks; qDebug() << "numLinks" << numLinks; - for (int i = 0; i < numLinks; i++) { + for (quint32 i = 0; i < numLinks; i++) { FS::LinkPair pair; in >> pair.src; in >> pair.dst; diff --git a/launcher/icons/IconUtils.cpp b/launcher/icons/IconUtils.cpp index bf530c16f..4015b329b 100644 --- a/launcher/icons/IconUtils.cpp +++ b/launcher/icons/IconUtils.cpp @@ -19,7 +19,7 @@ std::array validIconExtensions = {{ namespace IconUtils{ QString findBestIconIn(const QString &folder, const QString & iconKey) { - int best_found = validIconExtensions.size(); + size_t best_found = validIconExtensions.size(); QString best_filename; QDirIterator it(folder, QDir::NoDotAndDotDot | QDir::Files, QDirIterator::NoIteratorFlags); @@ -32,7 +32,7 @@ QString findBestIconIn(const QString &folder, const QString & iconKey) { auto extension = fileInfo.suffix(); - for(int i = 0; i < best_found; i++) { + for(size_t i = 0; i < best_found; i++) { if(extension == validIconExtensions[i]) { best_found = i; qDebug() << i << " : " << fileInfo.fileName(); diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 97815eba8..6acf2bbd7 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -40,7 +40,7 @@ public: /* methods */ } bool write(QByteArray & data) override { - this->data.append(data); + this->m_data.append(data); return true; } bool abort() override @@ -52,7 +52,7 @@ public: /* methods */ auto fname = m_entity->localFilename(); try { - auto doc = Json::requireDocument(data, fname); + auto doc = Json::requireDocument(m_data, fname); auto obj = Json::requireObject(doc, fname); m_entity->parse(obj); return true; @@ -65,7 +65,7 @@ public: /* methods */ } private: /* data */ - QByteArray data; + QByteArray m_data; Meta::BaseEntity *m_entity; }; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index aab930de0..974e3b389 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1061,8 +1061,8 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt { // actually launch the game - auto method = launchMethod(); - if(method == "LauncherPart") + auto launch_method = launchMethod(); + if(launch_method == "LauncherPart") { auto step = makeShared(pptr); step->setWorkingDirectory(gameRoot()); @@ -1070,7 +1070,7 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt step->setServerToJoin(serverToJoin); process->appendStep(step); } - else if (method == "DirectJava") + else if (launch_method == "DirectJava") { auto step = makeShared(pptr); step->setWorkingDirectory(gameRoot()); diff --git a/launcher/minecraft/MojangDownloadInfo.h b/launcher/minecraft/MojangDownloadInfo.h index 784374c87..6831d8d87 100644 --- a/launcher/minecraft/MojangDownloadInfo.h +++ b/launcher/minecraft/MojangDownloadInfo.h @@ -23,7 +23,7 @@ struct MojangDownloadInfo struct MojangLibraryDownloadInfo { - MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact): artifact(artifact) {} + MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact_): artifact(artifact_) {} MojangLibraryDownloadInfo() {} // types @@ -57,20 +57,20 @@ struct MojangAssetIndexInfo : public MojangDownloadInfo { } - MojangAssetIndexInfo(QString id) + MojangAssetIndexInfo(QString id_) { - this->id = id; + this->id = id_; // HACK: ignore assets from other version files than Minecraft // workaround for stupid assets issue caused by amazon: // https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/ - if(id == "legacy") + if(id_ == "legacy") { url = "https://piston-meta.mojang.com/mc/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/legacy.json"; } // HACK else { - url = "https://s3.amazonaws.com/Minecraft.Download/indexes/" + id + ".json"; + url = "https://s3.amazonaws.com/Minecraft.Download/indexes/" + id_ + ".json"; } known = false; } diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp index b586198bf..ddd98110c 100644 --- a/launcher/minecraft/OneSixVersionFormat.cpp +++ b/launcher/minecraft/OneSixVersionFormat.cpp @@ -413,7 +413,7 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch } LibraryPtr OneSixVersionFormat::plusJarModFromJson( - ProblemContainer & problems, + [[maybe_unused]] ProblemContainer & problems, const QJsonObject &libObj, const QString &filename, const QString &originalName diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index aff05dbc8..2b014fb60 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -225,11 +225,11 @@ static bool loadPackProfile(PackProfile * parent, const QString & filename, cons auto orderArray = Json::requireArray(obj.value("components")); for(auto item: orderArray) { - auto obj = Json::requireObject(item, "Component must be an object."); - container.append(componentFromJsonV1(parent, componentJsonPattern, obj)); + auto comp_obj = Json::requireObject(item, "Component must be an object."); + container.append(componentFromJsonV1(parent, componentJsonPattern, comp_obj)); } } - catch (const JSONValidationError &err) + catch ([[maybe_unused]] const JSONValidationError &err) { qCritical() << "Couldn't parse" << componentsFile.fileName() << ": bad file format"; container.clear(); @@ -414,7 +414,7 @@ void PackProfile::insertComponent(size_t index, ComponentPtr component) qWarning() << "Attempt to add a component that is already present!"; return; } - beginInsertRows(QModelIndex(), index, index); + beginInsertRows(QModelIndex(), static_cast(index), static_cast(index)); d->components.insert(index, component); d->componentIndex[id] = component; endInsertRows(); @@ -427,7 +427,7 @@ void PackProfile::componentDataChanged() auto objPtr = qobject_cast(sender()); if(!objPtr) { - qWarning() << "PackProfile got dataChenged signal from a non-Component!"; + qWarning() << "PackProfile got dataChanged signal from a non-Component!"; return; } if(objPtr->getID() == "net.minecraft") { @@ -445,7 +445,7 @@ void PackProfile::componentDataChanged() } index++; } - qWarning() << "PackProfile got dataChenged signal from a Component which does not belong to it!"; + qWarning() << "PackProfile got dataChanged signal from a Component which does not belong to it!"; } bool PackProfile::remove(const int index) @@ -532,9 +532,9 @@ ComponentPtr PackProfile::getComponent(const QString &id) return (*iter); } -ComponentPtr PackProfile::getComponent(int index) +ComponentPtr PackProfile::getComponent(size_t index) { - if(index < 0 || index >= d->components.size()) + if(index < 0 || index >= static_cast(d->components.size())) { return nullptr; } @@ -615,7 +615,7 @@ QVariant PackProfile::data(const QModelIndex &index, int role) const return QVariant(); } -bool PackProfile::setData(const QModelIndex& index, const QVariant& value, int role) +bool PackProfile::setData(const QModelIndex& index, [[maybe_unused]] const QVariant& value, int role) { if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index.parent())) { diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h index d144d875c..06741c2d7 100644 --- a/launcher/minecraft/PackProfile.h +++ b/launcher/minecraft/PackProfile.h @@ -145,7 +145,7 @@ public: ComponentPtr getComponent(const QString &id); /// get the profile component by index - ComponentPtr getComponent(int index); + ComponentPtr getComponent(size_t index); /// Add the component to the internal list of patches // todo(merged): is this the best approach diff --git a/launcher/minecraft/ProfileUtils.cpp b/launcher/minecraft/ProfileUtils.cpp index 03f8c1989..145570039 100644 --- a/launcher/minecraft/ProfileUtils.cpp +++ b/launcher/minecraft/ProfileUtils.cpp @@ -92,7 +92,7 @@ bool readOverrideOrders(QString path, PatchOrder &order) order.append(Json::requireString(item)); } } - catch (const JSONValidationError &err) + catch ([[maybe_unused]] const JSONValidationError &err) { qCritical() << "Couldn't parse" << orderFile.fileName() << ": bad file format"; qWarning() << "Ignoring overriden order"; diff --git a/launcher/minecraft/World.cpp b/launcher/minecraft/World.cpp index 54fb94346..21f2c4398 100644 --- a/launcher/minecraft/World.cpp +++ b/launcher/minecraft/World.cpp @@ -408,13 +408,13 @@ optional read_string (nbt::value& parent, const char * name) auto & tag_str = namedValue.as(); return QString::fromStdString(tag_str.get()); } - catch (const std::out_of_range &e) + catch ([[maybe_unused]] const std::out_of_range &e) { // fallback for old world formats qWarning() << "String NBT tag" << name << "could not be found."; return nullopt; } - catch (const std::bad_cast &e) + catch ([[maybe_unused]] const std::bad_cast &e) { // type mismatch qWarning() << "NBT tag" << name << "could not be converted to string."; @@ -434,13 +434,13 @@ optional read_long (nbt::value& parent, const char * name) auto & tag_str = namedValue.as(); return tag_str.get(); } - catch (const std::out_of_range &e) + catch ([[maybe_unused]] const std::out_of_range &e) { // fallback for old world formats qWarning() << "Long NBT tag" << name << "could not be found."; return nullopt; } - catch (const std::bad_cast &e) + catch ([[maybe_unused]] const std::bad_cast &e) { // type mismatch qWarning() << "NBT tag" << name << "could not be converted to long."; @@ -460,13 +460,13 @@ optional read_int (nbt::value& parent, const char * name) auto & tag_str = namedValue.as(); return tag_str.get(); } - catch (const std::out_of_range &e) + catch ([[maybe_unused]] const std::out_of_range &e) { // fallback for old world formats qWarning() << "Int NBT tag" << name << "could not be found."; return nullopt; } - catch (const std::bad_cast &e) + catch ([[maybe_unused]] const std::bad_cast &e) { // type mismatch qWarning() << "NBT tag" << name << "could not be converted to int."; diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index 0feee2999..fe0893783 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -278,7 +278,7 @@ QVariant WorldList::data(const QModelIndex &index, int role) const } } -QVariant WorldList::headerData(int section, Qt::Orientation orientation, int role) const +QVariant WorldList::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { switch (role) { @@ -320,7 +320,6 @@ QVariant WorldList::headerData(int section, Qt::Orientation orientation, int rol default: return QVariant(); } - return QVariant(); } QStringList WorldList::mimeTypes() const @@ -373,7 +372,7 @@ QMimeData *WorldList::mimeData(const QModelIndexList &indexes) const if (indexes.size() == 0) return new QMimeData(); - QList worlds; + QList worlds_; for(auto idx : indexes) { if(idx.column() != 0) @@ -381,13 +380,13 @@ QMimeData *WorldList::mimeData(const QModelIndexList &indexes) const int row = idx.row(); if (row < 0 || row >= this->worlds.size()) continue; - worlds.append(this->worlds[row]); + worlds_.append(this->worlds[row]); } - if(!worlds.size()) + if(!worlds_.size()) { return new QMimeData(); } - return new WorldMimeData(worlds); + return new WorldMimeData(worlds_); } Qt::ItemFlags WorldList::flags(const QModelIndex &index) const diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp index 44f7e2563..334c63b55 100644 --- a/launcher/minecraft/auth/AccountData.cpp +++ b/launcher/minecraft/auth/AccountData.cpp @@ -310,7 +310,7 @@ bool AccountData::resumeStateFromV2(QJsonObject data) { QJsonObject profileObject = profileVal.toObject(); QString id = profileObject.value("id").toString(""); QString name = profileObject.value("name").toString(""); - bool legacy = profileObject.value("legacy").toBool(false); + bool legacy_ = profileObject.value("legacy").toBool(false); if (id.isEmpty() || name.isEmpty()) { qWarning() << "Unable to load a profile" << name << "because it was missing an ID or a name."; @@ -319,7 +319,7 @@ bool AccountData::resumeStateFromV2(QJsonObject data) { if(id == currentProfile) { currentProfileIndex = index; } - profiles.append({id, name, legacy}); + profiles.append({id, name, legacy_}); } auto & profile = profiles[currentProfileIndex]; diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index c27941472..bf663f2df 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -365,7 +365,7 @@ QVariant AccountList::data(const QModelIndex &index, int role) const } } -QVariant AccountList::headerData(int section, Qt::Orientation orientation, int role) const +QVariant AccountList::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { switch (role) { diff --git a/launcher/minecraft/auth/Parsers.cpp b/launcher/minecraft/auth/Parsers.cpp index f3d9ad56b..98326272a 100644 --- a/launcher/minecraft/auth/Parsers.cpp +++ b/launcher/minecraft/auth/Parsers.cpp @@ -107,16 +107,16 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na if(!item.isObject()) { continue; } - auto obj = item.toObject(); - if(obj.contains("uhs")) { + auto obj_ = item.toObject(); + if(obj_.contains("uhs")) { foundUHS = true; } else { continue; } // consume all 'display claims' ... whatever that means - for(auto iter = obj.begin(); iter != obj.end(); iter++) { + for(auto iter = obj_.begin(); iter != obj_.end(); iter++) { QString claim; - if(!getString(obj.value(iter.key()), claim)) { + if(!getString(obj_.value(iter.key()), claim)) { qWarning() << "display claim " << iter.key() << " is not a string..."; return false; } diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.cpp b/launcher/minecraft/auth/steps/EntitlementsStep.cpp index bd6042926..b56827082 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.cpp +++ b/launcher/minecraft/auth/steps/EntitlementsStep.cpp @@ -35,9 +35,9 @@ void EntitlementsStep::rehydrate() { } void EntitlementsStep::onRequestDone( - QNetworkReply::NetworkError error, + [[maybe_unused]] QNetworkReply::NetworkError error, QByteArray data, - QList headers + [[maybe_unused]] QList headers ) { auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); diff --git a/launcher/minecraft/gameoptions/GameOptions.cpp b/launcher/minecraft/gameoptions/GameOptions.cpp index e547b32a3..ce0988cc8 100644 --- a/launcher/minecraft/gameoptions/GameOptions.cpp +++ b/launcher/minecraft/gameoptions/GameOptions.cpp @@ -112,12 +112,11 @@ QVariant GameOptions::data(const QModelIndex& index, int role) const default: return QVariant(); } - return QVariant(); } int GameOptions::rowCount(const QModelIndex&) const { - return contents.size(); + return static_cast(contents.size()); } int GameOptions::columnCount(const QModelIndex&) const diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index 8ecf715db..01df85439 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -54,7 +54,7 @@ LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent) if (instance->settings()->get("CloseAfterLaunch").toBool()) { std::shared_ptr connection{new QMetaObject::Connection}; - *connection = connect(&m_process, &LoggedProcess::log, this, [=](QStringList lines, MessageLevel::Enum level) { + *connection = connect(&m_process, &LoggedProcess::log, this, [=](QStringList lines, [[maybe_unused]] MessageLevel::Enum level) { qDebug() << lines; if (lines.filter(QRegularExpression(".*Setting user.+", QRegularExpression::CaseInsensitiveOption)).length() != 0) { diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d4e419f4f..9aa05f31d 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -72,7 +72,7 @@ public: auto issueTracker() const -> QString; /** Get the intneral path to the mod's icon file*/ - QString iconPath() const { return m_local_details.icon_file; }; + QString iconPath() const { return m_local_details.icon_file; } /** Gets the icon of the mod, converted to a QPixmap for drawing, and scaled to size. */ [[nodiscard]] QPixmap icon(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; /** Thread-safe. */ diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index b4e59d52d..ae36baa85 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -59,17 +59,17 @@ struct ModLicense { ModLicense() {} ModLicense(const QString license) { - // FIXME: come up with a better license parseing. + // FIXME: come up with a better license parsing. // handle SPDX identifiers? https://spdx.org/licenses/ auto parts = license.split(' '); QStringList notNameParts = {}; for (auto part : parts) { - auto url = QUrl(part); + auto _url = QUrl(part); if (part.startsWith("(") && part.endsWith(")")) - url = QUrl(part.mid(1, part.size() - 2)); + _url = QUrl(part.mid(1, part.size() - 2)); - if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { - this->url = url.toString(); + if (_url.isValid() && !_url.scheme().isEmpty() && !_url.host().isEmpty()) { + this->url = _url.toString(); notNameParts.append(part); continue; } @@ -89,12 +89,9 @@ struct ModLicense { } - ModLicense(const QString name, const QString id, const QString url, const QString description) { - this->name = name; - this->id = id; - this->url = url; - this->description = description; - } + ModLicense(const QString& name_, const QString& id_, const QString& url_, const QString& description_) + : name(name_), id(id_), url(url_), description(description_) + {} ModLicense(const ModLicense& other) : name(other.name) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index af98d8348..5cb53d3cb 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -139,7 +139,7 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const } } -QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, int role) const +QVariant ModFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { switch (role) { diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 7700fd36b..a5533bbdb 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -457,7 +457,7 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const } } -bool ResourceFolderModel::setData(const QModelIndex& index, const QVariant& value, int role) +bool ResourceFolderModel::setData(const QModelIndex& index, [[maybe_unused]] const QVariant& value, int role) { int row = index.row(); if (row < 0 || row >= rowCount(index.parent()) || !index.isValid()) @@ -469,7 +469,7 @@ bool ResourceFolderModel::setData(const QModelIndex& index, const QVariant& valu return false; } -QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientation, int role) const +QVariant ResourceFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { switch (role) { case Qt::DisplayRole: @@ -594,7 +594,7 @@ void ResourceFolderModel::enableInteraction(bool enabled) } /* Standard Proxy Model for createFilterProxyModel */ -[[nodiscard]] bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const +[[nodiscard]] bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, [[maybe_unused]] const QModelIndex& source_parent) const { auto* model = qobject_cast(sourceModel()); if (!model) diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 016679dd1..d2fb5ad61 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -97,9 +97,9 @@ class ResourceFolderModel : public QAbstractListModel { /* Basic columns */ enum Columns { ACTIVE_COLUMN = 0, NAME_COLUMN, DATE_COLUMN, NUM_COLUMNS }; - QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; }; + QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; } - [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast(size()); } + [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : size(); } [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; } [[nodiscard]] Qt::DropActions supportedDropActions() const override; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 41455599b..f1a0572ad 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -128,7 +128,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const } } -QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const +QVariant ResourcePackFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { switch (role) { case Qt::DisplayRole: @@ -165,7 +165,6 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient default: return {}; } - return {}; } int ResourcePackFolderModel::columnCount(const QModelIndex& parent) const diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 531a70232..3795db58c 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -114,7 +114,7 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const } } -QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const +QVariant TexturePackFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { switch (role) { case Qt::DisplayRole: diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index f8ecdb33e..0a0f57bf3 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -61,7 +61,7 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent, if (auto meta = mod->metadata(); meta) m_mods.append(meta); prepare(); -}; +} void GetModDependenciesTask::prepare() { @@ -130,7 +130,7 @@ QList GetModDependenciesTask::getDependenciesForVersion c_dependencies.append(getOverride(ver_dep, providerName)); } return c_dependencies; -}; +} Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptr pDep) { @@ -181,7 +181,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType }; ResourceAPI::DependencySearchCallbacks callbacks; - callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) { + callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, [[maybe_unused]] auto& pack) { try { QJsonArray arr; if (dep.version.length() != 0 && doc.isObject()) { @@ -215,27 +215,27 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } if (level == 0) { - qWarning() << "Dependency cycle exeeded"; + qWarning() << "Dependency cycle exceeded"; return; } if (dep.addonId.toString().isEmpty() && !pDep->version.addonId.toString().isEmpty()) { pDep->pack->addonId = pDep->version.addonId; - auto dep = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name); - if (dep.addonId != pDep->version.addonId) { + auto dep_ = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name); + if (dep_.addonId != pDep->version.addonId) { removePack(pDep->version.addonId); - addTask(prepareDependencyTask(dep, provider.name, level)); + addTask(prepareDependencyTask(dep_, provider.name, level)); } else addTask(getProjectInfoTask(pDep)); } - for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) { - addTask(prepareDependencyTask(dep, provider.name, level - 1)); + for (auto dep_ : getDependenciesForVersion(pDep->version, provider.name)) { + addTask(prepareDependencyTask(dep_, provider.name, level - 1)); } }; auto version = provider.api->getDependencyVersion(std::move(args), std::move(callbacks)); tasks->addTask(version); return tasks; -}; +} void GetModDependenciesTask::removePack(const QVariant addonId) { diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index f8d454cf6..ea23947fb 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -152,8 +152,8 @@ ModDetails ReadMCModTOML(QByteArray contents) QString authors = ""; if (auto authorsDatum = tomlData["authors"].as_string()) { authors = QString::fromStdString(authorsDatum->get()); - } else if (auto authorsDatum = (*modsTable)["authors"].as_string()) { - authors = QString::fromStdString(authorsDatum->get()); + } else if (auto authorsDatumMods = (*modsTable)["authors"].as_string()) { + authors = QString::fromStdString(authorsDatumMods->get()); } if (!authors.isEmpty()) { details.authors.append(authors); @@ -162,8 +162,8 @@ ModDetails ReadMCModTOML(QByteArray contents) QString homeurl = ""; if (auto homeurlDatum = tomlData["displayURL"].as_string()) { homeurl = QString::fromStdString(homeurlDatum->get()); - } else if (auto homeurlDatum = (*modsTable)["displayURL"].as_string()) { - homeurl = QString::fromStdString(homeurlDatum->get()); + } else if (auto homeurlDatumMods = (*modsTable)["displayURL"].as_string()) { + homeurl = QString::fromStdString(homeurlDatumMods->get()); } // fix up url. if (!homeurl.isEmpty() && !homeurl.startsWith("http://") && !homeurl.startsWith("https://") && !homeurl.startsWith("ftp://")) { @@ -174,16 +174,16 @@ ModDetails ReadMCModTOML(QByteArray contents) QString issueTrackerURL = ""; if (auto issueTrackerURLDatum = tomlData["issueTrackerURL"].as_string()) { issueTrackerURL = QString::fromStdString(issueTrackerURLDatum->get()); - } else if (auto issueTrackerURLDatum = (*modsTable)["issueTrackerURL"].as_string()) { - issueTrackerURL = QString::fromStdString(issueTrackerURLDatum->get()); + } else if (auto issueTrackerURLDatumMods = (*modsTable)["issueTrackerURL"].as_string()) { + issueTrackerURL = QString::fromStdString(issueTrackerURLDatumMods->get()); } details.issue_tracker = issueTrackerURL; QString license = ""; if (auto licenseDatum = tomlData["license"].as_string()) { license = QString::fromStdString(licenseDatum->get()); - } else if (auto licenseDatum =(*modsTable)["license"].as_string()) { - license = QString::fromStdString(licenseDatum->get()); + } else if (auto licenseDatumMods =(*modsTable)["license"].as_string()) { + license = QString::fromStdString(licenseDatumMods->get()); } if (!license.isEmpty()) details.licenses.append(ModLicense(license)); @@ -191,8 +191,8 @@ ModDetails ReadMCModTOML(QByteArray contents) QString logoFile = ""; if (auto logoFileDatum = tomlData["logoFile"].as_string()) { logoFile = QString::fromStdString(logoFileDatum->get()); - } else if (auto logoFileDatum =(*modsTable)["logoFile"].as_string()) { - logoFile = QString::fromStdString(logoFileDatum->get()); + } else if (auto logoFileDatumMods =(*modsTable)["logoFile"].as_string()) { + logoFile = QString::fromStdString(logoFileDatumMods->get()); } details.icon_file = logoFile; @@ -460,7 +460,7 @@ bool process(Mod& mod, ProcessingLevel level) } } -bool processZIP(Mod& mod, ProcessingLevel level) +bool processZIP(Mod& mod, [[maybe_unused]] ProcessingLevel level) { ModDetails details; @@ -593,7 +593,7 @@ bool processZIP(Mod& mod, ProcessingLevel level) return false; // no valid mod found in archive } -bool processFolder(Mod& mod, ProcessingLevel level) +bool processFolder(Mod& mod, [[maybe_unused]] ProcessingLevel level) { ModDetails details; @@ -614,7 +614,7 @@ bool processFolder(Mod& mod, ProcessingLevel level) return false; // no valid mcmod.info file found } -bool processLitemod(Mod& mod, ProcessingLevel level) +bool processLitemod(Mod& mod, [[maybe_unused]] ProcessingLevel level) { ModDetails details; diff --git a/launcher/minecraft/services/CapeChange.cpp b/launcher/minecraft/services/CapeChange.cpp index 1d5ea36da..301550553 100644 --- a/launcher/minecraft/services/CapeChange.cpp +++ b/launcher/minecraft/services/CapeChange.cpp @@ -45,7 +45,7 @@ CapeChange::CapeChange(QObject *parent, QString token, QString cape) { } -void CapeChange::setCape(QString& cape) { +void CapeChange::setCape([[maybe_unused]] QString& cape) { QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/capes/active")); auto requestString = QString("{\"capeId\":\"%1\"}").arg(m_capeId); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit()); diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index b76700511..ebc4167bb 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -143,7 +143,7 @@ inline auto getOverrideDeps() -> QList { "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH }, { "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } }; -}; +} } // namespace ModPlatform diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index a8f300b4e..baba550f8 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -131,12 +131,12 @@ class ResourceAPI { qWarning() << "TODO: ResourceAPI::searchProjects"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProject(QString addonId, std::shared_ptr response) const + [[nodiscard]] virtual Task::Ptr getProject([[maybe_unused]] QString addonId, [[maybe_unused]] std::shared_ptr response) const { qWarning() << "TODO: ResourceAPI::getProject"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const + [[nodiscard]] virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds, [[maybe_unused]] std::shared_ptr response) const { qWarning() << "TODO: ResourceAPI::getProjects"; return nullptr; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 84455e58a..ca961e9cf 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -89,7 +89,7 @@ void Flame::FileResolvingTask::netJobFinished() auto& out = m_toProcess.files[fileid]; try { out.parseFromObject(Json::requireObject(file)); - } catch (const JSONValidationError& e) { + } catch ([[maybe_unused]] const JSONValidationError& e) { qDebug() << "Blocked mod on curseforge" << out.fileName; auto hash = out.hash; if (!hash.isEmpty()) { diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 227ce4898..2215de190 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -54,7 +54,7 @@ void FlameMod::loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj) pack.extraDataLoaded = true; } -void FlameMod::loadBody(ModPlatform::IndexedPack& pack, QJsonObject& obj) +void FlameMod::loadBody(ModPlatform::IndexedPack& pack, [[maybe_unused]] QJsonObject& obj) { pack.extraData.body = api.getModDescription(pack.addonId.toInt()); @@ -75,7 +75,7 @@ static QString enumToString(int hash_algorithm) void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, - const shared_qobject_ptr& network, + [[maybe_unused]] const shared_qobject_ptr& network, const BaseInstance* inst) { QVector unsortedVersions; @@ -193,4 +193,5 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform:: }; std::sort(versions.begin(), versions.end(), orderSortPredicate); return versions.front(); -}; +} + diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index c278f800d..e5718acb2 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -145,4 +145,5 @@ Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args, }); return netJob; -}; +} + diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 4cd88aa69..d08759cf2 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -180,10 +180,10 @@ void ModrinthPackExportTask::parseApiResponse(const std::shared_ptr if (obj.isEmpty()) continue; - const QJsonArray files = obj["files"].toArray(); - if (auto fileIter = std::find_if(files.begin(), files.end(), + const QJsonArray files_array = obj["files"].toArray(); + if (auto fileIter = std::find_if(files_array.begin(), files_array.end(), [&iterator](const QJsonValue& file) { return file["hashes"]["sha512"] == iterator.value(); }); - fileIter != files.end()) { + fileIter != files_array.end()) { // map the file to the url resolvedFiles[iterator.key()] = ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), iterator.value(), @@ -293,7 +293,7 @@ QByteArray ModrinthPackExportTask::generateIndex() obj["dependencies"] = dependencies; } - QJsonArray files; + QJsonArray files_array; QMapIterator iterator(resolvedFiles); while (iterator.hasNext()) { iterator.next(); @@ -311,9 +311,9 @@ QByteArray ModrinthPackExportTask::generateIndex() file["hashes"] = hashes; file["fileSize"] = value.size; - files << file; + files_array << file; } - obj["files"] = files; + obj["files"] = files_array; return QJsonDocument(obj).toJson(QJsonDocument::Compact); } diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index b40373496..969018a9d 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -95,7 +95,7 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, - const shared_qobject_ptr& network, + [[maybe_unused]] const shared_qobject_ptr& network, const BaseInstance* inst) { QVector unsortedVersions; @@ -218,7 +218,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t return {}; } -auto Modrinth::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto Modrinth::loadDependencyVersions([[maybe_unused]] const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { QVector versions; @@ -235,4 +235,4 @@ auto Modrinth::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArr }; std::sort(versions.begin(), versions.end(), orderSortPredicate); return versions.length() != 0 ? versions.front() : ModPlatform::IndexedVersion(); -} \ No newline at end of file +} diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 967b8870c..82deef8b1 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -89,7 +89,8 @@ auto intEntry(toml::table table, QString entry_name) -> int return node.value_or(0); } -auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod +auto V1::createModFormat([[maybe_unused]] QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) + -> Mod { Mod mod; @@ -114,7 +115,7 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo return mod; } -auto V1::createModFormat(QDir& index_dir, ::Mod& internal_mod, QString slug) -> Mod +auto V1::createModFormat(QDir& index_dir, [[maybe_unused]] ::Mod& internal_mod, QString slug) -> Mod { // Try getting metadata if it exists Mod mod{ getIndexForMod(index_dir, slug) }; diff --git a/launcher/modplatform/technic/TechnicPackProcessor.cpp b/launcher/modplatform/technic/TechnicPackProcessor.cpp index df713a725..e473c1704 100644 --- a/launcher/modplatform/technic/TechnicPackProcessor.cpp +++ b/launcher/modplatform/technic/TechnicPackProcessor.cpp @@ -26,7 +26,12 @@ #include -void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, const QString &instName, const QString &instIcon, const QString &stagingPath, const QString &minecraftVersion, const bool isSolder) +void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, + const QString& instName, + const QString& instIcon, + const QString& stagingPath, + const QString& minecraftVersion, + [[maybe_unused]] const bool isSolder) { QString minecraftPath = FS::PathCombine(stagingPath, ".minecraft"); QString configPath = FS::PathCombine(stagingPath, "instance.cfg"); @@ -151,17 +156,16 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, const { QJsonDocument doc = Json::requireDocument(data); QJsonObject root = Json::requireObject(doc, "version.json"); - QString minecraftVersion = Json::ensureString(root, "inheritsFrom", QString(), ""); - if (minecraftVersion.isEmpty()) - { + QString packMinecraftVersion = Json::ensureString(root, "inheritsFrom", QString(), ""); + if (packMinecraftVersion.isEmpty()) { if (fmlMinecraftVersion.isEmpty()) { emit failed(tr("Could not understand \"version.json\":\ninheritsFrom is missing")); return; } - minecraftVersion = fmlMinecraftVersion; + packMinecraftVersion = fmlMinecraftVersion; } - components->setComponentVersion("net.minecraft", minecraftVersion, true); + components->setComponentVersion("net.minecraft", packMinecraftVersion, true); for (auto library: Json::ensureArray(root, "libraries", {})) { if (!library.isObject()) diff --git a/launcher/news/NewsEntry.cpp b/launcher/news/NewsEntry.cpp index cfe07e864..9726cab24 100644 --- a/launcher/news/NewsEntry.cpp +++ b/launcher/news/NewsEntry.cpp @@ -42,8 +42,8 @@ inline QString childValue(const QDomElement& element, const QString& childName, QDomNodeList nodes = element.elementsByTagName(childName); if (nodes.count() > 0) { - QDomElement element = nodes.at(0).toElement(); - return element.text(); + QDomElement elem = nodes.at(0).toElement(); + return elem.text(); } else { @@ -51,7 +51,7 @@ inline QString childValue(const QDomElement& element, const QString& childName, } } -bool NewsEntry::fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg) +bool NewsEntry::fromXmlElement(const QDomElement& element, NewsEntry* entry, [[maybe_unused]] QString* errorMsg) { QString title = childValue(element, "title", tr("Untitled")); QString content = childValue(element, "content", tr("No content.")); @@ -62,4 +62,3 @@ bool NewsEntry::fromXmlElement(const QDomElement& element, NewsEntry* entry, QSt entry->link = link; return true; } - diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp index ab425f1a0..78bf111e7 100644 --- a/launcher/screenshots/ImgurAlbumCreation.cpp +++ b/launcher/screenshots/ImgurAlbumCreation.cpp @@ -82,7 +82,7 @@ void ImgurAlbumCreation::executeTask() connect(rep, &QNetworkReply::sslErrors, this, &ImgurAlbumCreation::sslErrors); } -void ImgurAlbumCreation::downloadError(QNetworkReply::NetworkError error) +void ImgurAlbumCreation::downloadError([[maybe_unused]] QNetworkReply::NetworkError error) { qDebug() << m_reply->errorString(); m_state = State::Failed; diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index a50f9afae..4f7587672 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -97,7 +97,7 @@ void ImgurUpload::executeTask() connect(rep, &QNetworkReply::sslErrors, this, &ImgurUpload::sslErrors); } -void ImgurUpload::downloadError(QNetworkReply::NetworkError error) +void ImgurUpload::downloadError([[maybe_unused]] QNetworkReply::NetworkError error) { qCritical() << "ImgurUpload failed with error" << m_reply->errorString() << "Server reply:\n" << m_reply->readAll(); if(finished) diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index 9aada5e69..0f835369a 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -171,7 +171,7 @@ void ConcurrentTask::subTaskSucceeded(Task::Ptr task) startNext(); } -void ConcurrentTask::subTaskFailed(Task::Ptr task, const QString& msg) +void ConcurrentTask::subTaskFailed(Task::Ptr task, [[maybe_unused]] const QString& msg) { m_done.insert(task.get(), task); m_failed.insert(task.get(), task); diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index de0884c59..25c7f8be7 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -64,12 +64,13 @@ struct TaskStepProgress { QString status = ""; QString details = ""; TaskStepState state = TaskStepState::Waiting; + TaskStepProgress() { this->uid = QUuid::createUuid(); } - TaskStepProgress(QUuid uid) { - this->uid = uid; - } + + TaskStepProgress(QUuid uid_): uid(uid_) {} + bool isDone() const { return (state == TaskStepState::Failed) || (state == TaskStepState::Succeeded); } void update(qint64 new_current, qint64 new_total) { this->old_current = this->current; diff --git a/launcher/tools/JProfiler.cpp b/launcher/tools/JProfiler.cpp index 15c0cab6d..f08ee73df 100644 --- a/launcher/tools/JProfiler.cpp +++ b/launcher/tools/JProfiler.cpp @@ -34,7 +34,7 @@ void JProfiler::profilerStarted() emit readyToLaunch(tr("Listening on port: %1").arg(listeningPort)); } -void JProfiler::profilerFinished(int exit, QProcess::ExitStatus status) +void JProfiler::profilerFinished([[maybe_unused]] int exit, QProcess::ExitStatus status) { if (status == QProcess::CrashExit) { diff --git a/launcher/tools/JVisualVM.cpp b/launcher/tools/JVisualVM.cpp index 28ffb9cdc..2734f5ab8 100644 --- a/launcher/tools/JVisualVM.cpp +++ b/launcher/tools/JVisualVM.cpp @@ -32,7 +32,7 @@ void JVisualVM::profilerStarted() emit readyToLaunch(tr("JVisualVM started")); } -void JVisualVM::profilerFinished(int exit, QProcess::ExitStatus status) +void JVisualVM::profilerFinished([[maybe_unused]] int exit, QProcess::ExitStatus status) { if (status == QProcess::CrashExit) { diff --git a/launcher/translations/POTranslator.cpp b/launcher/translations/POTranslator.cpp index c77ae45d3..910a7f2c7 100644 --- a/launcher/translations/POTranslator.cpp +++ b/launcher/translations/POTranslator.cpp @@ -334,7 +334,7 @@ POTranslator::~POTranslator() delete d; } -QString POTranslator::translate(const char* context, const char* sourceText, const char* disambiguation, int n) const +QString POTranslator::translate(const char* context, const char* sourceText, const char* disambiguation, [[maybe_unused]] int n) const { if(disambiguation) { diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 6054b4b6a..70d8726e4 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -267,9 +267,7 @@ void readIndex(const QString & path, QMap& languages) try { data = FS::read(path); - } - catch (const Exception &e) - { + } catch ([[maybe_unused]] const Exception& e) { qCritical() << "Translations Download Failed: index file not readable"; return; } @@ -307,9 +305,7 @@ void readIndex(const QString & path, QMap& languages) languages.insert(lang.key, lang); } - } - catch (Json::JsonException & e) - { + } catch ([[maybe_unused]] Json::JsonException& e) { qCritical() << "Translations Download Failed: index file could not be parsed as json"; } } @@ -498,12 +494,12 @@ QVariant TranslationsModel::headerData(int section, Qt::Orientation orientation, return QAbstractListModel::headerData(section, orientation, role); } -int TranslationsModel::rowCount(const QModelIndex& parent) const +int TranslationsModel::rowCount([[maybe_unused]] const QModelIndex& parent) const { return d->m_languages.size(); } -int TranslationsModel::columnCount(const QModelIndex& parent) const +int TranslationsModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 2; } diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 496738e32..6d80d1d59 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -537,9 +537,9 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) actionCreateInstance->setToolTip(ui->actionAddInstance->toolTip()); if(!group.isNull()) { - QVariantMap data; - data["group"] = group; - actionCreateInstance->setData(data); + QVariantMap instance_action_data; + instance_action_data["group"] = group; + actionCreateInstance->setData(instance_action_data); } connect(actionCreateInstance, SIGNAL(triggered(bool)), SLOT(on_actionAddInstance_triggered())); @@ -550,9 +550,9 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) if(!group.isNull()) { QAction *actionDeleteGroup = new QAction(tr("Delete group '%1'").arg(group), this); - QVariantMap data; - data["group"] = group; - actionDeleteGroup->setData(data); + QVariantMap delete_group_action_data; + delete_group_action_data["group"] = group; + actionDeleteGroup->setData(delete_group_action_data); connect(actionDeleteGroup, SIGNAL(triggered(bool)), SLOT(deleteGroup())); actions.append(actionDeleteGroup); } @@ -799,9 +799,9 @@ void MainWindow::changeActiveAccount() if (sAction->data().type() != QVariant::Type::Int) return; - QVariant data = sAction->data(); + QVariant action_data = sAction->data(); bool valid = false; - int index = data.toInt(&valid); + int index = action_data.toInt(&valid); if(!valid) { index = -1; } @@ -1158,9 +1158,9 @@ void MainWindow::iconUpdated(QString icon) { if (icon == m_currentInstIcon) { - auto icon = APPLICATION->icons()->getIcon(m_currentInstIcon); - ui->actionChangeInstIcon->setIcon(icon); - changeIconButton->setIcon(icon); + auto new_icon = APPLICATION->icons()->getIcon(m_currentInstIcon); + ui->actionChangeInstIcon->setIcon(new_icon); + changeIconButton->setIcon(new_icon); } } @@ -1636,7 +1636,7 @@ void MainWindow::startTask(Task *task) task->start(); } -void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex &previous) +void MainWindow::instanceChanged(const QModelIndex ¤t, [[maybe_unused]] const QModelIndex &previous) { if (!current.isValid()) { @@ -1782,8 +1782,9 @@ void MainWindow::setInstanceActionsEnabled(bool enabled) ui->actionCreateInstanceShortcut->setEnabled(enabled); } -void MainWindow::refreshCurrentInstance(bool running) +void MainWindow::refreshCurrentInstance([[maybe_unused]] bool running) { auto current = view->selectionModel()->currentIndex(); instanceChanged(current, current); } + diff --git a/launcher/ui/dialogs/CopyInstanceDialog.cpp b/launcher/ui/dialogs/CopyInstanceDialog.cpp index d75bb5fe3..ffa1e31b9 100644 --- a/launcher/ui/dialogs/CopyInstanceDialog.cpp +++ b/launcher/ui/dialogs/CopyInstanceDialog.cpp @@ -220,7 +220,7 @@ void CopyInstanceDialog::on_iconButton_clicked() } } -void CopyInstanceDialog::on_instNameTextBox_textChanged(const QString& arg1) +void CopyInstanceDialog::on_instNameTextBox_textChanged([[maybe_unused]] const QString& arg1) { updateDialogState(); } diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index cc41c394d..5223391e0 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -203,8 +203,8 @@ void ExportInstanceDialog::loadPackIgnore() { return; } - auto data = ignoreFile.readAll(); - auto string = QString::fromUtf8(data); + auto ignoreData = ignoreFile.readAll(); + auto string = QString::fromUtf8(ignoreData); #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) proxyModel->setBlockedPaths(string.split('\n', Qt::SkipEmptyParts)); #else @@ -214,11 +214,11 @@ void ExportInstanceDialog::loadPackIgnore() void ExportInstanceDialog::savePackIgnore() { - auto data = proxyModel->blockedPaths().toStringList().join('\n').toUtf8(); + auto ignoreData = proxyModel->blockedPaths().toStringList().join('\n').toUtf8(); auto filename = ignoreFileName(); try { - FS::write(filename, data); + FS::write(filename, ignoreData); } catch (const Exception &e) { diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 7b9bb944c..95ded16e9 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -296,7 +296,7 @@ void NewInstanceDialog::on_iconButton_clicked() } } -void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1) +void NewInstanceDialog::on_instNameTextBox_textChanged([[maybe_unused]] const QString &arg1) { updateDialogState(); } diff --git a/launcher/ui/dialogs/ProfileSetupDialog.cpp b/launcher/ui/dialogs/ProfileSetupDialog.cpp index 64c0b924c..758f7f233 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.cpp +++ b/launcher/ui/dialogs/ProfileSetupDialog.cpp @@ -167,14 +167,14 @@ void ProfileSetupDialog::checkName(const QString &name) { void ProfileSetupDialog::checkFinished( QNetworkReply::NetworkError error, - QByteArray data, - QList headers + QByteArray profileData, + [[maybe_unused]] QList headers ) { auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); if(error == QNetworkReply::NoError) { - auto doc = QJsonDocument::fromJson(data); + auto doc = QJsonDocument::fromJson(profileData); auto root = doc.object(); auto statusValue = root.value("status").toString("INVALID"); if(statusValue == "AVAILABLE") { @@ -210,11 +210,11 @@ void ProfileSetupDialog::setupProfile(const QString &profileName) { request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8()); QString payloadTemplate("{\"profileName\":\"%1\"}"); - auto data = payloadTemplate.arg(profileName).toUtf8(); + auto profileData = payloadTemplate.arg(profileName).toUtf8(); AuthRequest *requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &ProfileSetupDialog::setupProfileFinished); - requestor->post(request, data); + requestor->post(request, profileData); isWorking = true; auto button = ui->buttonBox->button(QDialogButtonBox::Cancel); @@ -251,8 +251,8 @@ struct MojangError{ void ProfileSetupDialog::setupProfileFinished( QNetworkReply::NetworkError error, - QByteArray data, - QList headers + QByteArray errorData, + [[maybe_unused]] QList headers ) { auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); @@ -266,7 +266,7 @@ void ProfileSetupDialog::setupProfileFinished( accept(); } else { - auto parsedError = MojangError::fromJSON(data); + auto parsedError = MojangError::fromJSON(errorData); ui->errorLabel->setVisible(true); ui->errorLabel->setText(tr("The server returned the following error:") + "\n\n" + parsedError.errorMessage); qDebug() << parsedError.rawError; diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 246a0fd49..24f445e65 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -85,7 +85,7 @@ void ProgressDialog::on_skipButton_clicked(bool checked) { Q_UNUSED(checked); if (ui->skipButton->isEnabled()) // prevent other triggers from aborting - task->abort(); + m_task->abort(); } ProgressDialog::~ProgressDialog() @@ -116,7 +116,7 @@ void ProgressDialog::updateSize() int ProgressDialog::execWithTask(Task* task) { - this->task = task; + this->m_task = task; if (!task) { qDebug() << "Programmer error: Progress dialog created with null task."; @@ -168,8 +168,8 @@ int ProgressDialog::execWithTask(std::unique_ptr& task) bool ProgressDialog::handleImmediateResult(QDialog::DialogCode& result) { - if (task->isFinished()) { - if (task->wasSuccessful()) { + if (m_task->isFinished()) { + if (m_task->wasSuccessful()) { result = QDialog::Accepted; } else { result = QDialog::Rejected; @@ -181,12 +181,12 @@ bool ProgressDialog::handleImmediateResult(QDialog::DialogCode& result) Task* ProgressDialog::getTask() { - return task; + return m_task; } void ProgressDialog::onTaskStarted() {} -void ProgressDialog::onTaskFailed(QString failure) +void ProgressDialog::onTaskFailed([[maybe_unused]] QString failure) { reject(); hide(); @@ -198,10 +198,10 @@ void ProgressDialog::onTaskSucceeded() hide(); } -void ProgressDialog::changeStatus(const QString& status) +void ProgressDialog::changeStatus([[maybe_unused]] const QString& status) { - ui->globalStatusLabel->setText(task->getStatus()); - ui->globalStatusDetailsLabel->setText(task->getDetails()); + ui->globalStatusLabel->setText(m_task->getStatus()); + ui->globalStatusDetailsLabel->setText(m_task->getDetails()); updateSize(); } @@ -269,7 +269,7 @@ void ProgressDialog::keyPressEvent(QKeyEvent* e) void ProgressDialog::closeEvent(QCloseEvent* e) { - if (task && task->isRunning()) { + if (m_task && m_task->isRunning()) { e->ignore(); } else { QDialog::closeEvent(e); diff --git a/launcher/ui/dialogs/ProgressDialog.h b/launcher/ui/dialogs/ProgressDialog.h index fc9a0fbc3..ee55cecaa 100644 --- a/launcher/ui/dialogs/ProgressDialog.h +++ b/launcher/ui/dialogs/ProgressDialog.h @@ -98,7 +98,7 @@ private: private: Ui::ProgressDialog *ui; - Task *task; + Task *m_task; bool m_is_multi_step = false; QHash taskProgress; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 4f59f5605..cebc9e9ed 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -301,7 +301,7 @@ GetModDependenciesTask::Ptr ModDownloadDialog::getModDependenciesTask() return makeShared(this, m_instance, model, selectedVers); } return nullptr; -}; +} ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp index 7b33765fd..78c2542fd 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.cpp +++ b/launcher/ui/dialogs/ReviewMessageBox.cpp @@ -5,7 +5,7 @@ #include -ReviewMessageBox::ReviewMessageBox(QWidget* parent, QString const& title, QString const& icon) +ReviewMessageBox::ReviewMessageBox(QWidget* parent, [[maybe_unused]] QString const& title, [[maybe_unused]] QString const& icon) : QDialog(parent), ui(new Ui::ReviewMessageBox) { ui->setupUi(this); diff --git a/launcher/ui/dialogs/SkinUploadDialog.cpp b/launcher/ui/dialogs/SkinUploadDialog.cpp index 8180ac1f0..1ff15c877 100644 --- a/launcher/ui/dialogs/SkinUploadDialog.cpp +++ b/launcher/ui/dialogs/SkinUploadDialog.cpp @@ -155,15 +155,15 @@ SkinUploadDialog::SkinUploadDialog(MinecraftAccountPtr acct, QWidget *parent) ui->setupUi(this); // FIXME: add a model for this, download/refresh the capes on demand - auto &data = *acct->accountData(); + auto &accountData = *acct->accountData(); int index = 0; ui->capeCombo->addItem(tr("No Cape"), QVariant()); - auto currentCape = data.minecraftProfile.currentCape; + auto currentCape = accountData.minecraftProfile.currentCape; if(currentCape.isEmpty()) { ui->capeCombo->setCurrentIndex(index); } - for(auto & cape: data.minecraftProfile.capes) { + for(auto & cape: accountData.minecraftProfile.capes) { index++; if(cape.data.size()) { QPixmap capeImage; diff --git a/launcher/ui/instanceview/InstanceDelegate.cpp b/launcher/ui/instanceview/InstanceDelegate.cpp index 137cc8d58..384c33f3f 100644 --- a/launcher/ui/instanceview/InstanceDelegate.cpp +++ b/launcher/ui/instanceview/InstanceDelegate.cpp @@ -400,7 +400,9 @@ signals: void editingDone(); }; -void ListViewDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const +void ListViewDelegate::updateEditorGeometry(QWidget* editor, + const QStyleOptionViewItem& option, + [[maybe_unused]] const QModelIndex& index) const { const int iconSize = 48; QRect textRect = option.rect; @@ -412,17 +414,17 @@ void ListViewDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionV void ListViewDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { auto text = index.data(Qt::EditRole).toString(); - QTextEdit * realeditor = qobject_cast(editor); - realeditor->setAlignment(Qt::AlignHCenter | Qt::AlignTop); - realeditor->append(text); - realeditor->selectAll(); - realeditor->document()->clearUndoRedoStacks(); + QTextEdit* realEditor = qobject_cast(editor); + realEditor->setAlignment(Qt::AlignHCenter | Qt::AlignTop); + realEditor->append(text); + realEditor->selectAll(); + realEditor->document()->clearUndoRedoStacks(); } void ListViewDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { - QTextEdit * realeditor = qobject_cast(editor); - QString text = realeditor->toPlainText(); + QTextEdit * realEditor = qobject_cast(editor); + QString text = realEditor->toPlainText(); text.replace(QChar('\n'), QChar(' ')); text = text.trimmed(); // Prevent instance names longer than 128 chars @@ -433,7 +435,9 @@ void ListViewDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, } } -QWidget * ListViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const +QWidget* ListViewDelegate::createEditor(QWidget* parent, + [[maybe_unused]] const QStyleOptionViewItem& option, + [[maybe_unused]] const QModelIndex& index) const { auto editor = new NoReturnTextEdit(parent); connect(editor, &NoReturnTextEdit::editingDone, this, &ListViewDelegate::editingDone); diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index fbeffe350..3b27e9fa9 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -88,16 +88,18 @@ void InstanceView::setModel(QAbstractItemModel *model) connect(model, &QAbstractItemModel::rowsRemoved, this, &InstanceView::rowsRemoved); } -void InstanceView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) +void InstanceView::dataChanged([[maybe_unused]] const QModelIndex& topLeft, + [[maybe_unused]] const QModelIndex& bottomRight, + [[maybe_unused]] const QVector& roles) { scheduleDelayedItemsLayout(); } -void InstanceView::rowsInserted(const QModelIndex &parent, int start, int end) +void InstanceView::rowsInserted([[maybe_unused]] const QModelIndex& parent, [[maybe_unused]] int start, [[maybe_unused]] int end) { scheduleDelayedItemsLayout(); } -void InstanceView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void InstanceView::rowsAboutToBeRemoved([[maybe_unused]] const QModelIndex& parent, [[maybe_unused]] int start, [[maybe_unused]] int end) { scheduleDelayedItemsLayout(); } @@ -263,9 +265,9 @@ QString InstanceView::groupNameAt(const QPoint &point) { executeDelayedItemsLayout(); - VisualGroup::HitResults hitresult; - auto group = categoryAt(point + offset(), hitresult); - if(group && (hitresult & (VisualGroup::HeaderHit | VisualGroup::BodyHit))) + VisualGroup::HitResults hitResult; + auto group = categoryAt(point + offset(), hitResult); + if(group && (hitResult & (VisualGroup::HeaderHit | VisualGroup::BodyHit))) { return group->text; } @@ -300,9 +302,9 @@ void InstanceView::mousePressEvent(QMouseEvent *event) m_pressedAlreadySelected = selectionModel()->isSelected(m_pressedIndex); m_pressedPosition = geometryPos; - VisualGroup::HitResults hitresult; - m_pressedCategory = categoryAt(geometryPos, hitresult); - if (m_pressedCategory && hitresult & VisualGroup::CheckboxHit) + VisualGroup::HitResults hitResult; + m_pressedCategory = categoryAt(geometryPos, hitResult); + if (m_pressedCategory && hitResult & VisualGroup::CheckboxHit) { setState(m_pressedCategory->collapsed ? ExpandingState : CollapsingState); event->accept(); @@ -402,10 +404,10 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event) QPoint geometryPos = event->pos() + offset(); QPersistentModelIndex index = indexAt(visualPos); - VisualGroup::HitResults hitresult; + VisualGroup::HitResults hitResult; bool click = (index == m_pressedIndex && index.isValid()) || - (m_pressedCategory && m_pressedCategory == categoryAt(geometryPos, hitresult)); + (m_pressedCategory && m_pressedCategory == categoryAt(geometryPos, hitResult)); if (click && m_pressedCategory) { @@ -498,7 +500,7 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent *event) } } -void InstanceView::paintEvent(QPaintEvent *event) +void InstanceView::paintEvent([[maybe_unused]] QPaintEvent *event) { executeDelayedItemsLayout(); @@ -589,7 +591,7 @@ void InstanceView::paintEvent(QPaintEvent *event) #endif } -void InstanceView::resizeEvent(QResizeEvent *event) +void InstanceView::resizeEvent([[maybe_unused]] QResizeEvent *event) { int newItemsPerRow = calculateItemsPerRow(); if(newItemsPerRow != m_currentItemsPerRow) @@ -630,7 +632,7 @@ void InstanceView::dragMoveEvent(QDragMoveEvent *event) event->accept(); } -void InstanceView::dragLeaveEvent(QDragLeaveEvent *event) +void InstanceView::dragLeaveEvent([[maybe_unused]] QDragLeaveEvent *event) { executeDelayedItemsLayout(); @@ -655,9 +657,9 @@ void InstanceView::dropEvent(QDropEvent *event) { std::pair dropPos = rowDropPos(event->pos()); const VisualGroup *group = dropPos.first; - auto hitresult = dropPos.second; + auto hitResult = dropPos.second; - if (hitresult == VisualGroup::HitResult::NoHit) + if (hitResult == VisualGroup::HitResult::NoHit) { viewport()->update(); return; @@ -697,8 +699,8 @@ void InstanceView::startDrag(Qt::DropActions supportedActions) if(indexes.count() == 0) return; - QMimeData *data = model()->mimeData(indexes); - if (!data) + QMimeData *mimeData = model()->mimeData(indexes); + if (!mimeData) { return; } @@ -706,7 +708,7 @@ void InstanceView::startDrag(Qt::DropActions supportedActions) QPixmap pixmap = renderToPixmap(indexes, &rect); QDrag *drag = new QDrag(this); drag->setPixmap(pixmap); - drag->setMimeData(data); + drag->setMimeData(mimeData); drag->setHotSpot(m_pressedPosition - rect.topLeft()); Qt::DropAction defaultDropAction = Qt::IgnoreAction; if (this->defaultDropAction() != Qt::IgnoreAction && (supportedActions & this->defaultDropAction())) @@ -833,16 +835,16 @@ QList> InstanceView::draggablePaintPairs(const QMo return ret; } -bool InstanceView::isDragEventAccepted(QDropEvent *event) +bool InstanceView::isDragEventAccepted([[maybe_unused]] QDropEvent *event) { return true; } std::pair InstanceView::rowDropPos(const QPoint &pos) { - VisualGroup::HitResults hitresult; - auto group = categoryAt(pos + offset(), hitresult); - return std::make_pair(group, hitresult); + VisualGroup::HitResults hitResult; + auto group = categoryAt(pos + offset(), hitResult); + return std::make_pair(group, hitResult); } QPoint InstanceView::offset() const @@ -871,7 +873,7 @@ QRegion InstanceView::visualRegionForSelection(const QItemSelection &selection) return region; } -QModelIndex InstanceView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers) +QModelIndex InstanceView::moveCursor(QAbstractItemView::CursorAction cursorAction, [[maybe_unused]] Qt::KeyboardModifiers modifiers) { auto current = currentIndex(); if(!current.isValid()) @@ -896,23 +898,23 @@ QModelIndex InstanceView::moveCursor(QAbstractItemView::CursorAction cursorActio { if(row == 0) { - int prevgroupindex = group_index-1; - while(prevgroupindex >= 0) + int prevGroupIndex = group_index-1; + while(prevGroupIndex >= 0) { - auto prevgroup = m_groups[prevgroupindex]; - if(prevgroup->collapsed) + auto prevGroup = m_groups[prevGroupIndex]; + if(prevGroup->collapsed) { - prevgroupindex--; + prevGroupIndex--; continue; } - int newRow = prevgroup->numRows() - 1; - int newRowSize = prevgroup->rows[newRow].size(); + int newRow = prevGroup->numRows() - 1; + int newRowSize = prevGroup->rows[newRow].size(); int newColumn = m_currentCursorColumn; if (m_currentCursorColumn >= newRowSize) { newColumn = newRowSize - 1; } - return prevgroup->rows[newRow][newColumn]; + return prevGroup->rows[newRow][newColumn]; } } else @@ -932,22 +934,22 @@ QModelIndex InstanceView::moveCursor(QAbstractItemView::CursorAction cursorActio { if(row == cat->rows.size() - 1) { - int nextgroupindex = group_index+1; - while (nextgroupindex < m_groups.size()) + int nextGroupIndex = group_index+1; + while (nextGroupIndex < m_groups.size()) { - auto nextgroup = m_groups[nextgroupindex]; - if(nextgroup->collapsed) + auto nextGroup = m_groups[nextGroupIndex]; + if(nextGroup->collapsed) { - nextgroupindex++; + nextGroupIndex++; continue; } - int newRowSize = nextgroup->rows[0].size(); + int newRowSize = nextGroup->rows[0].size(); int newColumn = m_currentCursorColumn; if (m_currentCursorColumn >= newRowSize) { newColumn = newRowSize - 1; } - return nextgroup->rows[0][newColumn]; + return nextGroup->rows[0][newColumn]; } } else @@ -1031,7 +1033,7 @@ void InstanceView::scrollTo(const QModelIndex &index, ScrollHint hint) verticalScrollBar()->setValue(verticalScrollToValue(index, rect, hint)); } -int InstanceView::verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const +int InstanceView::verticalScrollToValue([[maybe_unused]] const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const { const QRect area = viewport()->rect(); const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top()); diff --git a/launcher/ui/instanceview/VisualGroup.cpp b/launcher/ui/instanceview/VisualGroup.cpp index e6bca17d6..70fad5a2e 100644 --- a/launcher/ui/instanceview/VisualGroup.cpp +++ b/launcher/ui/instanceview/VisualGroup.cpp @@ -165,7 +165,7 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti const QFontMetrics fontMetrics = QFontMetrics(font); QColor outlineColor = option.palette.text().color(); - outlineColor.setAlphaF(0.35); + outlineColor.setAlphaF(static_cast(0.35)); //BEGIN: top left corner { @@ -234,7 +234,7 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti painter->setRenderHint(QPainter::Antialiasing, false); painter->setFont(font); QColor penColor(option.palette.text().color()); - penColor.setAlphaF(0.6); + penColor.setAlphaF(static_cast(0.6)); painter->setPen(penColor); QRect iconSubRect(option.rect); iconSubRect.setTop(iconSubRect.top() + 7); @@ -278,7 +278,7 @@ void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &opti painter->save(); painter->setFont(font); QColor penColor(option.palette.text().color()); - penColor.setAlphaF(0.6); + penColor.setAlphaF(static_cast(0.6)); painter->setPen(penColor); painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text); painter->restore(); diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index 278f45c49..5cc3d7f37 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -84,9 +84,8 @@ AccountListPage::AccountListPage(QWidget *parent) QItemSelectionModel *selectionModel = ui->listView->selectionModel(); - connect(selectionModel, &QItemSelectionModel::selectionChanged, [this](const QItemSelection &sel, const QItemSelection &dsel) { - updateButtonStates(); - }); + connect(selectionModel, &QItemSelectionModel::selectionChanged, + [this]([[maybe_unused]] const QItemSelection& sel, [[maybe_unused]] const QItemSelection& dsel) { updateButtonStates(); }); connect(ui->listView, &VersionListView::customContextMenuRequested, this, &AccountListPage::ShowContextMenu); connect(m_accounts.get(), &AccountList::listChanged, this, &AccountListPage::listChanged); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 81dd4cc12..1f4dcc8da 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -176,7 +176,7 @@ void JavaPage::on_javaTestBtn_clicked() checker->run(); } -void JavaPage::on_maxMemSpinBox_valueChanged(int i) +void JavaPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i) { updateThresholds(); } diff --git a/launcher/ui/pages/global/ProxyPage.cpp b/launcher/ui/pages/global/ProxyPage.cpp index ffff8456c..5ccdb1528 100644 --- a/launcher/ui/pages/global/ProxyPage.cpp +++ b/launcher/ui/pages/global/ProxyPage.cpp @@ -73,7 +73,7 @@ void ProxyPage::updateCheckboxStuff() ui->proxyAuthBox->setEnabled(enableEditing); } -void ProxyPage::proxyGroupChanged(QAbstractButton *button) +void ProxyPage::proxyGroupChanged([[maybe_unused]] QAbstractButton *button) { updateCheckboxStuff(); } diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 173bcb663..5a7100b1f 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -300,7 +300,7 @@ bool ExternalResourcesPage::current(const QModelIndex& current, const QModelInde return onSelectionChanged(current, previous); } -bool ExternalResourcesPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +bool ExternalResourcesPage::onSelectionChanged(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous) { auto sourceCurrent = m_filterModel->mapToSource(current); int row = sourceCurrent.row(); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 2a7c5b271..311ebc86d 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -482,7 +482,7 @@ void InstanceSettingsPage::changeInstanceAccount(int index) } } -void InstanceSettingsPage::on_maxMemSpinBox_valueChanged(int i) +void InstanceSettingsPage::on_maxMemSpinBox_valueChanged([[maybe_unused]] int i) { updateThresholds(); } diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 90e7d0d62..f6b1a71c2 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -122,7 +122,7 @@ bool ModFolderPage::shouldDisplay() const return true; } -bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +bool ModFolderPage::onSelectionChanged(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous) { auto sourceCurrent = m_filterModel->mapToSource(current); int row = sourceCurrent.row(); diff --git a/launcher/ui/pages/instance/OtherLogsPage.cpp b/launcher/ui/pages/instance/OtherLogsPage.cpp index bbdd73248..f2b13f321 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.cpp +++ b/launcher/ui/pages/instance/OtherLogsPage.cpp @@ -287,23 +287,23 @@ void OtherLogsPage::on_btnClean_clicked() } if(!failed.empty()) { - QMessageBox *messageBox = new QMessageBox(this); - messageBox->setWindowTitle(tr("Error")); + QMessageBox *messageBoxFailure = new QMessageBox(this); + messageBoxFailure->setWindowTitle(tr("Error")); if(failed.size() > 5) { - messageBox->setText(tr("Couldn't delete some files!")); - messageBox->setDetailedText(failed.join('\n')); + messageBoxFailure->setText(tr("Couldn't delete some files!")); + messageBoxFailure->setDetailedText(failed.join('\n')); } else { - messageBox->setText(tr("Couldn't delete some files:\n%1").arg(failed.join('\n'))); + messageBoxFailure->setText(tr("Couldn't delete some files:\n%1").arg(failed.join('\n'))); } - messageBox->setStandardButtons(QMessageBox::Ok); - messageBox->setDefaultButton(QMessageBox::Ok); - messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse); - messageBox->setIcon(QMessageBox::Critical); - messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction); - messageBox->exec(); + messageBoxFailure->setStandardButtons(QMessageBox::Ok); + messageBoxFailure->setDefaultButton(QMessageBox::Ok); + messageBoxFailure->setTextInteractionFlags(Qt::TextSelectableByMouse); + messageBoxFailure->setIcon(QMessageBox::Critical); + messageBoxFailure->setTextInteractionFlags(Qt::TextBrowserInteraction); + messageBoxFailure->exec(); } } diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp index 24bfb38dc..2696acfcc 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.cpp +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -55,7 +55,7 @@ ResourcePackPage::ResourcePackPage(MinecraftInstance* instance, std::shared_ptr< ui->actionViewConfigs->setVisible(false); } -bool ResourcePackPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +bool ResourcePackPage::onSelectionChanged(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous) { auto sourceCurrent = m_filterModel->mapToSource(current); int row = sourceCurrent.row(); diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index 4b1fa08a3..09ed9e407 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -684,7 +684,7 @@ void ServersPage::runningStateChanged(bool running) updateState(); } -void ServersPage::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +void ServersPage::currentChanged(const QModelIndex ¤t, [[maybe_unused]] const QModelIndex &previous) { int nextServer = -1; if (!current.isValid()) @@ -700,7 +700,7 @@ void ServersPage::currentChanged(const QModelIndex ¤t, const QModelIndex & } // WARNING: this is here because currentChanged is not accurate when removing rows. the current item needs to be fixed up after removal. -void ServersPage::rowsRemoved(const QModelIndex& parent, int first, int last) +void ServersPage::rowsRemoved([[maybe_unused]] const QModelIndex& parent, int first, int last) { if(currentServer < first) { diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp index 427aba11a..f7b3bc8df 100644 --- a/launcher/ui/pages/instance/TexturePackPage.cpp +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -57,7 +57,7 @@ TexturePackPage::TexturePackPage(MinecraftInstance* instance, std::shared_ptractionViewConfigs->setVisible(false); } -bool TexturePackPage::onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) +bool TexturePackPage::onSelectionChanged(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous) { auto sourceCurrent = m_filterModel->mapToSource(current); int row = sourceCurrent.row(); diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 59107c53a..e3cef0d71 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -202,7 +202,7 @@ void VersionPage::showContextMenu(const QPoint& pos) delete menu; } -void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex &previous) +void VersionPage::packageCurrent(const QModelIndex ¤t, [[maybe_unused]] const QModelIndex &previous) { if (!current.isValid()) { @@ -647,7 +647,7 @@ void VersionPage::on_actionMinecraftFolder_triggered() DesktopServices::openDirectory(m_inst->gameRoot(), true); } -void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous) +void VersionPage::versionCurrent(const QModelIndex ¤t, [[maybe_unused]] const QModelIndex &previous) { currentIdx = current.row(); updateButtons(currentIdx); diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index b6ad159e1..d961a3822 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -352,7 +352,7 @@ void WorldListPage::mceditState(LoggedProcess::State state) } } -void WorldListPage::worldChanged(const QModelIndex ¤t, const QModelIndex &previous) +void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex ¤t, [[maybe_unused]] const QModelIndex &previous) { QModelIndex index = getSelectedWorld(); bool enable = index.isValid(); diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 30196aad6..8f30781e1 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -50,7 +50,7 @@ class UrlValidator : public QValidator public: using QValidator::QValidator; - State validate(QString &in, int &pos) const + State validate(QString &in, [[maybe_unused]] int &pos) const { const QUrl url(in); if (url.isValid() && !url.isRelative() && !url.isEmpty()) @@ -118,8 +118,8 @@ void ImportPage::updateState() if(fi.exists() && (isZip || isMRPack)) { - QFileInfo fi(url.fileName()); - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url,this)); + QFileInfo file_info(url.fileName()); + dialog->setSuggestedPack(file_info.completeBaseName(), new InstanceImportTask(url,this)); dialog->setSuggestedIcon("default"); } } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 49405a02b..26b96d549 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -102,7 +102,7 @@ QHash ResourceModel::roleNames() const return roles; } -bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int role) +bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, [[maybe_unused]] int role) { int pos = index.row(); if (pos >= m_packs.size() || pos < 0 || !index.isValid()) @@ -310,7 +310,7 @@ std::optional ResourceModel::getIcon(QModelIndex& index, const QUrl& url) #define NEED_FOR_CALLBACK_ASSERT(name) \ Q_ASSERT_X(0 != 0, #name, "You NEED to re-implement this if you intend on using the default callbacks.") -QJsonArray ResourceModel::documentToArray(QJsonDocument& doc) const +QJsonArray ResourceModel::documentToArray([[maybe_unused]] QJsonDocument& doc) const { NEED_FOR_CALLBACK_ASSERT("documentToArray"); return {}; @@ -372,7 +372,7 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) endInsertRows(); } -void ResourceModel::searchRequestFailed(QString reason, int network_error_code) +void ResourceModel::searchRequestFailed([[maybe_unused]] QString reason, int network_error_code) { switch (network_error_code) { default: diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.cpp b/launcher/ui/pages/modplatform/ResourcePackModel.cpp index 18c14bf81..d436f320f 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackModel.cpp @@ -9,7 +9,8 @@ namespace ResourceDownload { ResourcePackResourceModel::ResourcePackResourceModel(BaseInstance const& base_inst, ResourceAPI* api) - : ResourceModel(api), m_base_instance(base_inst){}; + : ResourceModel(api), m_base_instance(base_inst) +{} /******** Make data requests ********/ diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index aab2ee89a..b98f614fe 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -279,7 +279,7 @@ void ResourcePage::updateVersionList() updateSelectionButton(); } -void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) +void ResourcePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev) { if (!curr.isValid()) { return; @@ -306,9 +306,9 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) updateUi(); } -void ResourcePage::onVersionSelectionChanged(QString data) +void ResourcePage::onVersionSelectionChanged(QString versionData) { - if (data.isNull() || data.isEmpty()) { + if (versionData.isNull() || versionData.isEmpty()) { m_selected_version_index = -1; return; } diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index b4a87f573..3e8bb7d8a 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -97,7 +97,10 @@ class ResourcePage : public QWidget, public BasePage { virtual void openUrl(const QUrl&); /** Whether the version is opted out or not. Currently only makes sense in CF. */ - virtual bool optedOut(ModPlatform::IndexedVersion& ver) const { return false; }; + virtual bool optedOut(ModPlatform::IndexedVersion& ver) const { + Q_UNUSED(ver); + return false; + }; public: BaseInstance& m_base_instance; diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.cpp b/launcher/ui/pages/modplatform/ShaderPackModel.cpp index aabd3be6e..8c913657a 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackModel.cpp @@ -9,7 +9,8 @@ namespace ResourceDownload { ShaderPackResourceModel::ShaderPackResourceModel(BaseInstance const& base_inst, ResourceAPI* api) - : ResourceModel(api), m_base_instance(base_inst){}; + : ResourceModel(api), m_base_instance(base_inst) +{} /******** Make data requests ********/ diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp index 7b61daa71..289173e17 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -114,7 +114,7 @@ QVariant AtlOptionalModListModel::data(const QModelIndex &index, int role) const return {}; } -bool AtlOptionalModListModel::setData(const QModelIndex &index, const QVariant &value, int role) { +bool AtlOptionalModListModel::setData(const QModelIndex &index, [[maybe_unused]] const QVariant &value, int role) { if (role == Qt::CheckStateRole) { auto row = index.row(); auto mod = m_mods.at(row); @@ -206,7 +206,7 @@ void AtlOptionalModListModel::shareCodeSuccess() { AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); } -void AtlOptionalModListModel::shareCodeFailure(const QString& reason) { +void AtlOptionalModListModel::shareCodeFailure([[maybe_unused]] const QString& reason) { m_jobPtr.reset(); // fixme: plumb in an error message @@ -277,16 +277,16 @@ void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool // if the dependency is 'effectively hidden', then track which mods // depend on it - so we can efficiently disable it when no more dependents // depend on it. - auto dependants = m_dependants[dependencyName]; + auto dependents = m_dependents[dependencyName]; if (enable) { - dependants.append(mod.name); + dependents.append(mod.name); } else { - dependants.removeAll(mod.name); + dependents.removeAll(mod.name); // if there are no longer any dependents, let's disable the mod - if (dependencyMod.effectively_hidden && dependants.isEmpty()) { + if (dependencyMod.effectively_hidden && dependents.isEmpty()) { setMod(dependencyMod, dependencyIndex, false, shouldEmit); } } @@ -294,8 +294,8 @@ void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool // disable mods that depend on this one, if disabling if (!enable) { - auto dependants = m_dependants[mod.name]; - for (const auto& dependencyName : dependants) { + auto dependents = m_dependents[mod.name]; + for (const auto& dependencyName : dependents) { auto dependencyIndex = m_index[dependencyName]; auto dependencyMod = m_mods.at(dependencyIndex); diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h index 639f0d489..fe24d821d 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h @@ -91,7 +91,7 @@ private: QMap m_selection; QMap m_index; - QMap> m_dependants; + QMap> m_dependents; }; class AtlOptionalModDialog : public QDialog { diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp index 875444451..7c80ed2de 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp @@ -132,13 +132,13 @@ void AtlPage::triggerSearch() filterModel->setSearchTerm(ui->searchEdit->text()); } -void AtlPage::onSortingSelectionChanged(QString data) +void AtlPage::onSortingSelectionChanged(QString sort) { - auto toSet = filterModel->getAvailableSortings().value(data); + auto toSet = filterModel->getAvailableSortings().value(sort); filterModel->setSorting(toSet); } -void AtlPage::onSelectionChanged(QModelIndex first, QModelIndex second) +void AtlPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelIndex second) { ui->versionSelectionBox->clear(); @@ -162,14 +162,14 @@ void AtlPage::onSelectionChanged(QModelIndex first, QModelIndex second) suggestCurrent(); } -void AtlPage::onVersionSelectionChanged(QString data) +void AtlPage::onVersionSelectionChanged(QString version) { - if(data.isNull() || data.isEmpty()) + if(version.isNull() || version.isEmpty()) { selectedVersion = ""; return; } - selectedVersion = data; + selectedVersion = version; suggestCurrent(); } diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index fa55aa686..c693515f8 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -68,7 +68,7 @@ QVariant ListModel::data(const QModelIndex& index, int role) const return QVariant(); } -bool ListModel::setData(const QModelIndex &index, const QVariant &value, int role) +bool ListModel::setData(const QModelIndex &index, const QVariant &value, [[maybe_unused]] int role) { int pos = index.row(); if (pos >= modpacks.size() || pos < 0 || !index.isValid()) @@ -139,7 +139,7 @@ Qt::ItemFlags ListModel::flags(const QModelIndex& index) const return QAbstractListModel::flags(index); } -bool ListModel::canFetchMore(const QModelIndex& parent) const +bool ListModel::canFetchMore([[maybe_unused]] const QModelIndex& parent) const { return searchState == CanPossiblyFetchMore; } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index cef26bb6b..5942883f6 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -114,7 +114,7 @@ void FlamePage::triggerSearch() listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); } -void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) +void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev) { ui->versionSelectionBox->clear(); @@ -212,12 +212,12 @@ void FlamePage::suggestCurrent() [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } -void FlamePage::onVersionSelectionChanged(QString data) +void FlamePage::onVersionSelectionChanged(QString version) { bool is_blocked = false; ui->versionSelectionBox->currentData().toInt(&is_blocked); - if (data.isNull() || data.isEmpty() || is_blocked) { + if (version.isNull() || version.isEmpty() || is_blocked) { m_selected_version_index = -1; return; } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index 0fb67c507..2b020c48d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -32,7 +32,7 @@ void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonAr auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return FlameMod::loadDependencyVersions(m, arr); -}; +} auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 330dd4fb8..75b8f9d1a 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -76,7 +76,7 @@ bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) co return true; } -bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const +bool FilterModel::filterAcceptsRow([[maybe_unused]] int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const { return true; } @@ -173,10 +173,10 @@ QVariant ListModel::data(const QModelIndex& index, int role) const return QVariant(); } -void ListModel::fill(ModpackList modpacks) +void ListModel::fill(ModpackList modpacks_) { beginResetModel(); - this->modpacks = modpacks; + this->modpacks = modpacks_; endResetModel(); } diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index b3f6261fe..d4174ff1c 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -234,7 +234,7 @@ void Page::ftbPrivatePackDataDownloadSuccessfully(Modpack pack) privateListModel->addPack(pack); } -void Page::ftbPrivatePackDataDownloadFailed(QString reason, QString packCode) +void Page::ftbPrivatePackDataDownloadFailed([[maybe_unused]] QString reason, QString packCode) { auto reply = QMessageBox::question( this, @@ -247,7 +247,7 @@ void Page::ftbPrivatePackDataDownloadFailed(QString reason, QString packCode) } } -void Page::onPublicPackSelectionChanged(QModelIndex now, QModelIndex prev) +void Page::onPublicPackSelectionChanged(QModelIndex now, [[maybe_unused]] QModelIndex prev) { if(!now.isValid()) { @@ -258,7 +258,7 @@ void Page::onPublicPackSelectionChanged(QModelIndex now, QModelIndex prev) onPackSelectionChanged(&selectedPack); } -void Page::onThirdPartyPackSelectionChanged(QModelIndex now, QModelIndex prev) +void Page::onThirdPartyPackSelectionChanged(QModelIndex now, [[maybe_unused]] QModelIndex prev) { if(!now.isValid()) { @@ -269,7 +269,7 @@ void Page::onThirdPartyPackSelectionChanged(QModelIndex now, QModelIndex prev) onPackSelectionChanged(&selectedPack); } -void Page::onPrivatePackSelectionChanged(QModelIndex now, QModelIndex prev) +void Page::onPrivatePackSelectionChanged(QModelIndex now, [[maybe_unused]] QModelIndex prev) { if(!now.isValid()) { @@ -318,21 +318,21 @@ void Page::onPackSelectionChanged(Modpack* pack) suggestCurrent(); } -void Page::onVersionSelectionItemChanged(QString data) +void Page::onVersionSelectionItemChanged(QString version) { - if(data.isNull() || data.isEmpty()) + if(version.isNull() || version.isEmpty()) { selectedVersion = ""; return; } - selectedVersion = data; + selectedVersion = version; suggestCurrent(); } -void Page::onSortingSelectionChanged(QString data) +void Page::onSortingSelectionChanged(QString sort) { - FilterModel::Sorting toSet = publicFilterModel->getAvailableSortings().value(data); + FilterModel::Sorting toSet = publicFilterModel->getAvailableSortings().value(sort); publicFilterModel->setSorting(toSet); thirdPartyFilterModel->setSorting(toSet); privateFilterModel->setSorting(toSet); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index e0046d887..14e8e709d 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -115,7 +115,7 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian return {}; } -bool ModpackListModel::setData(const QModelIndex &index, const QVariant &value, int role) +bool ModpackListModel::setData(const QModelIndex &index, const QVariant &value, [[maybe_unused]] int role) { int pos = index.row(); if (pos >= modpacks.size() || pos < 0 || !index.isValid()) @@ -194,8 +194,6 @@ static auto sortFromIndex(int index) -> QString case 4: return "updated"; } - - return {}; } void ModpackListModel::searchWithTerm(const QString& term, const int sort) diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index c71dd9038..5e084c036 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -105,7 +105,7 @@ bool ModrinthPage::eventFilter(QObject* watched, QEvent* event) return QObject::eventFilter(watched, event); } -void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) +void ModrinthPage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev) { ui->versionSelectionBox->clear(); @@ -309,9 +309,9 @@ void ModrinthPage::triggerSearch() m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); } -void ModrinthPage::onVersionSelectionChanged(QString data) +void ModrinthPage::onVersionSelectionChanged(QString version) { - if (data.isNull() || data.isEmpty()) { + if (version.isNull() || version.isEmpty()) { selectedVersion = ""; return; } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index 8aa649898..512eb0274 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -45,7 +45,7 @@ void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJso auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return ::Modrinth::loadDependencyVersions(m, arr); -}; +} auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index fc678fa20..656009dbe 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -100,7 +100,7 @@ void TechnicPage::triggerSearch() { model->searchWithTerm(ui->searchEdit->text()); } -void TechnicPage::onSelectionChanged(QModelIndex first, QModelIndex second) +void TechnicPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelIndex second) { ui->versionSelectionBox->clear(); @@ -319,12 +319,12 @@ void TechnicPage::onSolderLoaded() { metadataLoaded(); } -void TechnicPage::onVersionSelectionChanged(QString data) { - if (data.isNull() || data.isEmpty()) { +void TechnicPage::onVersionSelectionChanged(QString version) { + if (version.isNull() || version.isEmpty()) { selectedVersion = ""; return; } - selectedVersion = data; + selectedVersion = version; selectVersion(); } diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 198e76ba1..13d6b6ffe 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -148,7 +148,7 @@ static bool writeThemeJson(const QString& path, try { Json::write(rootObj, path); return true; - } catch (const Exception& e) { + } catch ([[maybe_unused]] const Exception& e) { themeWarningLog() << "Failed to write theme json to" << path; return false; } diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 9c041bfe9..096a6c5d1 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -357,7 +357,7 @@ void InfoFrame::setImage(QPixmap img) } } -void InfoFrame::descriptionEllipsisHandler(QString link) +void InfoFrame::descriptionEllipsisHandler([[maybe_unused]] QString link) { if(!m_current_box) { @@ -371,7 +371,7 @@ void InfoFrame::descriptionEllipsisHandler(QString link) } } -void InfoFrame::licenseEllipsisHandler(QString link) +void InfoFrame::licenseEllipsisHandler([[maybe_unused]] QString link) { if(!m_current_box) { @@ -385,7 +385,7 @@ void InfoFrame::licenseEllipsisHandler(QString link) } } -void InfoFrame::boxClosed(int result) +void InfoFrame::boxClosed([[maybe_unused]] int result) { m_current_box = nullptr; } diff --git a/launcher/ui/widgets/SubTaskProgressBar.cpp b/launcher/ui/widgets/SubTaskProgressBar.cpp index 84ea5f207..96f4fe245 100644 --- a/launcher/ui/widgets/SubTaskProgressBar.cpp +++ b/launcher/ui/widgets/SubTaskProgressBar.cpp @@ -27,7 +27,7 @@ unique_qobject_ptr SubTaskProgressBar::create(QWidget* paren } SubTaskProgressBar::SubTaskProgressBar(QWidget* parent) - : ui(new Ui::SubTaskProgressBar) + : QWidget(parent), ui(new Ui::SubTaskProgressBar) { ui->setupUi(this); } From f1bd9700f71341ed726e205f04633bb0cb44e6fb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 2 Jul 2023 22:43:30 +0300 Subject: [PATCH 137/398] Fail NetRequest on connection close from QT Signed-off-by: Trial97 --- launcher/net/NetRequest.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/launcher/net/NetRequest.cpp b/launcher/net/NetRequest.cpp index 304577121..ff59da18b 100644 --- a/launcher/net/NetRequest.cpp +++ b/launcher/net/NetRequest.cpp @@ -157,7 +157,7 @@ void NetRequest::downloadError(QNetworkReply::NetworkError error) { if (error == QNetworkReply::OperationCanceledError) { qCCritical(logCat) << getUid().toString() << "Aborted " << m_url.toString(); - m_state = State::AbortedByUser; + m_state = State::Failed; } else { if (m_options & Option::AcceptLocalFiles) { if (m_sink->hasLocalData()) { @@ -274,6 +274,13 @@ void NetRequest::downloadFinished() if (data.size()) { qCDebug(logCat) << getUid().toString() << "Writing extra" << data.size() << "bytes"; m_state = m_sink->write(data); + if (m_state != State::Succeeded) { + qCDebug(logCat) << getUid().toString() << "Request failed to write:" << m_url.toString(); + m_sink->abort(); + emit failed(""); + emit finished(); + return; + } } // otherwise, finalize the whole graph @@ -309,10 +316,14 @@ void NetRequest::downloadReadyRead() auto NetRequest::abort() -> bool { + m_state = State::AbortedByUser; if (m_reply) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + disconnect(m_reply.get(), &QNetworkReply::errorOccurred, nullptr, nullptr); +#else + disconnect(m_reply.get(), QOverload::of(&QNetworkReply::error), nullptr, nullptr); +#endif m_reply->abort(); - } else { - m_state = State::AbortedByUser; } return true; } From 0e5c37768084cf0772ca2598b4554bf262cb581b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 3 Jul 2023 17:32:59 +0100 Subject: [PATCH 138/398] Various tweaks Signed-off-by: TheKodeToad --- .../multimc/128x128/instances/forge.png | Bin 0 -> 3229 bytes launcher/resources/multimc/multimc.qrc | 2 +- .../multimc/scalable/instances/forge.svg | 43 ---------- launcher/ui/dialogs/InstallLoaderDialog.cpp | 78 +++++++++++------- launcher/ui/dialogs/InstallLoaderDialog.h | 7 +- launcher/ui/widgets/PageContainer.cpp | 2 +- launcher/ui/widgets/PageContainer.h | 2 +- 7 files changed, 53 insertions(+), 81 deletions(-) create mode 100644 launcher/resources/multimc/128x128/instances/forge.png delete mode 100644 launcher/resources/multimc/scalable/instances/forge.svg diff --git a/launcher/resources/multimc/128x128/instances/forge.png b/launcher/resources/multimc/128x128/instances/forge.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ff79a537bedb9b16ed0f2824580cd8037f5847 GIT binary patch literal 3229 zcmcIn`8O2a8y;dXb~BccL`tL#`Ou8563LQvjCJf}8Dk&DzLY_h$P!Vch+&k%*mn^# zwn(y-OxCfC=9BQ9&mZyq;l0l}_nv#s``-KB=XoyP%+!DvBn|=q0KA5G^emVd_g`=V znPZQ(%P+8ApVE1x5Bch^qFo9+X%6#7MB@=i+T`oX0`XT- ztiy!4-TP6DtnC#$GS7P9)8xa)xmA}u&AeGtYf^#ohboGnc(yYW+`T-v=HRNUQ75jR zTUx6FUhTo;w$+m0TKp;{Q0ch70)gd7p1K zpu$$eqF57u2#CE`=u)}I2Q?Ns{vq1#M#W5FlZZZB3%(TR)1I zg)K_kuZH04=HI8MIk;j{8Q`5{JikA)u&Z+-^1dxE6#H!_xVe=}EtKw!Mkqh7u4{mE z2;k+AjL)zdR5N7H%fwCX&OOE9YC` z{bA=fea$@Xb9oZf*#!;c4p!})|1eAzzALAq@(!bR1Plt=3sk*$uUhdrx{lSt^p%Wy z2WM$a1DDiRt+-7mTlDqb!$WM@s}J$X*XFXK;b#p@qcbh5M9pojdyvgqPQZDRWy+;@ z^S!k%>0%c7o};s?y*=H){&Ir_PdqeuvvJ8z+C*d~HtoeB;)LIp8pU)&@!LlOqjH$g#!)=1aD; z&|qpE>PU3$xm6W$HLVUBwkvu5tVZ`*#q(M9#4QNKZ9H8}()cuA3 z8zh4AT5{lJbZlH%%Wr7tsLBRo-$>qC;etx&M?h?;Q{%5q`4{|Fh$(3m7~jBX@hS`i zcmPb2hk(v+-s#`3M9#IHz`?h}x)-LoHA@ULzfuqJ&eowyo=TA%>cP8B8RNim*#xxv zs_SmLSX2yE!%D%k)Zjk)Lej$`qs*_2i1qF3x*pcNGNQe*9aO1l^VzP(z@2Y{?(rrg zBTWT)8GAZTw=fiG{eWB=R&!=HM8`9pJWUov2StE?_SWd3V+5zoVO>oCf|b?OB5fzw z8;$NyS-f~ofcE~%#L$qCW==^FOSJn+KY!rTUDz~~r1x6qbn?ykOC1##F^D2~m0z8W5z(_S0InU)Ail3pct+se@T+n0 z^?ek>%5qsrsdIIQve4Z+4Nr0qYVlDujl#vRi?x;6uvT)H4kT81#A;lhm8Fomdmixh zPvTuL;h{gT*@XI^(SLATyw_bgQRKNIRukMR_K(PR9X^>mF9__$&m;r@pc$skgTzap}_u51X?9u)^*$yE@}c;>l15C3Y} z($Gg`2gIS!MD-u3Ue3Q2c@zl`a{oGw+Bud;lFKYaW!TIvg{oT-Wb^Vw(lg>IYI>Zs zBpg{5U*Ks>#UR!vfHG{@NUAepy+}+uZ|YA&7nNNZ3hmm@?|)~v+5|mUOs?Eg)W53x zW0I?eEOAY3^WjRssM~u}6Q~ah5Xe|=TY(l&p4l1S&_$ymT+vIh zbSFade855i{yY6Js*{T5z~M-4U%J0w{b$pZ$8wfDMQdNW4U`;dT?y_H);|~bjG$H` zadi1rs|Mfq{s-RIB9T=VRqs(oM%;FGly$#~fscx^8&#ulE`eOd&m^7wJ*qy(RCr`|iqe+WHY&rOjf{XGko-l{ z8&FWHkr~1%-g5QITkX`rMK%GDN%q?SiG)O;k7J(0d{W}2*E`)!W8&c=jwT%$92NY~ z;6LXHdmC^JL_#Rs$1wvYHfi`AkLP+kkLnuCkA>H92D>6$L#P-+B*@?)&qIqUy^S{` zc2{WvS~!@ep7G=xo=~VfOWx%I{QaEn_X_0|73_z6l70Kl^(iQoj(ZcMIJdALkR}cI zaV+n4P-spH|k z%c9Jll~5IJfAk37a!pE9T7Z+b^H2gQ@x@Pol_^TDHsdhDPhiR6Io>6~F(x6zGqb2y zUb6;*j|0DT$ObBDmSS%2#>=J@NTikF_^&Apk9F~t`k#m@R@c|V)QrJ3gv){6+lZ!S zjr$E9NSVG_rLS4EF{wfKAVy@w;+`WHbvpB3Lpe{+n>-RQu}c>%%#SOD79@2zaPT5+ z0(M@|%YZ|3>1RT)&P!;?Uf{kRK#I&(>h~>0ur!^udore0r7?~_thmcR8D*xgYj z+AhXT#S=c~P)w;Ylh#t@9s#kBo?v;^-v&W1glPP+FQ~TuyvTB#b=QMIZ?uQqtzI?h zY_$~>zv>vvm}yK&vHOfhcRpr+r~J3-oN?cJUQL2ASiVbg$lHu zli>mFyQw(AnJIa3;2!;M3sQRL_`lM&z~YArbyaGm({C@NG3D%P28 zzGY}iNs?@@7jrSU`3o2x+v%XB1s2Qs5x$dKMjk^uf%lWj=~vFqaRIOWpFVw>%@pItU647_Ap!S$m_{rEO}!7Ttg2dX*m!2<4dQ^? zYrtoFMy9x8v`aYm>G~LoF4Gl-t!2bSkA_IXf=GnZLiobyIc~5R0YJD%A=ZDm>F^1a zs4A74Crj_Pj*9(t(Sb}Ne7^aJN%ccgi02zF>@ma56I-e{dx>;VggCgnUpmT9o=J_& zrXgO4fr|7IH~=Yf`<$KP%Q~_C=5=j6OylNYJlyGpdL_NNYTTbsJQeqp6j^NAmNZe7 z&!khyi3^znWzE?I0{;L{or=n~!PdXPsZ{Ad literal 0 HcmV?d00001 diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 907fbb5d3..4a407d95a 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,9 +348,9 @@ scalable/launch.svg scalable/server.svg - scalable/instances/forge.svg scalable/instances/quiltmc.svg 22x22/fabricmc-small.png + 128x128/instances/forge.png 128x128/instances/fabricmc.png 128x128/instances/liteloader.png diff --git a/launcher/resources/multimc/scalable/instances/forge.svg b/launcher/resources/multimc/scalable/instances/forge.svg deleted file mode 100644 index ea402c5b2..000000000 --- a/launcher/resources/multimc/scalable/instances/forge.svg +++ /dev/null @@ -1,43 +0,0 @@ - - diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index acef60c69..31d6f9ab5 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -38,7 +38,7 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { // "lightweight" loaders are independent to any game version const bool lightweight, const std::shared_ptr profile) - : VersionSelectWidget(nullptr), m_id(id), m_icon(icon), m_name(name) + : VersionSelectWidget(nullptr), uid(id), iconName(icon), name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); @@ -49,21 +49,21 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { setCurrentVersion(currentVersion); } - QString id() const override { return m_id; } - QString displayName() const override { return m_name; } - QIcon icon() const override { return APPLICATION->getThemedIcon(m_icon); } + QString id() const override { return uid; } + QString displayName() const override { return name; } + QIcon icon() const override { return APPLICATION->getThemedIcon(iconName); } void openedImpl() override { - if (m_loaded) + if (loaded) return; - const auto versions = APPLICATION->metadataIndex()->get(m_id); + const auto versions = APPLICATION->metadataIndex()->get(uid); if (!versions) return; initialize(versions.get()); - m_loaded = true; + loaded = true; } void setParentContainer(BasePageContainer* container) override @@ -73,13 +73,13 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { } private: - const QString m_id; - const QString m_icon; - const QString m_name; - bool m_loaded = false; + const QString uid; + const QString iconName; + const QString name; + bool loaded = false; }; -InstallLoaderPage* pageCast(BasePage* page) +static InstallLoaderPage* pageCast(BasePage* page) { auto result = dynamic_cast(page); Q_ASSERT(result != nullptr); @@ -87,46 +87,55 @@ InstallLoaderPage* pageCast(BasePage* page) } InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, const QString& uid, QWidget* parent) - : QDialog(parent), m_profile(profile), m_container(new PageContainer(this, QString(), this)), m_buttons(new QDialogButtonBox(this)) + : QDialog(parent), profile(std::move(profile)), container(new PageContainer(this, QString(), this)), buttons(new QDialogButtonBox(this)) { auto layout = new QVBoxLayout(this); - m_container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - layout->addWidget(m_container); + container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + layout->addWidget(container); auto buttonLayout = new QHBoxLayout(this); auto refreshButton = new QPushButton(tr("&Refresh"), this); - connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(m_container->selectedPage())->loadList(); }); + connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); - m_buttons->setOrientation(Qt::Horizontal); - m_buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - buttonLayout->addWidget(m_buttons); + buttons->setOrientation(Qt::Horizontal); + buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonLayout->addWidget(buttons); layout->addLayout(buttonLayout); setWindowTitle(dialogTitle()); - resize(650, 400); + setWindowModality(Qt::WindowModal); + resize(520, 347); - pageCast(m_container->selectedPage())->selectSearch(); - for (BasePage* page : m_container->getPages()) + for (BasePage* page : container->getPages()) { if (page->id() == uid) - m_container->selectPage(page->id()); + container->selectPage(page->id()); + + connect(pageCast(page), &VersionSelectWidget::selectedVersionChanged, this, [this, page] { + if (page->id() == container->selectedPage()->id()) + validate(container->selectedPage()); + }); + } + connect(container, &PageContainer::selectedPageChanged, this, [this](BasePage* previous, BasePage* current) { validate(current); }); + pageCast(container->selectedPage())->selectSearch(); + validate(container->selectedPage()); } QList InstallLoaderDialog::getPages() { return { // Forge - new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, m_profile), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, m_profile), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, profile), // Quilt - new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, m_profile), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, profile), // LiteLoader - new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, m_profile) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, profile) }; } @@ -135,13 +144,18 @@ QString InstallLoaderDialog::dialogTitle() return tr("Install Loader"); } +void InstallLoaderDialog::validate(BasePage* page) +{ + buttons->button(QDialogButtonBox::Ok)->setEnabled(pageCast(page)->selectedVersion() != nullptr); +} + void InstallLoaderDialog::done(int result) { if (result == Accepted) { - auto* page = pageCast(m_container->selectedPage()); + auto* page = pageCast(container->selectedPage()); if (page->selectedVersion()) { - m_profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); - m_profile->resolve(Net::Mode::Online); + profile->setComponentVersion(page->id(), page->selectedVersion()->descriptor()); + profile->resolve(Net::Mode::Online); } } diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index 09d847778..cdcba2b96 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -35,10 +35,11 @@ class InstallLoaderDialog final : public QDialog, public BasePageProvider { QList getPages() override; QString dialogTitle() override; + void validate(BasePage* page); void done(int result) override; private: - std::shared_ptr m_profile; - PageContainer* m_container; - QDialogButtonBox* m_buttons; + std::shared_ptr profile; + PageContainer* container; + QDialogButtonBox* buttons; }; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 0a8a0544c..dbbed36a7 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -147,7 +147,7 @@ BasePage* PageContainer::selectedPage() const return m_currentPage; } -const QList PageContainer::getPages() const +const QList& PageContainer::getPages() const { return m_model->pages(); } diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index bb365c826..eac597232 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -82,7 +82,7 @@ public: bool selectPage(QString pageId) override; BasePage* selectedPage() const override; BasePage* getPage(QString pageId) override; - const QList getPages() const; + const QList& getPages() const; void refreshContainer() override; virtual void setParentContainer(BasePageContainer * container) From 64c591b234cec2519d8a04b32d4b6e85dcf204da Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 3 Jul 2023 20:48:37 +0100 Subject: [PATCH 139/398] Better parent version filtering; handle old fabric :P Signed-off-by: TheKodeToad --- launcher/Filter.cpp | 6 ++++++ launcher/Filter.h | 10 ++++++++++ launcher/ui/dialogs/InstallLoaderDialog.cpp | 17 +++++++++-------- launcher/ui/dialogs/VersionSelectDialog.cpp | 4 ++++ launcher/ui/dialogs/VersionSelectDialog.h | 1 + launcher/ui/pages/instance/VersionPage.cpp | 12 ++---------- launcher/ui/widgets/VersionSelectWidget.cpp | 9 +++++++-- launcher/ui/widgets/VersionSelectWidget.h | 1 + 8 files changed, 40 insertions(+), 20 deletions(-) diff --git a/launcher/Filter.cpp b/launcher/Filter.cpp index c65ca0ceb..f95305977 100644 --- a/launcher/Filter.cpp +++ b/launcher/Filter.cpp @@ -16,6 +16,12 @@ bool ExactFilter::accepts(const QString& value) return value == pattern; } +ExactIfPresentFilter::ExactIfPresentFilter(const QString& pattern) : pattern(pattern) {} +bool ExactIfPresentFilter::accepts(const QString& value) +{ + return value.isEmpty() || value == pattern; +} + RegexpFilter::RegexpFilter(const QString& regexp, bool invert) :invert(invert) { diff --git a/launcher/Filter.h b/launcher/Filter.h index b55067acb..d3cee2d8d 100644 --- a/launcher/Filter.h +++ b/launcher/Filter.h @@ -30,6 +30,16 @@ private: QString pattern; }; +class ExactIfPresentFilter: public Filter +{ + public: + ExactIfPresentFilter(const QString& pattern); + ~ExactIfPresentFilter() override = default; + bool accepts(const QString& value) override; + private: + QString pattern; +}; + class RegexpFilter: public Filter { public: diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 31d6f9ab5..bab5b8350 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -35,15 +35,16 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { InstallLoaderPage(const QString& id, const QString& icon, const QString& name, - // "lightweight" loaders are independent to any game version - const bool lightweight, + const Version& oldestVersion, const std::shared_ptr profile) : VersionSelectWidget(nullptr), uid(id), iconName(icon), name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); - if (!lightweight) - setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + setExactIfPresentFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + + if (oldestVersion != Version() && Version(minecraftVersion) < oldestVersion) + setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); if (const QString currentVersion = profile->getComponentVersion(id); !currentVersion.isNull()) setCurrentVersion(currentVersion); @@ -129,13 +130,13 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c QList InstallLoaderDialog::getPages() { return { // Forge - new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), false, profile), + new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), {}, profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), true, profile), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), Version("1.14"), profile), // Quilt - new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), true, profile), + new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), Version("1.14"), profile), // LiteLoader - new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), false, profile) + new InstallLoaderPage("com.mumfrey.liteloader", "liteloader", tr("LiteLoader"), {}, profile) }; } diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index e45787e4a..9fa3c90f4 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -152,6 +152,10 @@ void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QStri m_versionWidget->setExactFilter(role, filter); } +void VersionSelectDialog::setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter) { + m_versionWidget->setExactIfPresentFilter(role, filter); +} + void VersionSelectDialog::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) { m_versionWidget->setFuzzyFilter(role, filter); diff --git a/launcher/ui/dialogs/VersionSelectDialog.h b/launcher/ui/dialogs/VersionSelectDialog.h index 18a50cdb0..c20a9ed58 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.h +++ b/launcher/ui/dialogs/VersionSelectDialog.h @@ -49,6 +49,7 @@ public: void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); void setExactFilter(BaseVersionList::ModelRoles role, QString filter); + void setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter); void setEmptyString(QString emptyString); void setEmptyErrorString(QString emptyErrorString); void setResizeOn(int column); diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 31e0b9b37..a8e6e9484 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -434,22 +434,14 @@ void VersionPage::on_actionChange_version_triggered() } auto uid = list->uid(); - // FIXME: this is still a horrible HACK. - if (uid == "net.minecraftforge" || uid == "com.mumfrey.liteloader" || uid == "net.fabricmc.fabric-loader" || - uid == "org.quiltmc.quilt-loader") { - InstallLoaderDialog dialog(m_inst->getPackProfile(), uid, this); - dialog.exec(); - m_container->refreshContainer(); - return; - } - VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { vselect.setEmptyString(tr("No intermediary mappings versions are currently available.")); vselect.setEmptyErrorString(tr("Couldn't load or download the intermediary mappings version lists!")); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); } + vselect.setExactIfPresentFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); + auto currentVersion = patch->getVersion(); if(!currentVersion.isEmpty()) { diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index f20dad711..2b22a4a92 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -238,14 +238,19 @@ BaseVersion::Ptr VersionSelectWidget::selectedVersion() const return variant.value(); } +void VersionSelectWidget::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) +{ + m_proxyModel->setFilter(role, new ContainsFilter(filter)); +} + void VersionSelectWidget::setExactFilter(BaseVersionList::ModelRoles role, QString filter) { m_proxyModel->setFilter(role, new ExactFilter(filter)); } -void VersionSelectWidget::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter) +void VersionSelectWidget::setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter) { - m_proxyModel->setFilter(role, new ContainsFilter(filter)); + m_proxyModel->setFilter(role, new ExactIfPresentFilter(filter)); } void VersionSelectWidget::setFilter(BaseVersionList::ModelRoles role, Filter *filter) diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index 624d9a232..598e10591 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -70,6 +70,7 @@ public: void setCurrentVersion(const QString & version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); void setExactFilter(BaseVersionList::ModelRoles role, QString filter); + void setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter); void setFilter(BaseVersionList::ModelRoles role, Filter *filter); void setEmptyString(QString emptyString); void setEmptyErrorString(QString emptyErrorString); From f9578066d6b9d2813e05ad6501935304a787ce52 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Wed, 28 Jun 2023 17:30:11 -0300 Subject: [PATCH 140/398] make "browse" buttons and java pages more consistent Signed-off-by: leo78913 --- launcher/ui/pages/global/ExternalToolsPage.ui | 8 +- launcher/ui/pages/global/JavaPage.ui | 222 +++++++++--------- launcher/ui/pages/global/LauncherPage.ui | 8 +- .../ui/pages/instance/InstanceSettingsPage.ui | 62 ++--- 4 files changed, 150 insertions(+), 150 deletions(-) diff --git a/launcher/ui/pages/global/ExternalToolsPage.ui b/launcher/ui/pages/global/ExternalToolsPage.ui index 3643094df..47c77842a 100644 --- a/launcher/ui/pages/global/ExternalToolsPage.ui +++ b/launcher/ui/pages/global/ExternalToolsPage.ui @@ -47,7 +47,7 @@ - ... + Browse @@ -84,7 +84,7 @@ - ... + Browse @@ -121,7 +121,7 @@ - ... + Browse @@ -166,7 +166,7 @@ - ... + Browse diff --git a/launcher/ui/pages/global/JavaPage.ui b/launcher/ui/pages/global/JavaPage.ui index 6749cbe41..85afd5d65 100644 --- a/launcher/ui/pages/global/JavaPage.ui +++ b/launcher/ui/pages/global/JavaPage.ui @@ -160,117 +160,7 @@ Java Runtime
- - - - - 0 - 0 - - - - &Auto-detect... - - - - - - - - 0 - 0 - - - - JVM arguments: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - &Java path: - - - javaPathTextBox - - - - - - - - 0 - 0 - - - - &Test - - - - - - - - - - - - - 0 - 0 - - - - - 28 - 16777215 - - - - ... - - - - - - - - - - 0 - 0 - - - - If enabled, the launcher will not check if an instance is compatible with the selected Java version. - - - &Skip Java compatibility checks - - - - - - - If enabled, the launcher will not prompt you to choose a Java version if one isn't found. - - - Skip Java &Wizard - - - - + true @@ -289,6 +179,114 @@ + + + + + 0 + 0 + + + + If enabled, the launcher will not check if an instance is compatible with the selected Java version. + + + &Skip Java compatibility checks + + + + + + + + + + 0 + 0 + + + + &Auto-detect... + + + + + + + + 0 + 0 + + + + &Test + + + + + + + + + + 0 + 0 + + + + JVM arguments: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + 0 + 0 + + + + &Java path: + + + javaPathTextBox + + + + + + + + + + + 0 + 0 + + + + Browse + + + + + + + + + If enabled, the launcher will not prompt you to choose a Java version if one isn't found. + + + Skip Java &Wizard + + +
@@ -317,8 +315,6 @@ permGenSpinBox javaBrowseBtn javaPathTextBox - javaDetectBtn - javaTestBtn tabWidget diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index d9116bfcf..7c80c3af1 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -99,7 +99,7 @@ - ... + Browse @@ -109,7 +109,7 @@ - ... + Browse @@ -126,14 +126,14 @@ - ... + Browse - ... + Browse diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 8427965de..277deb2ae 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -61,31 +61,7 @@ false - - - - - - - Auto-detect... - - - - - - - Browse... - - - - - - - Test - - - - + If enabled, the launcher will not check if an instance is compatible with the selected Java version. @@ -95,6 +71,38 @@ + + + + + + + + + Browse + + + + + + + + + + + Auto-detect... + + + + + + + Test + + + + + @@ -674,10 +682,6 @@ openGlobalJavaSettingsButton settingsTabs javaSettingsGroupBox - javaPathTextBox - javaDetectBtn - javaBrowseBtn - javaTestBtn memoryGroupBox minMemSpinBox maxMemSpinBox From e8dc1564b67b9fa64ddae10ad3d0e076f9710787 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Mon, 3 Jul 2023 12:37:27 -0300 Subject: [PATCH 141/398] add _kde_side_panel_view property to page container With this the sidebars look better with the breeze theme Signed-off-by: leo78913 --- launcher/ui/widgets/PageContainer_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/widgets/PageContainer_p.h b/launcher/ui/widgets/PageContainer_p.h index da1a66f46..d469019cf 100644 --- a/launcher/ui/widgets/PageContainer_p.h +++ b/launcher/ui/widgets/PageContainer_p.h @@ -103,6 +103,7 @@ public: setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); setItemDelegate(new PageViewDelegate(this)); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setProperty("_kde_side_panel_view", true); } virtual QSize sizeHint() const From 22327bbe71b271a126521db737101ae07ba26f8d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Jul 2023 18:04:44 +0100 Subject: [PATCH 142/398] Combine launch buttons in Instance window, persist profiler Signed-off-by: TheKodeToad --- launcher/Application.cpp | 21 ++-- launcher/Application.h | 13 +-- launcher/BaseInstance.cpp | 5 +- launcher/BaseInstance.h | 14 ++- launcher/LaunchController.cpp | 10 +- launcher/NullInstance.h | 6 +- launcher/minecraft/MinecraftInstance.cpp | 50 ++++++++- launcher/minecraft/MinecraftInstance.h | 4 +- launcher/ui/InstanceWindow.cpp | 115 ++++++-------------- launcher/ui/InstanceWindow.h | 16 ++- launcher/ui/MainWindow.cpp | 119 ++------------------- launcher/ui/MainWindow.h | 8 +- launcher/ui/MainWindow.ui | 22 +--- launcher/ui/pages/instance/ServersPage.cpp | 4 +- 14 files changed, 143 insertions(+), 264 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1d97a5f2e..625cebd37 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1005,7 +1005,7 @@ void Application::performMainStartupAction() qDebug() << " Launching with account" << m_profileToUse; } - launch(inst, true, false, nullptr, serverToJoin, accountToUse); + launch(inst, true, false, serverToJoin, accountToUse); return; } } @@ -1120,7 +1120,6 @@ void Application::messageReceived(const QByteArray& message) instance, true, false, - nullptr, serverObject, accountObject ); @@ -1187,14 +1186,12 @@ bool Application::openJsonEditor(const QString &filename) } } -bool Application::launch( - InstancePtr instance, - bool online, - bool demo, - BaseProfilerFactory *profiler, - MinecraftServerTargetPtr serverToJoin, - MinecraftAccountPtr accountToUse -) { +bool Application::launch(InstancePtr instance, + bool online, + bool demo, + MinecraftServerTargetPtr serverToJoin, + MinecraftAccountPtr accountToUse) +{ if(m_updateRunning) { qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; @@ -1202,7 +1199,7 @@ bool Application::launch( else if(instance->canLaunch()) { auto & extras = m_instanceExtras[instance->id()]; - auto & window = extras.window; + auto window = extras.window; if(window) { if(!window->saveAll()) @@ -1215,7 +1212,7 @@ bool Application::launch( controller->setInstance(instance); controller->setOnline(online); controller->setDemo(demo); - controller->setProfiler(profiler); + controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get()); controller->setServerToJoin(serverToJoin); controller->setAccountToUse(accountToUse); if(window) diff --git a/launcher/Application.h b/launcher/Application.h index ced0af17d..b911edc18 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -222,14 +222,11 @@ signals: #endif public slots: - bool launch( - InstancePtr instance, - bool online = true, - bool demo = false, - BaseProfilerFactory *profiler = nullptr, - MinecraftServerTargetPtr serverToJoin = nullptr, - MinecraftAccountPtr accountToUse = nullptr - ); + bool launch(InstancePtr instance, + bool online = true, + bool demo = false, + MinecraftServerTargetPtr serverToJoin = nullptr, + MinecraftAccountPtr accountToUse = nullptr); bool kill(InstancePtr instance); void closeCurrentWindow(); diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp index a8fce879c..28b4cb5c3 100644 --- a/launcher/BaseInstance.cpp +++ b/launcher/BaseInstance.cpp @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -101,6 +102,8 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s m_settings->registerSetting("ManagedPackName", ""); m_settings->registerSetting("ManagedPackVersionID", ""); m_settings->registerSetting("ManagedPackVersionName", ""); + + m_settings->registerSetting("Profiler", ""); } QString BaseInstance::getPreLaunchCommand() diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index 83a8064fa..7da4e20b2 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,11 +38,12 @@ #pragma once #include -#include -#include "QObjectPtr.h" #include -#include +#include +#include #include +#include +#include "QObjectPtr.h" #include "settings/SettingsObject.h" @@ -270,6 +272,8 @@ public: virtual bool canEdit() const = 0; virtual bool canExport() const = 0; + virtual void populateLaunchMenu(QMenu* menu) = 0; + bool reloadSettings(); /** @@ -306,6 +310,8 @@ signals: void runningStatusChanged(bool running); + void profilerChanged(); + void statusChanged(Status from, Status to); protected slots: diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 070ee283c..5a79b2530 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -406,22 +407,21 @@ void LaunchController::readyForLaunch() if (!m_profiler->check(&error)) { m_launcher->abort(); - QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't start profiler: %1").arg(error)); emitFailed("Profiler startup failed!"); + QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Profiler check for %1 failed: %2").arg(m_profiler->name(), error)); return; } BaseProfiler *profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this); connect(profilerInstance, &BaseProfiler::readyToLaunch, [this](const QString & message) { - QMessageBox msg; + QMessageBox msg(m_parentWidget); msg.setText(tr("The game launch is delayed until you press the " "button. This is the right time to setup the profiler, as the " "profiler server is running now.\n\n%1").arg(message)); msg.setWindowTitle(tr("Waiting.")); msg.setIcon(QMessageBox::Information); - msg.addButton(tr("Launch"), QMessageBox::AcceptRole); - msg.setModal(true); + msg.addButton(tr("&Launch"), QMessageBox::AcceptRole); msg.exec(); m_launcher->proceed(); }); diff --git a/launcher/NullInstance.h b/launcher/NullInstance.h index 53edfa0b8..b0ec89f42 100644 --- a/launcher/NullInstance.h +++ b/launcher/NullInstance.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -110,6 +111,9 @@ public: { return false; } + void populateLaunchMenu(QMenu* menu) override + { + } QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override { QStringList out; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index aab930de0..d511451e5 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -3,7 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 Jamie Mansfield - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -88,6 +88,8 @@ #include "minecraft/gameoptions/GameOptions.h" #include "minecraft/update/FoldersTask.h" +#include "tools/BaseProfiler.h" + #ifdef Q_OS_LINUX #include "MangoHud.h" #endif @@ -234,6 +236,52 @@ QSet MinecraftInstance::traits() const return profile->getTraits(); } +void MinecraftInstance::populateLaunchMenu(QMenu* menu) +{ + QAction* normalLaunch = menu->addAction(tr("&Launch")); + normalLaunch->setShortcut(QKeySequence::Open); + QAction* normalLaunchOffline = menu->addAction(tr("Launch &Offline")); + normalLaunchOffline->setShortcut(QKeySequence(tr("Ctrl+Shift+O"))); + QAction* normalLaunchDemo = menu->addAction(tr("Launch &Demo")); + normalLaunchDemo->setShortcut(QKeySequence(tr("Ctrl+Alt+O"))); + + normalLaunchDemo->setEnabled(supportsDemo()); + + connect(normalLaunch, &QAction::triggered, [this] { APPLICATION->launch(shared_from_this()); }); + connect(normalLaunchOffline, &QAction::triggered, [this] { APPLICATION->launch(shared_from_this(), false, false); }); + connect(normalLaunchDemo, &QAction::triggered, [this] { APPLICATION->launch(shared_from_this(), false, true); }); + + QString profilersTitle = tr("Profilers"); + menu->addSeparator()->setText(profilersTitle); + + auto profilers = new QActionGroup(menu); + profilers->setExclusive(true); + connect(profilers, &QActionGroup::triggered, [this](QAction* action) { + settings()->set("Profiler", action->data()); + emit profilerChanged(); + }); + + QAction* noProfilerAction = menu->addAction(tr("&No Profiler")); + noProfilerAction->setData(""); + noProfilerAction->setCheckable(true); + noProfilerAction->setChecked(true); + profilers->addAction(noProfilerAction); + + for (auto profiler = APPLICATION->profilers().begin(); profiler != APPLICATION->profilers().end(); profiler++) { + QAction* profilerAction = menu->addAction(profiler.value()->name()); + profilers->addAction(profilerAction); + profilerAction->setData(profiler.key()); + profilerAction->setCheckable(true); + profilerAction->setChecked(settings()->get("Profiler").toString() == profiler.key()); + + QString error; + if (profiler.value()->check(&error)) + profilerAction->setIcon(APPLICATION->getThemedIcon("status-good")); + else + profilerAction->setIcon(APPLICATION->getThemedIcon("status-bad")); + } +} + QString MinecraftInstance::gameRoot() const { QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft")); diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 068b30082..c5ebbb7cb 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -77,6 +77,8 @@ public: return true; } + void populateLaunchMenu(QMenu* menu) override; + ////// Directories and files ////// QString jarModsDir() const; QString resourcePacksDir() const; diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index c62b370fd..350b19079 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,8 +44,6 @@ #include #include -#include "ui/dialogs/CustomMessageBox.h" -#include "ui/dialogs/ProgressDialog.h" #include "ui/widgets/PageContainer.h" #include "InstancePageProvider.h" @@ -83,33 +82,36 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) auto btnHelp = new QPushButton(); btnHelp->setText(tr("Help")); horizontalLayout->addWidget(btnHelp); - connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help())); + connect(btnHelp, &QPushButton::clicked, m_container, &PageContainer::help); auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout->addSpacerItem(spacer); - m_killButton = new QPushButton(); + m_launchButton = new QToolButton(this); + m_launchButton->setText(tr("&Launch")); + m_launchButton->setToolTip(tr("Launch the instance")); + m_launchButton->setPopupMode(QToolButton::MenuButtonPopup); + m_launchButton->setMinimumWidth(80); // HACK!! + horizontalLayout->addWidget(m_launchButton); + connect(m_launchButton, &QPushButton::clicked, this, [this] { APPLICATION->launch(m_instance); }); + + m_killButton = new QPushButton(this); + m_killButton->setText(tr("&Kill")); + m_killButton->setToolTip(tr("Kill the running instance")); horizontalLayout->addWidget(m_killButton); - connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked())); + connect(m_killButton, &QPushButton::clicked, this, [this] { APPLICATION->kill(m_instance); }); - m_launchOfflineButton = new QPushButton(); - horizontalLayout->addWidget(m_launchOfflineButton); - m_launchOfflineButton->setText(tr("Launch Offline")); - - m_launchDemoButton = new QPushButton(); - horizontalLayout->addWidget(m_launchDemoButton); - m_launchDemoButton->setText(tr("Launch Demo")); - - updateLaunchButtons(); - connect(m_launchOfflineButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftOffline_clicked())); - connect(m_launchDemoButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftDemo_clicked())); + updateButtons(); m_closeButton = new QPushButton(); m_closeButton->setText(tr("Close")); horizontalLayout->addWidget(m_closeButton); - connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked())); + connect(m_closeButton, &QPushButton::clicked, this, &QMainWindow::close); m_container->addButtons(horizontalLayout); + + connect(m_instance.get(), &BaseInstance::profilerChanged, this, &InstanceWindow::updateButtons); + connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceWindow::updateButtons); } // restore window state @@ -150,52 +152,18 @@ void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance } } -void InstanceWindow::updateLaunchButtons() +void InstanceWindow::updateButtons() { - if(m_instance->isRunning()) - { - m_launchOfflineButton->setEnabled(false); - m_launchDemoButton->setEnabled(false); - m_killButton->setText(tr("Kill")); - m_killButton->setObjectName("killButton"); - m_killButton->setToolTip(tr("Kill the running instance")); - } - else if(!m_instance->canLaunch()) - { - m_launchOfflineButton->setEnabled(false); - m_launchDemoButton->setEnabled(false); - m_killButton->setText(tr("Launch")); - m_killButton->setObjectName("launchButton"); - m_killButton->setToolTip(tr("Launch the instance")); - m_killButton->setEnabled(false); - } + m_launchButton->setEnabled(m_instance->canLaunch()); + m_killButton->setEnabled(m_instance->isRunning()); + + QMenu *launchMenu = m_launchButton->menu(); + if (launchMenu) + launchMenu->clear(); else - { - m_launchOfflineButton->setEnabled(true); - - // Disable demo-mode if not available. - auto instance = dynamic_cast(m_instance.get()); - if (instance) { - m_launchDemoButton->setEnabled(instance->supportsDemo()); - } - - m_killButton->setText(tr("Launch")); - m_killButton->setObjectName("launchButton"); - m_killButton->setToolTip(tr("Launch the instance")); - } - // NOTE: this is a hack to force the button to recalculate its style - m_killButton->setStyleSheet("/* */"); - m_killButton->setStyleSheet(QString()); -} - -void InstanceWindow::on_btnLaunchMinecraftOffline_clicked() -{ - APPLICATION->launch(m_instance, false, false, nullptr); -} - -void InstanceWindow::on_btnLaunchMinecraftDemo_clicked() -{ - APPLICATION->launch(m_instance, false, true, nullptr); + launchMenu = new QMenu(this); + m_instance->populateLaunchMenu(launchMenu); + m_launchButton->setMenu(launchMenu); } void InstanceWindow::instanceLaunchTaskChanged(shared_qobject_ptr proc) @@ -205,18 +173,13 @@ void InstanceWindow::instanceLaunchTaskChanged(shared_qobject_ptr pr void InstanceWindow::runningStateChanged(bool running) { - updateLaunchButtons(); + updateButtons(); m_container->refreshContainer(); if(running) { selectPage("log"); } } -void InstanceWindow::on_closeButton_clicked() -{ - close(); -} - void InstanceWindow::closeEvent(QCloseEvent *event) { bool proceed = true; @@ -241,18 +204,6 @@ bool InstanceWindow::saveAll() return m_container->saveAll(); } -void InstanceWindow::on_btnKillMinecraft_clicked() -{ - if(m_instance->isRunning()) - { - APPLICATION->kill(m_instance); - } - else - { - APPLICATION->launch(m_instance, true, false, nullptr); - } -} - QString InstanceWindow::instanceId() { return m_instance->id(); @@ -268,10 +219,6 @@ void InstanceWindow::refreshContainer() m_container->refreshContainer(); } -InstanceWindow::~InstanceWindow() -{ -} - bool InstanceWindow::requestClose() { if(m_container->prepareToClose()) diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index 554c4c740..64d9a45ef 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +38,7 @@ #include #include +#include #include "LaunchController.h" #include "launch/LaunchTask.h" @@ -53,7 +55,7 @@ class InstanceWindow : public QMainWindow, public BasePageContainer public: explicit InstanceWindow(InstancePtr proc, QWidget *parent = 0); - virtual ~InstanceWindow(); + virtual ~InstanceWindow() = default; bool selectPage(QString pageId) override; void refreshContainer() override; @@ -71,11 +73,6 @@ signals: private slots: - void on_closeButton_clicked(); - void on_btnKillMinecraft_clicked(); - void on_btnLaunchMinecraftOffline_clicked(); - void on_btnLaunchMinecraftDemo_clicked(); - void instanceLaunchTaskChanged(shared_qobject_ptr proc); void runningStateChanged(bool running); void on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus); @@ -84,7 +81,7 @@ protected: void closeEvent(QCloseEvent *) override; private: - void updateLaunchButtons(); + void updateButtons(); private: shared_qobject_ptr m_proc; @@ -92,7 +89,6 @@ private: bool m_doNotSave = false; PageContainer *m_container = nullptr; QPushButton *m_closeButton = nullptr; + QToolButton *m_launchButton = nullptr; QPushButton *m_killButton = nullptr; - QPushButton *m_launchOfflineButton = nullptr; - QPushButton *m_launchDemoButton = nullptr; }; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 515abf070..a2137dd3f 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -572,93 +572,14 @@ void MainWindow::updateMainToolBar() ui->mainToolBar->setVisible(ui->menuBar->isNativeMenuBar() || !APPLICATION->settings()->get("MenuBarInsteadOfToolBar").toBool()); } -void MainWindow::updateToolsMenu() +void MainWindow::updateLaunchButton() { - bool currentInstanceRunning = m_selectedInstance && m_selectedInstance->isRunning(); - - ui->actionLaunchInstance->setDisabled(!m_selectedInstance || currentInstanceRunning); - ui->actionLaunchInstanceOffline->setDisabled(!m_selectedInstance || currentInstanceRunning); - ui->actionLaunchInstanceDemo->setDisabled(!m_selectedInstance || currentInstanceRunning); - QMenu *launchMenu = ui->actionLaunchInstance->menu(); if (launchMenu) - { launchMenu->clear(); - } else - { launchMenu = new QMenu(this); - } - QAction *normalLaunch = launchMenu->addAction(tr("Launch")); - normalLaunch->setShortcut(QKeySequence::Open); - QAction *normalLaunchOffline = launchMenu->addAction(tr("Launch Offline")); - normalLaunchOffline->setShortcut(QKeySequence(tr("Ctrl+Shift+O"))); - QAction *normalLaunchDemo = launchMenu->addAction(tr("Launch Demo")); - normalLaunchDemo->setShortcut(QKeySequence(tr("Ctrl+Alt+O"))); - if (m_selectedInstance) - { - normalLaunch->setEnabled(m_selectedInstance->canLaunch()); - normalLaunchOffline->setEnabled(m_selectedInstance->canLaunch()); - normalLaunchDemo->setEnabled(m_selectedInstance->canLaunch()); - - connect(normalLaunch, &QAction::triggered, [this]() { - APPLICATION->launch(m_selectedInstance, true, false); - }); - connect(normalLaunchOffline, &QAction::triggered, [this]() { - APPLICATION->launch(m_selectedInstance, false, false); - }); - connect(normalLaunchDemo, &QAction::triggered, [this]() { - APPLICATION->launch(m_selectedInstance, false, true); - }); - } - else - { - normalLaunch->setDisabled(true); - normalLaunchOffline->setDisabled(true); - normalLaunchDemo->setDisabled(true); - } - - // Disable demo-mode if not available. - auto instance = dynamic_cast(m_selectedInstance.get()); - if (instance) { - normalLaunchDemo->setEnabled(instance->supportsDemo()); - } - - QString profilersTitle = tr("Profilers"); - launchMenu->addSeparator()->setText(profilersTitle); - for (auto profiler : APPLICATION->profilers().values()) - { - QAction *profilerAction = launchMenu->addAction(profiler->name()); - QAction *profilerOfflineAction = launchMenu->addAction(tr("%1 Offline").arg(profiler->name())); - QString error; - if (!profiler->check(&error)) - { - profilerAction->setDisabled(true); - profilerOfflineAction->setDisabled(true); - QString profilerToolTip = tr("Profiler not setup correctly. Go into settings, \"External Tools\"."); - profilerAction->setToolTip(profilerToolTip); - profilerOfflineAction->setToolTip(profilerToolTip); - } - else if (m_selectedInstance) - { - profilerAction->setEnabled(m_selectedInstance->canLaunch()); - profilerOfflineAction->setEnabled(m_selectedInstance->canLaunch()); - - connect(profilerAction, &QAction::triggered, [this, profiler]() - { - APPLICATION->launch(m_selectedInstance, true, false, profiler.get()); - }); - connect(profilerOfflineAction, &QAction::triggered, [this, profiler]() - { - APPLICATION->launch(m_selectedInstance, false, false, profiler.get()); - }); - } - else - { - profilerAction->setDisabled(true); - profilerOfflineAction->setDisabled(true); - } - } + m_selectedInstance->populateLaunchMenu(launchMenu); ui->actionLaunchInstance->setMenu(launchMenu); } @@ -1268,7 +1189,7 @@ void MainWindow::globalSettingsClosed() proxymodel->invalidate(); proxymodel->sort(0); updateMainToolBar(); - updateToolsMenu(); + updateLaunchButton(); updateThemeMenu(); updateStatusCenter(); // This needs to be done to prevent UI elements disappearing in the event the config is changed @@ -1471,22 +1392,6 @@ void MainWindow::activateInstance(InstancePtr instance) APPLICATION->launch(instance); } -void MainWindow::on_actionLaunchInstanceOffline_triggered() -{ - if (m_selectedInstance) - { - APPLICATION->launch(m_selectedInstance, false); - } -} - -void MainWindow::on_actionLaunchInstanceDemo_triggered() -{ - if (m_selectedInstance) - { - APPLICATION->launch(m_selectedInstance, false, true); - } -} - void MainWindow::on_actionKillInstance_triggered() { if(m_selectedInstance && m_selectedInstance->isRunning()) @@ -1633,6 +1538,7 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & } if (m_selectedInstance) { disconnect(m_selectedInstance.get(), &BaseInstance::runningStatusChanged, this, &MainWindow::refreshCurrentInstance); + disconnect(m_selectedInstance.get(), &BaseInstance::profilerChanged, this, &MainWindow::refreshCurrentInstance); } QString id = current.data(InstanceList::InstanceIDRole).toString(); m_selectedInstance = APPLICATION->instances()->getInstanceById(id); @@ -1641,14 +1547,6 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & ui->instanceToolBar->setEnabled(true); setInstanceActionsEnabled(true); ui->actionLaunchInstance->setEnabled(m_selectedInstance->canLaunch()); - ui->actionLaunchInstanceOffline->setEnabled(m_selectedInstance->canLaunch()); - ui->actionLaunchInstanceDemo->setEnabled(m_selectedInstance->canLaunch()); - - // Disable demo-mode if not available. - auto instance = dynamic_cast(m_selectedInstance.get()); - if (instance) { - ui->actionLaunchInstanceDemo->setEnabled(instance->supportsDemo()); - } ui->actionKillInstance->setEnabled(m_selectedInstance->isRunning()); ui->actionExportInstance->setEnabled(m_selectedInstance->canExport()); @@ -1657,19 +1555,18 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & updateStatusCenter(); updateInstanceToolIcon(m_selectedInstance->iconKey()); - updateToolsMenu(); + updateLaunchButton(); APPLICATION->settings()->set("SelectedInstance", m_selectedInstance->id()); connect(m_selectedInstance.get(), &BaseInstance::runningStatusChanged, this, &MainWindow::refreshCurrentInstance); + connect(m_selectedInstance.get(), &BaseInstance::profilerChanged, this, &MainWindow::refreshCurrentInstance); } else { ui->instanceToolBar->setEnabled(false); setInstanceActionsEnabled(false); ui->actionLaunchInstance->setEnabled(false); - ui->actionLaunchInstanceOffline->setEnabled(false); - ui->actionLaunchInstanceDemo->setEnabled(false); ui->actionKillInstance->setEnabled(false); APPLICATION->settings()->set("SelectedInstance", QString()); selectionBad(); @@ -1700,7 +1597,7 @@ void MainWindow::selectionBad() statusBar()->clearMessage(); ui->instanceToolBar->setEnabled(false); setInstanceActionsEnabled(false); - updateToolsMenu(); + updateLaunchButton(); renameButton->setText(tr("Rename Instance")); updateInstanceToolIcon("grass"); @@ -1769,7 +1666,7 @@ void MainWindow::setInstanceActionsEnabled(bool enabled) ui->actionCreateInstanceShortcut->setEnabled(enabled); } -void MainWindow::refreshCurrentInstance(bool running) +void MainWindow::refreshCurrentInstance() { auto current = view->selectionModel()->currentIndex(); instanceChanged(current, current); diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 3bb20c4a4..7814e5b1f 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -143,10 +143,6 @@ private slots: void on_actionLaunchInstance_triggered(); - void on_actionLaunchInstanceOffline_triggered(); - - void on_actionLaunchInstanceDemo_triggered(); - void on_actionKillInstance_triggered(); void on_actionDeleteInstance_triggered(); @@ -175,7 +171,7 @@ private slots: void updateMainToolBar(); - void updateToolsMenu(); + void updateLaunchButton(); void updateThemeMenu(); @@ -210,7 +206,7 @@ private slots: void keyReleaseEvent(QKeyEvent *event) override; #endif - void refreshCurrentInstance(bool running); + void refreshCurrentInstance(); private: void retranslateUi(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 113dfc1e0..bc1edf394 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -435,22 +435,6 @@ Ctrl+D - - - Launch &Offline - - - Launch the selected instance in offline mode. - - - - - Launch &Demo - - - Launch the selected instance in demo mode. - - @@ -465,7 +449,8 @@ - + + .. Prism Launcher (zip) @@ -473,7 +458,8 @@ - + + .. Modrinth (mrpack) diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index 4b1fa08a3..5e899a11f 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -3,7 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -835,7 +835,7 @@ void ServersPage::on_actionMove_Down_triggered() void ServersPage::on_actionJoin_triggered() { const auto &address = m_model->at(currentServer)->m_address; - APPLICATION->launch(m_inst, true, false, nullptr, std::make_shared(MinecraftServerTarget::parse(address))); + APPLICATION->launch(m_inst, true, false, std::make_shared(MinecraftServerTarget::parse(address))); } #include "ServersPage.moc" From 440dcdf02206e582814f7fdcc58c9b4755d8d3cc Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Jul 2023 18:31:59 +0100 Subject: [PATCH 143/398] Import QActionGroup properly :P Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index d511451e5..30f41de37 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -90,6 +90,8 @@ #include "tools/BaseProfiler.h" +#include + #ifdef Q_OS_LINUX #include "MangoHud.h" #endif From 4c25e3ce75158b6a17fafd60849621f5e0338fc9 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Jul 2023 21:04:21 +0100 Subject: [PATCH 144/398] Add keyboard shortcut to Kill action Signed-off-by: TheKodeToad --- launcher/ui/InstanceWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index 350b19079..78580bcb9 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -98,6 +98,7 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) m_killButton = new QPushButton(this); m_killButton->setText(tr("&Kill")); m_killButton->setToolTip(tr("Kill the running instance")); + m_killButton->setShortcut(QKeySequence(tr("Ctrl+K"))); horizontalLayout->addWidget(m_killButton); connect(m_killButton, &QPushButton::clicked, this, [this] { APPLICATION->kill(m_instance); }); From ec85266860b7503b24ff3840fb6bf74588acc7c8 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 7 Jul 2023 12:18:04 +0100 Subject: [PATCH 145/398] Memory leak fixes Signed-off-by: TheKodeToad --- launcher/ui/InstanceWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index 78580bcb9..ac8454c7e 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -75,11 +75,11 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) // Add custom buttons to the page container layout. { - auto horizontalLayout = new QHBoxLayout(); + auto horizontalLayout = new QHBoxLayout(this); horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); horizontalLayout->setContentsMargins(6, -1, 6, -1); - auto btnHelp = new QPushButton(); + auto btnHelp = new QPushButton(this); btnHelp->setText(tr("Help")); horizontalLayout->addWidget(btnHelp); connect(btnHelp, &QPushButton::clicked, m_container, &PageContainer::help); @@ -104,7 +104,7 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) updateButtons(); - m_closeButton = new QPushButton(); + m_closeButton = new QPushButton(this); m_closeButton->setText(tr("Close")); horizontalLayout->addWidget(m_closeButton); connect(m_closeButton, &QPushButton::clicked, this, &QMainWindow::close); From 3154c2644ab51314d979dffef75a1b66e4113281 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Fri, 7 Jul 2023 10:29:11 -0300 Subject: [PATCH 146/398] enable tear off on widebar context menu Signed-off-by: leo78913 --- launcher/ui/widgets/WideBar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index ac34e3aaa..ab73b7c97 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -195,8 +195,10 @@ static void copyAction(QAction* from, QAction* to) void WideBar::showVisibilityMenu(QPoint const& position) { - if (!m_bar_menu) + if (!m_bar_menu) { m_bar_menu = std::make_unique(this); + m_bar_menu->setTearOffEnabled(true); + } if (m_menu_state == MenuState::Dirty) { for (auto* old_action : m_bar_menu->actions()) From d1cceac7d129c83e41bc3db4700c720b412c88bc Mon Sep 17 00:00:00 2001 From: leo78913 Date: Fri, 7 Jul 2023 12:36:57 -0300 Subject: [PATCH 147/398] disable hiding enable and name columns on folder models Signed-off-by: leo78913 --- launcher/minecraft/mod/ModFolderModel.cpp | 1 + launcher/minecraft/mod/ResourceFolderModel.cpp | 2 ++ launcher/minecraft/mod/ResourceFolderModel.h | 1 + launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/TexturePackFolderModel.cpp | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index af98d8348..2db454e38 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -61,6 +61,7 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER}; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; + m_columnsHideable = { false, true, false, true, true, true }; } QVariant ModFolderModel::data(const QModelIndex &index, int role) const diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 7700fd36b..18b91d4d3 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -550,6 +550,8 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) menu->addSeparator()->setText(tr("Show / Hide Columns")); for (int col = 0; col < columnCount(); ++col) { + // Skip creating actions for columns that should not be hidden + if (!m_columnsHideable.at(col)) continue; auto act = new QAction(menu); setupHeaderAction(act, col); diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index eb1d7c4f6..bf3febcba 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -202,6 +202,7 @@ class ResourceFolderModel : public QAbstractListModel { QStringList m_column_names = {"Enable", "Name", "Last Modified"}; QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")}; QList m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents }; + QList m_columnsHideable = { false, false, true }; bool m_can_interact = true; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 41455599b..c8770d54f 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -54,7 +54,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstanc m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE}; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; - + m_columnsHideable = { false, true, false, true, true }; } QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 531a70232..28fe0a46a 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -49,6 +49,7 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE }; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents}; + m_columnsHideable = { false, true, false, true }; } From 149bc8e9ce1be5edf93de4a4d63b93129ad321b8 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 28 May 2023 11:54:32 -0700 Subject: [PATCH 148/398] cleanup: pull out data object so I'm not repeating myself Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/MainWindow.cpp | 22 ++++++++++---------- launcher/ui/pages/modplatform/ImportPage.cpp | 17 ++++++++------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index bc62f9521..25d39c85f 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1085,31 +1085,31 @@ void MainWindow::processURLs(QList urls) QString resource_name; - connect(job.get(), &Task::failed, this, [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(job.get(), &Task::succeeded, this, [this, array, addonId, fileId, &dl_url, &resource_name] { + connect(job.get(), &Task::succeeded, this, [this, array, addonId, fileId, &dl_url, &resource_name] { qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); auto doc = Json::requireDocument(*array); + auto data = Json::ensureObject(Json::ensureObject(doc.object()), "data"); // No way to find out if it's a mod or a modpack before here // And also we need to check if it ends with .zip, instead of any better way - auto fileName = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "fileName"); - + auto fileName = Json::ensureString(data, "fileName"); + // Have to use ensureString then use QUrl to get proper url encoding - dl_url = QUrl(Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", - "", "downloadUrl")); + dl_url = QUrl(Json::ensureString(data, "downloadUrl", "", "downloadUrl")); if (!dl_url.isValid()) { - CustomMessageBox::selectable(this, tr("Error"), tr("The modpack, mod, or resource is blocked for third-parties! Please download it manually at: \n%1").arg(dl_url.toDisplayString()), - QMessageBox::Critical) + CustomMessageBox::selectable( + this, tr("Error"), + tr("The modpack, mod, or resource %1 is blocked for third-parties! Please download it manually.").arg(fileName), + QMessageBox::Critical) ->show(); return; } QFileInfo dl_file(dl_url.fileName()); - resource_name = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "displayName", - dl_file.completeBaseName(), "displayName"); + resource_name = Json::ensureString(data, "displayName", dl_file.completeBaseName(), "displayName"); }); - + { // drop stack ProgressDialog dlUrlDialod(this); dlUrlDialod.setSkipButton(true, tr("Abort")); diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 1e540cf21..67dfbf457 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -144,23 +144,24 @@ void ImportPage::updateState() connect(job.get(), &NetJob::succeeded, this, [this, array, addonId, fileId] { qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); auto doc = Json::requireDocument(*array); + auto data = Json::ensureObject(Json::ensureObject(doc.object()), "data"); // No way to find out if it's a mod or a modpack before here // And also we need to check if it ends with .zip, instead of any better way - auto fileName = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "fileName"); + auto fileName = Json::ensureString(data, "fileName"); if (fileName.endsWith(".zip")) { // Have to use ensureString then use QUrl to get proper url encoding - auto dl_url = QUrl( - Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "downloadUrl", "", "downloadUrl")); + auto dl_url = QUrl(Json::ensureString(data, "downloadUrl", "", "downloadUrl")); if (!dl_url.isValid()) { - CustomMessageBox::selectable(this, tr("Error"), tr("The modpack is blocked ! Please download it manually"), - QMessageBox::Critical) + CustomMessageBox::selectable( + this, tr("Error"), + tr("The modpack %1 is blocked for third-parties! Please download it manually.").arg(fileName), + QMessageBox::Critical) ->show(); return; } QFileInfo dl_file(dl_url.fileName()); - QString pack_name = Json::ensureString(Json::ensureObject(Json::ensureObject(doc.object()), "data"), "displayName", - dl_file.completeBaseName(), "displayName"); + QString pack_name = Json::ensureString(data, "displayName", dl_file.completeBaseName(), "displayName"); QMap extra_info; extra_info.insert("pack_id", addonId); @@ -201,7 +202,7 @@ void ImportPage::setUrl(const QString& url) } void ImportPage::setExtraInfo(const QMap& extra_info) { - m_extra_info = QMap(extra_info); // copy + m_extra_info = extra_info; updateState(); } From 6d5a2ceefe7f842dd6872b6a38a355bc1b185fb3 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 11 Jul 2023 21:45:23 -0700 Subject: [PATCH 149/398] fix(flameapi): getFile use shared_ptr Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/flame/FlameAPI.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 66eba4ff3..485d67363 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -202,13 +202,12 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, std::shared_ptrresponse) const { auto netJob = makeShared(QString("Flame::GetFile"), APPLICATION->network()); netJob->addNetAction( Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), response)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); QObject::connect(netJob.get(), &NetJob::failed, [addonId, fileId] { qDebug() << "Flame API file failure" << addonId << fileId; }); return netJob; From 1208300ddfc03b409dca7a3b1b0bf5ab8715ba1a Mon Sep 17 00:00:00 2001 From: leo78913 Date: Wed, 12 Jul 2023 10:57:30 -0300 Subject: [PATCH 150/398] i forgor to change skin upload browse button Signed-off-by: leo78913 --- launcher/ui/dialogs/SkinUploadDialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/SkinUploadDialog.ui b/launcher/ui/dialogs/SkinUploadDialog.ui index c7b166455..2c81a7fed 100644 --- a/launcher/ui/dialogs/SkinUploadDialog.ui +++ b/launcher/ui/dialogs/SkinUploadDialog.ui @@ -42,7 +42,7 @@ - ... + Browse From cebb4dd17ae9bfab35210250ab7a5484c644abb0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 20:39:53 +0300 Subject: [PATCH 151/398] made the number of concurrent tasks configurable Signed-off-by: Trial97 --- launcher/Application.cpp | 2 ++ launcher/modplatform/EnsureMetadataTask.cpp | 2 +- .../modplatform/flame/FlamePackExportTask.cpp | 2 +- .../modrinth/ModrinthCheckUpdate.cpp | 2 +- launcher/tasks/ConcurrentTask.h | 5 +++- launcher/ui/dialogs/BlockedModsDialog.cpp | 4 ++-- launcher/ui/pages/global/LauncherPage.cpp | 4 ++++ launcher/ui/pages/global/LauncherPage.ui | 23 +++++++++++++++++++ 8 files changed, 38 insertions(+), 6 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 5aa9efc4a..e427eebdc 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -529,6 +529,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("MenuBarInsteadOfToolBar", false); + m_settings->registerSetting("NumberOfConcurrentTasks", 6); + QString defaultMonospace; int defaultSize = 11; #ifdef Q_OS_WIN32 diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index c3eadd06d..6977c1128 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -33,7 +33,7 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource EnsureMetadataTask::EnsureMetadataTask(QList& mods, QDir dir, ModPlatform::ResourceProvider prov) : Task(nullptr), m_index_dir(dir), m_provider(prov), m_current_task(nullptr) { - m_hashing_task.reset(new ConcurrentTask(this, "MakeHashesTask", 10)); + m_hashing_task.reset(new ConcurrentTask(this, "MakeHashesTask")); for (auto* mod : mods) { auto hash_task = createNewHash(mod); if (!hash_task) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index ac0da2142..48ddddf70 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -108,7 +108,7 @@ void FlamePackExportTask::collectHashes() setStatus(tr("Finding file hashes...")); setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); - ConcurrentTask::Ptr hashingTask(new ConcurrentTask(this, "MakeHashesTask", 10)); + ConcurrentTask::Ptr hashingTask(new ConcurrentTask(this, "MakeHashesTask")); task.reset(hashingTask); for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index a7c22832a..3b0528f0d 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -39,7 +39,7 @@ void ModrinthCheckUpdate::executeTask() QStringList hashes; auto best_hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first(); - ConcurrentTask hashing_task(this, "MakeModrinthHashesTask", 10); + ConcurrentTask hashing_task(this, "MakeModrinthHashesTask"); for (auto* mod : m_mods) { if (!mod->enabled()) { emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!")); diff --git a/launcher/tasks/ConcurrentTask.h b/launcher/tasks/ConcurrentTask.h index 6325fc9e7..7130ca3a9 100644 --- a/launcher/tasks/ConcurrentTask.h +++ b/launcher/tasks/ConcurrentTask.h @@ -41,6 +41,7 @@ #include #include +#include "Application.h" #include "tasks/Task.h" class ConcurrentTask : public Task { @@ -48,7 +49,9 @@ class ConcurrentTask : public Task { public: using Ptr = shared_qobject_ptr; - explicit ConcurrentTask(QObject* parent = nullptr, QString task_name = "", int max_concurrent = 6); + explicit ConcurrentTask(QObject* parent = nullptr, + QString task_name = "", + int max_concurrent = APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); ~ConcurrentTask() override; bool canAbort() const override { return true; } diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index fdfae5973..ebb136ede 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -44,7 +44,7 @@ BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods) : QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods) { - m_hashing_task = shared_qobject_ptr(new ConcurrentTask(this, "MakeHashesTask", 10)); + m_hashing_task = shared_qobject_ptr(new ConcurrentTask(this, "MakeHashesTask")); connect(m_hashing_task.get(), &Task::finished, this, &BlockedModsDialog::hashTaskFinished); ui->setupUi(this); @@ -313,7 +313,7 @@ bool BlockedModsDialog::checkValidPath(QString path) // efectivly compare two strings ignoring all separators and case auto laxCompare = [](QString fsfilename, QString metadataFilename) { // allowed character seperators - QList allowedSeperators = { '-', '+', '.' , '_'}; + QList allowedSeperators = { '-', '+', '.', '_' }; // copy in lowercase auto fsName = fsfilename.toLower(); diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 816dde723..9d62258ac 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -201,6 +201,8 @@ void LauncherPage::applySettings() s->set("MenuBarInsteadOfToolBar", ui->preferMenuBarCheckBox->isChecked()); + s->set("NumberOfConcurrentTasks", ui->numberOfConcurrentTasksSpinBox->value()); + // Console settings s->set("ShowConsole", ui->showConsoleCheck->isChecked()); s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked()); @@ -251,6 +253,8 @@ void LauncherPage::loadSettings() #endif ui->preferMenuBarCheckBox->setChecked(s->get("MenuBarInsteadOfToolBar").toBool()); + ui->numberOfConcurrentTasksSpinBox->setValue(s->get("NumberOfConcurrentTasks").toInt()); + // Console settings ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool()); ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool()); diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 26408f44f..33ad39442 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -189,6 +189,29 @@ + + + + Miscellaneous + + + + + + Number of concurrent tasks + + + + + + + 1 + + + + + + From db9f5f44e08dae27578f0d74e5092f47e40a1216 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 22:26:22 +0300 Subject: [PATCH 152/398] Split in two the options Signed-off-by: Trial97 --- launcher/Application.cpp | 3 ++- launcher/minecraft/mod/ResourceFolderModel.cpp | 1 + launcher/modplatform/EnsureMetadataTask.cpp | 3 ++- .../modplatform/flame/FlamePackExportTask.cpp | 4 +++- .../modrinth/ModrinthCheckUpdate.cpp | 2 +- launcher/net/NetJob.cpp | 5 +++++ launcher/net/NetJob.h | 2 +- launcher/tasks/ConcurrentTask.h | 8 ++++---- launcher/ui/dialogs/BlockedModsDialog.cpp | 3 ++- launcher/ui/dialogs/ModUpdateDialog.cpp | 17 ++++++++++------- launcher/ui/pages/global/LauncherPage.cpp | 2 ++ launcher/ui/pages/global/LauncherPage.ui | 14 ++++++++++++++ launcher/ui/pages/instance/ModFolderPage.cpp | 4 ++-- launcher/ui/pages/instance/ResourcePackPage.cpp | 3 ++- launcher/ui/pages/instance/ShaderPackPage.cpp | 2 +- launcher/ui/pages/instance/TexturePackPage.cpp | 3 ++- launcher/ui/pages/modplatform/ResourceModel.cpp | 1 + 17 files changed, 55 insertions(+), 22 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index e427eebdc..8f52c41cf 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -529,7 +529,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->registerSetting("MenuBarInsteadOfToolBar", false); - m_settings->registerSetting("NumberOfConcurrentTasks", 6); + m_settings->registerSetting("NumberOfConcurrentTasks", 10); + m_settings->registerSetting("NumberOfConcurrentDownloads", 6); QString defaultMonospace; int defaultSize = 11; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 39a61067e..e2aa957be 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -33,6 +33,7 @@ ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObje connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &ResourceFolderModel::directoryChanged); connect(&m_helper_thread_task, &ConcurrentTask::finished, this, [this] { m_helper_thread_task.clear(); }); + m_helper_thread_task.setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); } ResourceFolderModel::~ResourceFolderModel() diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index 6977c1128..a9ad22581 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -3,6 +3,7 @@ #include #include +#include "Application.h" #include "Json.h" #include "minecraft/mod/Mod.h" @@ -33,7 +34,7 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource EnsureMetadataTask::EnsureMetadataTask(QList& mods, QDir dir, ModPlatform::ResourceProvider prov) : Task(nullptr), m_index_dir(dir), m_provider(prov), m_current_task(nullptr) { - m_hashing_task.reset(new ConcurrentTask(this, "MakeHashesTask")); + m_hashing_task.reset(new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); for (auto* mod : mods) { auto hash_task = createNewHash(mod); if (!hash_task) diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 48ddddf70..b0e5638d9 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "Application.h" #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" @@ -108,7 +109,8 @@ void FlamePackExportTask::collectHashes() setStatus(tr("Finding file hashes...")); setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); - ConcurrentTask::Ptr hashingTask(new ConcurrentTask(this, "MakeHashesTask")); + ConcurrentTask::Ptr hashingTask( + new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); task.reset(hashingTask); for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 3b0528f0d..c1f83bbc5 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -39,7 +39,7 @@ void ModrinthCheckUpdate::executeTask() QStringList hashes; auto best_hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first(); - ConcurrentTask hashing_task(this, "MakeModrinthHashesTask"); + ConcurrentTask hashing_task(this, "MakeModrinthHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); for (auto* mod : m_mods) { if (!mod->enabled()) { emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!")); diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index 3869316e3..b99c5acb0 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -36,6 +36,11 @@ */ #include "NetJob.h" +#include "Application.h" + +NetJob::NetJob(QString job_name, shared_qobject_ptr network) + : ConcurrentTask(nullptr, job_name, APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()), m_network(network) +{} auto NetJob::addNetAction(NetAction::Ptr action) -> bool { diff --git a/launcher/net/NetJob.h b/launcher/net/NetJob.h index 764cec18b..1c4337ec6 100644 --- a/launcher/net/NetJob.h +++ b/launcher/net/NetJob.h @@ -52,7 +52,7 @@ class NetJob : public ConcurrentTask { public: using Ptr = shared_qobject_ptr; - explicit NetJob(QString job_name, shared_qobject_ptr network) : ConcurrentTask(nullptr, job_name), m_network(network) {} + explicit NetJob(QString job_name, shared_qobject_ptr network); ~NetJob() override = default; void startNext() override; diff --git a/launcher/tasks/ConcurrentTask.h b/launcher/tasks/ConcurrentTask.h index 7130ca3a9..1c333ce02 100644 --- a/launcher/tasks/ConcurrentTask.h +++ b/launcher/tasks/ConcurrentTask.h @@ -41,7 +41,6 @@ #include #include -#include "Application.h" #include "tasks/Task.h" class ConcurrentTask : public Task { @@ -49,11 +48,12 @@ class ConcurrentTask : public Task { public: using Ptr = shared_qobject_ptr; - explicit ConcurrentTask(QObject* parent = nullptr, - QString task_name = "", - int max_concurrent = APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); + explicit ConcurrentTask(QObject* parent = nullptr, QString task_name = "", int max_concurrent = 6); ~ConcurrentTask() override; + // safe to call before starting the task + void setMaxConcurrent(int max_concurrent) { m_total_max_size = max_concurrent; } + bool canAbort() const override { return true; } inline auto isMultiStep() const -> bool override { return totalSize() > 1; }; diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index ebb136ede..5a1a2f80e 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -44,7 +44,8 @@ BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods) : QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods) { - m_hashing_task = shared_qobject_ptr(new ConcurrentTask(this, "MakeHashesTask")); + m_hashing_task = shared_qobject_ptr( + new ConcurrentTask(this, "MakeHashesTask", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())); connect(m_hashing_task.get(), &Task::finished, this, &BlockedModsDialog::hashTaskFinished); ui->setupUi(this); diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 8618b9240..d08c2898f 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -43,7 +43,8 @@ ModUpdateDialog::ModUpdateDialog(QWidget* parent, , m_parent(parent) , m_mod_model(mods) , m_candidates(search_for) - , m_second_try_metadata(new ConcurrentTask()) + , m_second_try_metadata( + new ConcurrentTask(nullptr, "Second Metadata Search", APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt())) , m_instance(instance) { ReviewMessageBox::setGeometry(0, 0, 800, 600); @@ -89,15 +90,17 @@ void ModUpdateDialog::checkCandidates() if (!m_modrinth_to_update.empty()) { m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, m_mod_model)); - connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_modrinth_check_task); } if (!m_flame_to_update.empty()) { m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loaders, m_mod_model)); - connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_flame_check_task); } @@ -162,7 +165,7 @@ void ModUpdateDialog::checkCandidates() if (!recover_url.isEmpty()) //: %1 is the link to download it manually text += tr("Possible solution: Getting the latest version manually:
%1
") - .arg(QString("%1").arg(recover_url.toString())); + .arg(QString("%1").arg(recover_url.toString())); text += "
"; } @@ -342,7 +345,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R } else { QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") }; - m_failed_metadata.append({mod, reason}); + m_failed_metadata.append({ mod, reason }); } } diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 9d62258ac..86597a5e4 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -202,6 +202,7 @@ void LauncherPage::applySettings() s->set("MenuBarInsteadOfToolBar", ui->preferMenuBarCheckBox->isChecked()); s->set("NumberOfConcurrentTasks", ui->numberOfConcurrentTasksSpinBox->value()); + s->set("NumberOfConcurrentDownloads", ui->numberOfConcurrentDownloadsSpinBox->value()); // Console settings s->set("ShowConsole", ui->showConsoleCheck->isChecked()); @@ -254,6 +255,7 @@ void LauncherPage::loadSettings() ui->preferMenuBarCheckBox->setChecked(s->get("MenuBarInsteadOfToolBar").toBool()); ui->numberOfConcurrentTasksSpinBox->setValue(s->get("NumberOfConcurrentTasks").toInt()); + ui->numberOfConcurrentDownloadsSpinBox->setValue(s->get("NumberOfConcurrentDownloads").toInt()); // Console settings ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool()); diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 33ad39442..11c59ab78 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -209,6 +209,20 @@
+ + + + Number of concurrent downloads + + + + + + + 1 + + + diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index cef292bd9..a8ce68c56 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -166,7 +166,7 @@ void ModFolderPage::installMods() ResourceDownload::ModDownloadDialog mdownload(this, m_model, m_instance); if (mdownload.exec()) { - ConcurrentTask* tasks = new ConcurrentTask(this); + auto tasks = new ConcurrentTask(this, "Download Mods", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); @@ -225,7 +225,7 @@ void ModFolderPage::updateMods() } if (update_dialog.exec()) { - ConcurrentTask* tasks = new ConcurrentTask(this); + auto tasks = new ConcurrentTask(this, "Download Mods", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp index 12b371df4..cba80142a 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.cpp +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -72,7 +72,8 @@ void ResourcePackPage::downloadRPs() ResourceDownload::ResourcePackDownloadDialog mdownload(this, std::static_pointer_cast(m_model), m_instance); if (mdownload.exec()) { - auto tasks = new ConcurrentTask(this); + auto tasks = + new ConcurrentTask(this, "Download Resource Pack", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); diff --git a/launcher/ui/pages/instance/ShaderPackPage.cpp b/launcher/ui/pages/instance/ShaderPackPage.cpp index dc8b0a05b..40366a1be 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.cpp +++ b/launcher/ui/pages/instance/ShaderPackPage.cpp @@ -65,7 +65,7 @@ void ShaderPackPage::downloadShaders() ResourceDownload::ShaderPackDownloadDialog mdownload(this, std::static_pointer_cast(m_model), m_instance); if (mdownload.exec()) { - auto tasks = new ConcurrentTask(this); + auto tasks = new ConcurrentTask(this, "Download Shaders", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp index e477ceda3..bc07d495c 100644 --- a/launcher/ui/pages/instance/TexturePackPage.cpp +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -74,7 +74,8 @@ void TexturePackPage::downloadTPs() ResourceDownload::TexturePackDownloadDialog mdownload(this, std::static_pointer_cast(m_model), m_instance); if (mdownload.exec()) { - auto tasks = new ConcurrentTask(this); + auto tasks = + new ConcurrentTask(this, "Download Texture Packs", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); connect(tasks, &Task::failed, [this, tasks](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); tasks->deleteLater(); diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 49405a02b..e0b663522 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -31,6 +31,7 @@ QHash ResourceModel::s_running_models; ResourceModel::ResourceModel(ResourceAPI* api) : QAbstractListModel(), m_api(api) { s_running_models.insert(this, true); + m_current_info_job.setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); } ResourceModel::~ResourceModel() From 149b6d59cf848a3b3cd50b3aee1c112e9c47e633 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Jul 2023 23:22:11 +0300 Subject: [PATCH 153/398] fixed tests Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 +++ launcher/minecraft/mod/ResourceFolderModel.cpp | 3 +++ launcher/ui/pages/modplatform/ResourceModel.cpp | 2 ++ 3 files changed, 8 insertions(+) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index af3bc28e3..ea8b1b841 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1094,6 +1094,9 @@ endif() # Add executable add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) +if(BUILD_TESTING) +target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_TEST) +endif() target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(Launcher_logic systeminfo diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index e2aa957be..7c2dc4393 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -33,7 +33,10 @@ ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObje connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &ResourceFolderModel::directoryChanged); connect(&m_helper_thread_task, &ConcurrentTask::finished, this, [this] { m_helper_thread_task.clear(); }); +#ifndef LAUNCHER_TEST + // in tests the application macro doesn't work m_helper_thread_task.setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentTasks").toInt()); +#endif } ResourceFolderModel::~ResourceFolderModel() diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index e0b663522..9f95d0467 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -31,7 +31,9 @@ QHash ResourceModel::s_running_models; ResourceModel::ResourceModel(ResourceAPI* api) : QAbstractListModel(), m_api(api) { s_running_models.insert(this, true); +#ifndef LAUNCHER_TEST m_current_info_job.setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); +#endif } ResourceModel::~ResourceModel() From 20e2c70464059dec07f875b9cb703bacdcfeee57 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 16 Jul 2023 23:23:33 +0100 Subject: [PATCH 154/398] Rename groups and janky reference counting map Signed-off-by: TheKodeToad --- launcher/InstanceList.cpp | 93 ++++++++++++++++------ launcher/InstanceList.h | 46 ++++++++--- launcher/ui/MainWindow.cpp | 73 +++++++++-------- launcher/ui/MainWindow.h | 3 +- launcher/ui/dialogs/CopyInstanceDialog.cpp | 25 +++--- launcher/ui/dialogs/NewInstanceDialog.cpp | 28 +++---- 6 files changed, 166 insertions(+), 102 deletions(-) diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index b4c520cd9..6bc906ebd 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -237,8 +238,11 @@ GroupId InstanceList::getInstanceGroup(const InstanceId& id) const return GroupId(); } -void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name) +void InstanceList::setInstanceGroup(const InstanceId& id, GroupId name) { + if (name.isEmpty() && !name.isNull()) + name = QString(); + auto inst = getInstanceById(id); if (!inst) { qDebug() << "Attempt to set a null instance's group"; @@ -249,6 +253,9 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name) auto iter = m_instanceGroupIndex.find(inst->id()); if (iter != m_instanceGroupIndex.end()) { if (*iter != name) { + if (!iter->isEmpty() && --m_groupNameCache[*iter] == 0) + m_groupNameCache.remove(*iter); + *iter = name; changed = true; } @@ -258,7 +265,9 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name) } if (changed) { - m_groupNameCache.insert(name); + if (!name.isEmpty()) + m_groupNameCache[name]++; + auto idx = getInstIndex(inst.get()); emit dataChanged(index(idx), index(idx), { GroupRole }); saveGroupList(); @@ -267,29 +276,55 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name) QStringList InstanceList::getGroups() { - return m_groupNameCache.values(); + return m_groupNameCache.keys(); } -void InstanceList::deleteGroup(const QString& name) +void InstanceList::deleteGroup(const GroupId& name) { + m_groupNameCache.remove(name); + m_collapsedGroups.remove(name); + bool removed = false; qDebug() << "Delete group" << name; for (auto& instance : m_instances) { - const auto& instID = instance->id(); - auto instGroupName = getInstanceGroup(instID); + const QString& instID = instance->id(); + const QString instGroupName = getInstanceGroup(instID); if (instGroupName == name) { m_instanceGroupIndex.remove(instID); qDebug() << "Remove" << instID << "from group" << name; removed = true; auto idx = getInstIndex(instance.get()); - if (idx > 0) { + if (idx > 0) emit dataChanged(index(idx), index(idx), { GroupRole }); - } } } - if (removed) { + if (removed) saveGroupList(); +} + +void InstanceList::renameGroup(const QString& src, const QString& dst) +{ + m_groupNameCache.remove(src); + if (m_collapsedGroups.remove(src)) + m_collapsedGroups.insert(dst); + + bool modified = false; + qDebug() << "Rename group" << src << "to" << dst; + for (auto& instance : m_instances) { + const QString& instID = instance->id(); + const QString instGroupName = getInstanceGroup(instID); + if (instGroupName == src) { + m_instanceGroupIndex[instID] = dst; + m_groupNameCache[dst]++; + qDebug() << "Set" << instID << "group to" << dst; + modified = true; + auto idx = getInstIndex(instance.get()); + if (idx > 0) + emit dataChanged(index(idx), index(idx), { GroupRole }); + } } + if (modified) + saveGroupList(); } bool InstanceList::isGroupCollapsed(const QString& group) @@ -305,12 +340,15 @@ bool InstanceList::trashInstance(const InstanceId& id) return false; } - auto cachedGroupId = m_instanceGroupIndex[id]; + QString cachedGroupId = m_instanceGroupIndex[id]; qDebug() << "Will trash instance" << id; QString trashedLoc; if (m_instanceGroupIndex.remove(id)) { + if (!cachedGroupId.isEmpty() && --m_groupNameCache[cachedGroupId] == 0) + m_groupNameCache.remove(cachedGroupId); + saveGroupList(); } @@ -346,7 +384,8 @@ void InstanceList::undoTrashInstance() { QFile(top.trashPath).rename(top.polyPath); m_instanceGroupIndex[top.id] = top.groupName; - m_groupNameCache.insert(top.groupName); + if (!top.groupName.isEmpty()) + m_groupNameCache[top.groupName]++; saveGroupList(); emit instancesChanged(); @@ -360,7 +399,12 @@ void InstanceList::deleteInstance(const InstanceId& id) return; } + QString cachedGroupId = m_instanceGroupIndex[id]; + if (m_instanceGroupIndex.remove(id)) { + if (!cachedGroupId.isEmpty() && --m_groupNameCache[cachedGroupId] == 0) + m_groupNameCache.remove(cachedGroupId); + saveGroupList(); } @@ -621,7 +665,7 @@ void InstanceList::saveGroupList() QString groupFileName = m_instDir + "/instgroups.json"; QMap> reverseGroupMap; for (auto iter = m_instanceGroupIndex.begin(); iter != m_instanceGroupIndex.end(); iter++) { - QString id = iter.key(); + const QString& id = iter.key(); QString group = iter.value(); if (group.isEmpty()) continue; @@ -711,17 +755,22 @@ void InstanceList::loadGroupList() return; } - QSet groupSet; m_instanceGroupIndex.clear(); + m_groupNameCache.clear(); // Iterate through all the groups. QJsonObject groupMapping = rootObj.value("groups").toObject(); for (QJsonObject::iterator iter = groupMapping.begin(); iter != groupMapping.end(); iter++) { QString groupName = iter.key(); + if (iter.key().isEmpty()) { + qWarning() << "Redundant empty group found"; + continue; + } + // If not an object, complain and skip to the next one. if (!iter.value().isObject()) { - qWarning() << QString("Group '%1' in the group list should be an object.").arg(groupName).toUtf8(); + qWarning() << QString("Group '%1' in the group list should be an object").arg(groupName).toUtf8(); continue; } @@ -734,22 +783,19 @@ void InstanceList::loadGroupList() } // keep a list/set of groups for choosing - groupSet.insert(groupName); + m_groupNameCache[groupName]++; auto hidden = groupObj.value("hidden").toBool(false); - if (hidden) { + if (hidden) m_collapsedGroups.insert(groupName); - } // Iterate through the list of instances in the group. QJsonArray instancesArray = groupObj.value("instances").toArray(); - for (QJsonArray::iterator iter2 = instancesArray.begin(); iter2 != instancesArray.end(); iter2++) { - m_instanceGroupIndex[(*iter2).toString()] = groupName; - } + for (auto value : instancesArray) + m_instanceGroupIndex[value.toString()] = groupName; } m_groupsLoaded = true; - m_groupNameCache.unite(groupSet); qDebug() << "Group list loaded."; } @@ -924,7 +970,8 @@ bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& } m_instanceGroupIndex[instID] = groupName; - m_groupNameCache.insert(groupName); + if (!groupName.isEmpty()) + m_groupNameCache[groupName]++; } instanceSet.insert(instID); diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h index 48bede07d..61795d86c 100644 --- a/launcher/InstanceList.h +++ b/launcher/InstanceList.h @@ -1,16 +1,36 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * - * 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 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 @@ -110,9 +130,10 @@ public: bool isGroupCollapsed(const QString &groupName); GroupId getInstanceGroup(const InstanceId & id) const; - void setInstanceGroup(const InstanceId & id, const GroupId& name); + void setInstanceGroup(const InstanceId & id, GroupId name); void deleteGroup(const GroupId & name); + void renameGroup(const GroupId& src, const GroupId& dst); bool trashInstance(const InstanceId &id); bool trashedSomething(); void undoTrashInstance(); @@ -187,7 +208,8 @@ private: int totalPlayTime = 0; bool m_dirty = false; QList m_instances; - QSet m_groupNameCache; + // id -> refs + QMap m_groupNameCache; SettingsObjectPtr m_globalSettings; QString m_instDir; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index da572fc34..70a76e218 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -509,10 +509,10 @@ void MainWindow::showInstanceContextMenu(const QPoint& pos) } else { auto group = view->groupNameAt(pos); - QAction* actionVoid = new QAction(BuildConfig.LAUNCHER_DISPLAYNAME, this); + QAction* actionVoid = new QAction(group.isNull() ? BuildConfig.LAUNCHER_DISPLAYNAME : group, this); actionVoid->setEnabled(false); - QAction* actionCreateInstance = new QAction(tr("Create instance"), this); + QAction* actionCreateInstance = new QAction(tr("&Create instance"), this); actionCreateInstance->setToolTip(ui->actionAddInstance->toolTip()); if (!group.isNull()) { QVariantMap data; @@ -526,12 +526,13 @@ void MainWindow::showInstanceContextMenu(const QPoint& pos) actions.prepend(actionVoid); actions.append(actionCreateInstance); if (!group.isNull()) { - QAction* actionDeleteGroup = new QAction(tr("Delete group '%1'").arg(group), this); - QVariantMap data; - data["group"] = group; - actionDeleteGroup->setData(data); - connect(actionDeleteGroup, SIGNAL(triggered(bool)), SLOT(deleteGroup())); + QAction* actionDeleteGroup = new QAction(tr("&Delete group"), this); + connect(actionDeleteGroup, &QAction::triggered, this, [this, group] { deleteGroup(group); }); actions.append(actionDeleteGroup); + + QAction* actionRenameGroup = new QAction(tr("&Rename group"), this); + connect(actionRenameGroup, &QAction::triggered, this, [this, group] { renameGroup(group); }); + actions.append(actionRenameGroup); } } QMenu myMenu; @@ -1092,40 +1093,50 @@ void MainWindow::on_actionChangeInstGroup_triggered() if (!m_selectedInstance) return; - bool ok = false; InstanceId instId = m_selectedInstance->id(); - QString name(APPLICATION->instances()->getInstanceGroup(instId)); - auto groups = APPLICATION->instances()->getGroups(); - groups.insert(0, ""); - groups.sort(Qt::CaseInsensitive); - int foo = groups.indexOf(name); + QString src(APPLICATION->instances()->getInstanceGroup(instId)); + + QStringList groups = APPLICATION->instances()->getGroups(); + if (!groups.isEmpty()) + groups.prepend(""); + + int index = groups.indexOf(src); + bool ok = false; + QString dst = QInputDialog::getItem(this, tr("Group name"), tr("Enter a new group name."), groups, index, true, &ok); + dst = dst.simplified(); - name = QInputDialog::getItem(this, tr("Group name"), tr("Enter a new group name."), groups, foo, true, &ok); - name = name.simplified(); if (ok) { - APPLICATION->instances()->setInstanceGroup(instId, name); + APPLICATION->instances()->setInstanceGroup(instId, dst); } } -void MainWindow::deleteGroup() +void MainWindow::deleteGroup(QString group) { - QObject* obj = sender(); - if (!obj) + Q_ASSERT(!group.isEmpty()); + + const int reply = QMessageBox::question(this, tr("Delete group"), tr("Are you sure you want to delete the group '%1'?").arg(group), + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::Yes) + APPLICATION->instances()->deleteGroup(group); +} + +void MainWindow::renameGroup(QString group) { + Q_ASSERT(!group.isEmpty()); + + QString name = QInputDialog::getText(this, tr("Rename group"), tr("Enter a new group name."), QLineEdit::Normal, group); + name = name.simplified(); + if (name.isNull() || name == group) return; - QAction* action = qobject_cast(obj); - if (!action) + + const bool empty = name.isEmpty(); + const bool duplicate = APPLICATION->instances()->getGroups().contains(name, Qt::CaseInsensitive) && group.toLower() != name.toLower(); + + if (empty || duplicate) { + QMessageBox::warning(this, tr("Cannot rename group"), empty ? tr("Cannot set empty name.") : tr("Group already exists. :/")); return; - auto map = action->data().toMap(); - if (!map.contains("group")) - return; - QString groupName = map["group"].toString(); - if (!groupName.isEmpty()) { - auto reply = QMessageBox::question(this, tr("Delete group"), tr("Are you sure you want to delete the group %1?").arg(groupName), - QMessageBox::Yes | QMessageBox::No); - if (reply == QMessageBox::Yes) { - APPLICATION->instances()->deleteGroup(groupName); - } } + + APPLICATION->instances()->renameGroup(group, name); } void MainWindow::undoTrashInstance() diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 27c2756f6..77ed72a45 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -151,7 +151,8 @@ private slots: void on_actionDeleteInstance_triggered(); - void deleteGroup(); + void deleteGroup(QString group); + void renameGroup(QString group); void undoTrashInstance(); inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } diff --git a/launcher/ui/dialogs/CopyInstanceDialog.cpp b/launcher/ui/dialogs/CopyInstanceDialog.cpp index d75bb5fe3..ce12f605b 100644 --- a/launcher/ui/dialogs/CopyInstanceDialog.cpp +++ b/launcher/ui/dialogs/CopyInstanceDialog.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,22 +62,14 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget* parent) ui->iconButton->setIcon(APPLICATION->icons()->getIcon(InstIconKey)); ui->instNameTextBox->setText(original->name()); ui->instNameTextBox->setFocus(); -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - auto groupList = APPLICATION->instances()->getGroups(); - QSet groups(groupList.begin(), groupList.end()); - groupList = QStringList(groups.values()); -#else - auto groups = APPLICATION->instances()->getGroups().toSet(); - auto groupList = QStringList(groups.toList()); -#endif - groupList.sort(Qt::CaseInsensitive); - groupList.removeOne(""); - groupList.push_front(""); - ui->groupBox->addItems(groupList); - int index = groupList.indexOf(APPLICATION->instances()->getInstanceGroup(m_original->id())); - if (index == -1) { + + QStringList groups = APPLICATION->instances()->getGroups(); + groups.prepend(""); + ui->groupBox->addItems(groups); + int index = groups.indexOf(APPLICATION->instances()->getInstanceGroup(m_original->id())); + if (index == -1) index = 0; - } + ui->groupBox->setCurrentIndex(index); ui->groupBox->lineEdit()->setPlaceholderText(tr("No group")); ui->copySavesCheckbox->setChecked(m_selectedOptions.isCopySavesEnabled()); diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 7b9bb944c..30e41c09d 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -74,28 +75,17 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString InstIconKey = "default"; ui->iconButton->setIcon(APPLICATION->icons()->getIcon(InstIconKey)); -#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - auto groupList = APPLICATION->instances()->getGroups(); - auto groups = QSet(groupList.begin(), groupList.end()); - groupList = groups.values(); -#else - auto groups = APPLICATION->instances()->getGroups().toSet(); - auto groupList = QStringList(groups.toList()); -#endif - groupList.sort(Qt::CaseInsensitive); - groupList.removeOne(""); - groupList.push_front(initialGroup); - groupList.push_front(""); - ui->groupBox->addItems(groupList); - int index = groupList.indexOf(initialGroup); - if(index == -1) - { - index = 0; + QStringList groups = APPLICATION->instances()->getGroups(); + groups.prepend(""); + int index = groups.indexOf(initialGroup); + if (index == -1) { + index = 1; + groups.insert(index, initialGroup); } + ui->groupBox->addItems(groups); ui->groupBox->setCurrentIndex(index); ui->groupBox->lineEdit()->setPlaceholderText(tr("No group")); - // NOTE: m_buttons must be initialized before PageContainer, because it indirectly accesses m_buttons through setSuggestedPack! Do not move this below. m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel); From fb5aefffb2f12562910a85f67cb1c8ca3f2ed369 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 16 Jul 2023 23:36:01 +0100 Subject: [PATCH 155/398] Reduce bugginess Signed-off-by: TheKodeToad --- launcher/InstanceList.cpp | 51 +++++++++++++++++++++++---------------- launcher/InstanceList.h | 3 +++ 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 6bc906ebd..d6faaaf1a 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -253,9 +253,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, GroupId name) auto iter = m_instanceGroupIndex.find(inst->id()); if (iter != m_instanceGroupIndex.end()) { if (*iter != name) { - if (!iter->isEmpty() && --m_groupNameCache[*iter] == 0) - m_groupNameCache.remove(*iter); - + decreaseGroupCount(*iter); *iter = name; changed = true; } @@ -265,9 +263,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, GroupId name) } if (changed) { - if (!name.isEmpty()) - m_groupNameCache[name]++; - + increaseGroupCount(name); auto idx = getInstIndex(inst.get()); emit dataChanged(index(idx), index(idx), { GroupRole }); saveGroupList(); @@ -315,7 +311,7 @@ void InstanceList::renameGroup(const QString& src, const QString& dst) const QString instGroupName = getInstanceGroup(instID); if (instGroupName == src) { m_instanceGroupIndex[instID] = dst; - m_groupNameCache[dst]++; + increaseGroupCount(dst); qDebug() << "Set" << instID << "group to" << dst; modified = true; auto idx = getInstIndex(instance.get()); @@ -346,9 +342,7 @@ bool InstanceList::trashInstance(const InstanceId& id) QString trashedLoc; if (m_instanceGroupIndex.remove(id)) { - if (!cachedGroupId.isEmpty() && --m_groupNameCache[cachedGroupId] == 0) - m_groupNameCache.remove(cachedGroupId); - + decreaseGroupCount(cachedGroupId); saveGroupList(); } @@ -384,8 +378,7 @@ void InstanceList::undoTrashInstance() { QFile(top.trashPath).rename(top.polyPath); m_instanceGroupIndex[top.id] = top.groupName; - if (!top.groupName.isEmpty()) - m_groupNameCache[top.groupName]++; + increaseGroupCount(top.groupName); saveGroupList(); emit instancesChanged(); @@ -402,9 +395,7 @@ void InstanceList::deleteInstance(const InstanceId& id) QString cachedGroupId = m_instanceGroupIndex[id]; if (m_instanceGroupIndex.remove(id)) { - if (!cachedGroupId.isEmpty() && --m_groupNameCache[cachedGroupId] == 0) - m_groupNameCache.remove(cachedGroupId); - + decreaseGroupCount(cachedGroupId); saveGroupList(); } @@ -654,6 +645,26 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id) return inst; } + +void InstanceList::increaseGroupCount(const QString& group) +{ + if (group.isEmpty()) + return; + + ++m_groupNameCache[group]; +} + +void InstanceList::decreaseGroupCount(const QString& group) +{ + if (group.isEmpty()) + return; + + if (--m_groupNameCache[group] < 1) { + m_groupNameCache.remove(group); + m_collapsedGroups.remove(group); + } +} + void InstanceList::saveGroupList() { qDebug() << "Will save group list now."; @@ -782,9 +793,6 @@ void InstanceList::loadGroupList() continue; } - // keep a list/set of groups for choosing - m_groupNameCache[groupName]++; - auto hidden = groupObj.value("hidden").toBool(false); if (hidden) m_collapsedGroups.insert(groupName); @@ -792,8 +800,10 @@ void InstanceList::loadGroupList() // Iterate through the list of instances in the group. QJsonArray instancesArray = groupObj.value("instances").toArray(); - for (auto value : instancesArray) + for (auto value : instancesArray) { m_instanceGroupIndex[value.toString()] = groupName; + increaseGroupCount(groupName); + } } m_groupsLoaded = true; qDebug() << "Group list loaded."; @@ -970,8 +980,7 @@ bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& } m_instanceGroupIndex[instID] = groupName; - if (!groupName.isEmpty()) - m_groupNameCache[groupName]++; + increaseGroupCount(groupName); } instanceSet.insert(instID); diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h index 61795d86c..aaee3bb44 100644 --- a/launcher/InstanceList.h +++ b/launcher/InstanceList.h @@ -203,6 +203,9 @@ private: QList discoverInstances(); InstancePtr loadInstance(const InstanceId& id); + void increaseGroupCount(const QString& group); + void decreaseGroupCount(const QString& group); + private: int m_watchLevel = 0; int totalPlayTime = 0; From 49cebc2da48b4228d0e729298b2301c7ff281bc6 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 17 Jul 2023 12:49:12 +0100 Subject: [PATCH 156/398] More consistent behaviour Signed-off-by: TheKodeToad --- launcher/ui/MainWindow.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 70a76e218..d1ea95d1f 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1097,9 +1097,7 @@ void MainWindow::on_actionChangeInstGroup_triggered() QString src(APPLICATION->instances()->getInstanceGroup(instId)); QStringList groups = APPLICATION->instances()->getGroups(); - if (!groups.isEmpty()) - groups.prepend(""); - + groups.prepend(""); int index = groups.indexOf(src); bool ok = false; QString dst = QInputDialog::getItem(this, tr("Group name"), tr("Enter a new group name."), groups, index, true, &ok); From 5eec0f5901a0b11c9c01fd7b086968951b792fb6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 18 Jul 2023 23:40:03 +0300 Subject: [PATCH 157/398] feat:managed packs can update from file Signed-off-by: Trial97 --- .../ui/pages/instance/ManagedPackPage.cpp | 45 +++++++++++++++++++ launcher/ui/pages/instance/ManagedPackPage.h | 3 ++ launcher/ui/pages/instance/ManagedPackPage.ui | 13 ++++++ 3 files changed, 61 insertions(+) diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 0fc0c9867..1dbbae0f4 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -5,6 +5,7 @@ #include "ManagedPackPage.h" #include "ui_ManagedPackPage.h" +#include #include #include #include @@ -205,6 +206,7 @@ ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWin Q_ASSERT(inst->isManagedPack()); connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); connect(ui->updateButton, &QPushButton::clicked, this, &ModrinthManagedPackPage::update); + connect(ui->updateFromFileButton, &QPushButton::clicked, this, &ModrinthManagedPackPage::updateFromFile); } // MODRINTH @@ -332,6 +334,27 @@ void ModrinthManagedPackPage::update() m_instance_window->close(); } +void ModrinthManagedPackPage::updateFromFile() +{ + auto output = QFileDialog::getOpenFileUrl(this, tr("Choose update file"), QDir::homePath(), "Modrinth pack (*.mrpack *.zip)"); + QMap extra_info; + extra_info.insert("pack_id", m_inst->getManagedPackID()); + extra_info.insert("pack_version_id", QString()); + extra_info.insert("original_instance_id", m_inst->id()); + + auto extracted = new InstanceImportTask(output, this, std::move(extra_info)); + + extracted->setName(m_inst->name()); + extracted->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id())); + extracted->setIcon(m_inst->iconKey()); + extracted->setConfirmUpdate(false); + + auto did_succeed = runUpdateTask(extracted); + + if (m_instance_window && did_succeed) + m_instance_window->close(); +} + // FLAME FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent) @@ -340,6 +363,7 @@ FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* i Q_ASSERT(inst->isManagedPack()); connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); connect(ui->updateButton, &QPushButton::clicked, this, &FlameManagedPackPage::update); + connect(ui->updateFromFileButton, &QPushButton::clicked, this, &FlameManagedPackPage::updateFromFile); } void FlameManagedPackPage::parseManagedPack() @@ -474,4 +498,25 @@ void FlameManagedPackPage::update() m_instance_window->close(); } +void FlameManagedPackPage::updateFromFile() +{ + auto output = QFileDialog::getOpenFileUrl(this, tr("Choose update file"), QDir::homePath(), "CurseForge pack (*.zip)"); + + QMap extra_info; + extra_info.insert("pack_id", m_inst->getManagedPackID()); + extra_info.insert("pack_version_id", QString()); + extra_info.insert("original_instance_id", m_inst->id()); + + auto extracted = new InstanceImportTask(output, this, std::move(extra_info)); + + extracted->setName(m_inst->name()); + extracted->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id())); + extracted->setIcon(m_inst->iconKey()); + extracted->setConfirmUpdate(false); + + auto did_succeed = runUpdateTask(extracted); + + if (m_instance_window && did_succeed) + m_instance_window->close(); +} #include "ManagedPackPage.moc" diff --git a/launcher/ui/pages/instance/ManagedPackPage.h b/launcher/ui/pages/instance/ManagedPackPage.h index 1ac6fc038..d77cb97b8 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.h +++ b/launcher/ui/pages/instance/ManagedPackPage.h @@ -65,6 +65,7 @@ class ManagedPackPage : public QWidget, public BasePage { virtual void suggestVersion(); virtual void update(){}; + virtual void updateFromFile(){}; protected slots: /** Does the necessary UI changes for when something failed. @@ -123,6 +124,7 @@ class ModrinthManagedPackPage final : public ManagedPackPage { void suggestVersion() override; void update() override; + void updateFromFile() override; private: NetJob::Ptr m_fetch_job = nullptr; @@ -145,6 +147,7 @@ class FlameManagedPackPage final : public ManagedPackPage { void suggestVersion() override; void update() override; + void updateFromFile() override; private: NetJob::Ptr m_fetch_job = nullptr; diff --git a/launcher/ui/pages/instance/ManagedPackPage.ui b/launcher/ui/pages/instance/ManagedPackPage.ui index bbe44a940..96317be9f 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.ui +++ b/launcher/ui/pages/instance/ManagedPackPage.ui @@ -153,6 +153,19 @@ + + + + + 0 + 0 + + + + Update from file + + + From 97662f5c8ecdf32403939e427c74310f9175fb9e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 18 Jul 2023 22:50:43 +0100 Subject: [PATCH 158/398] Multiple icon themes! Signed-off-by: TheKodeToad --- launcher/Application.cpp | 5 + launcher/Application.h | 3 + launcher/CMakeLists.txt | 2 + launcher/resources/multimc/index.theme | 2 +- launcher/resources/pe_blue/index.theme | 2 +- launcher/resources/pe_colored/index.theme | 2 +- launcher/resources/pe_dark/index.theme | 2 +- launcher/resources/pe_light/index.theme | 2 +- launcher/ui/themes/IconTheme.cpp | 35 ++++++ launcher/ui/themes/IconTheme.h | 18 +++ launcher/ui/themes/ThemeManager.cpp | 117 ++++++++++++------ launcher/ui/themes/ThemeManager.h | 8 ++ .../ui/widgets/ThemeCustomizationWidget.cpp | 22 ++-- .../ui/widgets/ThemeCustomizationWidget.h | 19 +-- 14 files changed, 171 insertions(+), 68 deletions(-) create mode 100644 launcher/ui/themes/IconTheme.cpp create mode 100644 launcher/ui/themes/IconTheme.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index d6c135de7..df8a23636 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1163,6 +1163,11 @@ QList Application::getValidApplicationThemes() return m_themeManager->getValidApplicationThemes(); } +QList Application::getValidIconThemes() +{ + return m_themeManager->getValidIconThemes(); +} + void Application::applyCurrentlySelectedTheme(bool initial) { m_themeManager->applyCurrentlySelectedTheme(initial); diff --git a/launcher/Application.h b/launcher/Application.h index 527c536b3..0b953f0a5 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -70,6 +70,7 @@ class TranslationsModel; class ITheme; class MCEditTool; class ThemeManager; +class IconTheme; namespace Meta { class Index; @@ -124,6 +125,8 @@ public: QList getValidApplicationThemes(); + QList getValidIconThemes(); + void setApplicationTheme(const QString& name); shared_qobject_ptr updater() { diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 7cba97b4f..89fc901b0 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -759,6 +759,8 @@ SET(LAUNCHER_SOURCES ui/themes/ITheme.h ui/themes/SystemTheme.cpp ui/themes/SystemTheme.h + ui/themes/IconTheme.cpp + ui/themes/IconTheme.h ui/themes/ThemeManager.cpp ui/themes/ThemeManager.h diff --git a/launcher/resources/multimc/index.theme b/launcher/resources/multimc/index.theme index 070e23f10..4da8072d9 100644 --- a/launcher/resources/multimc/index.theme +++ b/launcher/resources/multimc/index.theme @@ -1,5 +1,5 @@ [Icon Theme] -Name=multimc +Name=Legacy Comment=Default Icons Inherits=default Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable,scalable/instances diff --git a/launcher/resources/pe_blue/index.theme b/launcher/resources/pe_blue/index.theme index c9e0d93ad..6d842b5d2 100644 --- a/launcher/resources/pe_blue/index.theme +++ b/launcher/resources/pe_blue/index.theme @@ -1,5 +1,5 @@ [Icon Theme] -Name=pe_blue +Name=Simple (Blue) Comment=Icons by pexner (blue) Inherits=multimc Directories=scalable diff --git a/launcher/resources/pe_colored/index.theme b/launcher/resources/pe_colored/index.theme index b757bbd79..bca5494f1 100644 --- a/launcher/resources/pe_colored/index.theme +++ b/launcher/resources/pe_colored/index.theme @@ -1,5 +1,5 @@ [Icon Theme] -Name=pe_colored +Name=Simple (Colored) Comment=Icons by pexner (colored) Inherits=multimc Directories=scalable diff --git a/launcher/resources/pe_dark/index.theme b/launcher/resources/pe_dark/index.theme index b7d1ad011..4cfbf09c4 100644 --- a/launcher/resources/pe_dark/index.theme +++ b/launcher/resources/pe_dark/index.theme @@ -1,5 +1,5 @@ [Icon Theme] -Name=pe_dark +Name=Simple (Dark) Comment=Icons by pexner (dark) Inherits=multimc Directories=scalable diff --git a/launcher/resources/pe_light/index.theme b/launcher/resources/pe_light/index.theme index c106acc8b..87b76d139 100644 --- a/launcher/resources/pe_light/index.theme +++ b/launcher/resources/pe_light/index.theme @@ -1,5 +1,5 @@ [Icon Theme] -Name=pe_light +Name=Simple (Light) Comment=Icons by pexner (light) Inherits=multimc Directories=scalable diff --git a/launcher/ui/themes/IconTheme.cpp b/launcher/ui/themes/IconTheme.cpp new file mode 100644 index 000000000..ef2455051 --- /dev/null +++ b/launcher/ui/themes/IconTheme.cpp @@ -0,0 +1,35 @@ +#include "IconTheme.h" + +#include +#include + +IconTheme::IconTheme(const QString& id, const QString& path) : m_id(id), m_path(path) {} + +bool IconTheme::load() +{ + QString path = m_path + "/index.theme"; + + if (!QFile::exists(path)) + return false; + + QSettings settings(path, QSettings::IniFormat); + settings.beginGroup("Icon Theme"); + m_name = settings.value("Name").toString(); + settings.endGroup(); + return !m_name.isNull(); +} + +QString IconTheme::id() +{ + return m_id; +} + +QString IconTheme::path() +{ + return m_path; +} + +QString IconTheme::name() +{ + return m_name; +} \ No newline at end of file diff --git a/launcher/ui/themes/IconTheme.h b/launcher/ui/themes/IconTheme.h new file mode 100644 index 000000000..cb05d8c73 --- /dev/null +++ b/launcher/ui/themes/IconTheme.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +class IconTheme { + public: + IconTheme(const QString& id, const QString& path); + + bool load(); + QString id(); + QString path(); + QString name(); + + private: + QString m_id; + QString m_path; + QString m_name; +}; \ No newline at end of file diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index b50c6157f..3453a2463 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -55,50 +55,84 @@ ITheme* ThemeManager::getTheme(QString themeId) void ThemeManager::initializeThemes() { // Icon themes - { - // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies! - // set icon theme search path! - auto searchPaths = QIcon::themeSearchPaths(); - searchPaths.append("iconthemes"); - QIcon::setThemeSearchPaths(searchPaths); - themeDebugLog() << "<> Icon themes initialized."; - } + initializeIcons(); // Initialize widget themes - { - themeDebugLog() << "<> Initializing Widget Themes"; - themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); - auto darkThemeId = addTheme(std::make_unique()); - themeDebugLog() << "Loading Built-in Theme:" << darkThemeId; - themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); + initializeWidgets(); +} - // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in - // dropdown?) - QString themeFolder = QDir("./themes/").absoluteFilePath(""); - themeDebugLog() << "Theme Folder Path: " << themeFolder; +void ThemeManager::initializeIcons() +{ + // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies! + // set icon theme search path! - QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); - while (directoryIterator.hasNext()) { - QDir dir(directoryIterator.next()); - QFileInfo themeJson(dir.absoluteFilePath("theme.json")); - if (themeJson.exists()) { - // Load "theme.json" based themes - themeDebugLog() << "Loading JSON Theme from:" << themeJson.absoluteFilePath(); - addTheme(std::make_unique(getTheme(darkThemeId), themeJson, true)); - } else { - // Load pure QSS Themes - QDirIterator stylesheetFileIterator(dir.absoluteFilePath(""), { "*.qss", "*.css" }, QDir::Files); - while (stylesheetFileIterator.hasNext()) { - QFile customThemeFile(stylesheetFileIterator.next()); - QFileInfo customThemeFileInfo(customThemeFile); - themeDebugLog() << "Loading QSS Theme from:" << customThemeFileInfo.absoluteFilePath(); - addTheme(std::make_unique(getTheme(darkThemeId), customThemeFileInfo, false)); - } - } + QString themeFolder = "iconthemes"; + + auto searchPaths = QIcon::themeSearchPaths(); + searchPaths.append(themeFolder); + QIcon::setThemeSearchPaths(searchPaths); + + themeDebugLog() << "<> Initializing Icon Themes"; + + for (const QString& id : builtinIcons) { + IconTheme theme(id, QString(":/icons/%1").arg(id)); + if (!theme.load()) { + themeWarningLog() << "Couldn't load built-in icon theme" << id; + continue; } - themeDebugLog() << "<> Widget themes initialized."; + m_icons.append(theme); + themeDebugLog() << "Loaded Built-In Icon Theme" << id; } + + QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (directoryIterator.hasNext()) { + QDir dir(directoryIterator.next()); + IconTheme theme(dir.dirName(), dir.path()); + if (!theme.load()) + continue; + + m_icons.append(theme); + themeDebugLog() << "Loaded Custom Icon Theme from" << dir.path(); + } + + themeDebugLog() << "<> Icon themes initialized."; +} + +void ThemeManager::initializeWidgets() +{ + themeDebugLog() << "<> Initializing Widget Themes"; + themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); + auto darkThemeId = addTheme(std::make_unique()); + themeDebugLog() << "Loading Built-in Theme:" << darkThemeId; + themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique()); + + // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in + // dropdown?) + QString themeFolder = QDir("./themes/").absoluteFilePath(""); + themeDebugLog() << "Theme Folder Path: " << themeFolder; + + QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (directoryIterator.hasNext()) { + QDir dir(directoryIterator.next()); + QFileInfo themeJson(dir.absoluteFilePath("theme.json")); + if (themeJson.exists()) { + // Load "theme.json" based themes + themeDebugLog() << "Loading JSON Theme from:" << themeJson.absoluteFilePath(); + addTheme(std::make_unique(getTheme(darkThemeId), themeJson, true)); + } else { + // Load pure QSS Themes + QDirIterator stylesheetFileIterator(dir.absoluteFilePath(""), { "*.qss", "*.css" }, QDir::Files); + while (stylesheetFileIterator.hasNext()) { + QFile customThemeFile(stylesheetFileIterator.next()); + QFileInfo customThemeFileInfo(customThemeFile); + themeDebugLog() << "Loading QSS Theme from:" << customThemeFileInfo.absoluteFilePath(); + addTheme(std::make_unique(getTheme(darkThemeId), customThemeFileInfo, false)); + } + } + } + + themeDebugLog() << "<> Widget themes initialized."; } QList ThemeManager::getValidApplicationThemes() @@ -111,6 +145,15 @@ QList ThemeManager::getValidApplicationThemes() return ret; } +QList ThemeManager::getValidIconThemes() +{ + QList ret; + ret.reserve(m_icons.size()); + for (IconTheme& theme : m_icons) + ret.append(&theme); + return ret; +} + void ThemeManager::setIconTheme(const QString& name) { QIcon::setThemeName(name); diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index d2a6fb70a..7509377c4 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -19,6 +19,7 @@ #include +#include "IconTheme.h" #include "ui/MainWindow.h" #include "ui/themes/ITheme.h" @@ -36,6 +37,7 @@ class ThemeManager { ThemeManager(MainWindow* mainWindow); QList getValidApplicationThemes(); + QList getValidIconThemes(); void setIconTheme(const QString& name); void applyCurrentlySelectedTheme(bool initial = false); void setApplicationTheme(const QString& name, bool initial = false); @@ -49,9 +51,15 @@ class ThemeManager { private: std::map> m_themes; + QList m_icons; MainWindow* m_mainWindow; void initializeThemes(); QString addTheme(std::unique_ptr theme); ITheme* getTheme(QString themeId); + void initializeIcons(); + void initializeWidgets(); + + const QStringList builtinIcons{ "pe_colored", "pe_light", "pe_dark", "pe_blue", "breeze_light", "breeze_dark", + "OSX", "iOS", "flat", "flat_white", "multimc" }; }; diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index 3bfcd8213..455cbb7b6 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -73,10 +73,9 @@ void ThemeCustomizationWidget::showFeatures(ThemeFields features) { void ThemeCustomizationWidget::applyIconTheme(int index) { auto settings = APPLICATION->settings(); auto originalIconTheme = settings->get("IconTheme").toString(); - auto& newIconTheme = m_iconThemeOptions[index].first; - settings->set("IconTheme", newIconTheme); - + auto newIconTheme = ui->iconsComboBox->currentData().toString(); if (originalIconTheme != newIconTheme) { + settings->set("IconTheme", newIconTheme); APPLICATION->applyCurrentlySelectedTheme(); } @@ -112,12 +111,17 @@ void ThemeCustomizationWidget::loadSettings() { auto settings = APPLICATION->settings(); - auto iconTheme = settings->get("IconTheme").toString(); - for (auto& iconThemeFromList : m_iconThemeOptions) { - QIcon iconForComboBox = QIcon(QString(":/icons/%1/scalable/settings").arg(iconThemeFromList.first)); - ui->iconsComboBox->addItem(iconForComboBox, iconThemeFromList.second); - if (iconTheme == iconThemeFromList.first) { - ui->iconsComboBox->setCurrentIndex(ui->iconsComboBox->count() - 1); + { + auto currentIconTheme = settings->get("IconTheme").toString(); + auto iconThemes = APPLICATION->getValidIconThemes(); + int idx = 0; + for (auto iconTheme : iconThemes) { + QIcon iconForComboBox = QIcon(iconTheme->path() + "/scalable/settings"); + ui->iconsComboBox->addItem(iconForComboBox, iconTheme->name(), iconTheme->id()); + if (currentIconTheme == iconTheme->id()) { + ui->iconsComboBox->setCurrentIndex(idx); + } + idx++; } } diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.h b/launcher/ui/widgets/ThemeCustomizationWidget.h index 6c33c3c50..976ede435 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.h +++ b/launcher/ui/widgets/ThemeCustomizationWidget.h @@ -31,7 +31,7 @@ class ThemeCustomizationWidget : public QWidget { public: explicit ThemeCustomizationWidget(QWidget* parent = nullptr); - ~ThemeCustomizationWidget(); + ~ThemeCustomizationWidget() override; void showFeatures(ThemeFields features); @@ -53,22 +53,7 @@ class ThemeCustomizationWidget : public QWidget { private: Ui::ThemeCustomizationWidget* ui; - //TODO finish implementing - QList> m_iconThemeOptions{ - { "pe_colored", QObject::tr("Simple (Colored Icons)") }, - { "pe_light", QObject::tr("Simple (Light Icons)") }, - { "pe_dark", QObject::tr("Simple (Dark Icons)") }, - { "pe_blue", QObject::tr("Simple (Blue Icons)") }, - { "breeze_light", QObject::tr("Breeze Light") }, - { "breeze_dark", QObject::tr("Breeze Dark") }, - { "OSX", QObject::tr("OSX") }, - { "iOS", QObject::tr("iOS") }, - { "flat", QObject::tr("Flat") }, - { "flat_white", QObject::tr("Flat (White)") }, - { "multimc", QObject::tr("Legacy") }, - { "custom", QObject::tr("Custom") } - }; - QList> m_catOptions{ + QList> m_catOptions{ { "kitteh", QObject::tr("Background Cat (from MultiMC)") }, { "rory", QObject::tr("Rory ID 11 (drawn by Ashtaka)") }, { "rory-flat", QObject::tr("Rory ID 11 (flat edition, drawn by Ashtaka)") }, From 58c2059e10a52ff0cb4481fdb14f512b198de964 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 19 Jul 2023 10:38:56 +0100 Subject: [PATCH 159/398] Remove recursion It will add icon packs which aren't available - as QIcon's search paths are not recursed! Signed-off-by: TheKodeToad --- launcher/ui/themes/ThemeManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 3453a2463..5e0fa580c 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -85,7 +85,7 @@ void ThemeManager::initializeIcons() themeDebugLog() << "Loaded Built-In Icon Theme" << id; } - QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); IconTheme theme(dir.dirName(), dir.path()); From 44ca7c7d22f89d28bc9026700c8e0f8efe89b668 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 19 Jul 2023 12:29:51 +0100 Subject: [PATCH 160/398] Licenses Signed-off-by: TheKodeToad --- launcher/ui/themes/IconTheme.cpp | 18 ++++++++++++++++++ launcher/ui/themes/IconTheme.h | 18 ++++++++++++++++++ launcher/ui/themes/ThemeManager.cpp | 1 + launcher/ui/themes/ThemeManager.h | 1 + 4 files changed, 38 insertions(+) diff --git a/launcher/ui/themes/IconTheme.cpp b/launcher/ui/themes/IconTheme.cpp index ef2455051..cd1dfbaf5 100644 --- a/launcher/ui/themes/IconTheme.cpp +++ b/launcher/ui/themes/IconTheme.cpp @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "IconTheme.h" #include diff --git a/launcher/ui/themes/IconTheme.h b/launcher/ui/themes/IconTheme.h index cb05d8c73..0282d7cbf 100644 --- a/launcher/ui/themes/IconTheme.h +++ b/launcher/ui/themes/IconTheme.h @@ -1,3 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #pragma once #include diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 5e0fa580c..84e11ccf3 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Tayou + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 7509377c4..9b97f3723 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -2,6 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Tayou + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 96ebdfc9a88004056b6ec581f071678e08c0c989 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 19 Jul 2023 14:12:39 +0100 Subject: [PATCH 161/398] Sorting and invalid reset Signed-off-by: TheKodeToad --- launcher/ui/themes/IconTheme.h | 1 + launcher/ui/themes/ThemeManager.cpp | 37 +++++++++++++++++++++++------ launcher/ui/themes/ThemeManager.h | 7 +++--- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/launcher/ui/themes/IconTheme.h b/launcher/ui/themes/IconTheme.h index 0282d7cbf..458ea12c1 100644 --- a/launcher/ui/themes/IconTheme.h +++ b/launcher/ui/themes/IconTheme.h @@ -23,6 +23,7 @@ class IconTheme { public: IconTheme(const QString& id, const QString& path); + IconTheme() = default; bool load(); QString id(); diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 84e11ccf3..8c9a6a585 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -53,6 +53,13 @@ ITheme* ThemeManager::getTheme(QString themeId) return m_themes[themeId].get(); } +QString ThemeManager::addIconTheme(IconTheme theme) +{ + QString id = theme.id(); + m_icons.emplace(id, std::move(theme)); + return id; +} + void ThemeManager::initializeThemes() { // Icon themes @@ -82,7 +89,7 @@ void ThemeManager::initializeIcons() continue; } - m_icons.append(theme); + addIconTheme(std::move(theme)); themeDebugLog() << "Loaded Built-In Icon Theme" << id; } @@ -93,7 +100,7 @@ void ThemeManager::initializeIcons() if (!theme.load()) continue; - m_icons.append(theme); + addIconTheme(std::move(theme)); themeDebugLog() << "Loaded Custom Icon Theme from" << dir.path(); } @@ -150,25 +157,39 @@ QList ThemeManager::getValidIconThemes() { QList ret; ret.reserve(m_icons.size()); - for (IconTheme& theme : m_icons) + for (auto&& [id, theme] : m_icons) { ret.append(&theme); + } return ret; } -void ThemeManager::setIconTheme(const QString& name) +bool ThemeManager::setIconTheme(const QString& name) { + if (m_icons.find(name) == m_icons.end()) { + themeWarningLog() << "Tried to set invalid icon theme:" << name; + return false; + } + QIcon::setThemeName(name); + return true; } void ThemeManager::applyCurrentlySelectedTheme(bool initial) { - setIconTheme(APPLICATION->settings()->get("IconTheme").toString()); + auto settings = APPLICATION->settings(); + if (!setIconTheme(settings->get("IconTheme").toString())) { + APPLICATION->settings()->reset("IconTheme"); + setIconTheme(settings->get("IconTheme").toString()); + } themeDebugLog() << "<> Icon theme set."; - setApplicationTheme(APPLICATION->settings()->get("ApplicationTheme").toString(), initial); + if (!setApplicationTheme(settings->get("ApplicationTheme").toString(), initial)) { + APPLICATION->settings()->reset("ApplicationTheme"); + setApplicationTheme(settings->get("ApplicationTheme").toString(), initial); + } themeDebugLog() << "<> Application theme set."; } -void ThemeManager::setApplicationTheme(const QString& name, bool initial) +bool ThemeManager::setApplicationTheme(const QString& name, bool initial) { auto systemPalette = qApp->palette(); auto themeIter = m_themes.find(name); @@ -176,8 +197,10 @@ void ThemeManager::setApplicationTheme(const QString& name, bool initial) auto& theme = themeIter->second; themeDebugLog() << "applying theme" << theme->name(); theme->apply(initial); + return true; } else { themeWarningLog() << "Tried to set invalid theme:" << name; + return false; } } diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 9b97f3723..2b6c57e97 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -39,9 +39,9 @@ class ThemeManager { QList getValidApplicationThemes(); QList getValidIconThemes(); - void setIconTheme(const QString& name); + bool setIconTheme(const QString& name); void applyCurrentlySelectedTheme(bool initial = false); - void setApplicationTheme(const QString& name, bool initial = false); + bool setApplicationTheme(const QString& name, bool initial = false); /// /// Returns the cat based on selected cat and with events (Birthday, XMas, etc.) @@ -52,12 +52,13 @@ class ThemeManager { private: std::map> m_themes; - QList m_icons; + std::map m_icons; MainWindow* m_mainWindow; void initializeThemes(); QString addTheme(std::unique_ptr theme); ITheme* getTheme(QString themeId); + QString addIconTheme(IconTheme theme); void initializeIcons(); void initializeWidgets(); From c633c6d083f7b2395cd98da2d26df361392cfa61 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 19 Jul 2023 14:17:17 +0100 Subject: [PATCH 162/398] Colors->Widgets Signed-off-by: TheKodeToad --- launcher/ui/widgets/ThemeCustomizationWidget.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.ui b/launcher/ui/widgets/ThemeCustomizationWidget.ui index f216a610e..6b2c87f97 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.ui +++ b/launcher/ui/widgets/ThemeCustomizationWidget.ui @@ -55,7 +55,7 @@ - &Colors + &Widgets widgetStyleComboBox From 54d393632d5c964f0c30ca9bc816853b92552c9c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 19 Jul 2023 16:29:52 +0100 Subject: [PATCH 163/398] Automatically create theme folders, and add an action to open them Signed-off-by: TheKodeToad --- launcher/ui/MainWindow.cpp | 25 ++++++++++----- launcher/ui/MainWindow.h | 10 +++--- launcher/ui/MainWindow.ui | 48 +++++++++++++++++++++++------ launcher/ui/themes/ThemeManager.cpp | 18 +++++++---- 4 files changed, 74 insertions(+), 27 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index da572fc34..600d245d9 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1134,16 +1134,30 @@ void MainWindow::undoTrashInstance() ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); } +void MainWindow::on_actionViewLauncherRootFolder_triggered() +{ + DesktopServices::openDirectory("."); +} + void MainWindow::on_actionViewInstanceFolder_triggered() { QString str = APPLICATION->settings()->get("InstanceDir").toString(); DesktopServices::openDirectory(str); } -void MainWindow::on_actionViewLauncherRootFolder_triggered() +void MainWindow::on_actionViewCentralModsFolder_triggered() { - const QString dataPath = QDir::currentPath(); - DesktopServices::openDirectory(dataPath); + DesktopServices::openDirectory(APPLICATION->settings()->get("CentralModsDir").toString(), true); +} + +void MainWindow::on_actionViewIconThemeFolder_triggered() +{ + DesktopServices::openDirectory("iconthemes"); +} + +void MainWindow::on_actionViewWidgetThemeFolder_triggered() +{ + DesktopServices::openDirectory("themes"); } void MainWindow::refreshInstances() @@ -1151,11 +1165,6 @@ void MainWindow::refreshInstances() APPLICATION->instances()->loadList(); } -void MainWindow::on_actionViewCentralModsFolder_triggered() -{ - DesktopServices::openDirectory(APPLICATION->settings()->get("CentralModsDir").toString(), true); -} - void MainWindow::checkForUpdates() { if (BuildConfig.UPDATER_ENABLED) { diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 27c2756f6..8756c0784 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -111,16 +111,18 @@ private slots: void on_actionChangeInstIcon_triggered(); - void on_actionViewInstanceFolder_triggered(); - void on_actionViewLauncherRootFolder_triggered(); + void on_actionViewInstanceFolder_triggered(); + void on_actionViewCentralModsFolder_triggered(); + + void on_actionViewIconThemeFolder_triggered(); + void on_actionViewWidgetThemeFolder_triggered(); + void on_actionViewSelectedInstFolder_triggered(); void refreshInstances(); - void on_actionViewCentralModsFolder_triggered(); - void checkForUpdates(); void on_actionSettings_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index e4421d400..1bc620277 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -131,7 +131,7 @@ 0 0 800 - 20 + 31 @@ -186,9 +186,13 @@ true - + + + + + @@ -465,7 +469,8 @@ - + + .. Prism Launcher (zip) @@ -473,7 +478,8 @@ - + + .. Modrinth (mrpack) @@ -481,15 +487,17 @@ - + + .. - CurseForge (zip) + CurseForge (zip) - + + .. Mod List @@ -552,7 +560,7 @@ .. - &View Instance Folder + View &Instance Folder Open the instance folder in a file browser. @@ -564,7 +572,7 @@ .. - &View Launcher Root Folder + View Launcher &Root Folder Open the launcher's root folder in a file browser. @@ -719,6 +727,28 @@ Open the %1 wiki + + + + + + View &Widget Themes Folder + + + View Widget Theme Folder + + + + + + + + View I&con Theme Folder + + + View Icon Theme Folder + + diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 8c9a6a585..525201be7 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -74,10 +74,13 @@ void ThemeManager::initializeIcons() // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies! // set icon theme search path! - QString themeFolder = "iconthemes"; + QDir themeFolder("iconthemes"); + if (!themeFolder.mkpath(".")) + themeWarningLog() << "Couldn't create icon theme folder"; + themeDebugLog() << "Icon Theme Folder Path: " << themeFolder.absolutePath(); auto searchPaths = QIcon::themeSearchPaths(); - searchPaths.append(themeFolder); + searchPaths.append(themeFolder.path()); QIcon::setThemeSearchPaths(searchPaths); themeDebugLog() << "<> Initializing Icon Themes"; @@ -93,7 +96,7 @@ void ThemeManager::initializeIcons() themeDebugLog() << "Loaded Built-In Icon Theme" << id; } - QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot); + QDirIterator directoryIterator(themeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); IconTheme theme(dir.dirName(), dir.path()); @@ -117,10 +120,13 @@ void ThemeManager::initializeWidgets() // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in // dropdown?) - QString themeFolder = QDir("./themes/").absoluteFilePath(""); - themeDebugLog() << "Theme Folder Path: " << themeFolder; - QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + QDir themeFolder("themes"); + if (!themeFolder.mkpath(".")) + themeWarningLog() << "Couldn't create theme folder"; + themeDebugLog() << "Theme Folder Path: " << themeFolder.absolutePath(); + + QDirIterator directoryIterator(themeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); QFileInfo themeJson(dir.absoluteFilePath("theme.json")); From 960093700a9daa4e2115d4663ab486a5dd1a4757 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 19 Jul 2023 20:57:08 +0100 Subject: [PATCH 164/398] Better theme reset Signed-off-by: TheKodeToad --- launcher/Application.cpp | 21 +++++++++---- launcher/ui/themes/ThemeManager.cpp | 46 ++++++++++++++--------------- launcher/ui/themes/ThemeManager.h | 9 +++--- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index df8a23636..ea706d6f4 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -526,7 +526,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings.reset(new INISettingsObject({ BuildConfig.LAUNCHER_CONFIGFILE, "polymc.cfg", "multimc.cfg" }, this)); // Theming - m_settings->registerSetting("IconTheme", QString("pe_colored")); + m_settings->registerSetting("IconTheme", QString()); m_settings->registerSetting("ApplicationTheme", QString()); m_settings->registerSetting("BackgroundCat", QString("kitteh")); @@ -801,7 +801,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) } // Themes - m_themeManager = std::make_unique(m_mainWindow); + m_themeManager = std::make_unique(); // initialize and load all instances { @@ -893,8 +893,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) } }); - applyCurrentlySelectedTheme(true); - updateCapabilities(); if(createSetupWizard()) @@ -902,6 +900,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) return; } + applyCurrentlySelectedTheme(true); performMainStartupAction(); } @@ -930,11 +929,21 @@ bool Application::createSetupWizard() }(); bool languageRequired = settings()->get("Language").toString().isEmpty(); bool pasteInterventionRequired = settings()->get("PastebinURL") != ""; - bool themeInterventionRequired = settings()->get("ApplicationTheme") == ""; + bool validWidgets = m_themeManager->isValidApplicationTheme(settings()->get("ApplicationTheme").toString()); + bool validIcons = m_themeManager->isValidIconTheme(settings()->get("IconTheme").toString()); + bool themeInterventionRequired = !validWidgets || !validIcons; bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired; if(wizardRequired) { + // set default theme after going into theme wizard + if (!validIcons) + settings()->set("IconTheme", QString("pe_colored")); + if (!validWidgets) + settings()->set("ApplicationTheme", QString("system")); + + applyCurrentlySelectedTheme(true); + m_setupWizard = new SetupWizard(nullptr); if (languageRequired) { @@ -953,9 +962,9 @@ bool Application::createSetupWizard() if (themeInterventionRequired) { - settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard)); } + connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished); m_setupWizard->show(); return true; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 525201be7..a9fae5896 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -29,9 +29,8 @@ #include "Application.h" -ThemeManager::ThemeManager(MainWindow* mainWindow) +ThemeManager::ThemeManager() { - m_mainWindow = mainWindow; initializeThemes(); } @@ -169,33 +168,27 @@ QList ThemeManager::getValidIconThemes() return ret; } -bool ThemeManager::setIconTheme(const QString& name) +bool ThemeManager::isValidApplicationTheme(const QString& id) +{ + return !id.isEmpty() && m_themes.find(id) != m_themes.end(); +} + +bool ThemeManager::isValidIconTheme(const QString& id) +{ + return !id.isEmpty() && m_icons.find(id) != m_icons.end(); +} + +void ThemeManager::setIconTheme(const QString& name) { if (m_icons.find(name) == m_icons.end()) { themeWarningLog() << "Tried to set invalid icon theme:" << name; - return false; + return; } QIcon::setThemeName(name); - return true; } -void ThemeManager::applyCurrentlySelectedTheme(bool initial) -{ - auto settings = APPLICATION->settings(); - if (!setIconTheme(settings->get("IconTheme").toString())) { - APPLICATION->settings()->reset("IconTheme"); - setIconTheme(settings->get("IconTheme").toString()); - } - themeDebugLog() << "<> Icon theme set."; - if (!setApplicationTheme(settings->get("ApplicationTheme").toString(), initial)) { - APPLICATION->settings()->reset("ApplicationTheme"); - setApplicationTheme(settings->get("ApplicationTheme").toString(), initial); - } - themeDebugLog() << "<> Application theme set."; -} - -bool ThemeManager::setApplicationTheme(const QString& name, bool initial) +void ThemeManager::setApplicationTheme(const QString& name, bool initial) { auto systemPalette = qApp->palette(); auto themeIter = m_themes.find(name); @@ -203,13 +196,20 @@ bool ThemeManager::setApplicationTheme(const QString& name, bool initial) auto& theme = themeIter->second; themeDebugLog() << "applying theme" << theme->name(); theme->apply(initial); - return true; } else { themeWarningLog() << "Tried to set invalid theme:" << name; - return false; } } +void ThemeManager::applyCurrentlySelectedTheme(bool initial) +{ + auto settings = APPLICATION->settings(); + setIconTheme(settings->get("IconTheme").toString()); + themeDebugLog() << "<> Icon theme set."; + setApplicationTheme(settings->get("ApplicationTheme").toString(), initial); + themeDebugLog() << "<> Application theme set."; +} + QString ThemeManager::getCatImage(QString catName) { QDateTime now = QDateTime::currentDateTime(); diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 2b6c57e97..627fdc75e 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -35,13 +35,15 @@ inline auto themeWarningLog() class ThemeManager { public: - ThemeManager(MainWindow* mainWindow); + ThemeManager(); QList getValidApplicationThemes(); QList getValidIconThemes(); - bool setIconTheme(const QString& name); + bool isValidApplicationTheme(const QString& id); + bool isValidIconTheme(const QString& id); void applyCurrentlySelectedTheme(bool initial = false); - bool setApplicationTheme(const QString& name, bool initial = false); + void setIconTheme(const QString& name); + void setApplicationTheme(const QString& name, bool initial = false); /// /// Returns the cat based on selected cat and with events (Birthday, XMas, etc.) @@ -53,7 +55,6 @@ class ThemeManager { private: std::map> m_themes; std::map m_icons; - MainWindow* m_mainWindow; void initializeThemes(); QString addTheme(std::unique_ptr theme); From 842f08dcfc29d24cae13c25264e67375dd069e27 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 20 Jul 2023 11:51:44 +0100 Subject: [PATCH 165/398] (UX) Add open folder button next to combo boxes Signed-off-by: TheKodeToad --- launcher/Application.cpp | 29 +----- launcher/Application.h | 10 +- launcher/DesktopServices.cpp | 2 +- launcher/ui/MainWindow.cpp | 8 +- launcher/ui/themes/ThemeManager.cpp | 50 +++++----- launcher/ui/themes/ThemeManager.h | 8 +- .../ui/widgets/ThemeCustomizationWidget.cpp | 35 ++++--- .../ui/widgets/ThemeCustomizationWidget.ui | 94 ++++++++++++++----- 8 files changed, 135 insertions(+), 101 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index ea706d6f4..40d506e35 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -900,7 +900,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) return; } - applyCurrentlySelectedTheme(true); + m_themeManager->applyCurrentlySelectedTheme(true); performMainStartupAction(); } @@ -942,7 +942,7 @@ bool Application::createSetupWizard() if (!validWidgets) settings()->set("ApplicationTheme", QString("system")); - applyCurrentlySelectedTheme(true); + m_themeManager->applyCurrentlySelectedTheme(true); m_setupWizard = new SetupWizard(nullptr); if (languageRequired) @@ -1167,31 +1167,6 @@ std::shared_ptr Application::javalist() return m_javalist; } -QList Application::getValidApplicationThemes() -{ - return m_themeManager->getValidApplicationThemes(); -} - -QList Application::getValidIconThemes() -{ - return m_themeManager->getValidIconThemes(); -} - -void Application::applyCurrentlySelectedTheme(bool initial) -{ - m_themeManager->applyCurrentlySelectedTheme(initial); -} - -void Application::setApplicationTheme(const QString& name) -{ - m_themeManager->setApplicationTheme(name); -} - -void Application::setIconTheme(const QString& name) -{ - m_themeManager->setIconTheme(name); -} - QIcon Application::getThemedIcon(const QString& name) { if(name == "logo") { diff --git a/launcher/Application.h b/launcher/Application.h index 0b953f0a5..b89960229 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -119,15 +119,7 @@ public: QIcon getThemedIcon(const QString& name); - void setIconTheme(const QString& name); - - void applyCurrentlySelectedTheme(bool initial = false); - - QList getValidApplicationThemes(); - - QList getValidIconThemes(); - - void setApplicationTheme(const QString& name); + ThemeManager* themeManager() { return m_themeManager.get(); } shared_qobject_ptr updater() { return m_updater; diff --git a/launcher/DesktopServices.cpp b/launcher/DesktopServices.cpp index 2984a1b4f..4939161f9 100644 --- a/launcher/DesktopServices.cpp +++ b/launcher/DesktopServices.cpp @@ -109,7 +109,7 @@ bool openDirectory(const QString &path, bool ensureExists) qDebug() << "Opening directory" << path; QDir parentPath; QDir dir(path); - if (!dir.exists()) + if (ensureExists && !dir.exists()) { parentPath.mkpath(dir.absolutePath()); } diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 600d245d9..00bb296fe 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -627,7 +627,7 @@ void MainWindow::updateThemeMenu() themeMenu = new QMenu(this); } - auto themes = APPLICATION->getValidApplicationThemes(); + auto themes = APPLICATION->themeManager()->getValidApplicationThemes(); QActionGroup* themesGroup = new QActionGroup(this); @@ -641,7 +641,7 @@ void MainWindow::updateThemeMenu() themeAction->setActionGroup(themesGroup); connect(themeAction, &QAction::triggered, [theme]() { - APPLICATION->setApplicationTheme(theme->id()); + APPLICATION->themeManager()->setApplicationTheme(theme->id()); APPLICATION->settings()->set("ApplicationTheme", theme->id()); }); } @@ -1152,12 +1152,12 @@ void MainWindow::on_actionViewCentralModsFolder_triggered() void MainWindow::on_actionViewIconThemeFolder_triggered() { - DesktopServices::openDirectory("iconthemes"); + DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path()); } void MainWindow::on_actionViewWidgetThemeFolder_triggered() { - DesktopServices::openDirectory("themes"); + DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path()); } void MainWindow::refreshInstances() diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index a9fae5896..32585618f 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -73,13 +73,12 @@ void ThemeManager::initializeIcons() // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies! // set icon theme search path! - QDir themeFolder("iconthemes"); - if (!themeFolder.mkpath(".")) + if (!m_iconThemeFolder.mkpath(".")) themeWarningLog() << "Couldn't create icon theme folder"; - themeDebugLog() << "Icon Theme Folder Path: " << themeFolder.absolutePath(); + themeDebugLog() << "Icon Theme Folder Path: " << m_iconThemeFolder.absolutePath(); auto searchPaths = QIcon::themeSearchPaths(); - searchPaths.append(themeFolder.path()); + searchPaths.append(m_iconThemeFolder.path()); QIcon::setThemeSearchPaths(searchPaths); themeDebugLog() << "<> Initializing Icon Themes"; @@ -95,7 +94,7 @@ void ThemeManager::initializeIcons() themeDebugLog() << "Loaded Built-In Icon Theme" << id; } - QDirIterator directoryIterator(themeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot); + QDirIterator directoryIterator(m_iconThemeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); IconTheme theme(dir.dirName(), dir.path()); @@ -120,12 +119,11 @@ void ThemeManager::initializeWidgets() // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in // dropdown?) - QDir themeFolder("themes"); - if (!themeFolder.mkpath(".")) + if (!m_applicationThemeFolder.mkpath(".")) themeWarningLog() << "Couldn't create theme folder"; - themeDebugLog() << "Theme Folder Path: " << themeFolder.absolutePath(); + themeDebugLog() << "Theme Folder Path: " << m_applicationThemeFolder.absolutePath(); - QDirIterator directoryIterator(themeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + QDirIterator directoryIterator(m_applicationThemeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); QFileInfo themeJson(dir.absoluteFilePath("theme.json")); @@ -148,16 +146,6 @@ void ThemeManager::initializeWidgets() themeDebugLog() << "<> Widget themes initialized."; } -QList ThemeManager::getValidApplicationThemes() -{ - QList ret; - ret.reserve(m_themes.size()); - for (auto&& [id, theme] : m_themes) { - ret.append(theme.get()); - } - return ret; -} - QList ThemeManager::getValidIconThemes() { QList ret; @@ -168,9 +156,14 @@ QList ThemeManager::getValidIconThemes() return ret; } -bool ThemeManager::isValidApplicationTheme(const QString& id) +QList ThemeManager::getValidApplicationThemes() { - return !id.isEmpty() && m_themes.find(id) != m_themes.end(); + QList ret; + ret.reserve(m_themes.size()); + for (auto&& [id, theme] : m_themes) { + ret.append(theme.get()); + } + return ret; } bool ThemeManager::isValidIconTheme(const QString& id) @@ -178,6 +171,21 @@ bool ThemeManager::isValidIconTheme(const QString& id) return !id.isEmpty() && m_icons.find(id) != m_icons.end(); } +bool ThemeManager::isValidApplicationTheme(const QString& id) +{ + return !id.isEmpty() && m_themes.find(id) != m_themes.end(); +} + +QDir ThemeManager::getIconThemesFolder() +{ + return m_iconThemeFolder; +} + +QDir ThemeManager::getApplicationThemesFolder() +{ + return m_applicationThemeFolder; +} + void ThemeManager::setIconTheme(const QString& name) { if (m_icons.find(name) == m_icons.end()) { diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 627fdc75e..5634a81a3 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -37,10 +37,12 @@ class ThemeManager { public: ThemeManager(); - QList getValidApplicationThemes(); QList getValidIconThemes(); - bool isValidApplicationTheme(const QString& id); + QList getValidApplicationThemes(); bool isValidIconTheme(const QString& id); + bool isValidApplicationTheme(const QString& id); + QDir getIconThemesFolder(); + QDir getApplicationThemesFolder(); void applyCurrentlySelectedTheme(bool initial = false); void setIconTheme(const QString& name); void setApplicationTheme(const QString& name, bool initial = false); @@ -55,6 +57,8 @@ class ThemeManager { private: std::map> m_themes; std::map m_icons; + QDir m_iconThemeFolder{ "iconthemes" }; + QDir m_applicationThemeFolder{ "themes" }; void initializeThemes(); QString addTheme(std::unique_ptr theme); diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index 455cbb7b6..106a9ca36 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -19,17 +19,22 @@ #include "ui_ThemeCustomizationWidget.h" #include "Application.h" +#include "DesktopServices.h" #include "ui/themes/ITheme.h" #include "ui/themes/ThemeManager.h" -ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ThemeCustomizationWidget) +ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget* parent) : QWidget(parent), ui(new Ui::ThemeCustomizationWidget) { ui->setupUi(this); loadSettings(); connect(ui->iconsComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyIconTheme); - connect(ui->widgetStyleComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyWidgetTheme); + connect(ui->widgetStyleComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ThemeCustomizationWidget::applyWidgetTheme); connect(ui->backgroundCatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyCatTheme); + + connect(ui->iconsFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path()); }); + connect(ui->widgetStyleFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path()); }); } ThemeCustomizationWidget::~ThemeCustomizationWidget() @@ -40,7 +45,7 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget() /// /// The layout was not quite right, so currently this just disables the UI elements, which should be hidden instead /// TODO FIXME -/// +/// /// Original Method One: /// ui->iconsComboBox->setVisible(features& ThemeFields::ICONS); /// ui->iconsLabel->setVisible(features& ThemeFields::ICONS); @@ -48,7 +53,7 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget() /// ui->widgetThemeLabel->setVisible(features& ThemeFields::WIDGETS); /// ui->backgroundCatComboBox->setVisible(features& ThemeFields::CAT); /// ui->backgroundCatLabel->setVisible(features& ThemeFields::CAT); -/// +/// /// original Method Two: /// if (!(features & ThemeFields::ICONS)) { /// ui->formLayout->setRowVisible(0, false); @@ -61,40 +66,44 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget() /// } /// /// -void ThemeCustomizationWidget::showFeatures(ThemeFields features) { +void ThemeCustomizationWidget::showFeatures(ThemeFields features) +{ ui->iconsComboBox->setEnabled(features & ThemeFields::ICONS); ui->iconsLabel->setEnabled(features & ThemeFields::ICONS); ui->widgetStyleComboBox->setEnabled(features & ThemeFields::WIDGETS); - ui->widgetThemeLabel->setEnabled(features & ThemeFields::WIDGETS); + ui->widgetStyleLabel->setEnabled(features & ThemeFields::WIDGETS); ui->backgroundCatComboBox->setEnabled(features & ThemeFields::CAT); ui->backgroundCatLabel->setEnabled(features & ThemeFields::CAT); } -void ThemeCustomizationWidget::applyIconTheme(int index) { +void ThemeCustomizationWidget::applyIconTheme(int index) +{ auto settings = APPLICATION->settings(); auto originalIconTheme = settings->get("IconTheme").toString(); auto newIconTheme = ui->iconsComboBox->currentData().toString(); if (originalIconTheme != newIconTheme) { settings->set("IconTheme", newIconTheme); - APPLICATION->applyCurrentlySelectedTheme(); + APPLICATION->themeManager()->applyCurrentlySelectedTheme(); } emit currentIconThemeChanged(index); } -void ThemeCustomizationWidget::applyWidgetTheme(int index) { +void ThemeCustomizationWidget::applyWidgetTheme(int index) +{ auto settings = APPLICATION->settings(); auto originalAppTheme = settings->get("ApplicationTheme").toString(); auto newAppTheme = ui->widgetStyleComboBox->currentData().toString(); if (originalAppTheme != newAppTheme) { settings->set("ApplicationTheme", newAppTheme); - APPLICATION->applyCurrentlySelectedTheme(); + APPLICATION->themeManager()->applyCurrentlySelectedTheme(); } emit currentWidgetThemeChanged(index); } -void ThemeCustomizationWidget::applyCatTheme(int index) { +void ThemeCustomizationWidget::applyCatTheme(int index) +{ auto settings = APPLICATION->settings(); settings->set("BackgroundCat", m_catOptions[index].first); @@ -113,7 +122,7 @@ void ThemeCustomizationWidget::loadSettings() { auto currentIconTheme = settings->get("IconTheme").toString(); - auto iconThemes = APPLICATION->getValidIconThemes(); + auto iconThemes = APPLICATION->themeManager()->getValidIconThemes(); int idx = 0; for (auto iconTheme : iconThemes) { QIcon iconForComboBox = QIcon(iconTheme->path() + "/scalable/settings"); @@ -127,7 +136,7 @@ void ThemeCustomizationWidget::loadSettings() { auto currentTheme = settings->get("ApplicationTheme").toString(); - auto themes = APPLICATION->getValidApplicationThemes(); + auto themes = APPLICATION->themeManager()->getValidApplicationThemes(); int idx = 0; for (auto& theme : themes) { ui->widgetStyleComboBox->addItem(theme->name(), theme->id()); diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.ui b/launcher/ui/widgets/ThemeCustomizationWidget.ui index 6b2c87f97..700c530c7 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.ui +++ b/launcher/ui/widgets/ThemeCustomizationWidget.ui @@ -40,20 +40,40 @@ - - - - 0 - 0 - - - - Qt::StrongFocus - - + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + + + + + View icon themes folder. + + + + + + + + + true + + + + - + &Widgets @@ -63,17 +83,37 @@ - - - - 0 - 0 - - - - Qt::StrongFocus - - + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + + + + + View widget themes folder. + + + + + + + + + true + + + + @@ -89,7 +129,7 @@ - + @@ -127,6 +167,12 @@ + + iconsComboBox + widgetStyleComboBox + backgroundCatComboBox + catInfoLabel + From 39f7bea53e8b8b30c1bb8c3e97eb4f856b361880 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 20 Jul 2023 14:13:29 +0100 Subject: [PATCH 166/398] Revert accidental change in MainWindow Signed-off-by: TheKodeToad --- launcher/ui/MainWindow.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 1bc620277..a3f6dff7c 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -131,7 +131,7 @@ 0 0 800 - 31 + 20 From 5088d33fd2aec8fed9725f9dedb64e9629226c11 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 20 Jul 2023 14:16:44 +0100 Subject: [PATCH 167/398] Finish things :P Signed-off-by: TheKodeToad --- launcher/ui/themes/IconTheme.cpp | 4 ++-- launcher/ui/themes/IconTheme.h | 2 +- launcher/ui/themes/ThemeManager.cpp | 11 +++++------ launcher/ui/widgets/ThemeCustomizationWidget.ui | 6 ------ 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/launcher/ui/themes/IconTheme.cpp b/launcher/ui/themes/IconTheme.cpp index cd1dfbaf5..4bd889854 100644 --- a/launcher/ui/themes/IconTheme.cpp +++ b/launcher/ui/themes/IconTheme.cpp @@ -25,7 +25,7 @@ IconTheme::IconTheme(const QString& id, const QString& path) : m_id(id), m_path( bool IconTheme::load() { - QString path = m_path + "/index.theme"; + const QString path = m_path + "/index.theme"; if (!QFile::exists(path)) return false; @@ -50,4 +50,4 @@ QString IconTheme::path() QString IconTheme::name() { return m_name; -} \ No newline at end of file +} diff --git a/launcher/ui/themes/IconTheme.h b/launcher/ui/themes/IconTheme.h index 458ea12c1..4e466c6ae 100644 --- a/launcher/ui/themes/IconTheme.h +++ b/launcher/ui/themes/IconTheme.h @@ -34,4 +34,4 @@ class IconTheme { QString m_id; QString m_path; QString m_name; -}; \ No newline at end of file +}; diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 32585618f..c929549e3 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -72,17 +72,12 @@ void ThemeManager::initializeIcons() { // TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies! // set icon theme search path! - - if (!m_iconThemeFolder.mkpath(".")) - themeWarningLog() << "Couldn't create icon theme folder"; - themeDebugLog() << "Icon Theme Folder Path: " << m_iconThemeFolder.absolutePath(); + themeDebugLog() << "<> Initializing Icon Themes"; auto searchPaths = QIcon::themeSearchPaths(); searchPaths.append(m_iconThemeFolder.path()); QIcon::setThemeSearchPaths(searchPaths); - themeDebugLog() << "<> Initializing Icon Themes"; - for (const QString& id : builtinIcons) { IconTheme theme(id, QString(":/icons/%1").arg(id)); if (!theme.load()) { @@ -94,6 +89,10 @@ void ThemeManager::initializeIcons() themeDebugLog() << "Loaded Built-In Icon Theme" << id; } + if (!m_iconThemeFolder.mkpath(".")) + themeWarningLog() << "Couldn't create icon theme folder"; + themeDebugLog() << "Icon Theme Folder Path: " << m_iconThemeFolder.absolutePath(); + QDirIterator directoryIterator(m_iconThemeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.ui b/launcher/ui/widgets/ThemeCustomizationWidget.ui index 700c530c7..266b1dd62 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.ui +++ b/launcher/ui/widgets/ThemeCustomizationWidget.ui @@ -167,12 +167,6 @@ - - iconsComboBox - widgetStyleComboBox - backgroundCatComboBox - catInfoLabel - From 8705e88e91959f7058902dd058d63bfd36f73cde Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 21 Jul 2023 11:19:55 +0100 Subject: [PATCH 168/398] Fix build on Windows Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 764cb0f2f..9841a72e0 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1079,7 +1079,6 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ScrollMessageBox.ui ui/dialogs/BlockedModsDialog.ui ui/dialogs/ChooseProviderDialog.ui - ui/dialogs/InstallLoaderDialog.ui ) qt_add_resources(LAUNCHER_RESOURCES From 1a7c5693cc9d21cf974ad56e55a3ca07a22c8477 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 21 Jul 2023 13:01:01 +0100 Subject: [PATCH 169/398] Remove redundant methods Signed-off-by: TheKodeToad --- launcher/Application.cpp | 10 ---------- launcher/Application.h | 4 ---- launcher/ui/instanceview/InstanceView.cpp | 4 ++-- launcher/ui/setupwizard/ThemeWizardPage.cpp | 2 +- launcher/ui/widgets/ThemeCustomizationWidget.cpp | 2 +- 5 files changed, 4 insertions(+), 18 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index e6a8562c2..acac2da26 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1175,16 +1175,6 @@ QIcon Application::getThemedIcon(const QString& name) return QIcon::fromTheme(name); } -QList Application::getValidCatPacks() -{ - return m_themeManager->getValidCatPacks(); -} - -QString Application::getCatPack(QString catName) -{ - return m_themeManager->getCatPack(catName); -} - bool Application::openJsonEditor(const QString& filename) { const QString file = QDir::current().absoluteFilePath(filename); diff --git a/launcher/Application.h b/launcher/Application.h index 203fd16ee..1c221cece 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -122,10 +122,6 @@ public: ThemeManager* themeManager() { return m_themeManager.get(); } - QList getValidCatPacks(); - - QString getCatPack(QString catName = ""); - shared_qobject_ptr updater() { return m_updater; } void triggerUpdateCheck(); diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 05f0004d1..155550e12 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -52,7 +52,7 @@ #include #include - +#include "ui/themes/ThemeManager.h" template bool listsIntersect(const QList &l1, const QList t2) { @@ -503,7 +503,7 @@ void InstanceView::setPaintCat(bool visible) { m_catVisible = visible; if (visible) - m_catPixmap.load(APPLICATION->getCatPack()); + m_catPixmap.load(APPLICATION->themeManager()->getCatPack()); else m_catPixmap = QPixmap(); } diff --git a/launcher/ui/setupwizard/ThemeWizardPage.cpp b/launcher/ui/setupwizard/ThemeWizardPage.cpp index 1c3369219..fe11ed9ae 100644 --- a/launcher/ui/setupwizard/ThemeWizardPage.cpp +++ b/launcher/ui/setupwizard/ThemeWizardPage.cpp @@ -61,7 +61,7 @@ void ThemeWizardPage::updateIcons() void ThemeWizardPage::updateCat() { qDebug() << "Setting Cat"; - ui->catImagePreviewButton->setIcon(QIcon(QString(R"(%1)").arg(APPLICATION->getCatPack()))); + ui->catImagePreviewButton->setIcon(QIcon(QString(R"(%1)").arg(APPLICATION->themeManager()->getCatPack()))); } void ThemeWizardPage::retranslate() diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index 8ccb5dcce..b9294908d 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -152,7 +152,7 @@ void ThemeCustomizationWidget::loadSettings() } auto cat = settings->get("BackgroundCat").toString(); - for (auto& catFromList : APPLICATION->getValidCatPacks()) { + for (auto& catFromList : APPLICATION->themeManager()->getValidCatPacks()) { QIcon catIcon = QIcon(QString("%1").arg(catFromList->path())); ui->backgroundCatComboBox->addItem(catIcon, catFromList->name(), catFromList->id()); if (cat == catFromList->id()) { From 516ddb22ae2c05e35401b0a5a6d81d93fc3d5ea1 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 21 Jul 2023 17:58:48 +0100 Subject: [PATCH 170/398] More catpack changes :3 This is just embarrasing Signed-off-by: TheKodeToad --- launcher/ui/themes/ThemeManager.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index fc7c3649b..46fe0b25d 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -62,7 +62,10 @@ ITheme* ThemeManager::getTheme(QString themeId) QString ThemeManager::addIconTheme(IconTheme theme) { QString id = theme.id(); - m_icons.emplace(id, std::move(theme)); + if (m_icons.find(id) == m_icons.end()) + m_icons.emplace(id, std::move(theme)); + else + themeWarningLog() << "IconTheme(" << id << ") not added to prevent id duplication"; return id; } @@ -129,7 +132,7 @@ void ThemeManager::initializeWidgets() themeWarningLog() << "Couldn't create theme folder"; themeDebugLog() << "Theme Folder Path: " << m_applicationThemeFolder.absolutePath(); - QDirIterator directoryIterator(m_applicationThemeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + QDirIterator directoryIterator(m_applicationThemeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); QFileInfo themeJson(dir.absoluteFilePath("theme.json")); From 816acc9c769eee50a4b738761d0b07995dc1eef6 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 26 Jul 2023 17:17:02 +0100 Subject: [PATCH 171/398] Open catpak folder action Signed-off-by: TheKodeToad --- launcher/ui/MainWindow.cpp | 5 +++++ launcher/ui/MainWindow.h | 1 + launcher/ui/MainWindow.ui | 17 ++++++++++++++--- launcher/ui/themes/ThemeManager.cpp | 15 ++++++++++----- launcher/ui/themes/ThemeManager.h | 2 ++ .../ui/widgets/ThemeCustomizationWidget.cpp | 1 + launcher/ui/widgets/ThemeCustomizationWidget.ui | 12 +++++++----- 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 00bb296fe..e4a699da6 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1160,6 +1160,11 @@ void MainWindow::on_actionViewWidgetThemeFolder_triggered() DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path()); } +void MainWindow::on_actionViewCatPackFolder_triggered() +{ + DesktopServices::openDirectory(APPLICATION->themeManager()->getCatPacksFolder().path()); +} + void MainWindow::refreshInstances() { APPLICATION->instances()->loadList(); diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 8756c0784..ffc7154a3 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -118,6 +118,7 @@ private slots: void on_actionViewIconThemeFolder_triggered(); void on_actionViewWidgetThemeFolder_triggered(); + void on_actionViewCatPackFolder_triggered(); void on_actionViewSelectedInstFolder_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index a3f6dff7c..ad0a0808a 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -131,7 +131,7 @@ 0 0 800 - 20 + 30 @@ -193,6 +193,7 @@ + @@ -729,7 +730,8 @@ - + + .. View &Widget Themes Folder @@ -740,7 +742,8 @@ - + + .. View I&con Theme Folder @@ -749,6 +752,14 @@ View Icon Theme Folder + + + + + + View Cat Packs Folder + + diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index 46fe0b25d..bce13b459 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -205,6 +205,11 @@ QDir ThemeManager::getApplicationThemesFolder() return m_applicationThemeFolder; } +QDir ThemeManager::getCatPacksFolder() +{ + return m_catPacksFolder; +} + void ThemeManager::setIconTheme(const QString& name) { if (m_icons.find(name) == m_icons.end()) { @@ -270,9 +275,9 @@ void ThemeManager::initializeCatPacks() for (auto [id, name] : defaultCats) { addCatPack(std::unique_ptr(new BasicCatPack(id, name))); } - QDir catpacksDir("catpacks"); - QString catpacksFolder = catpacksDir.absoluteFilePath(""); - themeDebugLog() << "CatPacks Folder Path:" << catpacksFolder; + if (!m_catPacksFolder.mkpath(".")) + themeWarningLog() << "Couldn't create theme folder"; + themeDebugLog() << "CatPacks Folder Path:" << m_catPacksFolder.absolutePath(); QStringList supportedImageFormats; for (auto format : QImageReader::supportedImageFormats()) { @@ -289,9 +294,9 @@ void ThemeManager::initializeCatPacks() } }; - loadFiles(catpacksDir); + loadFiles(m_catPacksFolder); - QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot); + QDirIterator directoryIterator(m_catPacksFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot); while (directoryIterator.hasNext()) { QDir dir(directoryIterator.next()); QFileInfo manifest(dir.absoluteFilePath("catpack.json")); diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h index 1eb83ce1e..b5c66677b 100644 --- a/launcher/ui/themes/ThemeManager.h +++ b/launcher/ui/themes/ThemeManager.h @@ -44,6 +44,7 @@ class ThemeManager { bool isValidApplicationTheme(const QString& id); QDir getIconThemesFolder(); QDir getApplicationThemesFolder(); + QDir getCatPacksFolder(); void applyCurrentlySelectedTheme(bool initial = false); void setIconTheme(const QString& name); void setApplicationTheme(const QString& name, bool initial = false); @@ -59,6 +60,7 @@ class ThemeManager { std::map m_icons; QDir m_iconThemeFolder{ "iconthemes" }; QDir m_applicationThemeFolder{ "themes" }; + QDir m_catPacksFolder{ "catpacks" }; std::map> m_catPacks; void initializeThemes(); diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index b9294908d..c999ac92c 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -35,6 +35,7 @@ ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget* parent) : QWidget(pa connect(ui->iconsFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path()); }); connect(ui->widgetStyleFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path()); }); + connect(ui->catPackFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getCatPacksFolder().path()); }); } ThemeCustomizationWidget::~ThemeCustomizationWidget() diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.ui b/launcher/ui/widgets/ThemeCustomizationWidget.ui index 266b1dd62..4503181c2 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.ui +++ b/launcher/ui/widgets/ThemeCustomizationWidget.ui @@ -63,7 +63,8 @@ - + + .. true @@ -106,7 +107,8 @@ - + + .. true @@ -147,15 +149,15 @@ - + - The cat appears in the background and is not shown by default. It is only made visible when pressing the Cat button in the Toolbar. + View cat packs folder. - + .. From 719d87de3bb6f65bc63ad518126074fd9f5f6283 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 26 Jul 2023 17:21:12 +0100 Subject: [PATCH 172/398] Update MainWindow.ui Signed-off-by: TheKodeToad --- launcher/ui/MainWindow.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index ad0a0808a..6ef32099f 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -131,7 +131,7 @@ 0 0 800 - 30 + 20 From d460986de0c84627d1725eada908e52911a97c5f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jul 2023 01:09:21 +0300 Subject: [PATCH 173/398] format Signed-off-by: Trial97 --- launcher/icons/IconList.cpp | 166 +++++++++++++++-------------------- launcher/icons/IconList.h | 64 +++++++------- launcher/icons/IconUtils.cpp | 32 +++---- launcher/icons/IconUtils.h | 4 +- launcher/icons/MMCIcon.cpp | 47 +++++----- launcher/icons/MMCIcon.h | 24 ++--- 6 files changed, 143 insertions(+), 194 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 13174f6e8..bfc5d5fbd 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -35,32 +35,29 @@ #include "IconList.h" #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #define MAX_SIZE 1024 -IconList::IconList(const QStringList &builtinPaths, QString path, QObject *parent) : QAbstractListModel(parent) +IconList::IconList(const QStringList& builtinPaths, QString path, QObject* parent) : QAbstractListModel(parent) { QSet builtinNames; // add builtin icons - for(auto & builtinPath: builtinPaths) - { + for (auto& builtinPath : builtinPaths) { QDir instance_icons(builtinPath); auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name); - for (auto file_info : file_info_list) - { + for (auto file_info : file_info_list) { builtinNames.insert(file_info.completeBaseName()); } } - for(auto & builtinName : builtinNames) - { + for (auto& builtinName : builtinNames) { addThemeIcon(builtinName); } @@ -78,31 +75,27 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren void IconList::sortIconList() { qDebug() << "Sorting icon list..."; - std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { - return a.m_key.localeAwareCompare(b.m_key) < 0; - }); + std::sort(icons.begin(), icons.end(), [](const MMCIcon& a, const MMCIcon& b) { return a.m_key.localeAwareCompare(b.m_key) < 0; }); reindex(); } -void IconList::directoryChanged(const QString &path) +void IconList::directoryChanged(const QString& path) { - QDir new_dir (path); - if(m_dir.absolutePath() != new_dir.absolutePath()) - { + QDir new_dir(path); + if (m_dir.absolutePath() != new_dir.absolutePath()) { m_dir.setPath(path); m_dir.refresh(); - if(is_watching) + if (is_watching) stopWatching(); startWatching(); } - if(!m_dir.exists()) - if(!FS::ensureFolderPathExists(m_dir.absolutePath())) + if (!m_dir.exists()) + if (!FS::ensureFolderPathExists(m_dir.absolutePath())) return; m_dir.refresh(); auto new_list = m_dir.entryList(QDir::Files, QDir::Name); - for (auto it = new_list.begin(); it != new_list.end(); it++) - { - QString &foo = (*it); + for (auto it = new_list.begin(); it != new_list.end(); it++) { + QString& foo = (*it); foo = m_dir.filePath(foo); } #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) @@ -111,8 +104,7 @@ void IconList::directoryChanged(const QString &path) auto new_set = new_list.toSet(); #endif QList current_list; - for (auto &it : icons) - { + for (auto& it : icons) { if (!it.has(IconType::FileBased)) continue; current_list.push_back(it.m_images[IconType::FileBased].filename); @@ -129,8 +121,7 @@ void IconList::directoryChanged(const QString &path) QSet to_add = new_set; to_add -= current_set; - for (auto remove : to_remove) - { + for (auto remove : to_remove) { qDebug() << "Removing " << remove; QFileInfo rmfile(remove); QString key = rmfile.completeBaseName(); @@ -144,23 +135,19 @@ void IconList::directoryChanged(const QString &path) if (idx == -1) continue; icons[idx].remove(IconType::FileBased); - if (icons[idx].type() == IconType::ToBeDeleted) - { + if (icons[idx].type() == IconType::ToBeDeleted) { beginRemoveRows(QModelIndex(), idx, idx); icons.remove(idx); reindex(); endRemoveRows(); - } - else - { + } else { dataChanged(index(idx), index(idx)); } m_watcher->removePath(remove); emit iconUpdated(key); } - for (auto add : to_add) - { + for (auto add : to_add) { qDebug() << "Adding " << add; QFileInfo addfile(add); @@ -171,8 +158,7 @@ void IconList::directoryChanged(const QString &path) if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif") key = addfile.fileName(); - if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased)) - { + if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased)) { m_watcher->addPath(add); emit iconUpdated(key); } @@ -181,7 +167,7 @@ void IconList::directoryChanged(const QString &path) sortIconList(); } -void IconList::fileChanged(const QString &path) +void IconList::fileChanged(const QString& path) { qDebug() << "Checking " << path; QFileInfo checkfile(path); @@ -200,9 +186,9 @@ void IconList::fileChanged(const QString &path) emit iconUpdated(key); } -void IconList::SettingChanged(const Setting &setting, QVariant value) +void IconList::SettingChanged(const Setting& setting, QVariant value) { - if(setting.id() != "IconsDir") + if (setting.id() != "IconsDir") return; directoryChanged(value.toString()); @@ -213,12 +199,9 @@ void IconList::startWatching() auto abs_path = m_dir.absolutePath(); FS::ensureFolderPathExists(abs_path); is_watching = m_watcher->addPath(abs_path); - if (is_watching) - { + if (is_watching) { qDebug() << "Started watching " << abs_path; - } - else - { + } else { qDebug() << "Failed to start watching " << abs_path; } } @@ -241,7 +224,11 @@ Qt::DropActions IconList::supportedDropActions() const return Qt::CopyAction; } -bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, [[maybe_unused]] const QModelIndex &parent) +bool IconList::dropMimeData(const QMimeData* data, + Qt::DropAction action, + [[maybe_unused]] int row, + [[maybe_unused]] int column, + [[maybe_unused]] const QModelIndex& parent) { if (action == Qt::IgnoreAction) return true; @@ -250,12 +237,10 @@ bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[mayb return false; // files dropped from outside? - if (data->hasUrls()) - { + if (data->hasUrls()) { auto urls = data->urls(); QStringList iconFiles; - for (auto url : urls) - { + for (auto url : urls) { // only local files may be dropped... if (!url.isLocalFile()) continue; @@ -267,7 +252,7 @@ bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[mayb return false; } -Qt::ItemFlags IconList::flags(const QModelIndex &index) const +Qt::ItemFlags IconList::flags(const QModelIndex& index) const { Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); if (index.isValid()) @@ -276,7 +261,7 @@ Qt::ItemFlags IconList::flags(const QModelIndex &index) const return Qt::ItemIsDropEnabled | defaultFlags; } -QVariant IconList::data(const QModelIndex &index, int role) const +QVariant IconList::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); @@ -286,28 +271,26 @@ QVariant IconList::data(const QModelIndex &index, int role) const if (row < 0 || row >= icons.size()) return QVariant(); - switch (role) - { - case Qt::DecorationRole: - return icons[row].icon(); - case Qt::DisplayRole: - return icons[row].name(); - case Qt::UserRole: - return icons[row].m_key; - default: - return QVariant(); + switch (role) { + case Qt::DecorationRole: + return icons[row].icon(); + case Qt::DisplayRole: + return icons[row].name(); + case Qt::UserRole: + return icons[row].m_key; + default: + return QVariant(); } } -int IconList::rowCount(const QModelIndex &parent) const +int IconList::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : icons.size(); } -void IconList::installIcons(const QStringList &iconFiles) +void IconList::installIcons(const QStringList& iconFiles) { - for (QString file : iconFiles) - { + for (QString file : iconFiles) { QFileInfo fileinfo(file); if (!fileinfo.isReadable() || !fileinfo.isFile()) continue; @@ -322,10 +305,10 @@ void IconList::installIcons(const QStringList &iconFiles) } } -void IconList::installIcon(const QString &file, const QString &name) +void IconList::installIcon(const QString& file, const QString& name) { QFileInfo fileinfo(file); - if(!fileinfo.isReadable() || !fileinfo.isFile()) + if (!fileinfo.isReadable() || !fileinfo.isFile()) return; QString target = FS::PathCombine(getDirectory(), name); @@ -333,17 +316,16 @@ void IconList::installIcon(const QString &file, const QString &name) QFile::copy(file, target); } -bool IconList::iconFileExists(const QString &key) const +bool IconList::iconFileExists(const QString& key) const { auto iconEntry = icon(key); - if(!iconEntry) - { + if (!iconEntry) { return false; } return iconEntry->has(IconType::FileBased); } -const MMCIcon *IconList::icon(const QString &key) const +const MMCIcon* IconList::icon(const QString& key) const { int iconIdx = getIconIndex(key); if (iconIdx == -1) @@ -351,7 +333,7 @@ const MMCIcon *IconList::icon(const QString &key) const return &icons[iconIdx]; } -bool IconList::deleteIcon(const QString &key) +bool IconList::deleteIcon(const QString& key) { if (!iconFileExists(key)) return false; @@ -359,7 +341,7 @@ bool IconList::deleteIcon(const QString &key) return QFile::remove(icon(key)->getFilePath()); } -bool IconList::trashIcon(const QString &key) +bool IconList::trashIcon(const QString& key) { if (!iconFileExists(key)) return false; @@ -370,15 +352,12 @@ bool IconList::trashIcon(const QString &key) bool IconList::addThemeIcon(const QString& key) { auto iter = name_index.find(key); - if (iter != name_index.end()) - { - auto &oldOne = icons[*iter]; + if (iter != name_index.end()) { + auto& oldOne = icons[*iter]; oldOne.replace(Builtin, key); dataChanged(index(*iter), index(*iter)); return true; - } - else - { + } else { // add a new icon beginInsertRows(QModelIndex(), icons.size(), icons.size()); { @@ -394,22 +373,19 @@ bool IconList::addThemeIcon(const QString& key) } } -bool IconList::addIcon(const QString &key, const QString &name, const QString &path, const IconType type) +bool IconList::addIcon(const QString& key, const QString& name, const QString& path, const IconType type) { // replace the icon even? is the input valid? QIcon icon(path); if (icon.isNull()) return false; auto iter = name_index.find(key); - if (iter != name_index.end()) - { - auto &oldOne = icons[*iter]; + if (iter != name_index.end()) { + auto& oldOne = icons[*iter]; oldOne.replace(type, icon, path); dataChanged(index(*iter), index(*iter)); return true; - } - else - { + } else { // add a new icon beginInsertRows(QModelIndex(), icons.size(), icons.size()); { @@ -425,26 +401,24 @@ bool IconList::addIcon(const QString &key, const QString &name, const QString &p } } -void IconList::saveIcon(const QString &key, const QString &path, const char * format) const +void IconList::saveIcon(const QString& key, const QString& path, const char* format) const { auto icon = getIcon(key); auto pixmap = icon.pixmap(128, 128); pixmap.save(path, format); } - void IconList::reindex() { name_index.clear(); int i = 0; - for (auto &iter : icons) - { + for (auto& iter : icons) { name_index[iter.m_key] = i; i++; } } -QIcon IconList::getIcon(const QString &key) const +QIcon IconList::getIcon(const QString& key) const { int icon_index = getIconIndex(key); @@ -459,7 +433,7 @@ QIcon IconList::getIcon(const QString &key) const return QIcon(); } -int IconList::getIconIndex(const QString &key) const +int IconList::getIconIndex(const QString& key) const { auto iter = name_index.find(key == "default" ? "grass" : key); if (iter != name_index.end()) @@ -473,4 +447,4 @@ QString IconList::getDirectory() const return m_dir.absolutePath(); } -//#include "IconList.moc" +// #include "IconList.moc" diff --git a/launcher/icons/IconList.h b/launcher/icons/IconList.h index 97141e4ae..bc1dd3b9b 100644 --- a/launcher/icons/IconList.h +++ b/launcher/icons/IconList.h @@ -15,10 +15,10 @@ #pragma once -#include #include -#include #include +#include +#include #include #include @@ -29,58 +29,58 @@ class QFileSystemWatcher; -class IconList : public QAbstractListModel -{ +class IconList : public QAbstractListModel { Q_OBJECT -public: - explicit IconList(const QStringList &builtinPaths, QString path, QObject *parent = 0); - virtual ~IconList() {}; + public: + explicit IconList(const QStringList& builtinPaths, QString path, QObject* parent = 0); + virtual ~IconList(){}; - QIcon getIcon(const QString &key) const; - int getIconIndex(const QString &key) const; + QIcon getIcon(const QString& key) const; + int getIconIndex(const QString& key) const; QString getDirectory() const; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; virtual QStringList mimeTypes() const override; virtual Qt::DropActions supportedDropActions() const override; - virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; - virtual Qt::ItemFlags flags(const QModelIndex &index) const override; + virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; + virtual Qt::ItemFlags flags(const QModelIndex& index) const override; - bool addThemeIcon(const QString &key); - bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type); - void saveIcon(const QString &key, const QString &path, const char * format) const; - bool deleteIcon(const QString &key); - bool trashIcon(const QString &key); - bool iconFileExists(const QString &key) const; + bool addThemeIcon(const QString& key); + bool addIcon(const QString& key, const QString& name, const QString& path, const IconType type); + void saveIcon(const QString& key, const QString& path, const char* format) const; + bool deleteIcon(const QString& key); + bool trashIcon(const QString& key); + bool iconFileExists(const QString& key) const; - void installIcons(const QStringList &iconFiles); - void installIcon(const QString &file, const QString &name); + void installIcons(const QStringList& iconFiles); + void installIcon(const QString& file, const QString& name); - const MMCIcon * icon(const QString &key) const; + const MMCIcon* icon(const QString& key) const; void startWatching(); void stopWatching(); -signals: + signals: void iconUpdated(QString key); -private: + private: // hide copy constructor - IconList(const IconList &) = delete; + IconList(const IconList&) = delete; // hide assign op - IconList &operator=(const IconList &) = delete; + IconList& operator=(const IconList&) = delete; void reindex(); void sortIconList(); -public slots: - void directoryChanged(const QString &path); + public slots: + void directoryChanged(const QString& path); -protected slots: - void fileChanged(const QString &path); - void SettingChanged(const Setting & setting, QVariant value); -private: + protected slots: + void fileChanged(const QString& path); + void SettingChanged(const Setting& setting, QVariant value); + + private: shared_qobject_ptr m_watcher; bool is_watching; QMap name_index; diff --git a/launcher/icons/IconUtils.cpp b/launcher/icons/IconUtils.cpp index bf530c16f..0b06639e7 100644 --- a/launcher/icons/IconUtils.cpp +++ b/launcher/icons/IconUtils.cpp @@ -1,24 +1,18 @@ #include "IconUtils.h" -#include "FileSystem.h" #include +#include "FileSystem.h" #include namespace { -std::array validIconExtensions = {{ - "svg", - "png", - "ico", - "gif", - "jpg", - "jpeg" -}}; +std::array validIconExtensions = { { "svg", "png", "ico", "gif", "jpg", "jpeg" } }; } -namespace IconUtils{ +namespace IconUtils { -QString findBestIconIn(const QString &folder, const QString & iconKey) { +QString findBestIconIn(const QString& folder, const QString& iconKey) +{ int best_found = validIconExtensions.size(); QString best_filename; @@ -27,13 +21,13 @@ QString findBestIconIn(const QString &folder, const QString & iconKey) { it.next(); auto fileInfo = it.fileInfo(); - if(fileInfo.completeBaseName() != iconKey) + if (fileInfo.completeBaseName() != iconKey) continue; auto extension = fileInfo.suffix(); - for(int i = 0; i < best_found; i++) { - if(extension == validIconExtensions[i]) { + for (int i = 0; i < best_found; i++) { + if (extension == validIconExtensions[i]) { best_found = i; qDebug() << i << " : " << fileInfo.fileName(); best_filename = fileInfo.fileName(); @@ -43,12 +37,13 @@ QString findBestIconIn(const QString &folder, const QString & iconKey) { return FS::PathCombine(folder, best_filename); } -QString getIconFilter() { +QString getIconFilter() +{ QString out; QTextStream stream(&out); stream << '('; - for(size_t i = 0; i < validIconExtensions.size() - 1; i++) { - if(i > 0) { + for (size_t i = 0; i < validIconExtensions.size() - 1; i++) { + if (i > 0) { stream << " "; } stream << "*." << validIconExtensions[i]; @@ -58,5 +53,4 @@ QString getIconFilter() { return out; } -} - +} // namespace IconUtils diff --git a/launcher/icons/IconUtils.h b/launcher/icons/IconUtils.h index be93d9143..8c6f677dd 100644 --- a/launcher/icons/IconUtils.h +++ b/launcher/icons/IconUtils.h @@ -5,9 +5,9 @@ namespace IconUtils { // Given a folder and an icon key, find 'best' of the icons with the given key in there and return its path -QString findBestIconIn(const QString &folder, const QString & iconKey); +QString findBestIconIn(const QString& folder, const QString& iconKey); // Get icon file type filter for file browser dialogs QString getIconFilter(); -} +} // namespace IconUtils diff --git a/launcher/icons/MMCIcon.cpp b/launcher/icons/MMCIcon.cpp index 436ef75ff..9c1b366c3 100644 --- a/launcher/icons/MMCIcon.cpp +++ b/launcher/icons/MMCIcon.cpp @@ -37,23 +37,21 @@ #include #include -IconType operator--(IconType &t, int) +IconType operator--(IconType& t, int) { IconType temp = t; - switch (t) - { - case IconType::Builtin: - t = IconType::ToBeDeleted; - break; - case IconType::Transient: - t = IconType::Builtin; - break; - case IconType::FileBased: - t = IconType::Transient; - break; - default: - { - } + switch (t) { + case IconType::Builtin: + t = IconType::ToBeDeleted; + break; + case IconType::Transient: + t = IconType::Builtin; + break; + case IconType::FileBased: + t = IconType::Transient; + break; + default: { + } } return temp; } @@ -79,8 +77,8 @@ QIcon MMCIcon::icon() const { if (m_current_type == IconType::ToBeDeleted) return QIcon(); - auto & icon = m_images[m_current_type].icon; - if(!icon.isNull()) + auto& icon = m_images[m_current_type].icon; + if (!icon.isNull()) return icon; // FIXME: inject this. return QIcon::fromTheme(m_images[m_current_type].key); @@ -90,10 +88,8 @@ void MMCIcon::remove(IconType rm_type) { m_images[rm_type].filename = QString(); m_images[rm_type].icon = QIcon(); - for (auto iter = rm_type; iter != IconType::ToBeDeleted; iter--) - { - if (m_images[iter].present()) - { + for (auto iter = rm_type; iter != IconType::ToBeDeleted; iter--) { + if (m_images[iter].present()) { m_current_type = iter; return; } @@ -103,8 +99,7 @@ void MMCIcon::remove(IconType rm_type) void MMCIcon::replace(IconType new_type, QIcon icon, QString path) { - if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) - { + if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) { m_current_type = new_type; } m_images[new_type].icon = icon; @@ -114,8 +109,7 @@ void MMCIcon::replace(IconType new_type, QIcon icon, QString path) void MMCIcon::replace(IconType new_type, const QString& key) { - if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) - { + if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted) { m_current_type = new_type; } m_images[new_type].icon = QIcon(); @@ -125,13 +119,12 @@ void MMCIcon::replace(IconType new_type, const QString& key) QString MMCIcon::getFilePath() const { - if(m_current_type == IconType::ToBeDeleted){ + if (m_current_type == IconType::ToBeDeleted) { return QString(); } return m_images[m_current_type].filename; } - bool MMCIcon::isBuiltIn() const { return m_current_type == IconType::Builtin; diff --git a/launcher/icons/MMCIcon.h b/launcher/icons/MMCIcon.h index 13d99318a..c968f306a 100644 --- a/launcher/icons/MMCIcon.h +++ b/launcher/icons/MMCIcon.h @@ -14,32 +14,20 @@ */ #pragma once -#include #include #include +#include -enum IconType : unsigned -{ - Builtin, - Transient, - FileBased, - ICONS_TOTAL, - ToBeDeleted -}; +enum IconType : unsigned { Builtin, Transient, FileBased, ICONS_TOTAL, ToBeDeleted }; -struct MMCImage -{ +struct MMCImage { QIcon icon; QString key; QString filename; - bool present() const - { - return !icon.isNull() || !key.isEmpty(); - } + bool present() const { return !icon.isNull() || !key.isEmpty(); } }; -struct MMCIcon -{ +struct MMCIcon { QString m_key; QString m_name; MMCImage m_images[ICONS_TOTAL]; @@ -51,7 +39,7 @@ struct MMCIcon QIcon icon() const; void remove(IconType rm_type); void replace(IconType new_type, QIcon icon, QString path = QString()); - void replace(IconType new_type, const QString &key); + void replace(IconType new_type, const QString& key); bool isBuiltIn() const; QString getFilePath() const; }; From 1ca7e5efe946d24f3898c8623ff1af3ef9dd96e6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jul 2023 01:12:15 +0300 Subject: [PATCH 174/398] added license header Signed-off-by: Trial97 --- launcher/icons/IconList.cpp | 3 ++- launcher/icons/IconList.h | 41 ++++++++++++++++++++++++++---------- launcher/icons/IconUtils.cpp | 35 ++++++++++++++++++++++++++++++ launcher/icons/IconUtils.h | 35 ++++++++++++++++++++++++++++++ launcher/icons/MMCIcon.cpp | 3 ++- launcher/icons/MMCIcon.h | 41 ++++++++++++++++++++++++++---------- 6 files changed, 134 insertions(+), 24 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index bfc5d5fbd..50aef7900 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/icons/IconList.h b/launcher/icons/IconList.h index bc1dd3b9b..8afd05574 100644 --- a/launcher/icons/IconList.h +++ b/launcher/icons/IconList.h @@ -1,18 +1,37 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 * - * 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 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 diff --git a/launcher/icons/IconUtils.cpp b/launcher/icons/IconUtils.cpp index 0b06639e7..39830bc21 100644 --- a/launcher/icons/IconUtils.cpp +++ b/launcher/icons/IconUtils.cpp @@ -1,3 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 "IconUtils.h" #include diff --git a/launcher/icons/IconUtils.h b/launcher/icons/IconUtils.h index 8c6f677dd..41aea6761 100644 --- a/launcher/icons/IconUtils.h +++ b/launcher/icons/IconUtils.h @@ -1,3 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 diff --git a/launcher/icons/MMCIcon.cpp b/launcher/icons/MMCIcon.cpp index 9c1b366c3..fed588958 100644 --- a/launcher/icons/MMCIcon.cpp +++ b/launcher/icons/MMCIcon.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/icons/MMCIcon.h b/launcher/icons/MMCIcon.h index c968f306a..a6e305668 100644 --- a/launcher/icons/MMCIcon.h +++ b/launcher/icons/MMCIcon.h @@ -1,18 +1,37 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 * - * 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 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. * - * http://www.apache.org/licenses/LICENSE-2.0 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 From 7e58b965b770ab75c14f2265b7bd7ded081c66b5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jul 2023 01:15:21 +0300 Subject: [PATCH 175/398] refactor icon list Signed-off-by: Trial97 --- launcher/icons/IconList.cpp | 92 ++++++++++++++---------------------- launcher/icons/IconUtils.cpp | 39 ++++----------- launcher/icons/IconUtils.h | 1 + launcher/icons/MMCIcon.cpp | 4 +- 4 files changed, 49 insertions(+), 87 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 50aef7900..a1026e833 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -43,6 +43,7 @@ #include #include #include +#include "icons/IconUtils.h" #define MAX_SIZE 1024 @@ -129,7 +130,7 @@ void IconList::directoryChanged(const QString& path) QString suffix = rmfile.suffix(); // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well - if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif") + if (!IconUtils::isIconSuffix(suffix)) key = rmfile.fileName(); int idx = getIconIndex(key); @@ -156,7 +157,7 @@ void IconList::directoryChanged(const QString& path) QString suffix = addfile.suffix(); // The icon doesnt have a suffix, but it can have other .s in the name, so we account for those as well - if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif") + if (!IconUtils::isIconSuffix(suffix)) key = addfile.fileName(); if (addIcon(key, QString(), addfile.filePath(), IconType::FileBased)) { @@ -258,8 +259,7 @@ Qt::ItemFlags IconList::flags(const QModelIndex& index) const Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); if (index.isValid()) return Qt::ItemIsDropEnabled | defaultFlags; - else - return Qt::ItemIsDropEnabled | defaultFlags; + return Qt::ItemIsDropEnabled | defaultFlags; } QVariant IconList::data(const QModelIndex& index, int role) const @@ -291,19 +291,8 @@ int IconList::rowCount(const QModelIndex& parent) const void IconList::installIcons(const QStringList& iconFiles) { - for (QString file : iconFiles) { - QFileInfo fileinfo(file); - if (!fileinfo.isReadable() || !fileinfo.isFile()) - continue; - QString target = FS::PathCombine(getDirectory(), fileinfo.fileName()); - - QString suffix = fileinfo.suffix(); - if (suffix != "jpeg" && suffix != "png" && suffix != "jpg" && suffix != "ico" && suffix != "svg" && suffix != "gif") - continue; - - if (!QFile::copy(file, target)) - continue; - } + for (QString file : iconFiles) + installIcon(file, {}); } void IconList::installIcon(const QString& file, const QString& name) @@ -312,18 +301,17 @@ void IconList::installIcon(const QString& file, const QString& name) if (!fileinfo.isReadable() || !fileinfo.isFile()) return; - QString target = FS::PathCombine(getDirectory(), name); + if (!IconUtils::isIconSuffix(fileinfo.suffix())) + return; + QString target = FS::PathCombine(getDirectory(), name.isEmpty() ? fileinfo.fileName() : name); QFile::copy(file, target); } bool IconList::iconFileExists(const QString& key) const { auto iconEntry = icon(key); - if (!iconEntry) { - return false; - } - return iconEntry->has(IconType::FileBased); + return iconEntry && iconEntry->has(IconType::FileBased); } const MMCIcon* IconList::icon(const QString& key) const @@ -336,18 +324,12 @@ const MMCIcon* IconList::icon(const QString& key) const bool IconList::deleteIcon(const QString& key) { - if (!iconFileExists(key)) - return false; - - return QFile::remove(icon(key)->getFilePath()); + return iconFileExists(key) && QFile::remove(icon(key)->getFilePath()); } bool IconList::trashIcon(const QString& key) { - if (!iconFileExists(key)) - return false; - - return FS::trash(icon(key)->getFilePath(), nullptr); + return iconFileExists(key) && FS::trash(icon(key)->getFilePath(), nullptr); } bool IconList::addThemeIcon(const QString& key) @@ -358,20 +340,19 @@ bool IconList::addThemeIcon(const QString& key) oldOne.replace(Builtin, key); dataChanged(index(*iter), index(*iter)); return true; - } else { - // add a new icon - beginInsertRows(QModelIndex(), icons.size(), icons.size()); - { - MMCIcon mmc_icon; - mmc_icon.m_name = key; - mmc_icon.m_key = key; - mmc_icon.replace(Builtin, key); - icons.push_back(mmc_icon); - name_index[key] = icons.size() - 1; - } - endInsertRows(); - return true; } + // add a new icon + beginInsertRows(QModelIndex(), icons.size(), icons.size()); + { + MMCIcon mmc_icon; + mmc_icon.m_name = key; + mmc_icon.m_key = key; + mmc_icon.replace(Builtin, key); + icons.push_back(mmc_icon); + name_index[key] = icons.size() - 1; + } + endInsertRows(); + return true; } bool IconList::addIcon(const QString& key, const QString& name, const QString& path, const IconType type) @@ -386,20 +367,19 @@ bool IconList::addIcon(const QString& key, const QString& name, const QString& p oldOne.replace(type, icon, path); dataChanged(index(*iter), index(*iter)); return true; - } else { - // add a new icon - beginInsertRows(QModelIndex(), icons.size(), icons.size()); - { - MMCIcon mmc_icon; - mmc_icon.m_name = name; - mmc_icon.m_key = key; - mmc_icon.replace(type, icon, path); - icons.push_back(mmc_icon); - name_index[key] = icons.size() - 1; - } - endInsertRows(); - return true; } + // add a new icon + beginInsertRows(QModelIndex(), icons.size(), icons.size()); + { + MMCIcon mmc_icon; + mmc_icon.m_name = name; + mmc_icon.m_key = key; + mmc_icon.replace(type, icon, path); + icons.push_back(mmc_icon); + name_index[key] = icons.size() - 1; + } + endInsertRows(); + return true; } void IconList::saveIcon(const QString& key, const QString& path, const char* format) const diff --git a/launcher/icons/IconUtils.cpp b/launcher/icons/IconUtils.cpp index 39830bc21..99c38f47a 100644 --- a/launcher/icons/IconUtils.cpp +++ b/launcher/icons/IconUtils.cpp @@ -38,17 +38,14 @@ #include #include "FileSystem.h" -#include - namespace { -std::array validIconExtensions = { { "svg", "png", "ico", "gif", "jpg", "jpeg" } }; +static const QStringList validIconExtensions = { { "svg", "png", "ico", "gif", "jpg", "jpeg" } }; } namespace IconUtils { QString findBestIconIn(const QString& folder, const QString& iconKey) { - int best_found = validIconExtensions.size(); QString best_filename; QDirIterator it(folder, QDir::NoDotAndDotDot | QDir::Files, QDirIterator::NoIteratorFlags); @@ -56,36 +53,20 @@ QString findBestIconIn(const QString& folder, const QString& iconKey) it.next(); auto fileInfo = it.fileInfo(); - if (fileInfo.completeBaseName() != iconKey) - continue; - - auto extension = fileInfo.suffix(); - - for (int i = 0; i < best_found; i++) { - if (extension == validIconExtensions[i]) { - best_found = i; - qDebug() << i << " : " << fileInfo.fileName(); - best_filename = fileInfo.fileName(); - } - } + if (fileInfo.completeBaseName() == iconKey && isIconSuffix(fileInfo.suffix())) + return fileInfo.absoluteFilePath(); } - return FS::PathCombine(folder, best_filename); + return {}; } QString getIconFilter() { - QString out; - QTextStream stream(&out); - stream << '('; - for (size_t i = 0; i < validIconExtensions.size() - 1; i++) { - if (i > 0) { - stream << " "; - } - stream << "*." << validIconExtensions[i]; - } - stream << " *." << validIconExtensions[validIconExtensions.size() - 1]; - stream << ')'; - return out; + return "(*." + validIconExtensions.join(" *.") + ")"; +} + +bool isIconSuffix(QString suffix) +{ + return validIconExtensions.contains(suffix); } } // namespace IconUtils diff --git a/launcher/icons/IconUtils.h b/launcher/icons/IconUtils.h index 41aea6761..90cdfe5ab 100644 --- a/launcher/icons/IconUtils.h +++ b/launcher/icons/IconUtils.h @@ -45,4 +45,5 @@ QString findBestIconIn(const QString& folder, const QString& iconKey); // Get icon file type filter for file browser dialogs QString getIconFilter(); +bool isIconSuffix(QString suffix); } // namespace IconUtils diff --git a/launcher/icons/MMCIcon.cpp b/launcher/icons/MMCIcon.cpp index fed588958..991b470c0 100644 --- a/launcher/icons/MMCIcon.cpp +++ b/launcher/icons/MMCIcon.cpp @@ -51,8 +51,8 @@ IconType operator--(IconType& t, int) case IconType::FileBased: t = IconType::Transient; break; - default: { - } + default: + break; } return temp; } From 97ff7afbe749358728bf4843f1022f2994902ef7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jul 2023 01:16:00 +0300 Subject: [PATCH 176/398] keep the icon suffix Signed-off-by: Trial97 --- launcher/ui/dialogs/NewInstanceDialog.cpp | 11 +++++------ .../ui/pages/modplatform/atlauncher/AtlListModel.cpp | 5 ++--- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 12 +++++++----- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 11 ++++------- .../ui/pages/modplatform/legacy_ftb/ListModel.cpp | 4 ++-- .../ui/pages/modplatform/modrinth/ModrinthModel.cpp | 7 ++----- .../ui/pages/modplatform/technic/TechnicModel.cpp | 4 ++-- .../ui/pages/modplatform/technic/TechnicPage.cpp | 11 ++++------- 8 files changed, 28 insertions(+), 37 deletions(-) diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 7b9bb944c..fb91b8ae7 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -284,28 +284,27 @@ QString NewInstanceDialog::iconKey() const void NewInstanceDialog::on_iconButton_clicked() { - importIconNow(); //so the user can switch back + importIconNow(); // so the user can switch back IconPickerDialog dlg(this); dlg.execWithSelection(InstIconKey); - if (dlg.result() == QDialog::Accepted) - { + if (dlg.result() == QDialog::Accepted) { InstIconKey = dlg.selectedIconKey; ui->iconButton->setIcon(APPLICATION->icons()->getIcon(InstIconKey)); importIcon = false; } } -void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1) +void NewInstanceDialog::on_instNameTextBox_textChanged(const QString& arg1) { updateDialogState(); } void NewInstanceDialog::importIconNow() { - if(importIcon) { + if (importIcon) { APPLICATION->icons()->installIcon(importIconPath, importIconName); - InstIconKey = importIconName; + InstIconKey = importIconName.section('.', 0, 0); importIcon = false; } APPLICATION->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index c6b087d67..d51da8260 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -137,8 +137,7 @@ void ListModel::requestFailed(QString reason) void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback) { if (m_logoMap.contains(logo)) { - callback( - APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); + callback(APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo))->getFullPath()); } else { requestLogo(logo, logoUrl); } @@ -168,7 +167,7 @@ void ListModel::requestLogo(QString file, QString url) return; } - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file.section(".", 0, 0))); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file)); auto job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network()); job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index fa55aa686..5efc901ec 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -40,14 +40,16 @@ QVariant ListModel::data(const QModelIndex& index, int role) const return edit; } return pack.description; - } case Qt::DecorationRole: { + } + case Qt::DecorationRole: { if (m_logoMap.contains(pack.logoName)) { return (m_logoMap.value(pack.logoName)); } QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl); return icon; - } case Qt::UserRole: { + } + case Qt::UserRole: { QVariant v; v.setValue(pack); return v; @@ -68,7 +70,7 @@ QVariant ListModel::data(const QModelIndex& index, int role) const return QVariant(); } -bool ListModel::setData(const QModelIndex &index, const QVariant &value, int role) +bool ListModel::setData(const QModelIndex& index, const QVariant& value, int role) { int pos = index.row(); if (pos >= modpacks.size() || pos < 0 || !index.isValid()) @@ -102,7 +104,7 @@ void ListModel::requestLogo(QString logo, QString url) return; } - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo.section(".", 0, 0))); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo)); auto job = new NetJob(QString("Flame Icon Download %1").arg(logo), APPLICATION->network()); job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); @@ -128,7 +130,7 @@ void ListModel::requestLogo(QString logo, QString url) void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback) { if (m_logoMap.contains(logo)) { - callback(APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); + callback(APPLICATION->metacache()->resolveEntry("FlamePacks", QString("logos/%1").arg(logo))->getFullPath()); } else { requestLogo(logo, logoUrl); } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index cef26bb6b..6bec54954 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -42,9 +42,9 @@ #include "FlameModel.h" #include "InstanceImportTask.h" #include "Json.h" +#include "modplatform/flame/FlameAPI.h" #include "ui/dialogs/NewInstanceDialog.h" #include "ui/widgets/ProjectItem.h" -#include "modplatform/flame/FlameAPI.h" static FlameAPI api; @@ -207,7 +207,7 @@ void FlamePage::suggestCurrent() dialog->setSuggestedPack(current.name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info))); QString editedLogoName; - editedLogoName = "curseforge_" + current.logoName.section(".", 0, 0); + editedLogoName = "curseforge_" + current.logoName; listModel->getLogo(current.logoName, current.logoUrl, [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } @@ -252,10 +252,8 @@ void FlamePage::updateUi() text += "
" + tr(" by ") + authorStrs.join(", "); } - if(current.extraInfoLoaded) { - if (!current.extra.issuesUrl.isEmpty() - || !current.extra.sourceUrl.isEmpty() - || !current.extra.wikiUrl.isEmpty()) { + if (current.extraInfoLoaded) { + if (!current.extra.issuesUrl.isEmpty() || !current.extra.sourceUrl.isEmpty() || !current.extra.wikiUrl.isEmpty()) { text += "

" + tr("External links:") + "
"; } @@ -267,7 +265,6 @@ void FlamePage::updateUi() text += "- " + tr("Source code: %1").arg(current.extra.sourceUrl) + "
"; } - text += "
"; text += api.getModDescription(current.addonId).toUtf8(); diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 330dd4fb8..1ee6b3424 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -229,7 +229,7 @@ void ListModel::requestLogo(QString file) return; } - MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0))); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file)); NetJob* job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network()); job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); @@ -255,7 +255,7 @@ void ListModel::requestLogo(QString file) void ListModel::getLogo(const QString& logo, LogoCallback callback) { if (m_logoMap.contains(logo)) { - callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); + callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo))->getFullPath()); } else { requestLogo(logo); } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index e0046d887..1495628c4 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -218,9 +218,7 @@ void ModpackListModel::searchWithTerm(const QString& term, const int sort) void ModpackListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback) { if (m_logoMap.contains(logo)) { - callback(APPLICATION->metacache() - ->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo.section(".", 0, 0))) - ->getFullPath()); + callback(APPLICATION->metacache()->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo))->getFullPath()); } else { requestLogo(logo, logoUrl); } @@ -232,8 +230,7 @@ void ModpackListModel::requestLogo(QString logo, QString url) return; } - MetaEntryPtr entry = - APPLICATION->metacache()->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo.section(".", 0, 0))); + MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry(m_parent->metaEntryBase(), QString("logos/%1").arg(logo)); auto job = new NetJob(QString("%1 Icon Download %2").arg(m_parent->debugName()).arg(logo), APPLICATION->network()); job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index f08eb2897..954be76d4 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -157,7 +157,7 @@ void Technic::ListModel::searchRequestFinished() pack.logoName = "null"; } else { pack.logoUrl = rawURL; - pack.logoName = rawURL.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0); + pack.logoName = rawURL.section(QLatin1Char('/'), -1); } pack.broken = false; newList.append(pack); @@ -179,7 +179,7 @@ void Technic::ListModel::searchRequestFinished() auto iconUrl = Json::requireString(iconObj, "url"); pack.logoUrl = iconUrl; - pack.logoName = iconUrl.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0); + pack.logoName = iconUrl.section(QLatin1Char('/'), -1); } else { pack.logoUrl = "null"; pack.logoName = "null"; diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index fc678fa20..dbf8c94b3 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -129,14 +129,11 @@ void TechnicPage::suggestCurrent() return; } - QString editedLogoName = "technic_" + current.logoName.section(".", 0, 0); - model->getLogo(current.logoName, current.logoUrl, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); + QString editedLogoName = "technic_" + current.logoName; + model->getLogo(current.logoName, current.logoUrl, + [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); - if (current.metadataLoaded) - { + if (current.metadataLoaded) { metadataLoaded(); return; } From fcac98b367a10e9e8c047a3be648c56fe7310736 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jul 2023 10:05:22 +0300 Subject: [PATCH 177/398] removed comment Signed-off-by: Trial97 --- launcher/icons/IconList.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index a1026e833..2b3746aee 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -427,5 +427,3 @@ QString IconList::getDirectory() const { return m_dir.absolutePath(); } - -// #include "IconList.moc" From 83fce74bb1675abf80664dbf3828e11a0a624c08 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Fri, 28 Jul 2023 13:11:56 +0300 Subject: [PATCH 178/398] Update launcher/ui/dialogs/NewInstanceDialog.cpp Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/dialogs/NewInstanceDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index fb91b8ae7..d844e585e 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -304,7 +304,7 @@ void NewInstanceDialog::importIconNow() { if (importIcon) { APPLICATION->icons()->installIcon(importIconPath, importIconName); - InstIconKey = importIconName.section('.', 0, 0); + InstIconKey = importIconName.mid(0, importIconName.lastIndexOf('.'); importIcon = false; } APPLICATION->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); From 4789708cc296a16d887bd0bc86b7bacd1ac924ee Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jul 2023 13:16:57 +0300 Subject: [PATCH 179/398] added missing ) Signed-off-by: Trial97 --- launcher/ui/dialogs/NewInstanceDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index d844e585e..4be025f4c 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -304,7 +304,7 @@ void NewInstanceDialog::importIconNow() { if (importIcon) { APPLICATION->icons()->installIcon(importIconPath, importIconName); - InstIconKey = importIconName.mid(0, importIconName.lastIndexOf('.'); + InstIconKey = importIconName.mid(0, importIconName.lastIndexOf('.')); importIcon = false; } APPLICATION->settings()->set("NewInstanceGeometry", saveGeometry().toBase64()); From c3eb17db74097c49ab3892a53857dfa24937833b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 28 Jul 2023 13:22:04 +0300 Subject: [PATCH 180/398] removed unneded if condition Signed-off-by: Trial97 --- launcher/icons/IconList.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 2b3746aee..5576b9745 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -257,8 +257,6 @@ bool IconList::dropMimeData(const QMimeData* data, Qt::ItemFlags IconList::flags(const QModelIndex& index) const { Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); - if (index.isValid()) - return Qt::ItemIsDropEnabled | defaultFlags; return Qt::ItemIsDropEnabled | defaultFlags; } From 945939ba6885145d6e2abf281ef8b9010b994037 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 30 Jul 2023 04:46:44 -0400 Subject: [PATCH 181/398] chore(actions): add new labels to update-flake Signed-off-by: seth --- .github/workflows/update-flake.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index ad22120ee..6bad57030 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -25,4 +25,6 @@ jobs: pr-title: "chore(nix): update lockfile" pr-labels: | Linux + packaging simple change + changelog:omit From 5740ee04449865158c752e1806e0c329dbe74117 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 12:40:32 -0700 Subject: [PATCH 182/398] fix(windows console): properly bind windows console Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 134 ++++++++++++++++++++++++++++++++------- 1 file changed, 110 insertions(+), 24 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index aeea90f13..ff6864f5b 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -135,13 +135,16 @@ #include "updater/MacSparkleUpdater.h" #endif - #if defined Q_OS_WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif -#include +#include +#include #include +#include +#include + #endif #define STRINGIFY(x) #x @@ -168,32 +171,115 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt fflush(stderr); } -} +} // namespace -Application::Application(int &argc, char **argv) : QApplication(argc, argv) + +#if defined Q_OS_WIN32 + +// taken from https://stackoverflow.com/a/25927081 +// getting a proper output to console with redirection support on windows is apearently hell +void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) +{ + // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been + // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 + // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our + // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value + // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to + // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target + // using the "_dup2" function. + if (bindStdIn) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "r", stdin); + } + if (bindStdOut) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stdout); + } + if (bindStdErr) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stderr); + } + + // Redirect unbuffered stdin from the current standard input handle + if (bindStdIn) { + HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "r"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdin)); + if (dup2Result == 0) { + setvbuf(stdin, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stdout to the current standard output handle + if (bindStdOut) { + HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdout)); + if (dup2Result == 0) { + setvbuf(stdout, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stderr to the current standard error handle + if (bindStdErr) { + HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stderr)); + if (dup2Result == 0) { + setvbuf(stderr, NULL, _IONBF, 0); + } + } + } + } + } + + // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the + // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In + // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything + // has been read from or written to the targets or not. + if (bindStdIn) { + std::wcin.clear(); + std::cin.clear(); + } + if (bindStdOut) { + std::wcout.clear(); + std::cout.clear(); + } + if (bindStdErr) { + std::wcerr.clear(); + std::cerr.clear(); + } +} +#endif + +Application::Application(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 - // attach the parent console - if(AttachConsole(ATTACH_PARENT_PROCESS)) - { - // if attach succeeds, reopen and sync all the i/o - if(freopen("CON", "w", stdout)) - { - std::cout.sync_with_stdio(); + // attach the parent console if stdout not already captured + auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + BindCrtHandlesToStdHandles(true, true, true); + consoleAttached = true; } - if(freopen("CON", "w", stderr)) - { - std::cerr.sync_with_stdio(); - } - if(freopen("CON", "r", stdin)) - { - std::cin.sync_with_stdio(); - } - auto out = GetStdHandle (STD_OUTPUT_HANDLE); - DWORD written; - const char * endline = "\n"; - WriteConsole(out, endline, strlen(endline), &written, NULL); - consoleAttached = true; } #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); From 186211244de92b432713759c14629234cf3e8c1a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 13:32:31 -0700 Subject: [PATCH 183/398] refactor(windows console): move to external file Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/Application.cpp | 113 +----------------------------- launcher/CMakeLists.txt | 8 +++ launcher/WindowsConsole.cpp | 134 ++++++++++++++++++++++++++++++++++++ launcher/WindowsConsole.h | 25 +++++++ 4 files changed, 170 insertions(+), 110 deletions(-) create mode 100644 launcher/WindowsConsole.cpp create mode 100644 launcher/WindowsConsole.h diff --git a/launcher/Application.cpp b/launcher/Application.cpp index ff6864f5b..745aa31cb 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -136,15 +136,7 @@ #endif #if defined Q_OS_WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include -#include -#include - +#include "WindowsConsole.h" #endif #define STRINGIFY(x) #x @@ -174,112 +166,13 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt } // namespace -#if defined Q_OS_WIN32 - -// taken from https://stackoverflow.com/a/25927081 -// getting a proper output to console with redirection support on windows is apearently hell -void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) -{ - // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been - // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 - // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our - // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value - // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to - // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target - // using the "_dup2" function. - if (bindStdIn) { - FILE* dummyFile; - freopen_s(&dummyFile, "nul", "r", stdin); - } - if (bindStdOut) { - FILE* dummyFile; - freopen_s(&dummyFile, "nul", "w", stdout); - } - if (bindStdErr) { - FILE* dummyFile; - freopen_s(&dummyFile, "nul", "w", stderr); - } - - // Redirect unbuffered stdin from the current standard input handle - if (bindStdIn) { - HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "r"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stdin)); - if (dup2Result == 0) { - setvbuf(stdin, NULL, _IONBF, 0); - } - } - } - } - } - - // Redirect unbuffered stdout to the current standard output handle - if (bindStdOut) { - HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "w"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stdout)); - if (dup2Result == 0) { - setvbuf(stdout, NULL, _IONBF, 0); - } - } - } - } - } - - // Redirect unbuffered stderr to the current standard error handle - if (bindStdErr) { - HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "w"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stderr)); - if (dup2Result == 0) { - setvbuf(stderr, NULL, _IONBF, 0); - } - } - } - } - } - - // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the - // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In - // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything - // has been read from or written to the targets or not. - if (bindStdIn) { - std::wcin.clear(); - std::cin.clear(); - } - if (bindStdOut) { - std::wcout.clear(); - std::cout.clear(); - } - if (bindStdErr) { - std::wcerr.clear(); - std::cerr.clear(); - } -} -#endif Application::Application(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 // attach the parent console if stdout not already captured - auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); - if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { - if (AttachConsole(ATTACH_PARENT_PROCESS)) { - BindCrtHandlesToStdHandles(true, true, true); - consoleAttached = true; - } + if (AttachWindowsConsole()) { + consoleAttached = true; } #endif setOrganizationName(BuildConfig.LAUNCHER_NAME); diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 2d06dbf4e..276f1d05d 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1018,6 +1018,14 @@ SET(LAUNCHER_SOURCES ui/instanceview/VisualGroup.h ) +if(WIN32) + set(LAUNCHER_SOURCES + WindowsConsole.cpp + WindowsConsole.h + ${LAUNCHER_SOURCES} + ) +endif() + qt_wrap_ui(LAUNCHER_UI ui/MainWindow.ui ui/setupwizard/PasteWizardPage.ui diff --git a/launcher/WindowsConsole.cpp b/launcher/WindowsConsole.cpp new file mode 100644 index 000000000..fa9920ef8 --- /dev/null +++ b/launcher/WindowsConsole.cpp @@ -0,0 +1,134 @@ +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include + +// taken from https://stackoverflow.com/a/25927081 +// getting a proper output to console with redirection support on windows is apparently hell +void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) +{ + // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been + // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 + // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our + // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value + // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to + // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target + // using the "_dup2" function. + if (bindStdIn) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "r", stdin); + } + if (bindStdOut) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stdout); + } + if (bindStdErr) { + FILE* dummyFile; + freopen_s(&dummyFile, "nul", "w", stderr); + } + + // Redirect unbuffered stdin from the current standard input handle + if (bindStdIn) { + HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "r"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdin)); + if (dup2Result == 0) { + setvbuf(stdin, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stdout to the current standard output handle + if (bindStdOut) { + HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stdout)); + if (dup2Result == 0) { + setvbuf(stdout, NULL, _IONBF, 0); + } + } + } + } + } + + // Redirect unbuffered stderr to the current standard error handle + if (bindStdErr) { + HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, "w"); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stderr)); + if (dup2Result == 0) { + setvbuf(stderr, NULL, _IONBF, 0); + } + } + } + } + } + + // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the + // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In + // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything + // has been read from or written to the targets or not. + if (bindStdIn) { + std::wcin.clear(); + std::cin.clear(); + } + if (bindStdOut) { + std::wcout.clear(); + std::cout.clear(); + } + if (bindStdErr) { + std::wcerr.clear(); + std::cerr.clear(); + } +} + + +bool AttachWindowsConsole() { + auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + BindCrtHandlesToStdHandles(true, true, true); + return true; + } + } + return false; +} + + diff --git a/launcher/WindowsConsole.h b/launcher/WindowsConsole.h new file mode 100644 index 000000000..ab53864b4 --- /dev/null +++ b/launcher/WindowsConsole.h @@ -0,0 +1,25 @@ +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr); +bool AttachWindowsConsole(); From a7ef6637353a6ccffae850c92a170813a704ec41 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 14:03:20 -0700 Subject: [PATCH 184/398] fix(windows console): use new logic in FileLink exe Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/filelink/FileLink.cpp | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index c9599b820..e549fbe69 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -37,11 +37,7 @@ #include #if defined Q_OS_WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include +#include "WindowsConsole.h" #endif // Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header @@ -67,21 +63,7 @@ FileLinkApp::FileLinkApp(int& argc, char** argv) : QCoreApplication(argc, argv), { #if defined Q_OS_WIN32 // attach the parent console - if (AttachConsole(ATTACH_PARENT_PROCESS)) { - // if attach succeeds, reopen and sync all the i/o - if (freopen("CON", "w", stdout)) { - std::cout.sync_with_stdio(); - } - if (freopen("CON", "w", stderr)) { - std::cerr.sync_with_stdio(); - } - if (freopen("CON", "r", stdin)) { - std::cin.sync_with_stdio(); - } - auto out = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD written; - const char* endline = "\n"; - WriteConsole(out, endline, strlen(endline), &written, NULL); + if (AttachWindowsConsole()) { consoleAttached = true; } #endif From 6d564628b7280ecff3f595e982721d3890d4a615 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 15:11:00 -0700 Subject: [PATCH 185/398] fix(FileLink): drop FreeConsole Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/filelink/FileLink.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index e549fbe69..fb0f5fcc8 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -170,7 +170,7 @@ void FileLinkApp::runLink() FS::LinkResult result = { src_path, dst_path, QString::fromStdString(os_err.message()), os_err.value() }; m_path_results.append(result); } else { - FS::LinkResult result = { src_path, dst_path }; + FS::LinkResult result = { src_path, dst_path, "", 0}; m_path_results.append(result); } } @@ -230,7 +230,7 @@ void FileLinkApp::readPathPairs() in >> numLinks; qDebug() << "numLinks" << numLinks; - for (int i = 0; i < numLinks; i++) { + for (unsigned int i = 0; i < numLinks; i++) { FS::LinkPair pair; in >> pair.src; in >> pair.dst; @@ -253,7 +253,6 @@ FileLinkApp::~FileLinkApp() fclose(stdout); fclose(stdin); fclose(stderr); - FreeConsole(); } #endif } From 760b80934f35db1d35dc251692014d05caaa0614 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 15:22:18 -0700 Subject: [PATCH 186/398] fix(filelink exe): add console sources Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 276f1d05d..a806b241a 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -563,6 +563,9 @@ set(ATLAUNCHER_SOURCES ) set(LINKEXE_SOURCES + WindowsConsole.cpp + WindowsConsole.h + filelink/FileLink.h filelink/FileLink.cpp FileSystem.h From 5d68a4c992d07cdda847764931b4924572826ad5 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 14:43:04 -0700 Subject: [PATCH 187/398] fix: religate export zip to launcher app only Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> fix(MMCZip): include QUrl Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> fix(FileLink): drop FreeConsole Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> fix(filelink exe): add console sources Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/CMakeLists.txt | 4 +++- launcher/MMCZip.cpp | 9 ++++++++- launcher/MMCZip.h | 3 +++ launcher/filelink/FileLink.cpp | 5 ++--- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 49deda07a..c639d10d2 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -577,6 +577,9 @@ set(ATLAUNCHER_SOURCES ) set(LINKEXE_SOURCES + WindowsConsole.cpp + WindowsConsole.h + filelink/FileLink.h filelink/FileLink.cpp FileSystem.h @@ -1206,7 +1209,6 @@ endif() # Add executable add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) -target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_link_libraries(Launcher_logic diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index ad47c1d03..40790a824 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -42,7 +42,11 @@ #include #include +#include + +#if defined(LAUNCHER_APPLICATION) #include +#endif namespace MMCZip { // ours @@ -424,6 +428,7 @@ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, Q return true; } +#if defined(LAUNCHER_APPLICATION) void ExportToZipTask::executeTask() { setStatus("Adding files..."); @@ -502,5 +507,7 @@ bool ExportToZipTask::abort() } return false; } +#endif + +} // namespace MMCZip -} // namespace MMCZip \ No newline at end of file diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 163f71671..8afb12410 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -151,6 +151,8 @@ bool extractFile(QString fileCompressed, QString file, QString dir); */ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList* files, FilterFunction excludeFilter); + +#if defined(LAUNCHER_APPLICATION) class ExportToZipTask : public Task { public: ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false) @@ -193,4 +195,5 @@ class ExportToZipTask : public Task { QFuture m_build_zip_future; QFutureWatcher m_build_zip_watcher; }; +#endif } // namespace MMCZip diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index 6e869bad4..35d745dbd 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -269,7 +269,7 @@ void FileLinkApp::runLink() FS::LinkResult result = { src_path, dst_path, QString::fromStdString(os_err.message()), os_err.value() }; m_path_results.append(result); } else { - FS::LinkResult result = { src_path, dst_path }; + FS::LinkResult result = { src_path, dst_path, "", 0}; m_path_results.append(result); } } @@ -329,7 +329,7 @@ void FileLinkApp::readPathPairs() in >> numLinks; qDebug() << "numLinks" << numLinks; - for (int i = 0; i < numLinks; i++) { + for (unsigned int i = 0; i < numLinks; i++) { FS::LinkPair pair; in >> pair.src; in >> pair.dst; @@ -352,7 +352,6 @@ FileLinkApp::~FileLinkApp() fclose(stdout); fclose(stdin); fclose(stderr); - FreeConsole(); } #endif } From 1e947ca8931f47e78e3b4fbf64e1b03ce749332c Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 15:42:15 -0700 Subject: [PATCH 188/398] fix(flame creation task): import ApiDownload Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .../modplatform/flame/FlameInstanceCreationTask.cpp | 10 ++++++---- launcher/modplatform/flame/FlameInstanceCreationTask.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index c2c7080f0..61f8d4f51 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -62,6 +62,8 @@ #include "minecraft/World.h" #include "minecraft/mod/tasks/LocalResourceParse.h" +#include "net/ApiDownload.h" + static const FlameAPI api; bool FlameCreationTask::abort() @@ -542,7 +544,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) m_mod_id_resolver.reset(); connect(m_files_job.get(), &NetJob::succeeded, this, [&]() { m_files_job.reset(); - validateZIPResouces(); + validateZIPResources(); }); connect(m_files_job.get(), &NetJob::failed, [&](QString reason) { m_files_job.reset(); @@ -591,7 +593,7 @@ void FlameCreationTask::copyBlockedMods(QList const& blocked_mods) setAbortable(true); } -void FlameCreationTask::validateZIPResouces() +void FlameCreationTask::validateZIPResources() { qDebug() << "Validating whether resources stored as .zip are in the right place"; for (auto [fileName, targetFolder] : m_ZIP_resources) { @@ -644,8 +646,8 @@ void FlameCreationTask::validateZIPResouces() validatePath(fileName, targetFolder, "datapacks"); break; case PackedResourceType::ShaderPack: - // in theroy flame API can't do this but who knows, that *may* change ? - // better to handle it if it *does* occure in the future + // in theory flame API can't do this but who knows, that *may* change ? + // better to handle it if it *does* occur in the future validatePath(fileName, targetFolder, "shaderpacks"); break; case PackedResourceType::WorldSave: diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h index 603d3693e..02ad48f2e 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.h +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h @@ -74,7 +74,7 @@ class FlameCreationTask final : public InstanceCreationTask { void idResolverSucceeded(QEventLoop&); void setupDownloadJob(QEventLoop&); void copyBlockedMods(QList const& blocked_mods); - void validateZIPResouces(); + void validateZIPResources(); QString getVersionForLoader(QString uid, QString loaderType, QString version, QString mcVersion); private: From 7091bc81c24b056a07f8577556b5e0a28a27f62a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 15:56:38 -0700 Subject: [PATCH 189/398] chore(rename): fix unfinshed renames from deshadow changes Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ExportInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ProgressDialog.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 2e9f62251..703736d68 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -209,7 +209,7 @@ void ExportInstanceDialog::savePackIgnore() auto ignoreData = proxyModel->blockedPaths().toStringList().join('\n').toUtf8(); auto filename = ignoreFileName(); try { - FS::write(filename, data); + FS::write(filename, ignoreData); } catch (const Exception& e) { qWarning() << e.cause(); } diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 69bfe162f..222ce9735 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -216,9 +216,9 @@ void ProgressDialog::onTaskSucceeded() void ProgressDialog::changeStatus([[maybe_unused]] const QString& status) { - ui->globalStatusLabel->setText(task->getStatus()); + ui->globalStatusLabel->setText(m_task->getStatus()); ui->globalStatusLabel->adjustSize(); - ui->globalStatusDetailsLabel->setText(task->getDetails()); + ui->globalStatusDetailsLabel->setText(m_task->getDetails()); ui->globalStatusDetailsLabel->adjustSize(); From 14e16db01ee8827c485e111b7d5ff852b0a476aa Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 30 Jul 2023 16:02:37 -0700 Subject: [PATCH 190/398] refactor(filelink): drop moved funciton Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/filelink/FileLink.cpp | 96 ---------------------------------- 1 file changed, 96 deletions(-) diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index 35d745dbd..c3f9bb852 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -59,102 +59,6 @@ namespace fs = std::filesystem; namespace fs = ghc::filesystem; #endif -#if defined Q_OS_WIN32 - -// taken from https://stackoverflow.com/a/25927081 -// getting a proper output to console with redirection support on windows is apparently hell -void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) -{ - // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been - // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 - // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our - // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value - // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to - // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target - // using the "_dup2" function. - if (bindStdIn) { - FILE* dummyFile; - freopen_s(&dummyFile, "nul", "r", stdin); - } - if (bindStdOut) { - FILE* dummyFile; - freopen_s(&dummyFile, "nul", "w", stdout); - } - if (bindStdErr) { - FILE* dummyFile; - freopen_s(&dummyFile, "nul", "w", stderr); - } - - // Redirect unbuffered stdin from the current standard input handle - if (bindStdIn) { - HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "r"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stdin)); - if (dup2Result == 0) { - setvbuf(stdin, NULL, _IONBF, 0); - } - } - } - } - } - - // Redirect unbuffered stdout to the current standard output handle - if (bindStdOut) { - HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "w"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stdout)); - if (dup2Result == 0) { - setvbuf(stdout, NULL, _IONBF, 0); - } - } - } - } - } - - // Redirect unbuffered stderr to the current standard error handle - if (bindStdErr) { - HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "w"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stderr)); - if (dup2Result == 0) { - setvbuf(stderr, NULL, _IONBF, 0); - } - } - } - } - } - - // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the - // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In - // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything - // has been read from or written to the targets or not. - if (bindStdIn) { - std::wcin.clear(); - std::cin.clear(); - } - if (bindStdOut) { - std::wcout.clear(); - std::cout.clear(); - } - if (bindStdErr) { - std::wcerr.clear(); - std::cerr.clear(); - } -} -#endif - FileLinkApp::FileLinkApp(int& argc, char** argv) : QCoreApplication(argc, argv), socket(new QLocalSocket(this)) { #if defined Q_OS_WIN32 From d8f2a1354f0f38a6649ce5220da2c4f27cfc2cc4 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 31 Jul 2023 17:52:50 +0200 Subject: [PATCH 191/398] chore: update Nix docs Signed-off-by: Sefa Eyeoglu --- nix/NIX.md | 89 ----------------------- nix/README.md | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+), 89 deletions(-) delete mode 100644 nix/NIX.md create mode 100644 nix/README.md diff --git a/nix/NIX.md b/nix/NIX.md deleted file mode 100644 index aa945acc6..000000000 --- a/nix/NIX.md +++ /dev/null @@ -1,89 +0,0 @@ -# Running on Nix - -## Putting it in your system configuration - -### On flakes-enabled nix - -#### Directly installing - -The `prismlauncher` flake provides a package which you can install along with -the rest of your packages - -```nix -# In your flake.nix: -{ - inputs = { - prismlauncher.url = "github:PrismLauncher/PrismLauncher"; - }; -} -``` - -```nix -# And in your system configuration: -environment.systemPackages = [ prismlauncher.packages.${pkgs.system}.prismlauncher ]; - -# Or in your home-manager configuration: -home.packages = [ prismlauncher.packages.${pkgs.system}.prismlauncher ]; -``` - -#### Using the overlay - -Alternatively, you can overlay the prismlauncher version in nixpkgs which will -allow you to install using `pkgs` as you normally would while also using the -latest version - -```nix -# In your flake.nix: -{ - inputs = { - prismlauncher.url = "github:PrismLauncher/PrismLauncher"; - }; -} -``` - -```nix -# And in your system configuration: -nixpkgs.overlays = [ inputs.prismlauncher.overlay ]; -environment.systemPackages = [ pkgs.prismlauncher ]; - -# Or in your home-manager configuration: -config.nixpkgs.overlays = [ inputs.prismlauncher.overlay ]; -home.packages = [ pkgs.prismlauncher ]; -``` - -### Without flakes-enabled nix - -
-Using channels - -```sh -nix-channel --add https://github.com/PrismLauncher/PrismLauncher/archive/master.tar.gz prismlauncher -nix-channel --update prismlauncher -nix-env -iA prismlauncher -``` - -
- -
-Using the overlay - -```nix -# In your configuration.nix: -{ - nixpkgs.overlays = [ - (import (builtins.fetchTarball "https://github.com/PrismLauncher/PrismLauncher/archive/develop.tar.gz")).overlay - ]; - - environment.systemPackages = with pkgs; [ prismlauncher ]; -} -``` - -
- -## Running ad-hoc - -If you're on a flakes-enabled nix you can run the launcher in one-line - -```sh -nix run github:PrismLauncher/PrismLauncher -``` diff --git a/nix/README.md b/nix/README.md new file mode 100644 index 000000000..7a422fc5b --- /dev/null +++ b/nix/README.md @@ -0,0 +1,193 @@ +# Prism Launcher Nix Packaging + +## Installing a stable release (nixpkgs) + +Prism Launcher is packaged in [nixpkgs](https://github.com/NixOS/nixpkgs/) since 22.11. + +See [Package variants](#package-variants) for a list of available packages. + +## Installing a development release (flake) + +We use [garnix](https://garnix.io/) to build and cache our development builds. +If you want to avoid rebuilds you may add the garnix cache to your substitutors. + +Example (NixOS): + +```nix +{...}: +{ + nix.settings = { + trusted-substituters = [ + "https://cache.garnix.io" + ]; + + trusted-public-keys = [ + "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g=" + ]; + }; +} +``` + +### Using the overlay + +After adding `github:PrismLauncher/PrismLauncher` to your flake inputs, you can add the `default` overlay to your nixpkgs instance. + +Example: + +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + prismlauncher = { + url = "github:PrismLauncher/PrismLauncher"; + # Optional: Override the nixpkgs input of prismlauncher to use the same revision as the rest of your flake + # Note that overriding any input of prismlauncher may break reproducibility + # inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = {nixpkgs, prismlauncher}: { + nixosConfigurations.foo = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + + modules = [ + ({pkgs, ...}: { + nixpkgs.overlays = [prismlauncher.overlays.default]; + + environment.systemPackages = [pkgs.prismlauncher]; + }) + ]; + }; + } +} +``` + +### Installing the package directly + +Alternatively, if you don't want to use an overlay, you can install Prism Launcher directly by installing the `prismlauncher` package. +This way the installed package is fully reproducible. + +Example: + +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + prismlauncher = { + url = "github:PrismLauncher/PrismLauncher"; + # Optional: Override the nixpkgs input of prismlauncher to use the same revision as the rest of your flake + # Note that overriding any input of prismlauncher may break reproducibility + # inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = {nixpkgs, prismlauncher}: { + nixosConfigurations.foo = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + + modules = [ + ({pkgs, ...}: { + environment.systemPackages = [prismlauncher.packages.${pkgs.system}.prismlauncher]; + }) + ]; + }; + } +} +``` + +### Installing the package ad-hoc (`nix shell`, `nix run`, etc.) + +You can simply call the default package of this flake. + +Example: + +```shell +nix run github:PrismLauncher/PrismLauncher + +nix shell github:PrismLauncher/PrismLauncher + +nix profile install github:PrismLauncher/PrismLauncher +``` + +## Installing a development release (without flakes) + +We use [garnix](https://garnix.io/) to build and cache our development builds. +If you want to avoid rebuilds you may add the garnix cache to your substitutors. + +Example (NixOS): + +```nix +{...}: +{ + nix.settings = { + trusted-substituters = [ + "https://cache.garnix.io" + ]; + + trusted-public-keys = [ + "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g=" + ]; + }; +} +``` + +### Using the overlay (`fetchTarball`) + +We use flake-compat to allow using this Flake on a system that doesn't use flakes. + +Example: + +```nix +{pkgs, ...}: { + nixpkgs.overlays = [(import (builtins.fetchTarball "https://github.com/PrismLauncher/PrismLauncher/archive/develop.tar.gz")).overlays.default]; + + environment.systemPackages = [pkgs.prismlauncher]; +} +``` + +### Installing the package directly (`fetchTarball`) + +Alternatively, if you don't want to use an overlay, you can install Prism Launcher directly by installing the `prismlauncher` package. +This way the installed package is fully reproducible. + +Example: + +```nix +{pkgs, ...}: { + environment.systemPackages = [(import (builtins.fetchTarball "https://github.com/PrismLauncher/PrismLauncher/archive/develop.tar.gz")).packages.${pkgs.system}.prismlauncher]; +} +``` + +### Installing the package ad-hoc (`nix-env`) + +You can add this repository as a channel and install its packages that way. + +Example: + +```shell +nix-channel --add https://github.com/PrismLauncher/PrismLauncher/archive/develop.tar.gz prismlauncher + +nix-channel --update prismlauncher + +nix-env -iA prismlauncher.prismlauncher +``` + +## Package variants + +Both Nixpkgs and this repository offer the following packages: + +- `prismlauncher` - Preferred build using Qt 6 +- `prismlauncher-qt5` - Legacy build using Qt 5 (i.e. for Qt 5 theming support) + +Both of these packages also have `-unwrapped` counterparts, that are not wrapped and can therefore be customized even further than what the wrapper packages offer. + +### Customizing wrapped packages + +The wrapped packages (`prismlauncher` and `prismlauncher-qt5`) offer some build parameters to further customize the launcher's environment. + +The following parameters can be overridden: + +- `msaClientID` (default: `null`, requires full rebuild!) Client ID used for Microsoft Authentication +- `gamemodeSupport` (default: `true`) Turn on/off support for [Feral GameMode](https://github.com/FeralInteractive/gamemode) +- `jdks` (default: `[ jdk17 jdk8 ]`) Java runtimes added to `PRISMLAUNCHER_JAVA_PATHS` variable +- `additionalLibs` (default: `[ ]`) Additional libraries that will be added to `LD_LIBRARY_PATH` From 5a9f780cf842a8def9bccf60e84ce405dc9acc32 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 31 Jul 2023 22:36:13 -0700 Subject: [PATCH 192/398] fix(FlameInstanceCreationTask): include Net::Apidownload Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index c2c7080f0..c170a4f5c 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -61,6 +61,7 @@ #include "meta/VersionList.h" #include "minecraft/World.h" #include "minecraft/mod/tasks/LocalResourceParse.h" +#include "net/ApiDownload.h" static const FlameAPI api; From b4ae6e9774c535bf02b06325e6763d2d7ee02f21 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 31 Jul 2023 23:25:49 -0700 Subject: [PATCH 193/398] fix(compiler warnings): suppress omtimisation flag conflict warnings. leave optimisation to Byild type defaults - enable ASan for RelWithDebInfo builds --- CMakeLists.txt | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cf3c4b17..e01a0a2f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,38 +92,40 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") + option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" on) # If this is a Debug build turn on address sanitiser -if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) +if ((CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") AND DEBUG_ADDRESS_SANITIZER) message(STATUS "Address Sanitizer enabled for Debug builds, Turn it off with -DDEBUG_ADDRESS_SANITIZER=off") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") # using clang with clang-cl front end message(STATUS "Address Sanitizer available on Clang MSVC frontend") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /O1 /Oy-") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-") else() # AppleClang and Clang message(STATUS "Address Sanitizer available on Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # GCC message(STATUS "Address Sanitizer available on GCC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") link_libraries("asan") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "Address Sanitizer available on MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /O1 /Oy-") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Oy-") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /Oy-") else() message(STATUS "Address Sanitizer not available on compiler ${CMAKE_CXX_COMPILER_ID}") endif() endif() + option(ENABLE_LTO "Enable Link Time Optimization" off) if(ENABLE_LTO) From f19e8dd086cd046c694a4a9a02d83827b08952b0 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 1 Aug 2023 18:53:51 -0700 Subject: [PATCH 194/398] Apply suggestions from code review Co-authored-by: TheKodeToad Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/net/ApiHeaderProxy.h | 2 +- launcher/net/Download.h | 2 +- launcher/net/HeaderProxy.h | 2 +- launcher/net/NetRequest.h | 2 +- launcher/net/RawHeaderProxy.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/net/ApiHeaderProxy.h b/launcher/net/ApiHeaderProxy.h index 6fd3e4c19..789a6fada 100644 --- a/launcher/net/ApiHeaderProxy.h +++ b/launcher/net/ApiHeaderProxy.h @@ -27,7 +27,7 @@ namespace Net { class ApiHeaderProxy : public HeaderProxy { public: - ApiHeaderProxy() : HeaderProxy(){}; + ApiHeaderProxy() : HeaderProxy() {} virtual ~ApiHeaderProxy() = default; public: diff --git a/launcher/net/Download.h b/launcher/net/Download.h index dc3ccacf0..5f6a5caf1 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -48,7 +48,7 @@ class Download : public NetRequest { Q_OBJECT public: using Ptr = shared_qobject_ptr; - explicit Download() : NetRequest() { logCat = taskDownloadLogC; }; + explicit Download() : NetRequest() { logCat = taskDownloadLogC; } #if defined(LAUNCHER_APPLICATION) static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; diff --git a/launcher/net/HeaderProxy.h b/launcher/net/HeaderProxy.h index 308455e48..f41c5875a 100644 --- a/launcher/net/HeaderProxy.h +++ b/launcher/net/HeaderProxy.h @@ -43,7 +43,7 @@ class HeaderProxy { for (auto header : headers(request)) { request.setRawHeader(header.headerName, header.headerValue); } - }; + } }; } // namespace Net diff --git a/launcher/net/NetRequest.h b/launcher/net/NetRequest.h index 6ebdcab05..9a6021620 100644 --- a/launcher/net/NetRequest.h +++ b/launcher/net/NetRequest.h @@ -67,7 +67,7 @@ class NetRequest : public NetAction { public: void addValidator(Validator* v); auto abort() -> bool override; - auto canAbort() const -> bool override { return true; }; + auto canAbort() const -> bool override { return true; } private: auto handleRedirect() -> bool; diff --git a/launcher/net/RawHeaderProxy.h b/launcher/net/RawHeaderProxy.h index c1aea0a8d..09b3d4d02 100644 --- a/launcher/net/RawHeaderProxy.h +++ b/launcher/net/RawHeaderProxy.h @@ -27,7 +27,7 @@ namespace Net { class RawHeaderProxy : public HeaderProxy { public: - RawHeaderProxy() : HeaderProxy(){}; + RawHeaderProxy() : HeaderProxy() {} virtual ~RawHeaderProxy() = default; public: From e64e4d7ef7206d13ce3507de36886ce98524ccf6 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 1 Aug 2023 18:57:35 -0700 Subject: [PATCH 195/398] Fix: always false comparison Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/PackProfile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index ea5ebdb1e..00809bb06 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -535,7 +535,7 @@ ComponentPtr PackProfile::getComponent(const QString &id) ComponentPtr PackProfile::getComponent(size_t index) { - if(index < 0 || index >= static_cast(d->components.size())) + if(index >= static_cast(d->components.size())) { return nullptr; } From bae59a8c076cb3815a04fd79ee24a6a5137ab2da Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 2 Aug 2023 06:19:43 -0700 Subject: [PATCH 197/398] refactor(windows console): reduce code duplication Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/WindowsConsole.cpp | 88 ++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/launcher/WindowsConsole.cpp b/launcher/WindowsConsole.cpp index fa9920ef8..860af01fd 100644 --- a/launcher/WindowsConsole.cpp +++ b/launcher/WindowsConsole.cpp @@ -26,6 +26,24 @@ #include #include +void RedirectHandle(DWORD handle, FILE* stream, const char* mode ) { + + HANDLE stdHandle = GetStdHandle(handle); + if (stdHandle != INVALID_HANDLE_VALUE) { + int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); + if (fileDescriptor != -1) { + FILE* file = _fdopen(fileDescriptor, mode); + if (file != NULL) { + int dup2Result = _dup2(_fileno(file), _fileno(stream)); + if (dup2Result == 0) { + setvbuf(stream, NULL, _IONBF, 0); + } + } + } + } + +} + // taken from https://stackoverflow.com/a/25927081 // getting a proper output to console with redirection support on windows is apparently hell void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) @@ -52,53 +70,17 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr // Redirect unbuffered stdin from the current standard input handle if (bindStdIn) { - HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "r"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stdin)); - if (dup2Result == 0) { - setvbuf(stdin, NULL, _IONBF, 0); - } - } - } - } + RedirectHandle(STD_INPUT_HANDLE, stdin, "r"); } // Redirect unbuffered stdout to the current standard output handle if (bindStdOut) { - HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "w"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stdout)); - if (dup2Result == 0) { - setvbuf(stdout, NULL, _IONBF, 0); - } - } - } - } + RedirectHandle(STD_OUTPUT_HANDLE, stdout, "w"); } // Redirect unbuffered stderr to the current standard error handle if (bindStdErr) { - HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); - if (stdHandle != INVALID_HANDLE_VALUE) { - int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); - if (fileDescriptor != -1) { - FILE* file = _fdopen(fileDescriptor, "w"); - if (file != NULL) { - int dup2Result = _dup2(_fileno(file), _fileno(stderr)); - if (dup2Result == 0) { - setvbuf(stderr, NULL, _IONBF, 0); - } - } - } - } + RedirectHandle(STD_ERROR_HANDLE, stderr, "w"); } // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the @@ -121,13 +103,29 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr bool AttachWindowsConsole() { - auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); - if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { - if (AttachConsole(ATTACH_PARENT_PROCESS)) { - BindCrtHandlesToStdHandles(true, true, true); - return true; - } + auto stdinType = GetFileType(GetStdHandle(STD_INPUT_HANDLE)); + auto stdoutType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + auto stderrType = GetFileType(GetStdHandle(STD_ERROR_HANDLE)); + + bool bindStdIn = false; + bool bindStdOut = false; + bool bindStdErr = false; + + if (stdinType == FILE_TYPE_CHAR || stdinType == FILE_TYPE_UNKNOWN) { + bindStdIn = true; } + if (stdoutType == FILE_TYPE_CHAR || stdoutType == FILE_TYPE_UNKNOWN) { + bindStdOut = true; + } + if (stderrType == FILE_TYPE_CHAR || stderrType == FILE_TYPE_UNKNOWN) { + bindStdErr = true; + } + + if (AttachConsole(ATTACH_PARENT_PROCESS)) { + BindCrtHandlesToStdHandles(bindStdIn, bindStdOut, bindStdErr); + return true; + } + return false; } From 40c614b3a579dd7435f917cf60289712190a379b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Aug 2023 20:23:09 +0100 Subject: [PATCH 198/398] Pressed -> Clicked (doh) Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index bab5b8350..0b65882ef 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -98,7 +98,7 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c auto buttonLayout = new QHBoxLayout(this); auto refreshButton = new QPushButton(tr("&Refresh"), this); - connect(refreshButton, &QPushButton::pressed, this, [this] { pageCast(container->selectedPage())->loadList(); }); + connect(refreshButton, &QPushButton::clicked, this, [this] { pageCast(container->selectedPage())->loadList(); }); buttonLayout->addWidget(refreshButton); buttons->setOrientation(Qt::Horizontal); From 8b3c465a50e6be2a09c3968f1fd1e91b0428cbb0 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Aug 2023 20:24:15 +0100 Subject: [PATCH 199/398] Use protected inheritance for BasePageProvider Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.h b/launcher/ui/dialogs/InstallLoaderDialog.h index cdcba2b96..86cb3bdd2 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.h +++ b/launcher/ui/dialogs/InstallLoaderDialog.h @@ -26,7 +26,7 @@ class PageContainer; class PackProfile; class QDialogButtonBox; -class InstallLoaderDialog final : public QDialog, public BasePageProvider { +class InstallLoaderDialog final : public QDialog, protected BasePageProvider { Q_OBJECT public: From 1bafa36c17604f6faa23f25b9ab61a46ed0de753 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 2 Aug 2023 20:32:23 +0100 Subject: [PATCH 200/398] icon -> iconName Signed-off-by: TheKodeToad --- launcher/ui/dialogs/InstallLoaderDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 0b65882ef..6302cadbc 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -33,11 +33,11 @@ class InstallLoaderPage : public VersionSelectWidget, public BasePage { public: InstallLoaderPage(const QString& id, - const QString& icon, + const QString& iconName, const QString& name, const Version& oldestVersion, const std::shared_ptr profile) - : VersionSelectWidget(nullptr), uid(id), iconName(icon), name(name) + : VersionSelectWidget(nullptr), uid(id), iconName(iconName), name(name) { const QString minecraftVersion = profile->getComponentVersion("net.minecraft"); setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); From d48dd7eb6a43351ed181637dae4687163f92ce92 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 4 Aug 2023 16:00:02 +0100 Subject: [PATCH 201/398] Use override-based setting for online fixes Signed-off-by: TheKodeToad --- launcher/Application.cpp | 3 ++ launcher/minecraft/MinecraftInstance.cpp | 6 ++- launcher/ui/pages/global/MinecraftPage.cpp | 5 +++ launcher/ui/pages/global/MinecraftPage.ui | 21 ++++++++- .../pages/instance/InstanceSettingsPage.cpp | 11 +++-- .../ui/pages/instance/InstanceSettingsPage.ui | 43 +++++++++++++------ 6 files changed, 69 insertions(+), 20 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index d6c135de7..bbea34c76 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -614,6 +614,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Mod loader settings m_settings->registerSetting("DisableQuiltBeacon", false); + // Legacy settings + m_settings->registerSetting("OnlineFixes", true); + // Native library workarounds m_settings->registerSetting("UseNativeOpenAL", false); m_settings->registerSetting("UseNativeGLFW", false); diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index e0e4cdcf0..b4b0b4aa3 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -191,6 +191,10 @@ void MinecraftInstance::loadSpecificSettings() auto modLoaderSettings = m_settings->registerSetting("OverrideModLoaderSettings", false); m_settings->registerOverride(global_settings->getSetting("DisableQuiltBeacon"), modLoaderSettings); + // Legacy-related options + auto legacySettings = m_settings->registerSetting("OverrideLegacySettings", true); + m_settings->registerOverride(global_settings->getSetting("OnlineFixes"), legacySettings); + m_settings->set("InstanceType", "OneSix"); } @@ -202,8 +206,6 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerSetting("UseAccountForInstance", false); m_settings->registerSetting("InstanceAccountId", ""); - m_settings->registerSetting("OnlineFixes", true); - qDebug() << "Instance-type specific settings were loaded!"; setSpecificSettingsLoaded(true); diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp index 954823564..cdab4feb6 100644 --- a/launcher/ui/pages/global/MinecraftPage.cpp +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -103,6 +103,9 @@ void MinecraftPage::applySettings() // Mod loader settings s->set("DisableQuiltBeacon", ui->disableQuiltBeaconCheckBox->isChecked()); + + // Legacy settings + s->set("OnlineFixes", ui->onlineFixes->isChecked()); } void MinecraftPage::loadSettings() @@ -143,6 +146,8 @@ void MinecraftPage::loadSettings() ui->quitAfterGameStopCheck->setChecked(s->get("QuitAfterGameStop").toBool()); ui->disableQuiltBeaconCheckBox->setChecked(s->get("DisableQuiltBeacon").toBool()); + + ui->onlineFixes->setChecked(s->get("OnlineFixes").toBool()); } void MinecraftPage::retranslate() diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index a3188dccb..cd0f4fafd 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -198,11 +198,30 @@ + + Disable Quilt loader's beacon for counting monthly active users + Disable Quilt Loader Beacon + + + +
+
+ + + + Legacy settings + + + + - Disable Quilt loader's beacon for counting monthly active users + <html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>This currently allows modern skins to be used.</p></body></html> + + + Enable online fixes diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 4d3cd16dd..7b019282b 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -290,8 +290,13 @@ void InstanceSettingsPage::applySettings() m_settings->reset("DisableQuiltBeacon"); } - bool onlineFixes = ui->onlineFixes->isChecked(); - m_settings->set("OnlineFixes", onlineFixes); + bool overrideLegacySettings = ui->legacySettingsGroupBox->isChecked(); + m_settings->set("OverrideLegacySettings", overrideLegacySettings); + if (overrideLegacySettings) { + m_settings->set("OnlineFixes", ui->onlineFixes->isChecked()); + } else { + m_settings->reset("OnlineFixes"); + } // FIXME: This should probably be called by a signal instead m_instance->updateRuntimeContext(); @@ -398,8 +403,8 @@ void InstanceSettingsPage::loadSettings() ui->modLoaderSettingsGroupBox->setChecked(m_settings->get("OverrideModLoaderSettings").toBool()); ui->disableQuiltBeaconCheckBox->setChecked(m_settings->get("DisableQuiltBeacon").toBool()); + ui->legacySettingsGroupBox->setChecked(m_settings->get("OverrideLegacySettings").toBool()); ui->onlineFixes->setChecked(m_settings->get("OnlineFixes").toBool()); - ui->onlineFixes->setVisible(m_instance->traits().contains("legacyServices")); } void InstanceSettingsPage::on_javaDetectBtn_clicked() diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 9018659aa..4548b2e72 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -543,23 +543,48 @@ + + Mod loader settings + true false - - Mod loader settings - + + Disable Quilt loader's beacon for counting monthly active users + Disable Quilt Loader Beacon + + + + + + + + + Legacy settings + + + true + + + false + + + + - Disable Quilt loader's beacon for counting monthly active users + <html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>This currently allows modern skins to be used.</p></body></html> + + + Enable online fixes @@ -668,16 +693,6 @@ - - - - <html><head/><body><p>Fixes usages of old online services which are no longer operating by emulating them or redirecting to their modern counterparts.</p><p>This currently only allows modern skins to be used.</p></body></html> - - - Enable online fixes - - - From 37e5f6af48efc27469856fa04d5417a790eea4d0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 6 Aug 2023 00:17:51 +0000 Subject: [PATCH 202/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-parts': 'github:hercules-ci/flake-parts/8e8d955c22df93dbe24f19ea04f47a74adbdc5ec' (2023-07-04) → 'github:hercules-ci/flake-parts/59cf3f1447cfc75087e7273b04b31e689a8599fb' (2023-08-01) • Updated input 'flake-parts/nixpkgs-lib': 'github:NixOS/nixpkgs/4bc72cae107788bf3f24f30db2e2f685c9298dc9?dir=lib' (2023-06-29) → 'github:NixOS/nixpkgs/9e1960bc196baf6881340d53dccb203a951745a2?dir=lib' (2023-08-01) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/d2b52322f35597c62abf56de91b0236746b2a03d' (2023-07-29) → 'github:nixos/nixpkgs/0d2fb29f5071a12d7983319c2c2576be6a130582' (2023-08-05) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/1e2443dd3f669eb65433b2fc26a3065e05a7dc9c' (2023-07-29) → 'github:cachix/pre-commit-hooks.nix/3139c4d1f7732cab89f06492bdd4677b877e3785' (2023-08-05) --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index af7ecae7c..3f1d7d25c 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1688466019, - "narHash": "sha256-VeM2akYrBYMsb4W/MmBo1zmaMfgbL4cH3Pu8PGyIwJ0=", + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "8e8d955c22df93dbe24f19ea04f47a74adbdc5ec", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", "type": "github" }, "original": { @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1690630721, - "narHash": "sha256-Y04onHyBQT4Erfr2fc82dbJTfXGYrf4V0ysLUYnPOP8=", + "lastModified": 1691218994, + "narHash": "sha256-46GJ5vLf9H+Oh7Jii2gJI9GATJHGbx2iQpon5nUSFPI=", "owner": "nixos", "repo": "nixpkgs", - "rev": "d2b52322f35597c62abf56de91b0236746b2a03d", + "rev": "0d2fb29f5071a12d7983319c2c2576be6a130582", "type": "github" }, "original": { @@ -108,11 +108,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1688049487, - "narHash": "sha256-100g4iaKC9MalDjUW9iN6Jl/OocTDtXdeAj7pEGIRh4=", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4bc72cae107788bf3f24f30db2e2f685c9298dc9", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1690628027, - "narHash": "sha256-OTSbA2hM6VmxyZ/4siYPANffMBzIsKu04GLjXcv8ST0=", + "lastModified": 1691256628, + "narHash": "sha256-M0YXHemR3zbyhM7PvJa5lzGhWVf6kM/fpZ4cWe/VIhI=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "1e2443dd3f669eb65433b2fc26a3065e05a7dc9c", + "rev": "3139c4d1f7732cab89f06492bdd4677b877e3785", "type": "github" }, "original": { From 99fd1e622c4ab0218c206abed5876dbb273f5110 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 6 Aug 2023 17:43:30 +0200 Subject: [PATCH 203/398] chore: replace fabricmc icons with SVG Signed-off-by: Sefa Eyeoglu --- .../multimc/128x128/instances/fabricmc.png | Bin 4839 -> 0 bytes .../multimc/22x22/fabricmc-small.png | Bin 5672 -> 0 bytes launcher/resources/multimc/multimc.qrc | 3 +- .../multimc/scalable/instances/fabricmc.svg | 71 ++++++++++++++++++ launcher/ui/dialogs/InstallLoaderDialog.cpp | 2 +- 5 files changed, 73 insertions(+), 3 deletions(-) delete mode 100644 launcher/resources/multimc/128x128/instances/fabricmc.png delete mode 100644 launcher/resources/multimc/22x22/fabricmc-small.png create mode 100644 launcher/resources/multimc/scalable/instances/fabricmc.svg diff --git a/launcher/resources/multimc/128x128/instances/fabricmc.png b/launcher/resources/multimc/128x128/instances/fabricmc.png deleted file mode 100644 index c78543aeebf2b630810d2f5c8bd4d58ea6949ef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4839 zcmeHLdsGzH8J}HNP*95q8i^^>jj0bZJF~OPvb)^{3=mmmfhr=_v~_l77Dm{eWoKX) z4B??w%ma^F^DqRBnwlCPZE7slB2Xnws|klx(b!0QR31rzB0f-b>7ChKgrn#5cuw;l zvwQd6`R@1qzVH6-cfT{Un=;ZCO$m++h9GE)DJ5ws=*xvRF%bNoj3Z7%kR+VWHd#%k z1<*tw3jqQdBoTB#lZ+ZmB>_+XkZlERszeHff&OjK!hl@R7h0rbg4pi|Lz!#E28@2{PvjFBj&?LJa#w+;oUypifx1{|B=&xrI z6EjSSiLk@TTA6$rg4{KwTZ}0u6J|I6a@8mD0Z zF>rxqnoZrB|lEx{%&w7#i~Hkk&i53iLCmdw1i($ndgeQC`XmV|^k zwZsNy`r+y6wu^zCrIv~adi!9F`_$f$uz2Us`v>3Pny$kw;b-_Y)!Fcj5ahrSEP6*| zzpNnh9RK$pSPfY^wxDfsL|fh5GGfj?6fJnK0}jh>l+UTk$Y=^&{JUv;md|Z|;nmyM z;yjY`=$0ivIv@CyuH&a00>8SoZn&w>e(?U_+i!($3g|(r2b8k)u8NX#1t&H?v+ot@ z`r3-<`fl`md3XAkADNL7*-d-E%=2dRR{;uFxo2*ohF%feI=N$@acEZQvKd{+CmhSF zZ;u?(mO@{iU4A1_tCejC`E`BAK<^iA?H=Ply841%k9Ph(zVvT3AdlTlW;UN~PSumF zO+iqsg;uz24sja|@oon}=FvQCp>r6!QQmjFK@KyNQNAL^jF}yYbS{%p;-r_Aq-ByN zd8Ce#$HxU5+^$+w$$4-ffhNxOy-a#Hbt=RroxkJR4+NBI~4KwL-1HkYqPg zgv;ZCVS|&h>X#Pm4bEVph}%ihhjL2;|S0|xMDj`xDh+| ztN`J~NTNB?$vAk1wZj4?VPOk-qg)Q=VSju!huJ&=Z|8h006tJR;XsuN47J(N(H0z^ zTm(RT0X^1&%Pe-#=u( zr&yAq^x{ybCM{Nq(ju5vsY28g9gAqK7>Vdejn0B&RvL7ppiFj-C+s9GKml+C18{Vd zg@{#BBw|roEr{BpR3d~9i$ySvPNRv5wbHm+GYTTz$$+dR@<&G{Kv4k7s#B>5wGKlp z7L5i`YtagdC69VD-g&8KJ99MW% zMM*|J!CQfWQJ%`!3*8S@GZ`Dbj3)#(l^Sg<4p@kd#nc*H<&9ai&Z3r8*Oj>eRF z%p1M{XJ#qJTKvDXg~J0IfIisr6o%tjXR#>qo~UJXf%ndPo6m?x35LZ(p(jZ15;&rW zro=b_mUoKGCG0sgs2;v_^~;&ZqynjpiHV_T3Q?*^EuzM?8ib&f7^2hQN*u6DlB9Ml zI>%ah7vZEA<^Uc6S0Ft_uHbp%M$I3q?aHNvT>ylE>_TwNPgtyvFx0nTRHzyL6&uh; zI5CI{qlyf$^U6T+0<{nwDTY4IgtGHJUcSBf9z6i)aVJm2?>JrKbUhIRPozAaUE_2; z5d%-8Jf2e+z*f9@Z%4)Ft7o2?x%wRZ<7?4NwEB!Tp9D4cN0?(gHi>o_b8{5_Z#|g{N)XA7t?|y#gZ2!>4SAKi=%7M*w z7iBOcD~CcMY2)n1xZ!ud`zY%JANl$wW@%l3C`xJJ|{T zK+B=Q-ErMfaC^?3k2_@V*<1GIkDklCmvgCgNVbJ3YaeX`fonl`K;-2rrpk5ts&H#c MPD?uU!s^QZ0?GJ_YXATM diff --git a/launcher/resources/multimc/22x22/fabricmc-small.png b/launcher/resources/multimc/22x22/fabricmc-small.png deleted file mode 100644 index e21ae9e88b7cfb9b26b3a81725bea57759d63846..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5672 zcmeHLc~}$I79SP?BUnLD+%U$aTA5_BkYpkeksw43QURrk!enLwQL;1{B%&xHqTnu8 zC`B+Xv}#2~ajBG6L=btR2-ar>T(DY;h|6=uC+|)`gs=U+_xZio|D1d`_s+TJ{LZ<* zd+wP`(t?8moEU={5Cl2N17$NoKY(rycHq10XzT z)opBTWdqp&`4-UnT3JIbpw9x$1;}ZAx(&AKW$E{U@sQ4OAsCPC)S>OUz}5-$KY+#q zV^`3h15LfU!*4wp)0czg<7Xf-iX@ovYAS{qAXfxKB5TNE^RB0bOdgwyu=xUji17Fl zL@41QOfD+n3ncR1wjOgV|0rGaNA4LutfQp9rewMiEf-);9?lP+H1mL5E!j&VSewQ-qmM(U`uXFu1& z;+KcR5#VFz{FQ4}R{yi3mR4MqTF3sl_ONHWaruV%UeV(wO=9MTIo6J8Wac&= zbt-QwE1tPE^tSOfH-jDc<{WjcNmSk|6Wvz%&HXxW?hH@YU&FQdo|pw?A!W{Cwd3-t zOyBbwmEV80f9liR2di%7lobAh${raQ=nBm6%%Ky1VkXr$4t1N(>p`exg^xFU5`7ZQ?}e za$VRHJF(byXRq_~Uo4J~U!rTzRX=}WV;X4K>!(zH4RUX;Iy9ULS4@}SIt?2mbV`zK z(&#PQ=~B&p;;|+& znBE3LC7CIk(g^|Xq^uZ<(n~m;`1p8sJfE#IM02<(igFMhhsT3~25elcr7#n$HIAeq zIxu9U5jUvylv<}{(wLZ17e`51EHKY}7oSG2P;|j-jh!q2J~$>!&*8EWjz+`jZegVS z7XgsYfd10L7`j+ba%Pf7U7P_Y{TGp1YGii^0`Icd#~ETR%OP+M8B1z_su6hQ_Hap` z%PtF=f@rlyZ?OVo_t2!&s`q5|h>f1HET?-Qz`P5$hxWU*Ta;1VLc17!~2LkV}$Ek}FVQUi@wlGYo2wl~`=|sAwnxK;a~!5+eu- zV_dNa7Kps~uo5SEFs?+r1ek!Y@ACS2khESIu) zY~;NpI2NN+z(C5HuGYqx-cN+8HDm~d(QI;sVi8X)kjl zVJ+tLwn)HY0I?XIrvShr2Wyd7%Bao|s?)_vSzWccYgz%06M<2f3{-Uh+EuMX-&O1J z2v>r1gipgMbc9;9_`hk>hllA6^ud+~s*RM+u-GE%I8h!YUPx!vX{m!AgQpz&MGD#C#MHgM{rF^#8iVjwiUF=Mud+bXk12 zsotDFZF`48w>k=_>5zf?49Y#HtKN5VMpxFq@#;*sztIDL{^;a``29%NN4h?Ufe%vt zm|Y*~`XB~ANcm%S{om+fynkaPwcv+dJa`{0(WmVKZlaqdcd12kix-L6mS-IT15#HPYnWLZdvrr<{o!Xt+t1APp1g)&_KR)4pI%*`{WVAG7`-uBGsO1i zUHei!Q!eCAe=c9$_d$ajqu0der;xWN(oQXM(k*-Z=yYP!X8oZfd;V~E{o|uo#q8tP zuhm|?Iv)1)6f78jpniFVPd|@kl1i7uPH)Xb>t;n_!|;|Hr;Lb8??RtXb)|*2rDn+G z@z^6N?uSy=Jf|x1RWt8fLkkuEJnhVbo3}qcEUf^JhW!y#WyhE=y!C_9T zl!H>$W_W1Infv-1#c@lbxEX$hKYe>N3*K#&bffn5l3jH*H4p86UuBA}cw7^G?8WHY zp9gNSRb0Woux4l4_^nKQl+Ykv{&=uwZE{6ZYW@&!cgGS(rtQrKiD^|=rj)g8-B6Nn z=Tgn)VRMhik5(35Y_=Nt!wX4N_5dhZW0Q)RBleCs9+84ESYyy{F60+w!AqaFmbD!G z$)Jy9c_dCiFHP_kKeEj#i^>`^s{E$@9Fu20DsbOtmvpJY&95Z9wCs+n%i|#1Hzi9a zUMy(rb3P#8nE2_d+tY^pI+nIZ@4a?Bu&pmE`FacFyu#Sq<9PqLGbvcsA5o zYeF|w-jx;2YHzsoEUn%Uv~qpkm@y&C50nZYX_w43&DhCj^gE4AN6K#+&>i>f=D<$* zYTs>WPTxWM_L;*y7iO|&R4Xo4C(31!l@SAERHUyss?BlUuKdd~bNDLFbqBlRsC7(Z z-xEo%r}j_Zxw9r1k@8nJha3?x&R+iZ9(!K9)1)Tfc{h)(Z(aCIGJ`|p@f`ceY|Gt? zJqC(1p}?qh=2`n$nVdPbdtZ%@uFh@$6zm|l@#t->oA;wwGNz2SS>Z&dQ!)EIlNi-(y3R}rFwY=s8o>LKS)+EIV$-- DtF#j+ diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 4a407d95a..bdf3495be 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -349,9 +349,8 @@ scalable/server.svg scalable/instances/quiltmc.svg - 22x22/fabricmc-small.png + scalable/instances/fabricmc.svg 128x128/instances/forge.png - 128x128/instances/fabricmc.png 128x128/instances/liteloader.png diff --git a/launcher/resources/multimc/scalable/instances/fabricmc.svg b/launcher/resources/multimc/scalable/instances/fabricmc.svg new file mode 100644 index 000000000..7bfc75487 --- /dev/null +++ b/launcher/resources/multimc/scalable/instances/fabricmc.svg @@ -0,0 +1,71 @@ + + + + diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 6302cadbc..840a328f3 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -132,7 +132,7 @@ QList InstallLoaderDialog::getPages() return { // Forge new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), {}, profile), // Fabric - new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc-small", tr("Fabric"), Version("1.14"), profile), + new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc", tr("Fabric"), Version("1.14"), profile), // Quilt new InstallLoaderPage("org.quiltmc.quilt-loader", "quiltmc", tr("Quilt"), Version("1.14"), profile), // LiteLoader From a83e5be8f2acd66f83ad181e54fe688ed08c1b6f Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 6 Aug 2023 21:51:03 +0200 Subject: [PATCH 204/398] fix: makeShared for QByteArray Signed-off-by: Sefa Eyeoglu --- launcher/ui/MainWindow.cpp | 2 +- launcher/ui/pages/modplatform/ImportPage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 25d39c85f..9feb7cf27 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1078,7 +1078,7 @@ void MainWindow::processURLs(QList urls) extra_info.insert("pack_id", addonId); extra_info.insert("pack_version_id", fileId); - auto array = new QByteArray(); + auto array = std::make_shared(); auto api = FlameAPI(); auto job = api.getFile(addonId, fileId, array); diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 67dfbf457..8250193ab 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -134,7 +134,7 @@ void ImportPage::updateState() QUrlQuery query(url); auto addonId = query.allQueryItemValues("addonId")[0]; auto fileId = query.allQueryItemValues("fileId")[0]; - auto array = new QByteArray(); + auto array = std::make_shared(); auto api = FlameAPI(); auto job = api.getFile(addonId, fileId, array); From eeb5fdbc9f7848717a167b251ddae521f19a056e Mon Sep 17 00:00:00 2001 From: seth Date: Fri, 4 Aug 2023 11:55:31 -0400 Subject: [PATCH 205/398] feat(nix): add darwin support Signed-off-by: seth --- nix/default.nix | 5 +-- nix/distribution.nix | 1 + nix/package.nix | 89 ++++++++++++++++++++++++-------------------- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 47172927a..71c95c2cf 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -25,8 +25,7 @@ systems = [ "x86_64-linux" "aarch64-linux" - # Disabled due to our packages not supporting darwin yet. - # "x86_64-darwin" - # "aarch64-darwin" + "x86_64-darwin" + "aarch64-darwin" ]; } diff --git a/nix/distribution.nix b/nix/distribution.nix index 0f2e26f3e..d0904d41d 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -17,6 +17,7 @@ mkPrism = qt: qt.callPackage ./package.nix { inherit (inputs) libnbtplusplus; + inherit (prev.darwin.apple_sdk.frameworks) Cocoa; inherit self version; }; in { diff --git a/nix/package.nix b/nix/package.nix index edc266dc4..1dbadd405 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -2,6 +2,8 @@ lib, stdenv, cmake, + cmark, + Cocoa, ninja, jdk17, zlib, @@ -9,57 +11,62 @@ quazip, extra-cmake-modules, tomlplusplus, - cmark, ghc_filesystem, gamemode, msaClientID ? null, - gamemodeSupport ? true, + gamemodeSupport ? stdenv.isLinux, self, version, libnbtplusplus, }: -stdenv.mkDerivation rec { - pname = "prismlauncher-unwrapped"; - inherit version; +assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is only available on Linux"; + stdenv.mkDerivation rec { + pname = "prismlauncher-unwrapped"; + inherit version; - src = lib.cleanSource self; + src = lib.cleanSource self; - nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja]; - buildInputs = - [ - qtbase - zlib - quazip - ghc_filesystem - tomlplusplus - cmark - ] - ++ lib.optional gamemodeSupport gamemode; + nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja]; + buildInputs = + [ + qtbase + zlib + quazip + ghc_filesystem + tomlplusplus + cmark + ] + ++ lib.optional gamemodeSupport gamemode + ++ lib.optionals stdenv.isDarwin [Cocoa]; - hardeningEnable = ["pie"]; + hardeningEnable = lib.optionals stdenv.isLinux ["pie"]; - cmakeFlags = - lib.optionals (msaClientID != null) ["-DLauncher_MSA_CLIENT_ID=${msaClientID}"] - ++ lib.optionals (lib.versionOlder qtbase.version "6") ["-DLauncher_QT_VERSION_MAJOR=5"]; + cmakeFlags = + [ + "-DLauncher_BUILD_PLATFORM=nixpkgs" + ] + ++ lib.optionals (msaClientID != null) ["-DLauncher_MSA_CLIENT_ID=${msaClientID}"] + ++ lib.optionals (lib.versionOlder qtbase.version "6") ["-DLauncher_QT_VERSION_MAJOR=5"] + ++ lib.optionals stdenv.isDarwin ["-DINSTALL_BUNDLE=nodeps" "-DMACOSX_SPARKLE_UPDATE_FEED_URL=''"]; - postUnpack = '' - rm -rf source/libraries/libnbtplusplus - ln -s ${libnbtplusplus} source/libraries/libnbtplusplus - ''; - - dontWrapQtApps = true; - - meta = with lib; { - homepage = "https://prismlauncher.org/"; - description = "A free, open source launcher for Minecraft"; - longDescription = '' - Allows you to have multiple, separate instances of Minecraft (each with - their own mods, texture packs, saves, etc) and helps you manage them and - their associated options with a simple interface. + postUnpack = '' + rm -rf source/libraries/libnbtplusplus + ln -s ${libnbtplusplus} source/libraries/libnbtplusplus ''; - platforms = platforms.linux; - changelog = "https://github.com/PrismLauncher/PrismLauncher/releases/tag/${version}"; - license = licenses.gpl3Only; - maintainers = with maintainers; [minion3665 Scrumplex]; - }; -} + + dontWrapQtApps = true; + + meta = with lib; { + homepage = "https://prismlauncher.org/"; + description = "A free, open source launcher for Minecraft"; + longDescription = '' + Allows you to have multiple, separate instances of Minecraft (each with + their own mods, texture packs, saves, etc) and helps you manage them and + their associated options with a simple interface. + ''; + platforms = with platforms; linux ++ darwin; + changelog = "https://github.com/PrismLauncher/PrismLauncher/releases/tag/${version}"; + license = licenses.gpl3Only; + maintainers = with maintainers; [minion3665 Scrumplex getchoo]; + }; + } From 9a9a4fcfd462f5d269e533713307abfb4b01bcf4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:16:30 -0700 Subject: [PATCH 206/398] Apply suggestions from code review Co-authored-by: Sefa Eyeoglu Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fa6f0f61b..9bffe2a1f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ on: description: Private key for AppImage signing required: false GPG_PRIVATE_KEY_ID: - description: ID for the GPG_PRIVATE_KEY, to select the signign key + description: ID for the GPG_PRIVATE_KEY, to select the signing key required: false jobs: From e079cbb055556fdd6bd379e8f8fc426915fa25c0 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 7 Aug 2023 12:10:21 +0100 Subject: [PATCH 207/398] Fix actions Signed-off-by: TheKodeToad --- launcher/Application.cpp | 3 +-- launcher/ui/MainWindow.h | 5 +---- launcher/ui/instanceview/InstanceView.cpp | 2 +- launcher/ui/widgets/ThemeCustomizationWidget.cpp | 9 ++++++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 840bd9a36..03ce2f290 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -895,8 +895,7 @@ bool Application::createSetupWizard() bool themeInterventionRequired = !validWidgets || !validIcons; bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired; - if(wizardRequired) - { + if (wizardRequired) { // set default theme after going into theme wizard if (!validIcons) settings()->set("IconTheme", QString("pe_colored")); diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index be9c4994b..dd35d5d00 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -155,10 +155,7 @@ class MainWindow : public QMainWindow { void deleteGroup(); void undoTrashInstance(); - inline void on_actionExportInstance_triggered() - { - on_actionExportInstanceZip_triggered(); - } + inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); void on_actionExportInstanceFlamePack_triggered(); diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 4569c42ea..7afa03d49 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -47,8 +47,8 @@ #include #include -#include #include "VisualGroup.h" +#include "ui/themes/ThemeManager.h" #include #include diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index c999ac92c..0de97441f 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -33,9 +33,12 @@ ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget* parent) : QWidget(pa &ThemeCustomizationWidget::applyWidgetTheme); connect(ui->backgroundCatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyCatTheme); - connect(ui->iconsFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path()); }); - connect(ui->widgetStyleFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path()); }); - connect(ui->catPackFolder, &QPushButton::clicked, this, [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getCatPacksFolder().path()); }); + connect(ui->iconsFolder, &QPushButton::clicked, this, + [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path()); }); + connect(ui->widgetStyleFolder, &QPushButton::clicked, this, + [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path()); }); + connect(ui->catPackFolder, &QPushButton::clicked, this, + [] { DesktopServices::openDirectory(APPLICATION->themeManager()->getCatPacksFolder().path()); }); } ThemeCustomizationWidget::~ThemeCustomizationWidget() From d9cd6f9c5016080034e01289773b167a2f23f15b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 8 Aug 2023 18:20:26 +0000 Subject: [PATCH 208/398] chore(deps): update hendrikmuhs/ccache-action action to v1.2.10 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a7b8f652a..432f39fb0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -152,7 +152,7 @@ jobs: - name: Setup ccache if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug' - uses: hendrikmuhs/ccache-action@v1.2.9 + uses: hendrikmuhs/ccache-action@v1.2.10 with: key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }} From a351d1834a01d13a64f38fe970d33e2a9059c54a Mon Sep 17 00:00:00 2001 From: comp500 Date: Wed, 9 Aug 2023 20:48:02 +0100 Subject: [PATCH 209/398] Allow empty lines in log output Preserving empty lines in the game log ensures that crash reports and debugging information has necessary whitespace - the previous behaviour made crash reports hard to read. Signed-off-by: comp500 --- launcher/LoggedProcess.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/launcher/LoggedProcess.cpp b/launcher/LoggedProcess.cpp index 6978777e1..40c47d376 100644 --- a/launcher/LoggedProcess.cpp +++ b/launcher/LoggedProcess.cpp @@ -66,13 +66,12 @@ QStringList LoggedProcess::reprocess(const QByteArray& data, QTextDecoder& decod } #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) - auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed, QString::SkipEmptyParts); + auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed); #else - auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed, Qt::SkipEmptyParts); + auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed); #endif - if (!str.endsWith(QChar::LineFeed)) - m_leftover_line = lines.takeLast(); + m_leftover_line = lines.takeLast(); return lines; } From 1c3449e5a292820d3144b7648b5e67ec25d7d46c Mon Sep 17 00:00:00 2001 From: comp500 Date: Wed, 9 Aug 2023 23:04:44 +0100 Subject: [PATCH 210/398] Remove unnecessary #if Signed-off-by: comp500 --- launcher/LoggedProcess.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/launcher/LoggedProcess.cpp b/launcher/LoggedProcess.cpp index 40c47d376..fadd64e68 100644 --- a/launcher/LoggedProcess.cpp +++ b/launcher/LoggedProcess.cpp @@ -65,11 +65,7 @@ QStringList LoggedProcess::reprocess(const QByteArray& data, QTextDecoder& decod m_leftover_line = ""; } -#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed); -#else - auto lines = str.remove(QChar::CarriageReturn).split(QChar::LineFeed); -#endif m_leftover_line = lines.takeLast(); return lines; From b3da35be74cc9ed87c5ae5784820b1a521e87289 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 10 Aug 2023 12:19:38 +0300 Subject: [PATCH 211/398] Fixed curseforge import Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index e17cf1c2e..8b6622944 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -353,11 +353,11 @@ bool FlameCreationTask::createInstance() id.remove("forge-"); loaderType = "forge"; loaderUid = "net.minecraftforge"; - } else if (loaderType == "fabric") { + } else if (id.startsWith("fabric-")) { id.remove("fabric-"); loaderType = "fabric"; loaderUid = "net.fabricmc.fabric-loader"; - } else if (loaderType == "quilt") { + } else if (id.startsWith("quilt-")) { id.remove("quilt-"); loaderType = "quilt"; loaderUid = "org.quiltmc.quilt-loader"; From 8731f4ba275d6a0be44eb7cb1f0ad09a85cf4d16 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 10 Aug 2023 12:24:33 +0200 Subject: [PATCH 212/398] chore: add comment about _kde_side_panel_view Signed-off-by: Sefa Eyeoglu --- launcher/ui/widgets/PageContainer_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/widgets/PageContainer_p.h b/launcher/ui/widgets/PageContainer_p.h index d469019cf..8bf26618f 100644 --- a/launcher/ui/widgets/PageContainer_p.h +++ b/launcher/ui/widgets/PageContainer_p.h @@ -103,6 +103,7 @@ public: setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); setItemDelegate(new PageViewDelegate(this)); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + // Adjust margins when using Breeze theme setProperty("_kde_side_panel_view", true); } From 97ef8e8d0ee063315aeae5c29abcdc53563c0431 Mon Sep 17 00:00:00 2001 From: maple! Date: Thu, 10 Aug 2023 15:32:47 +0200 Subject: [PATCH 213/398] Fix transparency in skin icon QPainter has a bug where drawing transparency to a freshly initialized, empty QPixmap causes garbage data to be drawn. This broke the rendering of the skin icon. The fix is simply to fill the QPixmap with empty transparent pixels beforehand. Signed-off-by: maple! --- launcher/SkinUtils.cpp | 1 + launcher/minecraft/auth/MinecraftAccount.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/launcher/SkinUtils.cpp b/launcher/SkinUtils.cpp index 20d3b52e7..15be1cec6 100644 --- a/launcher/SkinUtils.cpp +++ b/launcher/SkinUtils.cpp @@ -35,6 +35,7 @@ QPixmap getFaceFromCache(QString username, int height, int width) QPixmap skinTexture(fskin.fileName()); if (!skinTexture.isNull()) { QPixmap skin = QPixmap(8, 8); + skin.fill(QColorConstants::Transparent); QPainter painter(&skin); painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8)); painter.drawPixmap(0, 0, skinTexture.copy(40, 8, 8, 8)); diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 1dcea2072..79213fe91 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -126,6 +126,7 @@ QPixmap MinecraftAccount::getFace() const return QPixmap(); } QPixmap skin = QPixmap(8, 8); + skin.fill(QColorConstants::Transparent); QPainter painter(&skin); painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8)); painter.drawPixmap(0, 0, skinTexture.copy(40, 8, 8, 8)); From d67277a668410e46a86870b3f9ab6bfdb90b4be4 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 10 Aug 2023 20:18:16 +0200 Subject: [PATCH 214/398] chore: replace LiteLoader logo with high quality version Signed-off-by: Sefa Eyeoglu --- .../multimc/128x128/instances/liteloader.png | Bin 20337 -> 7619 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/launcher/resources/multimc/128x128/instances/liteloader.png b/launcher/resources/multimc/128x128/instances/liteloader.png index 88295e6448fdea083a04969c0e2cc7eae0fbc259..646217de03371fcbddd6903ebbe10181a7a4e8e3 100644 GIT binary patch literal 7619 zcmV;!9X#TRP)>mw_RP-S?Nhg1HMh6BGqW@E`}Ozk zZZ4%{{Wg1>=s$u!0s5^^fPU)}pxa6TYH9+_r)Ahc}+03fKbRuANQ62SEsTq6*Hr^nFm zVY`0q_q8hN#{pVx@e!1=!1n=}MGolMMp{tY!GA9LTL?Vv14dyzJEAWEnq=|ggD=wa ziyCIod-J48Ub{~9{ziVQPk?E*2Y&dx7o<;~eQI;8*l7X?ZegCZ=@Xz?Iz|B$XAq;2 zHdDeRMxSI~x%;2ATd1$CPk`38MjvpNNcRyYPyD-t@u?uVw!O+t>=U3JQlKCa8WHJv z`__{%a7{Wml$^tNfd{;S&=xPCTg7Y`1bA)ICta-fB6sc?mwgE^1Kr!L);5HR7t9^B zAz_ws5g~$zE+Txa_LUHZHn|Dyf$+WrC@7}8+0}w;15n*y5eAarWB3T|4YHqZagSS( zT_FMTj5*)&jau)%^Y5|7pX&zF{b-aBLd)=#8(Ky_khC@L6M(c!{^0afj2_zkPp+>C z%N8;85J(^R@E!X0nE9i>>mvb(|DwdnOHyf4+O)OWU+&mFrr-BMnzFZL`p<8W+mJ$k##O0iw3}wAu9+)a|e6ICcLBpFnzt=wH2~d7LdRgk;cFT zPXel!>^b0A$|N^y=#w&( zFjUHTh@@}8+70}GCP25w+TpRIAxJ@YYYZr$MQi~)4)@EG6x4tONo0@X2c!h(wnlMr zdpCkj8y2e+QF)CtBPn?Gnm|<$$m~5~QB~Z&c!eoq?VU zaVe_-DCJGadmj6D+0zohSiw@8;`ALH_&rF{*#}xZ9Dg|cG-q4C&2!DhQSe1mW~p2JYo+G z-NQsl-E3H5mtAm9E|5r+*u-M189cgQqlF!Cu6^T^nJyl>Zxqlx(9qgX_wXc#Py~E> zzat+$sj!6XdIG%hwcoYQe(fRi% zo(wU`2iP&k9Hp*yK!cB}p%Ej7XT%xYhUMh2KY9l!#%W=zPc^{)IEo3+)u_63RS~l# zm8}}>)KUU03ExmXUtMz?sJjpfyb2SQNP%m_IyYewI|L|7a9?Dzy-W?9qAmFg`HISZT1XDiTgkArFW~D~54@5dS{#i_|Y>*$elM{uCaQ{LHx@ zFHtU8>n+2FT~09SnMBsnY(XJxL8HwHXV zz$*z*Qg?CZ$U7|J;1*V9=3VF~6e#gF=9z0ei-P{k^;vp`V76> z?|V9R{#K4*Y`O&a+{ccW9NZ!>+|}v1D6>)}Fi$3^DBUjDy7M>thX*TLfeR}ccw*g$ z>H$mPKxWLVK3oNggt5X_Vfvn&Y zk@K_z_4$ATcS@0s8=JsB;0iZ7AKW~y&MPXCEel@ORtJ2B4;zP~V{fN{9NK$v1X8_t zzwdKjv=7@O&%9X3IBaG1xTyqyo)6MKtT5dJfdTNk>X4U=r>E}Y!DqpOhc4_$e+B%- zXUx^WLeQuj#@f|`TdxF>#|B{9xLh-OID@Re1d4&k2j(a>6ARnR6dR->0caF1(+||A z!?V)3Ss~q`ZXS{i|Npxup34nZ9dgjTs`bBf&sdKTK$eu)wdx*?)`;{h#*Aei*M>9{ zmh7Qt$8sL7A&F4OUbt$Q3H1X!id3%#=mY&lp!c)3Lpd}%tNjiazc%7X{pO0p7VFe2 z7*>CJ)j63x)@KM#7kt;chu@&Px~fN1hrv(uRwQtW4`?7G3ske4elF_Vk32iB#XN)= zKD_uCRm?B&%eQ4L&<<>C0LwyuJ-`21fd1iSr~I$7_mD z>32{_>Z*`DqY!~lo>5!_JdzjQzvsxMRVmPF@S9G63LnsVUK?Re&SS&`Xdw-t+Vle# z5$q1vrcie_qzE&`jO_uP{{P-&?0Ea2*RAkOLZg?17WQJbYgdb?*uGiFmCQPHhB~Dj?ELxux;7 zOCFm7q(xa6vM?KWl-#egeLlRK;&uITU#J()332;;m68099?8KA=4M7HTbUJXvKKI? z3T8Plz;OHE-FtA~1Naau6ivF<*rp+*l>jfj%@_uZ@3`^8%wB~)e9>qi-S^QS|GWk) zD#qRHBY=;U&v|XlWoPl8Ai!UJ=P7>e?{RtRQHBJPSnmPLCjefIRv*o<7l=xL-d{2v zp(l4=+uI)h$uIQ(qyPGgYVTir{ROG09=(r8fBa(VeM(|D*+=;8?YqZnKJ(jDF>7^e zdMFqSt>@n~ypcRLY?xLD_JjrAb8|1e>51$(65`|) zp(0TdHm+E;LVH?OuiN+oyw!kRCf=D42q}>XhU1-A^i#)p2K>ywV%1 z$RfZ>E9Ol=j8`YA%4)|Qxr9}sI8`*-69j0QOR1jCiyJChdQ_y5CIFy}jYNT-4Td4O zoF^V^xgm^xz(5KT0)F2Wf5SFS6`QaE z12*-BwYi~UYT&_VVBJ$O|EeA9=*A*;kZ>=a1}3m*H33>8Uz(A*gxEcJ1~RfeU6`H^ z(i_N7iS2jrphTj6;JeWNK2{xRi2?8D9nr8`rH$AEa|tG{Bd=Qb>6!$V68rRjFbaKh z81-aPXl%mrS`wfw0De0Z?Ns7KRO%if42Xg;Z*G86G$3X|$wOTv0Ujq9Q3=`;2x|%} zM9xriD%OkO0Q+Ds7IuItjUAvmp`Sz4PY0KDHd1ZMRVy@4xyXT^|UpRVfToBuM5HFxLh>5&}XK;|9>7;kh1TFA@3Z z)}c$6DrZlHdJ_YW&N`B1Ji_jdaUMx?|*W=Qh3Upi>BD<+DqBOa0eUa6NU(}t^R7V z1khDzu`wbyiKEzw>OpVaxmS+}7S_NsVPB>PV<7NU3`;v81ut!4OzmSWcUr+CocV_n zX^`~#?Ko?Q9a~Txd*F#UqAF>}!0NWSfjlVb?Yu8MR{iXO$Dbm-MzT`5tTtt)zwsTm zK<;33!f_qE0cjCAMrITl;*@RT34=c91pxRZ8~8cvns4jhK;7&nVgP(s{|a9sfERNK zUH1+Er5;7CvBz){3H^SNbpzWmI;<@OC}PaO!41^^@g$*|3%hMSCbWorXJ^;SRDPVsyCXv_7PIkaZfchj!s(@Wx zN_8|41c)LON%q-&_U_oC_rL1Xmm8yQN{RN$1bgDHE7^r#eMqsv+~#XF4Yjk+jqeBR=sQULY8Yxrduc^LK6My0)OL5|VH>Gi>(zFtMAaI2>(-1qK8 z6R9-@QWGtt*B)>UGhf`^CES1g@)d7<*PUz{UB6?OA5u3rKn+57jDUL`pC0*OTgHdC zb&{x<=*dn@u<06qzEwuxx|S}Q&kkF*r26^hE!&bAA=Uf$zxTM5*!F?%{vMou@xr;b z*Js-fAo^SF`n8<^pFI22)D2zoC*P8+1CwI`2$TDhsGA$$0f2l`=&(ag#BTG}cT*Eu zKtKoeyUS-6eDnnJ0za{xqqv=|Gd4g+z?Z4`JOBX!o-E*9cQ8`Np;S2jsHN2$LDtG+ zXg+{0-@bdF?%_DgiO(xRH}%F#e}8t&66RLa=FJ}j#-FGe0UW0TnVu` zM-99@H#PPYeo9%)y~Scvw0&Tsv(tkI0B#=+6zxRo7y$r);RTD>#NJ(*)33TNqVF?q zGfStO{vo#hR~xl~1wGnp(fbU6Y5Lqg!eYTFNQMpXY)?s^r1YzHX*-u}2R;D+WH5Rl z7O!Uz6MnF4Pxljm*F^5{LF0IQtk!j>jOA1UOf%%_5;n=}k7thb!F|Edi)AwF8J;ib zfNJcV1c+lzg5mj#ms6Ne}vBp0)SP$Nx4=MC4rNFKX};@)dz`LIIscYsKSQk z&STp*Cj4 zZ*F1fch?aB9^7(80_Y)|Hg8RJIjSd9`Vk5Z)OV1P8=ilVCJ|Yrp-`*-=9Xk4Vxa~d<>PuVKpK<(mo@Gvv{p>| z)H4!*ISV{wRp0pR2CSCF01L$U(ekG@fG-X}t!*S8iskC0PR>A4ceYRjpAPPX@7<&i zN)x;$Jb$aFf9-k#&`_}3ot+Nc)Spvl|HN383~*XA zD@T&E_Z=e~z^P4v{L2da0{BK9CH_6s^+P-V%v1QezjJa|t{Egc^}|4d+i$p#r)Jm4 z02at{=+Z+{8M;g(&-o5W00|(vpKrJoHRK>d_kk0Str73gR{i#IHQ;B>69AtB_^gW? z@0KN9F8RW@r7y|`z`N;VVT&p0gUA1?s>5l+bLXWdYNG8oj$T$(NiaE+>#INaKd)8) zr(*(L@WBp2HPY^+PR|pdN(3iW3pOioXV8fZe0W8Sw;jCPst055N zN*4h4R~t5I0^o2ji0IMv3NfkEY2Uu53E)ZuH%5R&00QWqZ&v_EB4kMbN)#$FR!S4wIP$GzUvKF+A@GbQk++JTV+lM+Ib$U!j_u}`E`P=#2MeKwH{|WB{wF%zM z%cS?33h;me4_A*kTyxuZE8d`x#~nj2A{lN~Up3GQ9hs`xx86y4oQ?f-#7v20P6z+O z;H60I6EnNIe4hZ#10FX$9l+X~E;~rQ4qST6H@C)OATbUz7M-FtLSC)`+`rg~^d&ic z!>|AS!Nu&LU`e?)(ChKf3z(UbuxvLVLevXH2zvm0VS$H%#sjvu!8Ul`*RMO- z5aG`CF-xYD#}qC1OwU%6YjD8Fm_yYLut}t-JjJ&B@DJGnnCF0pOvDu?q#}X&4On|- zQf>R~>y+KPo(N%=_xiwIqXyh=L-uu!B}91N*RMSr_PzAhJO7#1=3&q%_Qdm1B0y%3 zR_|1zs7CzXboobC|Mks_pO_4|0$%D~4=bQZJr|um_aY1Ue!ESO|3M;DKs9tD3BoS! z^`QkAz#g_6f;?p%7JK0TFnPtA%g-Kx zbC>r)pneNPzPb1(81ATtd=Gd!6HUo3NjiyHOg1T?W3efR;#apKG@v`;bfax)FHB zoC#*Wal^#`8oS}P?~U>xNc(tBtN@EKlVT6^`7NK)z$dlgx)LeQ z<)cLYNUgtYr$D#HpbSmv+Vy|7ZN!pMI%=!rY@sE>WH+gVu*<+7u%aG-pHIMd#l5$! zIE;wCIU9wYUwzvUA(jC^`n6}dkH|mN1Z>ppc!=UZ)^BV#GSOq?4=2&Ep?%`G-zw(aR=ljoWXC-ye>a&)z z`@i=2k^854;X+o78&LoLaHl!Q9gG^cW~BfsTaX$sBRLq4Xh1fm0vcZ3gcFsAQg6uqAF!4zv(>#4fD@m8koJV4 z4`PEN0=RlY6dT>kS$aQQ#{esRk5SS9+{paiE~|7h_Fpia`{soBgCxGeJ0S%+sR9Iv zoME7ZH{27V<|t2TS2tOyNO1I_wL}oHu_h%qN<<2X1H{uMKfU(>64{(}5`ad`M5Ew? z4%cf9H{pUxL{)%PIYyD-SSu0MeR0Vsvoj0*_`yfPfIcV+3fs7eF$7_z;4O zKncr>_-Xx5))99jJ?Znm~4c6VW4FXGS^+%VmlAh`%Xa?(Oq)<4K#95&N z++ay@aZPW)E+Nb9{J^m_4#7UqYZ%+C9V3fbhTQKZNY9*psFjt?!S1?u8++ub?Pex) zunR&yll%4sh}sW8yW)4Ovx3DoLOhsUmRzngd8l44E(|=8aEO zCT&1TGPB0P3MCPqS)rtu5Oyni;=K&OIX^~vWUz@!Boz~5=fFxBpmaHj|$tp5v%pMxy{<`Hk8IHvOF!sCJKswh+RQ8aJQ8JKme#7s>~(=0N8Ua_&|dB)(#M?jYbi;dNY-| zU<;OGV;jWv)q-9rhneD#U6ug5Eg{-oAJC~}5cYyHONu8k8rW8=SWeUN0*@lXMJlYf zP(TexVgS-A;*Qk{c503wX$Mf?gP35oxqz0E0OJ3Voc^jD2)a#3vW>;TheN0AJ!73< z#5$A>>|{LvN`XnM{|20(NXt~g%0mtK+=3|V8ixo0BIQPA^twd0;v}$3(tsp@`wCm`0u~@Y1Rdh%Ia= z27c^-Pw%zDI#?Fg(fI*9^?(bkYgo7{Xr_`t*ZW&Z5ZM*V+#bCWE00*R%IWLHEq=G> z@3BVTK1=+llOE@GFkk-%G%+_|#mx@#vO;A=nG1oSuVqbJH3a(jnko7kAw1d(``r zS>Vq$FCdEqZV$pC*M*0Mbr^Vb^CYV#%P(%)y~;B!l$m`HBS|MdbGa0kR%6?Ok&m5|oHU za4U>ldw~}OoBkh@Yw-a;$ucI0=*C{(3j}bbfpkbf3o2a_P$J}!ffwlIF6fbCmrOZ; zmx-wFYT&!g4J>phOAolr8-`sX-%}D~5kYzkP`Xt-;M1)_K#ykveB1HpAp-cwAXvJ% zl!ETs1_8?+tjX&1dfNLV58$zL{PacMER6#+!}a1$FL!&saEQZl2;h?f?k1ZBdfx_U zj&)9B37lnD-sX7+S$2T*{FY<~KnvM{)m(76M|CuMt^)?_*+76i5b-^q#&HL1<2^E? lX}`6oiT)#)-R=Jc7yxfM9`r5-7Bm0=002ovPDHLkV1hmme}n)4 literal 20337 zcmeFZbyQnV*EXC43m)7{poQY@8VVG5cMWdE-CYV4N^zGKFIFfH1&S2+7B2;gyThCQ zZeP#4*0-LuzW2ZTgvrd=v*((bYxeBS3@3?ERhGfVAjbdz0N8S}QtF5}_)h?%BHnw& z%!UB~AR$~=&Pq;>2>?dOFcAV|0Pv3vA^`s_4FVzokPxyrh=2nG0q_xVIwIgBW%?N`*bG5Lh=$E0n%MIB5w_n=SQ#IG!);Uwy zWbeMZFKqDlqr4ML8_e377U5K3AzajTvM8~!`=ap$Piu-XZ`iw%YuUW=ZH4@4?q0-N zc1PWad*)MFQ#=I-4eTWmU8>pBmlevf5rq2#0e8LCCePj}R^t=8vgCuX-|V8@hOI2= zUk{?QGg6`nnNV(75Q6tX37H%I)WXUe$Y3!f9p7P-4@lg3#dG@lKf&AIQQ4{uGTYD$ z4*-%Xk(Tn+gvEoKr(L&X0UE@l%_zRJZOfUr0s(-@X{{4f0RiMflp*6wA1^OI=f_;z zi%TSL64wus=H?j)JNCBK)OFWYQWUaqc4RZNbT)^xc{{rNHH;$S-Y#Yq_HcKoIo#UT zNtE`mwUZWVYbi>r!>h!h1=hBXE`OCmko_N;?zUF{BI`fe_9y4B?)-a05XJwA z`ybl>==)#F2rVTgAt`4Ik3Y?mlM<^oqd;q9cV}0hzeInV zQ5x`9f4lqJt%L1fQwa+FYf=cAS^TXFZf2fv%fH%*!1`O3g^ih$H5}nR{%)@SklX%W zOhHhP$4r2a*MimDjMJQz2hPRIYR)TQ&T3|6$;-jP!E0&8Z}Fe#Zq8QjUS_Uv32Ow8 z2(A$3`Pb(dl;N*|V*F2SFB|xuQ9uyJ%E8CV#qkfqc>hiq``NwhqsJob|AP~e zzZCw>$so%8O@?q@2w%wlPiOdd&i=Ta|A*J#$KwBC4G8G}R`S2%_rG-gm#+U61OF@K z|6137>H1$W@V`?2uXX+ZMi<7vwo`B?#45-Ou~`y^7%C#RTBzmn#HlWUboVPRn% zlc4+aEPm(ZHoc$M)c|r@pj1ip^oRqJ+YwFDC5?c+qn6gWYYR(7-5CH1I$j<&Z>c?O zzcs#Ac^G`O0&)Q4oCg4RvtyZA4olzj2=G$Xk5SThUadq$KNBsy-ELp;7O&#%8)Ny_ z?z1%fg#DJkDffAf3@T)DBhjPC`dJXj^kGf>3Qeclr1PPF?JcwO-r->o%~+i%K)W;QbtTIczueRL&Zfp+W*{7{>!HqH!`)vD9IYyxUf+o}4T zNBWr6!$nTw9vXEUwIRGuk3v}`amnlP4EOFBC3IH*1>_l-xIFO4f(hm;1O)ItK9ZJr zPgk{|-pLVmi9AJ7m6~q#IsH{-@X0A)V|8_vcm!pMBYY1Ez5? z^`r?G3RmTJvl(G$G?&)2msXJ0MCy@(K$!q|RUo&`Y_CzD3mRxRFL&ogeX*-v@w-yzpLe!~5UVuf8W|eob68;#u0yj~W-{*?6vT{ep zkd~5XtRj?%36+h#0)UZeqs7CZs1C?gsqg#Mr~2V$w8TmHC84CmQrBTL_|Wwn+=6m@ zna1zf@p0uBUOI1?b2riNc*1XJ82~^IlgEXc!=+}Q)3`8+$K9~Cqh09aP-r{^dE`a;Mmah%Z7^6Lz#wh@)jh1156M)wNx?Jj zEtSzo+I`WKoG0fKX8+etd9k27na8!2(ZF9-pFEfSPZQo%uQVSwhK1edQQ+J-|MUse zVw{mAFiDY0R@Y;I$--+@G<-^D~3jRPdYwJsEzxxN?A|)D5 zws{WM1VNqH{Oyx@;g{cRxSz;(NJ>HAO#5R*VA_PZ{MnvL)|jsA;6)+Bku-OIu|9X> z(C8#;}AzPfD?d;KkFD78T6)3ubuPJ@`@P1Juc1fF_nGeX z6dB*FQU~(xiqKEdDUVt;r?Y+3opE7)M?L4o5*Ai;ZP^&OeW|j zJ|A>UNb6P+C4_cdEc#d?w$3wS^R4=j!^`d1{6^!vvuD%q0pz7>!Ds#!JiaXwR_jX09{vV(#%Kh~vX=yH~F`*&g>)I*smsIX{$2SDJ*gmRx-RsqRK?NaMwj z$sy!JW{VL`dpEnfy=Tn6 zW$h2EmWQiHXIp^}>?SZv{Ls8n>(k@Gu#E-&&g*Y|hYtsj>Sji{_lgYR*Y4pej^VT5 z*H1i&a0j-gVN&jleDXP4a$%Qs!6Dx?6M@vtT3>$M7lFK46yg?r0QoH33ohf-`+M=R z-KNoPU%8}T zzn^5!$;-=ocOTg4Il3@ox0&O1GAexdb!!lWjQ4895M5yj%0G#R?-73G(w*>RL;uOc zqk?=n6rzhv+ji`r3`jZ$ig8H6VhJ-we(I%d^^@Anpk_u!W6<)_65*uIE|Xehw3z== zPu~g)d~}#Uq%!LCJU^K0xR~AVyyk!Gf2EbSacwTx-Yk%pn`6S#epyjoxtAmC)#Lnl z@i?DA_Vc+Kkd$`Rud~iWG=$4dZJ{9Yci7?^lL5roUum~ zX>E27WhLw(03|7TX1G)_z^pj>BE}`B_A)biMB384N;K=6l}w+vKVkaeZP&nZlm@>$ zK?;2M@uc&nX1LYsaQ1Om{Kn|AkfCQv8}PB|B<0v=v)$xpd-o(EQjI$*EsWpR_+*%V zczpLfUx^q=VDU3$D9+^E{Q~*yKE37lz3l2;C@lmt6(3TvnmR|?4KIj_g%8osLd~jB z3JJ&;G^B*(Cx`&K8CA2sY_w(2bLeo~M#Wq;Rm`dYvRM7Ba+@0gP~~wn=*Ek9Bkptt z?Xc72{-);9cWIE}in|7|WnFf6aoMpE8`wEn`rbnuS)Frh?3D6ef?6-FHyul-+PIIo zrY%&WbI$d+_^J1ryF8pVwcpV_C@`bNMuo4W5W*OY%=CpzoLe%S|ErfP`dMWRRBAjQ z8y3S*_c=OR>Y0vw2FqA|fqHKxgHybxXNP4@p73t}>>{T9eumoxPxw)Obp-)Op7tlF zocqO^`^BH10(U?C0x$tC^vd3D7y|fR4{o7d!#B} zDe$P@vM^Jxft~@q`N&{nca0Wt)b-xM327i%E9JsEV5}!)vseYq(B2 zd5gfR12D+wCeY&QeY85G)9G@O;OxI~_Aco9-B?9Axrw3S$iq*A75zK@&SMI=JgfM5 z`Wj*ZQ(>R|WaTLgFO^>PrM$h3MQtnhmosy;alxBjD*t25Px*4HmZ*AZA*pug(A|01 z6Rt-!*~#?>mS8uaht~SuPjFe;^P^=M*jG|Zz1Je_`ARr62}4L)`vtO}obuI#h*6Qj zELEX>DY><%jcH<{gpE97&lyTmIq7wzgoYJWnm;LoQ^-&32D60w42`5fdJt>H=Tkdp zf#9{}a|-^0$EwcrPh(CiEus~>b~`yWZ`Fxm-dj1;Czv$=&K`4sA~-jgd=FS1a=Ixv znmCnmVcczU>-Fdeu{5Go|6NeITA-d-sqk6pRdfp@37TPc&T5o%5VeO<$!E#eg$$}^ zXxryeUvGqi$+|RN7j8>;bC=1;VbFj_Ob^zv@rQ?_!-+l@+s$;1#)6BVl1QX-fk;8V z6Il>~FLAPTv~aLlGJFAr@f?=5XVXycb-48~$(|kT^5g|6JMrnUgHVog+37;q)YQzx z{q052&28sKUYZt%xALcIlOP7y71^C99baQE2|ifvlryV9tXN36e>|*Gu@IkrWtp7# z{8Kt);(>S1s6FE0fcIxF5}{9&%^SivjhGA+h?y*iMH)<7uEbryFHWT<@`wSj)gR!j zLve%f&^~_=Cp$*U&86pQQ+K!7ZQ39r&|FtLs#H}^vT5hR^<>M7rrCmOh0QmvsB$|8 zN%tAau{k4*z({FRaIFnmu z$Q0UU>sK^T6_INZfdi#IW-%BNN{dP$>YlLk5o76S_{ z%q7yc8y;yh{TYJELb&lyLt1(@+YXZ+YwJ!fh!?Nc8G^rVu%(FTXPym;;54m=M>;SK z<{<^w6A2(kgEi&l{93y6P4ZWUldbhw_!#9GX=ylUxZV*&78G44N>@61Q!sKTS1tAz zea7VTkjD=$CuFo}0LD_P3QPTpO!BF6^>(wp{%y)*3`{Sn>~0Tc3m*Tzl&n~h4-SE@ z`*+pV1zQC3bm1uTkRr=nY7=a~@^x#$A50^oEqQ{e!QU9l!o5vIb|Mlc*H=_(bM~G; z7RVqYEzuw}iJFjIm)01ePUSj8UgoWfLWn2zfxdehumfoxP;F(gdslD+_2`ce00n=Z)4T4dV(mV@!(IpF0my}T<`by7y9P-pcZ#Du)o@n^jH6GymYpU5- zVd}_cA-Kp^A=cgHb-Jl(m0Mp+HHuS?&TXu9SbxCUqml(`uiKs6GJ$7CZffsaA}dF!;23|aC>cJurFmGLGF&xc4cdgDXls%J#K=_oA| z2o^mfMVYYRXhnBN{eh3)g6>ov6OY}wN)iu#1aahyy?eY5x}|uKRt4N-==il$_+8J` zv=CDUmLW+5mc3z#ea!*Gqcpu@rL5yd0&8H5CON+Y`oEs-eh`V3QjioAqY0V<3%tw)*_4OaZJ^?jO3n3B@}2#kbH&Om5ImF*GsSsOhSlpM^6k)}2EWzzF$)s7XR1+WAe z8VQr=f|L$#n8{tOTbw~rv(>uewZS8c*W;KYb787$AiLd7q%l_mWb3i-D8;Gt-xnx| zKY2#B*LZU}&q%bZ`z^XjaFqa*-gKn`Q1Z*jUSL9X!CC1NGU?baP+y>gyMoDrF~H|g zCWTH7)_&ZQZYG%!ECv#A?^DA^b=2KU4K@{Ucdt(r9Z~vERJh6~vAKrnk5SC=oVL?Isk@7X8EG#v*Vc&`U=Dbs19eiPJ8N_Ntl8?a%0eS%l|W_W+Ss9 z<$Y>*7+JQSka=2@`|c)TDdTfp0%5`uYx590X~#qf zi%g0keN1&;?NG6514TYxlGgV4_-G!cnCe0WJ)Q7`>i21?c%-vvnvH#Rl^+dfbW?e) zPKo-bN-{@v>^jN^TgFS<#uR{r!Fv__XlTM=cL}lI3{n>TuZv=QZP(tf#3}Q8{;)CC z1n9i%YQ!_;8RuI|vQyC|xh->wgej##!bF2%_<&acN}d|i@bO(gSrwsdBoKGEZ&-@D zSqp%k#f1^Lk7}kAOR|flgbS)t=uMmpd5NuW$$3J(acK&Q=0{m!cp({)=z%Q(rz$+pTbuCd2la8ayBbd} zSC%SztWMA(884!|6m5{s#)-rzkog%nEiqAheF&ZhjB;19;}!3tg{yG_>_;38E)M~G zO9Ne;`}R)^#EN1$fm4}&-X9j6BFX{S46!xCldODl69JVysZPkyl(I5kcYd)#Zj7lJf2gZo!sZ-`oiZmO!y*~RWZ7|s*elIC$yQ%6Io6%o;pb%}Kl<>XH&lae}hZEDjKhb}*1;nEbPM@1Y9zQ;HmM-L3D~rrDL~ zA*P~cZOE^!!Z!rhEXh{p7@!97B2^#vP2p(G;Xt9Yo&*|byQa| zS1f9uUXQ$1NzBUwS!QaL7GOFmt;nWPlxX$7eIeg1p#76eDG4x=7VL(RA$R?WN94hK zE=Sp{WPPO(BPnp!{ceQ0$6GGF60D_^ltk~rX-a?!rRBgMmw`E%TYTUnAF{#n6}<4e znWwr)vMwzt0m4>2@N7gst;$pwG^U;*heve1uawl&XBomcm5vxJ{NkWz_OVV^i@4F_ zqb;gUYnFu-#F}1jtFp1FysFA-DyH?aI}c%`rb)6GV-}6sW=-nkMH=FrkZdF?EEZ-v zl~=><3LRR!*B%uByD9)N6@~9c?d3WxUS#(^OrvNm_h#txL%QGOzA-j zU6FePbwvt@gmkpUG^ZxV?XA}`+b{0NoKGu$fql@O+J;PFU?CJ&`e=dVWb(!uxc%Nw22}{l* zeXF1`p3Hm7a84R*;iD(VPtjGP#BP6J&cZY^Yt~ZEnNj27%Q=9UDLZxH9%ea$rU{Bx zN;`r9hotEk>*GAt;c&(zSI)c^l_B)2FR*dXGd2Uc?*yk{oBCjU4M`xkV`-?-K?k4* zRsbgBWyv}BLj$s)+a15x>n*|6`6-BV`Evd{8C0dmd8$hjXqZR|myMPLQ=qCNQ4b6# zN!6e~%OIQeVHqY*S-^Ns!kw)`oX#R&$%IB-c*JcnE1D$5p)XlR4q$jiwIJ;-@r9sP zQ_8JKNs!EBeybdC_Ec49dxL>DQAj!|iU=tSqks`kV)R{VVm%2T+4X%108@f7p*ugy zK1x_%o~rPx(lGtvI7c$hwfj;Osd$j$y1COzSF62o@MQtfgZsyx1@DlJda}_n1x>C(tTS6a72O^M{AF)XAn`rr}hJZ`Nmc$(6`gsGuvFA*7nJ^%}Z(As) zdei&ra1y=f+fC3rml-PjkJ_0w^dK~32GSHW9`e=2H8vd2sIT=7qOSBr9-sXITcXfp z2}_7QIQvfTC)g!R3pvf^V3@q#CuXP6uST_1R@(VQSMG!Bvm#g84^nFsRg2BRlEO>z zKmk0@V3D^EAu7cHHn6os+o^fgR;H}rY)@>f?f2dZZpUcC94i%Hft3|L{uhZ~;-2(9 ze{GrwjRx7aTRpxyzl&UDRH zFDgP?_e|tnMk&?Oah$&6#oec{T<~t*ppbKE6%(0R9J#VVnbA+zhT^VeGNWU`2f{H})sNUJc?9@foQZX}>-mA%{b zW_f>I`Nwj~%2OqR-=Dn;XOXyq=le#Kv}v|e)3YM=VfJ({3F`4>B;Kv7qE6L?=H+3M zvS&!<`!3_sNib~<{)%kQm@QzyW3ZXRXP6nh{J!m_u}zW8$2N%Hl)A3Q8C7gLj?xve zokuc^k2_ild0SLX!_=p zT{9pE&|@PgP{2h6C-G^(}SLNm9mO)lj}1Q>RH}gb-nLsNRukqqbaxIE83bCv@FB<~|3p(2M7wBs~6N zM)fTU>Oy0xC#*~2B0=O^k1rfXgqSe`KPUYD0gbJ#yu186U(Em5Vd@UN#G>Ap?( zGZ*Y=;`5xoL8jfyU@i$h=OJ*B|5DB~ZP%X&SFzcCo|!Lo-Xf(egm4e`H;i}0DZ3e9`qO#?L>URRkn zT1<-|*WoETgN?BAPo7BGBkSi0ki3X{Y9_-JA`5lS|VZyRx&Rjn_0$HRQ zh}wtg-^`YO87O+mx&k|b=x^(Fbr*Stn)<4?Q(4~QxpRhdiE`|mo1%~RUkS=Juxue^ zpB{-xi7$~kRpE!X9^55|Uk_-sO>{Ul;ZKM2sK2;tQ0I7A@@xL;_MBnKY9l_HBMK6l z6+gCw=KR=wiVG5EVH%+Ifav>_mT04A7b&I;nPWF94XP_p@Kzm~^{R|NbrTX1dt6DU zfwF!YMFaV^GI&Zaybpm z7K$rLfH$#|KEuh4o>HGnt&PkE$pu6(Zo$paX}qc1&b#MQj^{hvE_YZOt}J1YIPXX= z3GLY_T^KGXmFqMxY(y+u><&DKCLxajXiI?UC%gAhWlC5|vndsbRk(rW>n-24@G&JuAn4sf)>ZW-r)KA?SIwX!T4;#rmfD4rjJrwFAwQL56rKS+I7_ z){;16DGBY8=3ko%79=PE=Yi`_Uoc@$Xu^D{eQR;+-LQRY(PU8Bz}bmU&GRk3!=E!;W&n2^aC`9oO>GlSszMmlx zA{3vm3@o>0ObLb*YSr#6PYy~oapmy3l7&h=d)^YMxZ9+o+AQ2quJ$Iq-%c8W(-R^p zl}*2?t|pt?3NlRXAt{-re$A;&zeAca^|)*jVB6q#o{$x0;GDj8{;nf?Q zc%$@Y@pEolLt5i)a>+tsskY6-CkJQQLS@T%7~0_wy-rAXU~*`YxOe=RqWV< z=I5fcuSTO}9q2+LqrraYW@bhK`frCd4BlZ@&aI1ip?F(5%?pi|n#nKnQTNPle~Q|( ze$Ge;4yBKtWEF!vy^u-`kDLqVAbqiKEPc3&8d)TPJgT=C_#!g&ov#A$=fpyoyKu}z z#cEpim1RAg0vDQaEpT9Es2EbR#V;{T-&voHfY{2CnDw1xjP85|;V5Ke z9AG8UGiF#Hp!6Mm2p#k#zQ+h!q;@rmV-uQECD{N|_aN3=fA5WfETH!pr`Q2sP_EL_-v~sqaKfM2sRGU>fTZ5yjw9~-C7YB7JPs*!o1Ch zx@Jpst=m6(t~s1{&20Mh7&7cvbDe3CxCDGGe+l1zPZ1M#^pw+a?zwuCt|XJ$#c%xH zobax1&>dc)N*dcQMlUBY2s0$qer})pGhs)I!y$&E zZAvmgjskf9iq?;HU&lc2zAeE$@HArUXwg^f;LS3;Gv&)!)*GS66zNN@%ZtUV_1I4s zM4W4T?J_-TSnt0#gA#oi=hC&R(6i@y5^9Y6kC=2jRS-3cqm@85Q^}wEV#?Y?aKhx{fH#bhy=!S{lAMBskmS=Ky zYaaK!w}x2D6mgUj(nALhG4AGl8`M=7gBwCDOh48^nC4m|2&Vd@=AE5$R%!t~c!iGg zU-ds!;hpS01Q3}$|4EABTwLA>gR{ z-Dpb-u9@enz`9I-jGo77LQ`hxGq}+$9%H|63NH}Maaasvv$tgR9Eejc+p?k@Usw&(%O@15ic|+S{7-c%vUUfMC z*}qf&+u`h{e-l&KqargbMZr2lBF$P=NOD~1oMmQSi`<{F?O0z<*eeZ!$5tdiY3-F3Ne`M4)v!1B#O3&VqNU{sjE9r z24rXb%(gHH-yzYbJ!FbD17B;E>?*N_^WTmJtcasy>qDL4g=tj(exj~)+2|3svpCSu z&m#%_Dbj(`53|4uG&V0pS+)UMi=d5^^7AbP>7y5lSLF{AW!vxIp+@Mgfo9SU` zlW~A1+qOGbaHCI=I>OZvL?bQn@i8DY5L*mw2gz`3*3SXhQqjC)Q_j z^;(LKY;Wmf)jIje8sw;i(49?it$$a)(~~KhMvl~fvkDJOnn;qUj2m}w6lTa#ZZG@b zI;VM9*w^h_=@5lG?sz_$AQ#7p1*Lt`tpKiA-D|0zk@0Bp_Y=(X5AydsxoH1>7$}fs zn0?V*E4svcu4{~la>=4aU5;Gim{+#6brPbqalLv_i>sqPb3k+SpjJ>{* z!Rl4E^gQ&P#~F6t%ID`XK9Az-A`=QTZ|s&`3x7*0OHfVZ^TLvPtop8GmG3c8DzTO6 zCo3lA`ADztO}@PvAS-`R!i|x^$lj3pkdhq!B#__cb zb^B%SY0<4$#pUv~+t`>**gUry07oKSP?lvv@XK39`NhHD9ru#OVEGhS7E>0(Otr_t z9=BYUXlMg>K+9>{x9N|q6}8-{<=hieP0*-=4^Dxf`p-&?SQ?k9#=+w1ql-pJP#ReX zI_BY$oY7nH?APoa9=@(8?VIKo5B_{&xyIR}4}Fj4e!OD42EA;pf?I~amROL3DBEsT zZKt00p|Oz0x&ZN(CacqdDBFA<(;v)ei&GL3?poDAJoNl<>~DtDkPsq~(xqO9R;-vHK0ZZ7Kc7|wU35Mcd3E0AIOieh zt_wQS1kuCB&BgR2c8We5wi(s@YN^d*NNJ}TXOA1#ipBz{eK!o5S4#){qD;RPmBVEOv^#Xb#Zaiqvn|3;{`$imauA@1S! zN_U}aU|lU6-(K;lu6aFspqsAgAZI>=g}qF(De~kmm8U5DF_>=mciK)_MXFVf%)O?`Gr7uF1_}vG}6s1id(Y3Kh|P&aIELd*#V8 zh5S!CP<3pfQSDBO>=Ssw`yCKEqpl?mq@V$}xwX#0Xvo$MJ;C{9y+HYt)iS;SK{H{p zEXp8l|M)bauTLc8#qN{%3C;kNIB>m7E#;kvfZxyElN?vU`-i@TL9c_A>(!;cvvqHO z&mcar*4-;CYy{-*g&P3cB`5O<#O-BI^MPSN95-sAH6)%I7V zGKGFjcR%B}r`N(k7mlbM`*@6-8xy13SJpwtE1jJ|=lv5dmqP(X+v(h=3_YCI88acU!Z;r`m}P}ou{b6UV0%dc+4IPa+m0V za7Re%Dy!_d@MLNUb&ic3G98id9PcvtI@_fL#iaV^rHTQHqddMlSYB|1rM^h}?3mRP ze<{WYY|Kw`e=cdlrC%;huAvqUcpuL<+l696)sceggr_!p8#bpzzC2KF=5Vb1 zI+7}sbxp_O>N;S4=T&2yfLKO0b%47k=ff)X!^Y#~lXX{_OIplFY4u?2IG4kRSG*lT zl!zx-_4N`w=~)COwa#g5Pf=4J%3=44kaN`h>JWF_V#OZ3MG@n&9u=$Ep7?to+vi7g z&a596zO?9Kc-qbr@DfN$LHF=ppnnnw$ytud`H|-9yTZmcYQ0rfHg$T6MmPIK$#;SX z)|sEDK-opzcG@H?++l$DFO@4N#aIq2$#R;O%P1-_JFRgzl2ka@yrGnK>?^6Hew9wU zI&FLtN=_=7<;x<(BKP9db6tnKv$O64jL7;fn!XnQ`H{j&g+}@FPiiX5VFqpN=j%m- z?kB57DO1P$#|OJ(dHY=HQEUYUs zkgX$-2w?rBT9z%7`Wm!U)duw%w{I_FOrW3?V(yFBuX`xtIFT+PS?h#xE~}=ys!9Rr zD{7uMz=grqpYNzcmLj}OMz@A<9_0KAXYYLAt_ZXLqiG1YW~Vigtv$kWyL^ zY8fz!l!GfOp+kiBH#nDu((tGQtAlN!THZoMX-!OI{Cq!TdLW4dC@TTzd(ncqZIFl; zoO5=qgaN9G=D~c@TQaew!rB#iMA1!x_yL8;9Wek0n1-;TPZ3XTwTt<1Z{)l0i`5Kz z7N92}g_f&0l{o35U;&*FKlKMsASq!>j8D7v2dokBGTPx@9UIB>xSi{XtFzIVyf$mM z+iuyY6rkk{6fP~pJ!7M;HGYuGKMvCkt_u9u=K@r*0U>P{3{m) zps(!rdXjq1yeCUd!-IN`I#YlPEc7pX(&_Edx-b#$sMU5HN=?(!((?C>FO$j6;wal` z6LZ>n_HwGq%d;!fPK)~7@7DTu+WoA(9{jDeSLTGT7v7Fc3p24^6HC-8mu_UV20b?T zbL1`#T0Sux2qoi*!=WxWll$S$cGBVnG+Nt|`+EQEC{R6`7BL$6`vH7{b9)M`d*^my zYDMk6t_?w(2QHVZ-KNdLL$|%VrQ7YG$=heewqXRY94AAoi)zHW(cCxC_4e%SXVJpX zyV0L##{2Zt2SzPog3uwoWG9HUnZzn|R*=owO()UXc+z^WY@pK3ndJovIHn7)OP<2z z=)^}Wct2$Y+<_P9ww@I?2R3GY;Y5g<(H)XD^KJ85n16Thc8D> zJ>u&SKX0RSaOw-iX@_Kc86qWKl4pdf8V*<*?Grb#jgizJ-%o9{Qnx*h=B)?{c6jv< zKXr4o<{d9Di*5ilMsnjg6CBgj=CEgH_0t*qGQZyW3|jgKhJ>I+!Q>?czHTW2*$5t* zTE^G}&*@q37g@2Yi3N>^xY|mIoER~57z}MXb*oBe9Msv_N<};JsRZ5IbCy2Ot;{&Q z95RcJZ}_PXim7pE$=2-nEKZi!>E-Hvc(Ei*o%`eZsC{Q)Q0@Nr+s$s9ab~U}Un!$c z3$MfQf%7$T57T&ci})SO?&#_=@(NS0@VofxEk{Wn$=o=@fe;sB>Il z@8Y|M^*7*EE(zeLU>*gnsL$k8dtnbEt<1viN%meTHkU%~ufUEMQe@K(e%xhOJs*Xu ziBrCNiTOS*9R_U~$Xp%-HVBA{xdP5~j2DX}RtV`CyNc3GzxLj58?C4q#7;;{NJDc4 z!^cukwqM@1KRZ+N-E&6oT#Gu3?+;|}JvV->Q^#;+pufh1=NU8p92$p|HeS?R(;{xd z@=B47eK%?UE%OYuG4$||^SaL*Z*RYaEKu{^aBKbX&b{9!ae?;x?$*<|(|Xiz+&(W$ zzcTQX3#xgg@Pv@pxs`Q$DX?$jOWO?NB!GD8Vbqx^rv&AI#Mmn|1F_CV{MhkfZpt&R zwrp!}UjB)n_7Re_STRXO+(C@Tf;Y6=GdRuZ0=j-!207!Squ{VLu`~1Em3k~`)y)Fp z!lI%brw>n)%km#LK4G7*C7?3xzuso@z``Welm< z6OF`G0*o}~zny2vSxkkY*jBhj!5Z*xMwn zTP4Rd9s<3t>QD9%@B|V_yL?1!S&OM~*=YB|1h!f(ScuT3RiJH->8$`&uR5yB6bGQq zE|0a`(UQm`7fl^F`&_qnRdKfJLbRk-hSSBrkbk9)Ib#;D!K}L)eDSs?SACwFytPLF z&vcaKDGb$C)XZS400#%coT8$5*rAAiqM#~yE!P0}j*;Yu{-{=#K4p&g9K;NIP9=7q z;z;W4&Q}Ny0AksmHTHC?}Yvrrt1B5nq5$@4@} z#tp^~29!c3GhR*%*J@Y_jPT$z_BaWNl7Elup*^I zx}My}_OnW*;OYrw(O5k&b@OGKD~$6wQmI49XVp{`{dLAq3d^#%oxI`-*9|MBcvDfX_(6kxmrd_P>n1>#kwKwNg{L3V2ciKC`&H zx9%Vfe+~%@&Tjyc46Q5wUNnyB#zuG))VdxPO=VhNNU444w~^R8Gj5}H-x{iB2Oo~U8+%c=nsOk!v%vaY;F(}&iv z5V4Cdc!*zQihyd)#cPq(>gp?6&6+4W@@D9@>iQtL4L?tq zp!)?fdh2q(CJ+8?3*+{gl~0MC|viyUJq|N|#DG$Xz3^%>sBv zP7DpZ&lnvOuC&gKa||<3?+V zo=ixrDQ3zT3Re%6$q33Kbe&NPw$_ID&PtemLM9g?ZC+9jeI64k*oX4)=Ab%?tpR{9 zup9*^eI4rMX^`}FHYN>QZj_E&f@-Kf_EtH6{ZQ-6~`{<>4D*M ze(Q%7;G!R^`pIiEBdfesuQc#3qLUmWew?I(sSFzbPXNRNJNybKf>~f3JCFBjhYzjC z-M}~#L51zv_UqH{li+J?7J~#o;nl$H=(oBg5L9@2`EawPJ~IjQ3g{i)VWJpBE1BxZsd3frg(3G8QdB-1^!x8Uv#+ zRD=SZ`Edd`i9zC-54ht4?gz%10C8CZMPW*`5KEExJm>L#S>ydxje9m=%u#W+1JP~a zuhM;){{N{ig#4^1fP9QHJWVBN{Iy5)*-iwtG-+2n`K!Qq-~v9f4)4?sANYVHW?YD% zgv6mv$wHiYk2}`k-OA#_%He@$OhwwkPjZRH^Bv(Y)4dz{^XE+gwteH{6yf87u_t*G zk+?V7hJcy{r9=U&04#&x+;vvQk2|Hs?b6{v zh+tEV&ECK5jHfaC+roe5zW+t31#HIy-Jf*}K--NWKdvHhngOwN1TPMYz&LXrBdsE- zBrujPVCn*)ti@+W=R!mFst-{pTwD7fAuOGlK94$atGY z+~pK1Jk)pBmSgD&+@CzbXS+=3VM|eMNBDKeTDUE!_k|b`@nR0HS${Uwi4D4iqecO? zmEaK#m_KqhA&(F|cdW*?;C)Bf-P3-V;N?ZS$auk(V4FkOC_^Loyz~F&5w1Z!CUB&W zIq8?hC1K0lUv~E|vfw`}3h*eTa9bH3r2zUdu7Muo3N91;Wy1Gc!VaCs@Q9%GrwZ_t z6rt-Pw(AMouHZ>5!N;BaZ3WnB>f8umG9KaA77aYH<1gKb}_qe;k;Yp2TPZ7@!2fKt$t@m>vMbP^i;M1pqq6!tV+_ Ra037U002ovPDHLkV1k0UW?29L From 8140374e26dc97c7b1752f1018991bf19ee86f7c Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 10 Aug 2023 20:18:28 +0200 Subject: [PATCH 215/398] chore: add licensing info to loader logos Signed-off-by: Sefa Eyeoglu --- launcher/resources/multimc/multimc.qrc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index bdf3495be..8f079bb37 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -348,9 +348,9 @@ scalable/launch.svg scalable/server.svg - scalable/instances/quiltmc.svg - scalable/instances/fabricmc.svg - 128x128/instances/forge.png - 128x128/instances/liteloader.png + scalable/instances/quiltmc.svg + scalable/instances/fabricmc.svg + 128x128/instances/forge.png + 128x128/instances/liteloader.png From ea43d0f687391db08459ea43794ee97b93e654fa Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 10 Aug 2023 20:41:52 +0200 Subject: [PATCH 216/398] fix: fix more warnings Signed-off-by: Sefa Eyeoglu --- launcher/BaseVersion.h | 4 ++-- launcher/FileSystem.h | 12 ++++++------ launcher/Version.h | 2 +- launcher/minecraft/mod/ResourceFolderModel.h | 2 +- launcher/net/HeaderProxy.h | 4 ++-- launcher/net/NetRequest.h | 4 ++-- launcher/ui/themes/CatPack.h | 4 ++-- tests/Task_test.cpp | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/launcher/BaseVersion.h b/launcher/BaseVersion.h index c4c9a1c5b..2837ff3a9 100644 --- a/launcher/BaseVersion.h +++ b/launcher/BaseVersion.h @@ -43,8 +43,8 @@ class 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(); }; + virtual bool operator<(BaseVersion& a) { return name() < a.name(); } + virtual bool operator>(BaseVersion& a) { return name() > a.name(); } }; Q_DECLARE_METATYPE(BaseVersion::Ptr) diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index f8a82baef..2a4b26209 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -112,8 +112,8 @@ class copy : public QObject { bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); } - int totalCopied() { return m_copied; } - int totalFailed() { return m_failedPaths.length(); } + qsizetype totalCopied() { return m_copied; } + qsizetype totalFailed() { return m_failedPaths.length(); } QStringList failed() { return m_failedPaths; } signals: @@ -130,7 +130,7 @@ class copy : public QObject { bool m_whitelist = false; QDir m_src; QDir m_dst; - int m_copied; + qsizetype m_copied; QStringList m_failedPaths; }; @@ -475,8 +475,8 @@ class clone : public QObject { bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); } - int totalCloned() { return m_cloned; } - int totalFailed() { return m_failedClones.length(); } + qsizetype totalCloned() { return m_cloned; } + qsizetype totalFailed() { return m_failedClones.length(); } QList> failed() { return m_failedClones; } @@ -492,7 +492,7 @@ class clone : public QObject { bool m_whitelist = false; QDir m_src; QDir m_dst; - int m_cloned; + qsizetype m_cloned; QList> m_failedClones; }; diff --git a/launcher/Version.h b/launcher/Version.h index 659f8e54e..df379082c 100644 --- a/launcher/Version.h +++ b/launcher/Version.h @@ -63,7 +63,7 @@ class Version { struct Section { explicit Section(QString fullString) : m_fullString(std::move(fullString)) { - int cutoff = m_fullString.size(); + qsizetype cutoff = m_fullString.size(); for (int i = 0; i < m_fullString.size(); i++) { if (!m_fullString[i].isDigit()) { cutoff = i; diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 45a5cc3a3..e78848944 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -78,7 +78,7 @@ class ResourceFolderModel : public QAbstractListModel { /** Creates a new parse task, if needed, for 'res' and start it.*/ virtual void resolveResource(Resource* res); - [[nodiscard]] int size() const { return m_resources.size(); } + [[nodiscard]] qsizetype size() const { return m_resources.size(); } [[nodiscard]] bool empty() const { return size() == 0; } [[nodiscard]] Resource& at(int index) { return *m_resources.at(index); } [[nodiscard]] Resource const& at(int index) const { return *m_resources.at(index); } diff --git a/launcher/net/HeaderProxy.h b/launcher/net/HeaderProxy.h index f41c5875a..213c04c58 100644 --- a/launcher/net/HeaderProxy.h +++ b/launcher/net/HeaderProxy.h @@ -31,8 +31,8 @@ struct HeaderPair { class HeaderProxy { public: - HeaderProxy(){}; - virtual ~HeaderProxy(){}; + HeaderProxy(){} + virtual ~HeaderProxy(){} public: virtual QList headers(const QNetworkRequest& request) const = 0; diff --git a/launcher/net/NetRequest.h b/launcher/net/NetRequest.h index 9a6021620..f91207ef3 100644 --- a/launcher/net/NetRequest.h +++ b/launcher/net/NetRequest.h @@ -52,7 +52,7 @@ namespace Net { class NetRequest : public NetAction { Q_OBJECT protected: - explicit NetRequest() : NetAction(){}; + explicit NetRequest() : NetAction(){} public: using Ptr = shared_qobject_ptr; @@ -62,7 +62,7 @@ class NetRequest : public NetAction { public: ~NetRequest() override = default; - void init() override{}; + void init() override{} public: void addValidator(Validator* v); diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h index b03a19f03..fdd117a7f 100644 --- a/launcher/ui/themes/CatPack.h +++ b/launcher/ui/themes/CatPack.h @@ -52,8 +52,8 @@ class BasicCatPack : public CatPack { public: BasicCatPack(QString id, QString name) : m_id(id), m_name(name) {} BasicCatPack(QString id) : BasicCatPack(id, id) {} - virtual QString id() { return m_id; }; - virtual QString name() { return m_name; }; + virtual QString id() { return m_id; } + virtual QString name() { return m_name; } virtual QString path(); protected: diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index eae3527d8..5bc737655 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -19,7 +19,7 @@ class BasicTask : public Task { BasicTask(bool show_debug_log = true) : Task(nullptr, show_debug_log) {} private: - void executeTask() override { emitSucceeded(); }; + void executeTask() override { emitSucceeded(); } }; /* Does nothing. Only used for testing. */ From d801151d5c2a0402980c4a435818983e766c8f55 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 11 Aug 2023 15:41:41 +0300 Subject: [PATCH 217/398] connect the abort signal in concurent task Signed-off-by: Trial97 --- launcher/tasks/ConcurrentTask.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index 884923466..efa162806 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -88,6 +88,7 @@ bool ConcurrentTask::abort() QMutableHashIterator doing_iter(m_doing); while (doing_iter.hasNext()) { auto task = doing_iter.next(); + disconnect(task->get(), &Task::aborted, this, 0); suceedeed &= (task.value())->abort(); } @@ -130,6 +131,7 @@ void ConcurrentTask::startNext() connect(next.get(), &Task::succeeded, this, [this, next]() { subTaskSucceeded(next); }); connect(next.get(), &Task::failed, this, [this, next](QString msg) { subTaskFailed(next, msg); }); + connect(next.get(), &Task::aborted, this, [this, next] { subTaskFailed(next, "Aborted"); }); connect(next.get(), &Task::status, this, [this, next](QString msg) { subTaskStatus(next, msg); }); connect(next.get(), &Task::details, this, [this, next](QString msg) { subTaskDetails(next, msg); }); From 73adac2501eb2279523531da9d04f514ab614853 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 10 Aug 2023 20:25:01 +0200 Subject: [PATCH 218/398] fix: use QColorConstants in Qt 5.14+ Signed-off-by: Sefa Eyeoglu --- launcher/SkinUtils.cpp | 4 ++++ launcher/minecraft/auth/MinecraftAccount.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/launcher/SkinUtils.cpp b/launcher/SkinUtils.cpp index 15be1cec6..989114ad5 100644 --- a/launcher/SkinUtils.cpp +++ b/launcher/SkinUtils.cpp @@ -35,7 +35,11 @@ QPixmap getFaceFromCache(QString username, int height, int width) QPixmap skinTexture(fskin.fileName()); if (!skinTexture.isNull()) { QPixmap skin = QPixmap(8, 8); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) skin.fill(QColorConstants::Transparent); +#else + skin.fill(QColor(0, 0, 0, 0)); +#endif QPainter painter(&skin); painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8)); painter.drawPixmap(0, 0, skinTexture.copy(40, 8, 8, 8)); diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 79213fe91..6c2f0805f 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -37,6 +37,7 @@ #include "MinecraftAccount.h" +#include #include #include #include @@ -126,7 +127,11 @@ QPixmap MinecraftAccount::getFace() const return QPixmap(); } QPixmap skin = QPixmap(8, 8); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) skin.fill(QColorConstants::Transparent); +#else + skin.fill(QColor(0, 0, 0, 0)); +#endif QPainter painter(&skin); painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8)); painter.drawPixmap(0, 0, skinTexture.copy(40, 8, 8, 8)); From 92dbe1684e3c7277a1b70711fe3450ba90c0e7d7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 11 Aug 2023 19:42:02 +0300 Subject: [PATCH 219/398] revert asan on debug on by default Signed-off-by: Trial97 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 350189c87..60f03640e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") -option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" on) +option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" off) # If this is a Debug build turn on address sanitiser if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) From bcf0635efd22d67b247d53562f91ae13a4095625 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 12 Aug 2023 10:06:27 +0300 Subject: [PATCH 220/398] Update CMakeLists.txt Co-authored-by: Sefa Eyeoglu Signed-off-by: Alexandru Ionut Tripon --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60f03640e..17f7c3d8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") -option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" off) +option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" OFF) # If this is a Debug build turn on address sanitiser if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) From 019e5ca3e819f5daf9933bc0fb091784b0ca561f Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sat, 12 Aug 2023 11:11:58 +0200 Subject: [PATCH 221/398] fix: use ApiDownload for CF URL handling Signed-off-by: Sefa Eyeoglu --- launcher/modplatform/flame/FlameAPI.cpp | 2 +- launcher/ui/MainWindow.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 2871f06a0..93d3b76a0 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -208,7 +208,7 @@ Task::Ptr FlameAPI::getFile(const QString& addonId, const QString& fileId, std:: { auto netJob = makeShared(QString("Flame::GetFile"), APPLICATION->network()); netJob->addNetAction( - Net::Download::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), response)); + Net::ApiDownload::makeByteArray(QUrl(QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(addonId, fileId)), response)); QObject::connect(netJob.get(), &NetJob::failed, [addonId, fileId] { qDebug() << "Flame API file failure" << addonId << fileId; }); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index dd383b239..8300fe295 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -85,7 +85,7 @@ #include #include #include -#include +#include #include #include #include @@ -1046,7 +1046,7 @@ void MainWindow::processURLs(QList urls) auto entry = APPLICATION->metacache()->resolveEntry("general", path); entry->setStale(true); auto dl_job = unique_qobject_ptr(new NetJob(tr("Modpack download"), APPLICATION->network())); - dl_job->addNetAction(Net::Download::makeCached(dl_url, entry)); + dl_job->addNetAction(Net::ApiDownload::makeCached(dl_url, entry)); auto archivePath = entry->getFullPath(); bool dl_success = false; From c9d628bf18ee8a2e8d1faf63fb9f8146b47099d6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 11 Aug 2023 19:42:02 +0300 Subject: [PATCH 222/398] revert asan on debug on by default Signed-off-by: Trial97 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 350189c87..60f03640e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") -option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" on) +option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" off) # If this is a Debug build turn on address sanitiser if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) From d6e4fe7c1f74222235a8eb4772fc999ba1d63d78 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 12 Aug 2023 10:06:27 +0300 Subject: [PATCH 223/398] Update CMakeLists.txt Co-authored-by: Sefa Eyeoglu Signed-off-by: Alexandru Ionut Tripon --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60f03640e..17f7c3d8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTOML_ENABLE_FLOAT16=0") # set CXXFLAGS for build targets set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS_RELEASE}") -option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" off) +option(DEBUG_ADDRESS_SANITIZER "Enable Address Sanitizer in Debug builds" OFF) # If this is a Debug build turn on address sanitiser if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER) From 71890707c034a0503a92128335c13773e51dc43b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 12 Aug 2023 12:54:10 +0300 Subject: [PATCH 224/398] format and apply the sugestion Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 2e0d9e37a..04fd42a7a 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -24,14 +24,11 @@ namespace ModPlatform { -static const QMap s_indexed_version_type_names = { - {"release", IndexedVersionType::Enum::Release}, - {"beta", IndexedVersionType::Enum::Beta}, - {"alpha", IndexedVersionType::Enum::Alpha} -}; +static const QMap s_indexed_version_type_names = { { "release", IndexedVersionType::Enum::Release }, + { "beta", IndexedVersionType::Enum::Beta }, + { "alpha", IndexedVersionType::Enum::Alpha } }; -IndexedVersionType::IndexedVersionType(const QString& type): IndexedVersionType(enumFromString(type)) -{} +IndexedVersionType::IndexedVersionType(const QString& type) : IndexedVersionType(enumFromString(type)) {} IndexedVersionType::IndexedVersionType(int type) { @@ -60,13 +57,13 @@ IndexedVersionType::IndexedVersionType(const IndexedVersionType& other) m_type = other.m_type; } -IndexedVersionType& IndexedVersionType::operator=(const IndexedVersionType& other) +IndexedVersionType& IndexedVersionType::operator=(const IndexedVersionType& other) { m_type = other.m_type; return *this; } -const QString IndexedVersionType::toString (const IndexedVersionType::Enum& type) +const QString IndexedVersionType::toString(const IndexedVersionType::Enum& type) { switch (type) { case IndexedVersionType::Enum::Release: @@ -78,18 +75,12 @@ const QString IndexedVersionType::toString (const IndexedVersionType::Enum& type case IndexedVersionType::Enum::UNKNOWN: default: return "unknown"; - } } IndexedVersionType::Enum IndexedVersionType::enumFromString(const QString& type) { - auto found = s_indexed_version_type_names.constFind(type); - if (found != s_indexed_version_type_names.constEnd()) { - return *found; - } else { - return IndexedVersionType::Enum::UNKNOWN; - } + return s_indexed_version_type_names.value(type, IndexedVersionType::Enum::UNKNOWN); } auto ProviderCapabilities::name(ResourceProvider p) -> const char* From 3c209ba502d946f8302192287c9e1c18bf5fdd7c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 12 Aug 2023 19:04:34 +0100 Subject: [PATCH 225/398] `theme` -> `catpacks` Co-authored-by: Alexandru Ionut Tripon Signed-off-by: TheKodeToad --- launcher/ui/themes/ThemeManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp index bce13b459..0bcac100c 100644 --- a/launcher/ui/themes/ThemeManager.cpp +++ b/launcher/ui/themes/ThemeManager.cpp @@ -276,7 +276,7 @@ void ThemeManager::initializeCatPacks() addCatPack(std::unique_ptr(new BasicCatPack(id, name))); } if (!m_catPacksFolder.mkpath(".")) - themeWarningLog() << "Couldn't create theme folder"; + themeWarningLog() << "Couldn't create catpacks folder"; themeDebugLog() << "CatPacks Folder Path:" << m_catPacksFolder.absolutePath(); QStringList supportedImageFormats; From 5056a51c188ef366d5ea13b6794dd14b11f78075 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 12 Aug 2023 21:18:22 +0100 Subject: [PATCH 226/398] Improvements and refinements to pack export - Persist fields - Toggle optional files Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 6 ++ .../modplatform/flame/FlamePackExportTask.cpp | 4 +- .../modplatform/flame/FlamePackExportTask.h | 2 + .../modrinth/ModrinthPackExportTask.cpp | 24 +++--- .../modrinth/ModrinthPackExportTask.h | 2 + launcher/ui/dialogs/ExportPackDialog.cpp | 71 +++++++++------ launcher/ui/dialogs/ExportPackDialog.ui | 86 ++++++++++++------- 7 files changed, 129 insertions(+), 66 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 305bff67b..c754640bb 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -194,6 +194,12 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerSetting("UseAccountForInstance", false); m_settings->registerSetting("InstanceAccountId", ""); + m_settings->registerSetting("ExportName", ""); + m_settings->registerSetting("ExportVersion", "1.0.0"); + m_settings->registerSetting("ExportSummary", ""); + m_settings->registerSetting("ExportAuthor", ""); + m_settings->registerSetting("ExportOptionalFiles", true); + qDebug() << "Instance-type specific settings were loaded!"; setSpecificSettingsLoaded(true); diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index f5f3af372..6cfc078ad 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -43,12 +43,14 @@ const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, const QString& author, + bool optionalFiles, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) : name(name) , version(version) , author(author) + , optionalFiles(optionalFiles) , instance(instance) , mcInstance(dynamic_cast(instance.get())) , gameRoot(instance->gameRoot()) @@ -407,7 +409,7 @@ QByteArray FlamePackExportTask::generateIndex() QJsonObject file; file["projectID"] = mod.addonId; file["fileID"] = mod.version; - file["required"] = mod.enabled; + file["required"] = mod.enabled || !optionalFiles; files << file; } obj["files"] = files; diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index d3dc6281e..78b46e91f 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -30,6 +30,7 @@ class FlamePackExportTask : public Task { FlamePackExportTask(const QString& name, const QString& version, const QString& author, + bool optionalFiles, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -44,6 +45,7 @@ class FlamePackExportTask : public Task { // inputs const QString name, version, author; + const bool optionalFiles; const InstancePtr instance; MinecraftInstance* mcInstance; const QDir gameRoot; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 7bf296398..ffd215018 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -33,12 +33,14 @@ const QStringList ModrinthPackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "z ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, const QString& version, const QString& summary, + bool optionalFiles, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) : name(name) , version(version) , summary(summary) + , optionalFiles(optionalFiles) , instance(instance) , mcInstance(dynamic_cast(instance.get())) , gameRoot(instance->gameRoot()) @@ -267,16 +269,18 @@ QByteArray ModrinthPackExportTask::generateIndex() QString path = iterator.key(); const ResolvedFile& value = iterator.value(); - // detect disabled mod - const QFileInfo pathInfo(path); - if (pathInfo.suffix() == "disabled") { - // rename it - path = pathInfo.dir().filePath(pathInfo.completeBaseName()); - // ...and make it optional - QJsonObject env; - env["client"] = "optional"; - env["server"] = "optional"; - fileOut["env"] = env; + if (optionalFiles) { + // detect disabled mod + const QFileInfo pathInfo(path); + if (pathInfo.suffix() == "disabled") { + // rename it + path = pathInfo.dir().filePath(pathInfo.completeBaseName()); + // ...and make it optional + QJsonObject env; + env["client"] = "optional"; + env["server"] = "optional"; + fileOut["env"] = env; + } } fileOut["path"] = path; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 1f9e0eb77..83540dfac 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -31,6 +31,7 @@ class ModrinthPackExportTask : public Task { ModrinthPackExportTask(const QString& name, const QString& version, const QString& summary, + bool optionalFiles, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -50,6 +51,7 @@ class ModrinthPackExportTask : public Task { // inputs const QString name, version, summary; + const bool optionalFiles; const InstancePtr instance; MinecraftInstance* mcInstance; const QDir gameRoot; diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index ad8db5ffb..0a97ee13c 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -37,15 +37,21 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) : QDialog(parent), instance(instance), ui(new Ui::ExportPackDialog), m_provider(provider) { + Q_ASSERT(m_provider == ModPlatform::ResourceProvider::MODRINTH || m_provider == ModPlatform::ResourceProvider::FLAME); + ui->setupUi(this); - ui->name->setText(instance->name()); + ui->name->setPlaceholderText(instance->name()); + ui->name->setText(instance->settings()->get("ExportName").toString()); + ui->version->setText(instance->settings()->get("ExportVersion").toString()); + ui->optionalFiles->setChecked(instance->settings()->get("ExportOptionalFiles").toBool()); + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { - ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); - setWindowTitle("Export Modrinth Pack"); + setWindowTitle(tr("Export Modrinth Pack")); + ui->summary->setText(instance->settings()->get("ExportSummary").toString()); } else { - setWindowTitle("Export CurseForge Pack"); - ui->version->setText(""); - ui->summaryLabel->setText("Author"); + setWindowTitle(tr("Export CurseForge Pack")); + ui->summaryLabel->setText(tr("&Author")); + ui->summary->setText(instance->settings()->get("ExportAuthor").toString()); } // ensure a valid pack is generated @@ -81,14 +87,14 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla proxy->blockedPaths().insert(root.relativeFilePath(index.absolutePath())); } - ui->treeView->setModel(proxy); - ui->treeView->setRootIndex(proxy->mapFromSource(model->index(instance->gameRoot()))); - ui->treeView->sortByColumn(0, Qt::AscendingOrder); + ui->files->setModel(proxy); + ui->files->setRootIndex(proxy->mapFromSource(model->index(instance->gameRoot()))); + ui->files->sortByColumn(0, Qt::AscendingOrder); model->setFilter(filter); model->setRootPath(instance->gameRoot()); - QHeaderView* headerView = ui->treeView->header(); + QHeaderView* headerView = ui->files->header(); headerView->setSectionResizeMode(QHeaderView::ResizeToContents); headerView->setSectionResizeMode(0, QHeaderView::Stretch); } @@ -100,26 +106,40 @@ ExportPackDialog::~ExportPackDialog() void ExportPackDialog::done(int result) { + auto settings = instance->settings(); + settings->set("ExportName", ui->name->text()); + settings->set("ExportVersion", ui->version->text()); + settings->set(m_provider == ModPlatform::ResourceProvider::FLAME ? "ExportAuthor" : "ExportSummary", ui->summary->text()); + settings->set("ExportOptionalFiles", ui->optionalFiles->isChecked()); + if (result == Accepted) { - const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); + const QString name = ui->name->text().isEmpty() ? instance->name() : ui->name->text(); + const QString filename = FS::RemoveInvalidFilenameChars(name); + QString output; - if (m_provider == ModPlatform::ResourceProvider::MODRINTH) - output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".mrpack"), "Modrinth pack (*.mrpack *.zip)", - nullptr); - else - output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".zip"), "CurseForge pack (*.zip)", nullptr); + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(name), FS::PathCombine(QDir::homePath(), filename + ".mrpack"), + "Modrinth pack (*.mrpack *.zip)", nullptr); + if (!(output.endsWith(".zip") || output.endsWith(".mrpack"))) + output.append(".mrpack"); + } else { + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(name), FS::PathCombine(QDir::homePath(), filename + ".zip"), + "CurseForge pack (*.zip)", nullptr); + if (!output.endsWith(".zip")) + output.append(".zip"); + } if (output.isEmpty()) return; + Task* task; - if (m_provider == ModPlatform::ResourceProvider::MODRINTH) - task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, - std::bind(&FileIgnoreProxy::filterFile, proxy, std::placeholders::_1)); - else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { + task = new ModrinthPackExportTask(name, ui->version->text(), ui->summary->text(), ui->optionalFiles->isChecked(), instance, + output, std::bind(&FileIgnoreProxy::filterFile, proxy, std::placeholders::_1)); + } else { + task = new FlamePackExportTask(name, ui->version->text(), ui->summary->text(), ui->optionalFiles->isChecked(), instance, output, std::bind(&FileIgnoreProxy::filterFile, proxy, std::placeholders::_1)); + } connect(task, &Task::failed, [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); @@ -140,7 +160,6 @@ void ExportPackDialog::done(int result) void ExportPackDialog::validate() { - const bool invalid = - ui->name->text().isEmpty() || ((m_provider == ModPlatform::ResourceProvider::MODRINTH) && ui->version->text().isEmpty()); - ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(invalid); + ui->buttonBox->button(QDialogButtonBox::Ok) + ->setDisabled(m_provider == ModPlatform::ResourceProvider::MODRINTH && ui->version->text().isEmpty()); } diff --git a/launcher/ui/dialogs/ExportPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui index 3976e28f8..09dea72a8 100644 --- a/launcher/ui/dialogs/ExportPackDialog.ui +++ b/launcher/ui/dialogs/ExportPackDialog.ui @@ -7,12 +7,9 @@ 0 0 650 - 413 + 510 - - Export Pack - true @@ -20,13 +17,16 @@ - Information + &Description - Summary + &Summary + + + summary @@ -36,14 +36,20 @@ - Name + &Name + + + name - Version + &Version + + + version @@ -57,31 +63,52 @@
- - - - Files + + + &Options - - - - - - true - - - QAbstractItemView::ExtendedSelection - - - true - - - false - + + + + + &Files + + + files + + + + + + + true + + + QAbstractItemView::ExtendedSelection + + + true + + + false + + + + + + + &Mark disabled files as optional + + + true + + + + @@ -97,7 +124,8 @@ name version summary - treeView + files + optionalFiles From 1aadaa208d287645f4e5ea6462f744e74ffa9670 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 13 Aug 2023 00:16:46 +0000 Subject: [PATCH 227/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/0d2fb29f5071a12d7983319c2c2576be6a130582' (2023-08-05) → 'github:nixos/nixpkgs/f0451844bbdf545f696f029d1448de4906c7f753' (2023-08-12) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/3139c4d1f7732cab89f06492bdd4677b877e3785' (2023-08-05) → 'github:cachix/pre-commit-hooks.nix/c5ac3aa3324bd8aebe8622a3fc92eeb3975d317a' (2023-08-11) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 3f1d7d25c..bfe151758 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1691218994, - "narHash": "sha256-46GJ5vLf9H+Oh7Jii2gJI9GATJHGbx2iQpon5nUSFPI=", + "lastModified": 1691853136, + "narHash": "sha256-wTzDsRV4HN8A2Sl0SVQY0q8ILs90CD43Ha//7gNZE+E=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0d2fb29f5071a12d7983319c2c2576be6a130582", + "rev": "f0451844bbdf545f696f029d1448de4906c7f753", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1691256628, - "narHash": "sha256-M0YXHemR3zbyhM7PvJa5lzGhWVf6kM/fpZ4cWe/VIhI=", + "lastModified": 1691747570, + "narHash": "sha256-J3fnIwJtHVQ0tK2JMBv4oAmII+1mCdXdpeCxtIsrL2A=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "3139c4d1f7732cab89f06492bdd4677b877e3785", + "rev": "c5ac3aa3324bd8aebe8622a3fc92eeb3975d317a", "type": "github" }, "original": { From 91ba4cf75ee30c64779edb5b7644e5a830de5026 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 14 Aug 2023 18:16:53 +0200 Subject: [PATCH 228/398] chore: reformat Signed-off-by: Sefa Eyeoglu --- buildconfig/BuildConfig.h | 6 +- flatpak/libdecor.json | 40 +- launcher/Application.cpp | 641 +-- launcher/Application.h | 123 +- launcher/ApplicationMessage.cpp | 8 +- launcher/ApplicationMessage.h | 6 +- launcher/BaseInstaller.cpp | 24 +- launcher/BaseInstaller.h | 19 +- launcher/BaseInstance.cpp | 58 +- launcher/BaseInstance.h | 89 +- launcher/BaseVersionList.cpp | 40 +- launcher/BaseVersionList.h | 27 +- launcher/Commandline.cpp | 28 +- launcher/Commandline.h | 5 +- launcher/DefaultVariable.h | 30 +- launcher/DesktopServices.cpp | 115 +- launcher/DesktopServices.h | 71 +- launcher/Exception.h | 29 +- launcher/ExponentialSeries.h | 17 +- launcher/FileSystem.cpp | 7 +- launcher/FileSystem.h | 39 +- launcher/Filter.cpp | 15 +- launcher/Filter.h | 75 +- launcher/GZip.cpp | 44 +- launcher/GZip.h | 10 +- launcher/InstanceCopyPrefs.cpp | 36 +- launcher/InstanceCopyPrefs.h | 2 +- launcher/InstanceCopyTask.cpp | 5 +- launcher/InstanceCopyTask.h | 9 +- launcher/InstanceImportTask.cpp | 62 +- launcher/InstanceImportTask.h | 35 +- launcher/InstanceList.cpp | 2 +- launcher/InstanceList.h | 114 +- launcher/InstancePageProvider.h | 44 +- launcher/InstanceTask.cpp | 10 +- launcher/JavaCommon.cpp | 55 +- launcher/JavaCommon.h | 69 +- launcher/Json.cpp | 159 +- launcher/Json.h | 202 +- launcher/KonamiCode.cpp | 36 +- launcher/KonamiCode.h | 13 +- launcher/LaunchController.cpp | 239 +- launcher/LaunchController.h | 62 +- launcher/LoggedProcess.cpp | 62 +- launcher/LoggedProcess.h | 31 +- launcher/MMCTime.cpp | 37 +- launcher/MMCTime.h | 6 +- launcher/MTPixmapCache.h | 6 +- launcher/MangoHud.cpp | 4 +- launcher/Markdown.h | 2 +- launcher/MessageLevel.cpp | 5 +- launcher/MessageLevel.h | 30 +- launcher/NullInstance.h | 92 +- launcher/ProblemProvider.h | 39 +- launcher/QVariantUtils.h | 23 +- launcher/RWStorage.h | 31 +- launcher/RecursiveFileSystemWatcher.cpp | 57 +- launcher/RecursiveFileSystemWatcher.h | 53 +- launcher/SeparatorPrefixTree.h | 182 +- launcher/SkinUtils.cpp | 17 +- launcher/SkinUtils.h | 3 +- launcher/StringUtils.h | 5 +- launcher/Usable.h | 16 +- launcher/Version.cpp | 8 +- launcher/Version.h | 32 +- launcher/VersionProxyModel.cpp | 209 +- launcher/VersionProxyModel.h | 67 +- launcher/WatchLock.h | 15 +- launcher/WindowsConsole.cpp | 14 +- launcher/filelink/FileLink.cpp | 2 +- launcher/java/JavaChecker.cpp | 56 +- launcher/java/JavaChecker.h | 25 +- launcher/java/JavaCheckerJob.cpp | 9 +- launcher/java/JavaCheckerJob.h | 23 +- launcher/java/JavaInstallList.cpp | 46 +- launcher/java/JavaInstallList.h | 40 +- launcher/java/JavaUtils.cpp | 197 +- launcher/java/JavaUtils.h | 5 +- launcher/java/JavaVersion.cpp | 65 +- launcher/java/JavaVersion.h | 38 +- launcher/launch/LaunchStep.cpp | 2 +- launcher/launch/LaunchStep.h | 30 +- launcher/launch/LaunchTask.cpp | 106 +- launcher/launch/LaunchTask.h | 66 +- launcher/launch/LogModel.cpp | 56 +- launcher/launch/LogModel.h | 29 +- launcher/launch/steps/CheckJava.cpp | 67 +- launcher/launch/steps/CheckJava.h | 24 +- launcher/launch/steps/LookupServerAddress.cpp | 41 +- launcher/launch/steps/LookupServerAddress.h | 27 +- launcher/launch/steps/PostLaunchCommand.cpp | 30 +- launcher/launch/steps/PostLaunchCommand.h | 22 +- launcher/launch/steps/PreLaunchCommand.cpp | 30 +- launcher/launch/steps/PreLaunchCommand.h | 22 +- launcher/launch/steps/QuitAfterGameStop.h | 14 +- launcher/launch/steps/TextPrint.cpp | 4 +- launcher/launch/steps/TextPrint.h | 13 +- launcher/launch/steps/Update.cpp | 23 +- launcher/launch/steps/Update.h | 19 +- launcher/main.cpp | 59 +- launcher/meta/BaseEntity.cpp | 83 +- launcher/meta/BaseEntity.h | 33 +- launcher/meta/Index.cpp | 97 +- launcher/meta/Index.h | 44 +- launcher/meta/JsonFormat.cpp | 114 +- launcher/meta/JsonFormat.h | 52 +- launcher/meta/Version.cpp | 44 +- launcher/meta/Version.h | 72 +- launcher/meta/VersionList.cpp | 154 +- launcher/meta/VersionList.h | 69 +- launcher/minecraft/Agent.h | 19 +- launcher/minecraft/AssetsUtils.cpp | 119 +- launcher/minecraft/AssetsUtils.h | 17 +- launcher/minecraft/Component.cpp | 192 +- launcher/minecraft/Component.h | 47 +- launcher/minecraft/ComponentUpdateTask.cpp | 408 +- launcher/minecraft/ComponentUpdateTask.h | 25 +- launcher/minecraft/ComponentUpdateTask_p.h | 19 +- launcher/minecraft/GradleSpecifier.h | 108 +- launcher/minecraft/LaunchProfile.cpp | 126 +- launcher/minecraft/LaunchProfile.h | 64 +- launcher/minecraft/Library.cpp | 187 +- launcher/minecraft/Library.h | 130 +- launcher/minecraft/MinecraftInstance.cpp | 331 +- launcher/minecraft/MinecraftInstance.h | 31 +- launcher/minecraft/MinecraftLoadAndCheck.cpp | 15 +- launcher/minecraft/MinecraftLoadAndCheck.h | 20 +- launcher/minecraft/MinecraftUpdate.cpp | 61 +- launcher/minecraft/MinecraftUpdate.h | 24 +- launcher/minecraft/MojangDownloadInfo.h | 34 +- launcher/minecraft/MojangVersionFormat.cpp | 218 +- launcher/minecraft/MojangVersionFormat.h | 25 +- launcher/minecraft/OneSixVersionFormat.cpp | 233 +- launcher/minecraft/OneSixVersionFormat.h | 34 +- launcher/minecraft/PackProfile.cpp | 435 +- launcher/minecraft/PackProfile.h | 64 +- launcher/minecraft/PackProfile_p.h | 12 +- launcher/minecraft/ParseUtils.cpp | 6 +- launcher/minecraft/ParseUtils.h | 2 +- launcher/minecraft/ProfileUtils.cpp | 88 +- launcher/minecraft/ProfileUtils.h | 14 +- launcher/minecraft/Rule.cpp | 14 +- launcher/minecraft/Rule.h | 71 +- .../minecraft/VanillaInstanceCreationTask.cpp | 8 +- launcher/minecraft/VersionFile.cpp | 20 +- launcher/minecraft/VersionFile.h | 29 +- launcher/minecraft/VersionFilterData.cpp | 65 +- launcher/minecraft/VersionFilterData.h | 12 +- launcher/minecraft/World.cpp | 282 +- launcher/minecraft/World.h | 97 +- launcher/minecraft/WorldList.cpp | 350 +- launcher/minecraft/WorldList.h | 87 +- launcher/minecraft/auth/AccountData.cpp | 207 +- launcher/minecraft/auth/AccountData.h | 23 +- launcher/minecraft/auth/AccountList.cpp | 430 +- launcher/minecraft/auth/AccountList.h | 54 +- launcher/minecraft/auth/AccountTask.cpp | 52 +- launcher/minecraft/auth/AccountTask.h | 45 +- launcher/minecraft/auth/AuthRequest.cpp | 53 +- launcher/minecraft/auth/AuthRequest.h | 41 +- launcher/minecraft/auth/AuthSession.cpp | 9 +- launcher/minecraft/auth/AuthSession.h | 10 +- launcher/minecraft/auth/AuthStep.cpp | 4 +- launcher/minecraft/auth/AuthStep.h | 20 +- launcher/minecraft/auth/MinecraftAccount.cpp | 144 +- launcher/minecraft/auth/MinecraftAccount.h | 118 +- launcher/minecraft/auth/Parsers.cpp | 190 +- launcher/minecraft/auth/Parsers.h | 27 +- launcher/minecraft/auth/Yggdrasil.cpp | 162 +- launcher/minecraft/auth/Yggdrasil.h | 40 +- launcher/minecraft/auth/flows/AuthFlow.cpp | 46 +- launcher/minecraft/auth/flows/AuthFlow.h | 31 +- launcher/minecraft/auth/flows/MSA.cpp | 21 +- launcher/minecraft/auth/flows/MSA.h | 20 +- launcher/minecraft/auth/flows/Mojang.cpp | 19 +- launcher/minecraft/auth/flows/Mojang.h | 23 +- launcher/minecraft/auth/flows/Offline.cpp | 12 +- launcher/minecraft/auth/flows/Offline.h | 20 +- .../minecraft/auth/steps/EntitlementsStep.cpp | 23 +- .../minecraft/auth/steps/EntitlementsStep.h | 9 +- launcher/minecraft/auth/steps/GetSkinStep.cpp | 24 +- launcher/minecraft/auth/steps/GetSkinStep.h | 7 +- .../auth/steps/LauncherLoginStep.cpp | 44 +- .../minecraft/auth/steps/LauncherLoginStep.h | 7 +- launcher/minecraft/auth/steps/MSAStep.cpp | 25 +- launcher/minecraft/auth/steps/MSAStep.h | 18 +- .../auth/steps/MigrationEligibilityStep.cpp | 26 +- .../auth/steps/MigrationEligibilityStep.h | 7 +- .../auth/steps/MinecraftProfileStep.cpp | 61 +- .../auth/steps/MinecraftProfileStep.h | 7 +- .../auth/steps/MinecraftProfileStepMojang.cpp | 63 +- .../auth/steps/MinecraftProfileStepMojang.h | 7 +- launcher/minecraft/auth/steps/OfflineStep.cpp | 9 +- launcher/minecraft/auth/steps/OfflineStep.h | 4 +- .../auth/steps/XboxAuthorizationStep.cpp | 132 +- .../auth/steps/XboxAuthorizationStep.h | 19 +- .../minecraft/auth/steps/XboxProfileStep.cpp | 54 +- .../minecraft/auth/steps/XboxProfileStep.h | 7 +- .../minecraft/auth/steps/XboxUserStep.cpp | 41 +- launcher/minecraft/auth/steps/XboxUserStep.h | 7 +- .../minecraft/auth/steps/YggdrasilStep.cpp | 25 +- launcher/minecraft/auth/steps/YggdrasilStep.h | 10 +- .../minecraft/gameoptions/GameOptions.cpp | 65 +- launcher/minecraft/gameoptions/GameOptions.h | 20 +- launcher/minecraft/launch/ClaimAccount.cpp | 8 +- launcher/minecraft/launch/ClaimAccount.h | 17 +- .../minecraft/launch/CreateGameFolders.cpp | 14 +- launcher/minecraft/launch/CreateGameFolders.h | 18 +- launcher/minecraft/launch/ExtractNatives.cpp | 46 +- launcher/minecraft/launch/ExtractNatives.h | 14 +- .../minecraft/launch/LauncherPartLaunch.cpp | 104 +- .../minecraft/launch/LauncherPartLaunch.h | 32 +- .../launch/MinecraftServerTarget.cpp | 31 +- .../minecraft/launch/MinecraftServerTarget.h | 2 +- launcher/minecraft/launch/ModMinecraftJar.cpp | 25 +- launcher/minecraft/launch/ModMinecraftJar.h | 15 +- .../minecraft/launch/PrintInstanceInfo.cpp | 79 +- launcher/minecraft/launch/PrintInstanceInfo.h | 18 +- .../minecraft/launch/ReconstructAssets.cpp | 7 +- launcher/minecraft/launch/ReconstructAssets.h | 12 +- launcher/minecraft/launch/ScanModFolders.cpp | 12 +- launcher/minecraft/launch/ScanModFolders.h | 19 +- .../minecraft/launch/VerifyJavaInstall.cpp | 22 +- launcher/minecraft/launch/VerifyJavaInstall.h | 9 +- launcher/minecraft/mod/DataPack.cpp | 8 +- launcher/minecraft/mod/MetadataHandler.h | 55 +- launcher/minecraft/mod/Mod.cpp | 81 +- launcher/minecraft/mod/Mod.h | 96 +- launcher/minecraft/mod/ModDetails.h | 106 +- launcher/minecraft/mod/ModFolderModel.cpp | 257 +- launcher/minecraft/mod/ModFolderModel.h | 107 +- launcher/minecraft/mod/Resource.cpp | 8 +- launcher/minecraft/mod/Resource.h | 21 +- .../minecraft/mod/ResourceFolderModel.cpp | 24 +- launcher/minecraft/mod/ResourceFolderModel.h | 21 +- launcher/minecraft/mod/ResourcePack.cpp | 2 +- .../minecraft/mod/ResourcePackFolderModel.cpp | 23 +- .../minecraft/mod/ResourcePackFolderModel.h | 21 +- .../minecraft/mod/ShaderPackFolderModel.h | 6 +- launcher/minecraft/mod/TexturePack.cpp | 2 +- .../minecraft/mod/TexturePackFolderModel.cpp | 26 +- .../minecraft/mod/TexturePackFolderModel.h | 23 +- .../minecraft/mod/tasks/BasicFolderLoadTask.h | 12 +- .../minecraft/mod/tasks/LocalModParseTask.cpp | 24 +- .../minecraft/mod/tasks/LocalModUpdateTask.h | 30 +- .../mod/tasks/LocalResourcePackParseTask.cpp | 8 +- .../mod/tasks/LocalResourceParse.cpp | 29 +- .../mod/tasks/LocalTexturePackParseTask.cpp | 11 +- .../mod/tasks/LocalWorldSaveParseTask.cpp | 8 +- .../mod/tasks/LocalWorldSaveParseTask.h | 2 +- .../minecraft/mod/tasks/ModFolderLoadTask.cpp | 77 +- .../minecraft/mod/tasks/ModFolderLoadTask.h | 82 +- launcher/minecraft/services/CapeChange.cpp | 30 +- launcher/minecraft/services/CapeChange.h | 20 +- launcher/minecraft/services/SkinDelete.cpp | 15 +- launcher/minecraft/services/SkinDelete.h | 13 +- launcher/minecraft/services/SkinUpload.cpp | 19 +- launcher/minecraft/services/SkinUpload.h | 20 +- launcher/minecraft/update/AssetUpdateTask.cpp | 30 +- launcher/minecraft/update/AssetUpdateTask.h | 17 +- .../minecraft/update/FMLLibrariesTask.cpp | 53 +- launcher/minecraft/update/FMLLibrariesTask.h | 22 +- launcher/minecraft/update/FoldersTask.cpp | 8 +- launcher/minecraft/update/FoldersTask.h | 15 +- launcher/minecraft/update/LibrariesTask.cpp | 35 +- launcher/minecraft/update/LibrariesTask.h | 19 +- launcher/modplatform/CheckUpdateTask.h | 17 +- launcher/modplatform/EnsureMetadataTask.h | 5 +- launcher/modplatform/ModIndex.cpp | 30 +- launcher/modplatform/ModIndex.h | 2 - launcher/modplatform/ResourceAPI.h | 6 +- .../modplatform/atlauncher/ATLPackIndex.cpp | 11 +- .../modplatform/atlauncher/ATLPackIndex.h | 15 +- .../atlauncher/ATLPackInstallTask.cpp | 347 +- .../atlauncher/ATLPackManifest.cpp | 114 +- .../modplatform/atlauncher/ATLPackManifest.h | 48 +- .../modplatform/atlauncher/ATLShareCode.cpp | 2 +- .../modplatform/atlauncher/ATLShareCode.h | 4 +- .../modplatform/flame/FileResolvingTask.cpp | 2 +- launcher/modplatform/flame/FlameAPI.cpp | 6 +- launcher/modplatform/flame/FlameCheckUpdate.h | 5 +- launcher/modplatform/flame/FlameModIndex.cpp | 1 - launcher/modplatform/flame/FlamePackIndex.cpp | 9 +- launcher/modplatform/flame/PackManifest.cpp | 7 +- launcher/modplatform/flame/PackManifest.h | 34 +- .../helpers/NetworkResourceAPI.cpp | 1 - .../modplatform/legacy_ftb/PackFetchTask.cpp | 2 +- launcher/modplatform/legacy_ftb/PackHelpers.h | 22 +- .../legacy_ftb/PrivatePackManager.cpp | 19 +- .../legacy_ftb/PrivatePackManager.h | 30 +- .../modrinth/ModrinthCheckUpdate.h | 5 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 26 +- .../modrinth/ModrinthInstanceCreationTask.h | 5 +- .../modrinth/ModrinthPackExportTask.cpp | 2 - .../modrinth/ModrinthPackManifest.cpp | 25 +- .../modrinth/ModrinthPackManifest.h | 9 +- launcher/modplatform/packwiz/Packwiz.h | 54 +- .../technic/SingleZipPackInstallTask.cpp | 39 +- .../technic/SingleZipPackInstallTask.h | 16 +- .../technic/SolderPackInstallTask.cpp | 38 +- .../technic/SolderPackManifest.cpp | 2 +- .../modplatform/technic/SolderPackManifest.h | 4 +- .../technic/TechnicPackProcessor.cpp | 92 +- .../technic/TechnicPackProcessor.h | 29 +- launcher/net/HeaderProxy.h | 4 +- launcher/net/HttpMetaCache.cpp | 5 +- launcher/net/Logging.h | 4 +- launcher/net/MetaCacheSink.cpp | 31 +- launcher/net/NetAction.h | 4 +- launcher/net/NetJob.h | 4 +- launcher/net/NetRequest.h | 4 +- launcher/net/NetUtils.h | 37 +- launcher/net/PasteUpload.cpp | 247 +- launcher/net/PasteUpload.h | 28 +- launcher/net/Validator.h | 15 +- launcher/news/NewsChecker.cpp | 5 +- launcher/news/NewsChecker.h | 16 +- launcher/news/NewsEntry.cpp | 15 +- launcher/news/NewsEntry.h | 15 +- launcher/pathmatcher/FSTreeMatcher.h | 20 +- launcher/pathmatcher/IPathMatcher.h | 11 +- launcher/pathmatcher/MultiMatcher.h | 23 +- launcher/pathmatcher/RegexpMatcher.h | 26 +- launcher/screenshots/ImgurAlbumCreation.cpp | 28 +- launcher/screenshots/ImgurAlbumCreation.h | 27 +- launcher/screenshots/ImgurUpload.cpp | 31 +- launcher/screenshots/ImgurUpload.h | 18 +- launcher/screenshots/Screenshot.h | 6 +- launcher/settings/INIFile.h | 9 +- launcher/settings/INISettingsObject.cpp | 50 +- launcher/settings/INISettingsObject.h | 26 +- launcher/settings/OverrideSetting.cpp | 6 +- launcher/settings/OverrideSetting.h | 11 +- launcher/settings/PassthroughSetting.cpp | 15 +- launcher/settings/PassthroughSetting.h | 11 +- launcher/settings/Setting.cpp | 14 +- launcher/settings/Setting.h | 31 +- launcher/settings/SettingsObject.cpp | 67 +- launcher/settings/SettingsObject.h | 77 +- launcher/tasks/ConcurrentTask.cpp | 13 +- launcher/tasks/ConcurrentTask.h | 2 +- launcher/tasks/Task.cpp | 48 +- launcher/tasks/Task.h | 42 +- launcher/tools/BaseExternalTool.cpp | 27 +- launcher/tools/BaseExternalTool.h | 43 +- launcher/tools/BaseProfiler.cpp | 13 +- launcher/tools/BaseProfiler.h | 27 +- launcher/tools/JProfiler.cpp | 53 +- launcher/tools/JProfiler.h | 11 +- launcher/tools/JVisualVM.cpp | 51 +- launcher/tools/JVisualVM.h | 11 +- launcher/tools/MCEditTool.cpp | 26 +- launcher/tools/MCEditTool.h | 12 +- launcher/translations/POTranslator.cpp | 186 +- launcher/translations/POTranslator.h | 14 +- launcher/translations/TranslationsModel.cpp | 383 +- launcher/ui/ColorCache.cpp | 7 +- launcher/ui/ColorCache.h | 49 +- launcher/ui/GuiUtil.cpp | 73 +- launcher/ui/GuiUtil.h | 13 +- launcher/ui/InstanceWindow.cpp | 49 +- launcher/ui/InstanceWindow.h | 30 +- launcher/ui/MainWindow.cpp | 14 +- launcher/ui/MainWindow.h | 76 +- launcher/ui/dialogs/AboutDialog.cpp | 61 +- launcher/ui/dialogs/AboutDialog.h | 17 +- launcher/ui/dialogs/BlockedModsDialog.cpp | 2 +- launcher/ui/dialogs/CopyInstanceDialog.cpp | 4 +- launcher/ui/dialogs/CustomMessageBox.cpp | 14 +- launcher/ui/dialogs/CustomMessageBox.h | 7 +- launcher/ui/dialogs/EditAccountDialog.cpp | 11 +- launcher/ui/dialogs/EditAccountDialog.h | 26 +- launcher/ui/dialogs/IconPickerDialog.cpp | 39 +- launcher/ui/dialogs/IconPickerDialog.h | 23 +- launcher/ui/dialogs/ImportResourceDialog.h | 2 +- launcher/ui/dialogs/LoginDialog.cpp | 28 +- launcher/ui/dialogs/LoginDialog.h | 31 +- launcher/ui/dialogs/MSALoginDialog.cpp | 41 +- launcher/ui/dialogs/MSALoginDialog.h | 32 +- launcher/ui/dialogs/ModUpdateDialog.cpp | 14 +- launcher/ui/dialogs/ModUpdateDialog.h | 4 +- launcher/ui/dialogs/NewComponentDialog.cpp | 28 +- launcher/ui/dialogs/NewComponentDialog.h | 16 +- launcher/ui/dialogs/NewInstanceDialog.cpp | 33 +- launcher/ui/dialogs/NewInstanceDialog.h | 40 +- launcher/ui/dialogs/OfflineLoginDialog.cpp | 23 +- launcher/ui/dialogs/OfflineLoginDialog.h | 29 +- launcher/ui/dialogs/ProfileSelectDialog.cpp | 30 +- launcher/ui/dialogs/ProfileSelectDialog.h | 22 +- launcher/ui/dialogs/ProfileSetupDialog.cpp | 97 +- launcher/ui/dialogs/ProfileSetupDialog.h | 56 +- launcher/ui/dialogs/ProgressDialog.cpp | 27 +- launcher/ui/dialogs/ProgressDialog.h | 47 +- launcher/ui/dialogs/ScrollMessageBox.cpp | 9 +- launcher/ui/dialogs/ScrollMessageBox.h | 15 +- launcher/ui/dialogs/SkinUploadDialog.cpp | 82 +- launcher/ui/dialogs/SkinUploadDialog.h | 21 +- launcher/ui/dialogs/VersionSelectDialog.cpp | 16 +- launcher/ui/dialogs/VersionSelectDialog.h | 37 +- .../instanceview/AccessibleInstanceView.cpp | 147 +- .../ui/instanceview/AccessibleInstanceView.h | 4 +- .../instanceview/AccessibleInstanceView_p.h | 68 +- launcher/ui/instanceview/InstanceDelegate.cpp | 136 +- launcher/ui/instanceview/InstanceDelegate.h | 23 +- .../ui/instanceview/InstanceProxyModel.cpp | 33 +- launcher/ui/instanceview/InstanceProxyModel.h | 19 +- launcher/ui/instanceview/InstanceView.cpp | 451 +- launcher/ui/instanceview/InstanceView.h | 116 +- launcher/ui/instanceview/VisualGroup.h | 53 +- launcher/ui/pagedialog/PageDialog.cpp | 14 +- launcher/ui/pagedialog/PageDialog.h | 16 +- launcher/ui/pages/BasePageContainer.h | 5 +- launcher/ui/pages/BasePageProvider.h | 47 +- launcher/ui/pages/global/APIPage.cpp | 45 +- launcher/ui/pages/global/APIPage.h | 36 +- launcher/ui/pages/global/AccountListPage.cpp | 89 +- launcher/ui/pages/global/AccountListPage.h | 44 +- .../ui/pages/global/CustomCommandsPage.cpp | 20 +- launcher/ui/pages/global/CustomCommandsPage.h | 35 +- .../ui/pages/global/ExternalToolsPage.cpp | 103 +- launcher/ui/pages/global/ExternalToolsPage.h | 36 +- launcher/ui/pages/global/JavaPage.cpp | 44 +- launcher/ui/pages/global/JavaPage.h | 47 +- launcher/ui/pages/global/LanguagePage.cpp | 11 +- launcher/ui/pages/global/LanguagePage.h | 37 +- launcher/ui/pages/global/LauncherPage.cpp | 99 +- launcher/ui/pages/global/LauncherPage.h | 49 +- launcher/ui/pages/global/MinecraftPage.cpp | 6 +- launcher/ui/pages/global/MinecraftPage.h | 44 +- launcher/ui/pages/global/ProxyPage.cpp | 21 +- launcher/ui/pages/global/ProxyPage.h | 44 +- .../ui/pages/instance/ExternalResourcesPage.h | 4 +- .../ui/pages/instance/GameOptionsPage.cpp | 11 +- launcher/ui/pages/instance/GameOptionsPage.h | 38 +- .../pages/instance/InstanceSettingsPage.cpp | 127 +- .../ui/pages/instance/InstanceSettingsPage.h | 36 +- launcher/ui/pages/instance/LogPage.cpp | 146 +- launcher/ui/pages/instance/LogPage.h | 44 +- launcher/ui/pages/instance/NotesPage.cpp | 5 +- launcher/ui/pages/instance/NotesPage.h | 35 +- launcher/ui/pages/instance/OtherLogsPage.cpp | 140 +- launcher/ui/pages/instance/OtherLogsPage.h | 42 +- launcher/ui/pages/instance/ResourcePackPage.h | 11 +- .../ui/pages/instance/ScreenshotsPage.cpp | 244 +- launcher/ui/pages/instance/ScreenshotsPage.h | 58 +- launcher/ui/pages/instance/ServersPage.cpp | 382 +- launcher/ui/pages/instance/ServersPage.h | 59 +- launcher/ui/pages/instance/ShaderPackPage.h | 7 +- launcher/ui/pages/instance/TexturePackPage.h | 12 +- launcher/ui/pages/instance/VersionPage.cpp | 1 - launcher/ui/pages/instance/WorldListPage.cpp | 179 +- launcher/ui/pages/instance/WorldListPage.h | 64 +- launcher/ui/pages/modplatform/CustomPage.cpp | 83 +- launcher/ui/pages/modplatform/CustomPage.h | 44 +- launcher/ui/pages/modplatform/ImportPage.cpp | 66 +- launcher/ui/pages/modplatform/ImportPage.h | 43 +- .../ui/pages/modplatform/ResourcePackPage.cpp | 6 +- .../ui/pages/modplatform/ResourcePackPage.h | 2 +- launcher/ui/pages/modplatform/ResourcePage.h | 3 +- .../ui/pages/modplatform/TexturePackPage.h | 5 +- .../modplatform/atlauncher/AtlFilterModel.cpp | 16 +- .../modplatform/atlauncher/AtlFilterModel.h | 16 +- .../atlauncher/AtlOptionalModDialog.cpp | 130 +- .../atlauncher/AtlOptionalModDialog.h | 37 +- .../pages/modplatform/atlauncher/AtlPage.cpp | 34 +- .../ui/pages/modplatform/atlauncher/AtlPage.h | 46 +- .../AtlUserInteractionSupportImpl.cpp | 16 +- .../ui/pages/modplatform/flame/FlamePage.cpp | 3 +- .../ui/pages/modplatform/flame/FlamePage.h | 46 +- .../modplatform/flame/FlameResourcePages.cpp | 28 +- .../modplatform/flame/FlameResourcePages.h | 29 +- .../modplatform/legacy_ftb/ListModel.cpp | 2 +- .../pages/modplatform/legacy_ftb/ListModel.h | 49 +- .../ui/pages/modplatform/legacy_ftb/Page.cpp | 147 +- .../ui/pages/modplatform/legacy_ftb/Page.h | 62 +- .../modplatform/modrinth/ModrinthModel.cpp | 28 +- .../modplatform/modrinth/ModrinthModel.h | 9 +- .../modrinth/ModrinthResourcePages.cpp | 30 +- .../modrinth/ModrinthResourcePages.h | 30 +- .../pages/modplatform/technic/TechnicData.h | 2 +- .../pages/modplatform/technic/TechnicPage.cpp | 89 +- .../pages/modplatform/technic/TechnicPage.h | 44 +- launcher/ui/setupwizard/BaseWizardPage.h | 30 +- launcher/ui/setupwizard/JavaWizardPage.cpp | 40 +- launcher/ui/setupwizard/JavaWizardPage.h | 18 +- .../ui/setupwizard/LanguageWizardPage.cpp | 13 +- launcher/ui/setupwizard/LanguageWizardPage.h | 13 +- launcher/ui/setupwizard/PasteWizardPage.cpp | 11 +- launcher/ui/setupwizard/PasteWizardPage.h | 13 +- launcher/ui/setupwizard/SetupWizard.cpp | 47 +- launcher/ui/setupwizard/SetupWizard.h | 21 +- launcher/ui/themes/BrightTheme.cpp | 23 +- launcher/ui/themes/BrightTheme.h | 6 +- launcher/ui/themes/CustomTheme.cpp | 3 +- launcher/ui/themes/DarkTheme.cpp | 16 +- launcher/ui/themes/DarkTheme.h | 5 +- launcher/ui/themes/FusionTheme.h | 5 +- launcher/ui/themes/ITheme.cpp | 7 +- launcher/ui/themes/SystemTheme.cpp | 2 +- launcher/ui/widgets/CustomCommands.cpp | 13 +- launcher/ui/widgets/CustomCommands.h | 18 +- launcher/ui/widgets/DropLabel.cpp | 17 +- launcher/ui/widgets/DropLabel.h | 19 +- launcher/ui/widgets/ErrorFrame.cpp | 46 +- launcher/ui/widgets/ErrorFrame.h | 22 +- launcher/ui/widgets/FocusLineEdit.cpp | 9 +- launcher/ui/widgets/FocusLineEdit.h | 17 +- launcher/ui/widgets/IconLabel.cpp | 16 +- launcher/ui/widgets/IconLabel.h | 13 +- launcher/ui/widgets/JavaSettingsWidget.cpp | 145 +- launcher/ui/widgets/JavaSettingsWidget.h | 71 +- launcher/ui/widgets/LabeledToolButton.cpp | 46 +- launcher/ui/widgets/LabeledToolButton.h | 16 +- launcher/ui/widgets/LineSeparator.cpp | 14 +- launcher/ui/widgets/LineSeparator.h | 14 +- launcher/ui/widgets/LogView.cpp | 49 +- launcher/ui/widgets/LogView.h | 33 +- launcher/ui/widgets/ModFilterWidget.cpp | 110 +- launcher/ui/widgets/ModFilterWidget.h | 33 +- launcher/ui/widgets/ModListView.cpp | 46 +- launcher/ui/widgets/ModListView.h | 11 +- launcher/ui/widgets/PageContainer.cpp | 103 +- launcher/ui/widgets/PageContainer.h | 54 +- launcher/ui/widgets/PageContainer_p.h | 77 +- launcher/ui/widgets/ProjectItem.cpp | 5 +- launcher/ui/widgets/ProjectItem.h | 7 +- launcher/ui/widgets/SubTaskProgressBar.cpp | 6 +- launcher/ui/widgets/SubTaskProgressBar.h | 10 +- .../ui/widgets/ThemeCustomizationWidget.cpp | 18 +- .../ui/widgets/VariableSizedImageObject.cpp | 2 +- launcher/ui/widgets/VersionListView.cpp | 52 +- launcher/ui/widgets/VersionListView.h | 31 +- launcher/ui/widgets/VersionSelectWidget.cpp | 52 +- launcher/ui/widgets/VersionSelectWidget.h | 47 +- launcher/ui/widgets/WideBar.cpp | 10 +- launcher/updater/ExternalUpdater.h | 9 +- launcher/updater/MacSparkleUpdater.h | 11 +- launcher/updater/MacSparkleUpdater.mm | 107 +- libraries/LocalPeer/include/LocalPeer.h | 44 +- libraries/LocalPeer/src/LocalPeer.cpp | 65 +- libraries/LocalPeer/src/LockedFile.cpp | 6 +- libraries/LocalPeer/src/LockedFile.h | 10 +- libraries/LocalPeer/src/LockedFile_unix.cpp | 6 +- libraries/LocalPeer/src/LockedFile_win.cpp | 40 +- libraries/gamemode/include/gamemode_client.h | 296 +- libraries/javacheck/JavaCheck.java | 8 +- libraries/katabasis/include/katabasis/Bits.h | 16 +- .../katabasis/include/katabasis/DeviceFlow.h | 64 +- .../katabasis/include/katabasis/Globals.h | 4 +- .../katabasis/include/katabasis/PollServer.h | 25 +- libraries/katabasis/include/katabasis/Reply.h | 40 +- .../include/katabasis/RequestParameter.h | 8 +- libraries/katabasis/src/DeviceFlow.cpp | 184 +- libraries/katabasis/src/JsonResponse.cpp | 5 +- libraries/katabasis/src/JsonResponse.h | 6 +- libraries/katabasis/src/PollServer.cpp | 37 +- libraries/katabasis/src/Reply.cpp | 31 +- .../launcher/net/minecraft/Launcher.java | 8 +- .../org/prismlauncher/EntryPoint.java | 20 +- .../exception/ParameterNotFoundException.java | 2 - .../exception/ParseException.java | 2 - .../org/prismlauncher/launcher/Launcher.java | 2 - .../launcher/impl/AbstractLauncher.java | 8 +- .../launcher/impl/StandardLauncher.java | 6 +- .../launcher/impl/legacy/LegacyFrame.java | 12 +- .../launcher/impl/legacy/LegacyLauncher.java | 15 +- .../org/prismlauncher/utils/Parameters.java | 6 +- .../prismlauncher/utils/ReflectionUtils.java | 9 +- .../prismlauncher/utils/logging/Level.java | 1 - .../org/prismlauncher/utils/logging/Log.java | 4 +- libraries/murmur2/src/MurmurHash2.h | 4 +- libraries/rainbow/include/rainbow.h | 27 +- libraries/rainbow/src/rainbow.cpp | 187 +- libraries/systeminfo/include/distroutils.h | 17 +- libraries/systeminfo/include/sys.h | 32 +- libraries/systeminfo/src/distroutils.cpp | 166 +- libraries/systeminfo/src/sys_apple.cpp | 19 +- libraries/systeminfo/src/sys_test.cpp | 24 +- libraries/systeminfo/src/sys_unix.cpp | 56 +- libraries/systeminfo/src/sys_win32.cpp | 2 +- renovate.json | 20 +- tests/DataPackParse_test.cpp | 8 +- tests/FileSystem_test.cpp | 275 +- tests/GZip_test.cpp | 14 +- tests/GradleSpecifier_test.cpp | 22 +- tests/Index_test.cpp | 22 +- tests/JavaVersion_test.cpp | 69 +- tests/Library_test.cpp | 62 +- tests/MojangVersionFormat_test.cpp | 11 +- tests/Packwiz_test.cpp | 16 +- tests/ParseUtils_test.cpp | 24 +- tests/ResourceFolderModel_test.cpp | 100 +- tests/ResourceModel_test.cpp | 3 +- tests/ResourcePackParse_test.cpp | 14 +- tests/ShaderPackParse_test.cpp | 8 +- tests/Task_test.cpp | 7 +- tests/TexturePackParse_test.cpp | 8 +- tests/Version_test.cpp | 75 +- tests/WorldSaveParse_test.cpp | 18 +- .../MojangVersionFormat/1.9-simple.json | 3 +- tests/testdata/MojangVersionFormat/1.9.json | 54 +- .../MojangVersionFormat/lib-native.json | 12 +- .../PackageManifest/1.8.0_202-x64.json | 4668 ++++++++++++++++- 603 files changed, 15840 insertions(+), 16257 deletions(-) diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 11773d887..387f494f3 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -36,8 +36,8 @@ */ #pragma once -#include #include +#include /** * \brief The Config class holds all the build-time information passed from the build system. @@ -145,7 +145,7 @@ class Config { QString AUTH_BASE = "https://authserver.mojang.com/"; QString IMGUR_BASE_URL = "https://api.imgur.com/3/"; QString FMLLIBS_BASE_URL = "https://files.prismlauncher.org/fmllibs/"; // FIXME: move into CMakeLists - QString TRANSLATIONS_BASE_URL = "https://i18n.prismlauncher.org/"; // FIXME: move into CMakeLists + QString TRANSLATIONS_BASE_URL = "https://i18n.prismlauncher.org/"; // FIXME: move into CMakeLists QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/"; @@ -162,7 +162,7 @@ class Config { QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2"; QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2"; - QStringList MODRINTH_MRPACK_HOSTS{"cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com"}; + QStringList MODRINTH_MRPACK_HOSTS{ "cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com" }; QString FLAME_BASE_URL = "https://api.curseforge.com/v1"; diff --git a/flatpak/libdecor.json b/flatpak/libdecor.json index 12afad69f..589310a35 100644 --- a/flatpak/libdecor.json +++ b/flatpak/libdecor.json @@ -1,22 +1,22 @@ { - "name": "libdecor", - "buildsystem": "meson", - "config-opts": [ - "-Ddemo=false" - ], - "sources": [ - { - "type": "git", - "url": "https://gitlab.freedesktop.org/libdecor/libdecor.git", - "commit": "73260393a97291c887e1074ab7f318e031be0ac6" - }, - { - "type": "patch", - "path": "patches/weird_libdecor.patch" - } - ], - "cleanup": [ - "/include", - "/lib/pkgconfig" - ] + "name": "libdecor", + "buildsystem": "meson", + "config-opts": [ + "-Ddemo=false" + ], + "sources": [ + { + "type": "git", + "url": "https://gitlab.freedesktop.org/libdecor/libdecor.git", + "commit": "73260393a97291c887e1074ab7f318e031be0ac6" + }, + { + "type": "patch", + "path": "patches/weird_libdecor.patch" + } + ], + "cleanup": [ + "/include", + "/lib/pkgconfig" + ] } diff --git a/launcher/Application.cpp b/launcher/Application.cpp index e89b7659b..6194527c5 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -49,27 +49,27 @@ #include "pathmatcher/MultiMatcher.h" #include "pathmatcher/SimplePrefixMatcher.h" #include "settings/INIFile.h" -#include "ui/MainWindow.h" #include "ui/InstanceWindow.h" +#include "ui/MainWindow.h" #include "ui/dialogs/ProgressDialog.h" #include "ui/instanceview/AccessibleInstanceView.h" #include "ui/pages/BasePageProvider.h" -#include "ui/pages/global/LauncherPage.h" -#include "ui/pages/global/MinecraftPage.h" +#include "ui/pages/global/APIPage.h" +#include "ui/pages/global/AccountListPage.h" +#include "ui/pages/global/CustomCommandsPage.h" +#include "ui/pages/global/ExternalToolsPage.h" #include "ui/pages/global/JavaPage.h" #include "ui/pages/global/LanguagePage.h" +#include "ui/pages/global/LauncherPage.h" +#include "ui/pages/global/MinecraftPage.h" #include "ui/pages/global/ProxyPage.h" -#include "ui/pages/global/ExternalToolsPage.h" -#include "ui/pages/global/AccountListPage.h" -#include "ui/pages/global/APIPage.h" -#include "ui/pages/global/CustomCommandsPage.h" -#include "ui/setupwizard/SetupWizard.h" -#include "ui/setupwizard/LanguageWizardPage.h" #include "ui/setupwizard/JavaWizardPage.h" +#include "ui/setupwizard/LanguageWizardPage.h" #include "ui/setupwizard/PasteWizardPage.h" +#include "ui/setupwizard/SetupWizard.h" #include "ui/setupwizard/ThemeWizardPage.h" #include "ui/dialogs/CustomMessageBox.h" @@ -83,20 +83,20 @@ #include #include -#include #include #include +#include #include #include -#include -#include +#include +#include #include #include +#include #include -#include #include +#include #include -#include #include "InstanceList.h" #include "MTPixmapCache.h" @@ -116,19 +116,19 @@ #include "settings/INISettingsObject.h" #include "settings/Setting.h" -#include "translations/TranslationsModel.h" #include "meta/Index.h" +#include "translations/TranslationsModel.h" -#include #include +#include #include #include #ifdef Q_OS_LINUX #include -#include "gamemode_client.h" #include "MangoHud.h" +#include "gamemode_client.h" #endif #if defined(Q_OS_MAC) && defined(SPARKLE_ENABLED) @@ -149,10 +149,10 @@ PixmapCache* PixmapCache::s_instance = nullptr; namespace { /** This is used so that we can output to the log file in addition to the CLI. */ -void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) { static std::mutex loggerMutex; - const std::lock_guard lock(loggerMutex); // synchronized, QFile logFile is not thread-safe + const std::lock_guard lock(loggerMutex); // synchronized, QFile logFile is not thread-safe QString out = qFormatLogMessage(type, context, msg); out += QChar::LineFeed; @@ -165,8 +165,6 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt } // namespace - - Application::Application(int& argc, char** argv) : QApplication(argc, argv) { #if defined Q_OS_WIN32 @@ -190,15 +188,14 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) QCommandLineParser parser; parser.setApplicationDescription(BuildConfig.LAUNCHER_DISPLAYNAME); - parser.addOptions({ - {{"d", "dir"}, "Use a custom path as application root (use '.' for current directory)", "directory"}, - {{"l", "launch"}, "Launch the specified instance (by instance ID)", "instance"}, - {{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"}, - {{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"}, - {"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"}, - {{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}, - {"show", "Opens the window for the specified instance (by instance ID)", "show"} - }); + parser.addOptions( + { { { "d", "dir" }, "Use a custom path as application root (use '.' for current directory)", "directory" }, + { { "l", "launch" }, "Launch the specified instance (by instance ID)", "instance" }, + { { "s", "server" }, "Join the specified server on launch (only valid in combination with --launch)", "address" }, + { { "a", "profile" }, "Use the account specified by its profile name (only valid in combination with --launch)", "profile" }, + { "alive", "Write a small '" + liveCheckFile + "' file after the launcher starts" }, + { { "I", "import" }, "Import instance from specified zip (local path or URL)", "file" }, + { "show", "Opens the window for the specified instance (by instance ID)", "show" } }); parser.addHelpOption(); parser.addVersionOption(); @@ -211,7 +208,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_instanceIdToShowWindowOf = parser.value("show"); - for (auto zip_path : parser.values("import")){ + for (auto zip_path : parser.values("import")) { m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); } @@ -220,10 +217,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_zipsToImport.append(QUrl::fromLocalFile(QFileInfo(zip_path).absoluteFilePath())); } - // error if --launch is missing with --server or --profile - if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) - { + if ((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty()) { std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl; m_status = Application::Failed; return; @@ -235,7 +230,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) { // Root path is used for updates and portable data #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr + QDir foo(FS::PathCombine(binPath, "..")); // typically portable-root or /usr m_rootPath = foo.absolutePath(); #elif defined(Q_OS_WIN32) m_rootPath = binPath; @@ -251,25 +246,19 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) QString dataPath; // change folder QString dirParam = parser.value("dir"); - if (!dirParam.isEmpty()) - { + if (!dirParam.isEmpty()) { // the dir param. it makes multimc data path point to whatever the user specified // on command line adjustedBy = "Command line"; dataPath = dirParam; - } - else - { + } else { QDir foo; - if (DesktopServices::isSnap()) - { + if (DesktopServices::isSnap()) { foo = QDir(getenv("SNAP_USER_COMMON")); - } - else - { + } else { foo = QDir(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); } - + dataPath = foo.absolutePath(); adjustedBy = "Persistent data path"; @@ -282,34 +271,27 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) #endif } - if (!FS::ensureFolderPathExists(dataPath)) - { + if (!FS::ensureFolderPathExists(dataPath)) { showFatalErrorMessage( "The launcher data folder could not be created.", - QString( - "The launcher data folder could not be created.\n" - "\n" - "Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n" - "(%1)\n" - "\n" - "The launcher cannot continue until you fix this problem." - ).arg(dataPath) - ); + QString("The launcher data folder could not be created.\n" + "\n" + "Make sure you have the right permissions to the launcher data folder and any folder needed to access it.\n" + "(%1)\n" + "\n" + "The launcher cannot continue until you fix this problem.") + .arg(dataPath)); return; } - if (!QDir::setCurrent(dataPath)) - { - showFatalErrorMessage( - "The launcher data folder could not be opened.", - QString( - "The launcher data folder could not be opened.\n" - "\n" - "Make sure you have the right permissions to the launcher data folder.\n" - "(%1)\n" - "\n" - "The launcher cannot continue until you fix this problem." - ).arg(dataPath) - ); + if (!QDir::setCurrent(dataPath)) { + showFatalErrorMessage("The launcher data folder could not be opened.", + QString("The launcher data folder could not be opened.\n" + "\n" + "Make sure you have the right permissions to the launcher data folder.\n" + "(%1)\n" + "\n" + "The launcher cannot continue until you fix this problem.") + .arg(dataPath)); return; } @@ -323,17 +305,15 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // FIXME: you can run the same binaries with multiple data dirs and they won't clash. This could cause issues for updates. m_peerInstance = new LocalPeer(this, appID); connect(m_peerInstance, &LocalPeer::messageReceived, this, &Application::messageReceived); - if(m_peerInstance->isClient()) { + if (m_peerInstance->isClient()) { int timeout = 2000; - if(m_instanceIdToLaunch.isEmpty()) - { + if (m_instanceIdToLaunch.isEmpty()) { ApplicationMessage activate; activate.command = "activate"; m_peerInstance->sendMessage(activate.serialize(), timeout); - if(!m_zipsToImport.isEmpty()) - { + if (!m_zipsToImport.isEmpty()) { for (auto zip_url : m_zipsToImport) { ApplicationMessage import; import.command = "import"; @@ -341,19 +321,15 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_peerInstance->sendMessage(import.serialize(), timeout); } } - } - else - { + } else { ApplicationMessage launch; launch.command = "launch"; launch.args["id"] = m_instanceIdToLaunch; - if(!m_serverToJoin.isEmpty()) - { + if (!m_serverToJoin.isEmpty()) { launch.args["server"] = m_serverToJoin; } - if(!m_profileToUse.isEmpty()) - { + if (!m_profileToUse.isEmpty()) { launch.args["profile"] = m_profileToUse; } m_peerInstance->sendMessage(launch.serialize(), timeout); @@ -397,44 +373,51 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) qInstallMessageHandler(appDebugOutput); qSetMessagePattern( - "%{time process}" " " - "%{if-debug}D%{endif}" "%{if-info}I%{endif}" "%{if-warning}W%{endif}" "%{if-critical}C%{endif}" "%{if-fatal}F%{endif}" - " " "|" " " - "%{if-category}[%{category}]: %{endif}" - "%{message}"); - + "%{time process}" + " " + "%{if-debug}D%{endif}" + "%{if-info}I%{endif}" + "%{if-warning}W%{endif}" + "%{if-critical}C%{endif}" + "%{if-fatal}F%{endif}" + " " + "|" + " " + "%{if-category}[%{category}]: %{endif}" + "%{message}"); + bool foundLoggingRules = false; - + auto logRulesFile = QStringLiteral("qtlogging.ini"); auto logRulesPath = FS::PathCombine(dataPath, logRulesFile); - - qDebug() << "Testing" << logRulesPath << "..."; + + qDebug() << "Testing" << logRulesPath << "..."; foundLoggingRules = QFile::exists(logRulesPath); // search the dataPath() // seach app data standard path - if(!foundLoggingRules && !isPortable() && dirParam.isEmpty()) { + if (!foundLoggingRules && !isPortable() && dirParam.isEmpty()) { logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, FS::PathCombine("..", logRulesFile)); - if(!logRulesPath.isEmpty()) { + if (!logRulesPath.isEmpty()) { qDebug() << "Found" << logRulesPath << "..."; foundLoggingRules = true; } } // seach root path - if(!foundLoggingRules) { + if (!foundLoggingRules) { #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - logRulesPath = FS::PathCombine(m_rootPath, "share", BuildConfig.LAUNCHER_NAME, logRulesFile); + logRulesPath = FS::PathCombine(m_rootPath, "share", BuildConfig.LAUNCHER_NAME, logRulesFile); #else - logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); + logRulesPath = FS::PathCombine(m_rootPath, logRulesFile); #endif qDebug() << "Testing" << logRulesPath << "..."; foundLoggingRules = QFile::exists(logRulesPath); } - - if(foundLoggingRules) { + + if (foundLoggingRules) { // load and set logging rules qDebug() << "Loading logging rules from:" << logRulesPath; - QSettings loggingRules(logRulesPath, QSettings::IniFormat); + QSettings loggingRules(logRulesPath, QSettings::IniFormat); loggingRules.beginGroup("Rules"); QStringList rule_names = loggingRules.childKeys(); QStringList rules; @@ -455,49 +438,44 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) bool migrated = false; if (!migrated) - migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", "polymc.cfg"); + migrated = handleDataMigration( + dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", + "polymc.cfg"); if (!migrated) - migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", "multimc.cfg"); + migrated = handleDataMigration( + dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", + "multimc.cfg"); } { - qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT; qDebug() << "Version : " << BuildConfig.printableVersionString(); qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM; qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT; qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC; - if (adjustedBy.size()) - { + if (adjustedBy.size()) { qDebug() << "Work dir before adjustment : " << origcwdPath; qDebug() << "Work dir after adjustment : " << QDir::currentPath(); qDebug() << "Adjusted by : " << adjustedBy; - } - else - { + } else { qDebug() << "Work dir : " << QDir::currentPath(); } qDebug() << "Binary path : " << binPath; qDebug() << "Application root path : " << m_rootPath; - if(!m_instanceIdToLaunch.isEmpty()) - { + if (!m_instanceIdToLaunch.isEmpty()) { qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch; } - if(!m_serverToJoin.isEmpty()) - { + if (!m_serverToJoin.isEmpty()) { qDebug() << "Address of server to join :" << m_serverToJoin; } qDebug() << "<> Paths set."; } - if(m_liveCheck) - { + if (m_liveCheck) { QFile check(liveCheckFile); - if(check.open(QIODevice::WriteOnly | QIODevice::Truncate)) - { + if (check.open(QIODevice::WriteOnly | QIODevice::Truncate)) { auto payload = appID.toString().toUtf8(); - if(check.write(payload) == payload.size()) - { + if (check.write(payload) == payload.size()) { check.close(); } else { qWarning() << "Could not write into" << liveCheckFile << "!"; @@ -543,7 +521,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) QString resolvedDefaultMonospace = consoleFontInfo.family(); QFont resolvedFont(resolvedDefaultMonospace); qDebug() << "Detected default console font:" << resolvedDefaultMonospace - << ", substitutions:" << resolvedFont.substitutions().join(','); + << ", substitutions:" << resolvedFont.substitutions().join(','); m_settings->registerSetting("ConsoleFont", resolvedDefaultMonospace); m_settings->registerSetting("ConsoleFontSize", defaultSize); @@ -552,7 +530,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // Folders m_settings->registerSetting("InstanceDir", "instances"); - m_settings->registerSetting({"CentralModsDir", "ModsDir"}, "mods"); + m_settings->registerSetting({ "CentralModsDir", "ModsDir" }, "mods"); m_settings->registerSetting("IconsDir", "icons"); m_settings->registerSetting("DownloadsDir", QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); m_settings->registerSetting("DownloadsDirWatchRecursive", false); @@ -571,20 +549,20 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("LogPrePostOutput", true); // Window Size - m_settings->registerSetting({"LaunchMaximized", "MCWindowMaximize"}, false); - m_settings->registerSetting({"MinecraftWinWidth", "MCWindowWidth"}, 854); - m_settings->registerSetting({"MinecraftWinHeight", "MCWindowHeight"}, 480); + m_settings->registerSetting({ "LaunchMaximized", "MCWindowMaximize" }, false); + m_settings->registerSetting({ "MinecraftWinWidth", "MCWindowWidth" }, 854); + m_settings->registerSetting({ "MinecraftWinHeight", "MCWindowHeight" }, 480); // Proxy Settings m_settings->registerSetting("ProxyType", "None"); - m_settings->registerSetting({"ProxyAddr", "ProxyHostName"}, "127.0.0.1"); + m_settings->registerSetting({ "ProxyAddr", "ProxyHostName" }, "127.0.0.1"); m_settings->registerSetting("ProxyPort", 8080); - m_settings->registerSetting({"ProxyUser", "ProxyUsername"}, ""); - m_settings->registerSetting({"ProxyPass", "ProxyPassword"}, ""); + m_settings->registerSetting({ "ProxyUser", "ProxyUsername" }, ""); + m_settings->registerSetting({ "ProxyPass", "ProxyPassword" }, ""); // Memory - m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512); - m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, suitableMaxMem()); + m_settings->registerSetting({ "MinMemAlloc", "MinMemoryAlloc" }, 512); + m_settings->registerSetting({ "MaxMemAlloc", "MaxMemoryAlloc" }, suitableMaxMem()); m_settings->registerSetting("PermGen", 128); // Java Settings @@ -626,8 +604,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("WrapperCommand", ""); // Custom Commands - m_settings->registerSetting({"PreLaunchCommand", "PreLaunchCmd"}, ""); - m_settings->registerSetting({"PostExitCommand", "PostExitCmd"}, ""); + m_settings->registerSetting({ "PreLaunchCommand", "PreLaunchCmd" }, ""); + m_settings->registerSetting({ "PostExitCommand", "PostExitCmd" }, ""); // The cat m_settings->registerSetting("TheCat", false); @@ -666,8 +644,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) QString pastebinURL = m_settings->get("PastebinURL").toString(); bool userHadDefaultPastebin = pastebinURL == "https://0x0.st"; - if (!pastebinURL.isEmpty() && !userHadDefaultPastebin) - { + if (!pastebinURL.isEmpty() && !userHadDefaultPastebin) { m_settings->set("PastebinType", PasteUpload::PasteType::NullPointer); m_settings->set("PastebinCustomAPIBase", pastebinURL); m_settings->reset("PastebinURL"); @@ -676,8 +653,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) bool ok; int pasteType = m_settings->get("PastebinType").toInt(&ok); // If PastebinType is invalid then reset the related settings. - if (!ok || !(PasteUpload::PasteType::First <= pasteType && pasteType <= PasteUpload::PasteType::Last)) - { + if (!ok || !(PasteUpload::PasteType::First <= pasteType && pasteType <= PasteUpload::PasteType::Last)) { m_settings->reset("PastebinType"); m_settings->reset("PastebinCustomAPIBase"); } @@ -758,8 +734,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } // initialize the updater - if(BuildConfig.UPDATER_ENABLED) - { + if (BuildConfig.UPDATER_ENABLED) { qDebug() << "Initializing updater"; #if defined(Q_OS_MAC) && defined(SPARKLE_ENABLED) m_updater.reset(new MacSparkleUpdater()); @@ -770,18 +745,11 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // Instance icons { auto setting = APPLICATION->settings()->getSetting("IconsDir"); - QStringList instFolders = - { - ":/icons/multimc/32x32/instances/", - ":/icons/multimc/50x50/instances/", - ":/icons/multimc/128x128/instances/", - ":/icons/multimc/scalable/instances/" - }; + QStringList instFolders = { ":/icons/multimc/32x32/instances/", ":/icons/multimc/50x50/instances/", + ":/icons/multimc/128x128/instances/", ":/icons/multimc/scalable/instances/" }; m_icons.reset(new IconList(instFolders, setting->get().toString())); - connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value) - { - m_icons->directoryChanged(value.toString()); - }); + connect(setting.get(), &Setting::SettingChanged, + [&](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); }); qDebug() << "<> Instance icons intialized."; } @@ -795,8 +763,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // and remember that we have to show him a dialog when the gui starts (if it does so) QString instDir = InstDirSetting->get().toString(); qDebug() << "Instance path : " << instDir; - if (FS::checkProblemticPathJava(QDir(instDir))) - { + if (FS::checkProblemticPathJava(QDir(instDir))) { qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!"; } m_instances.reset(new InstanceList(m_settings, instDir, this)); @@ -846,11 +813,10 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // now we have network, download translation updates m_translations->downloadIndex(); - //FIXME: what to do with these? + // FIXME: what to do with these? m_profilers.insert("jprofiler", std::shared_ptr(new JProfilerFactory())); m_profilers.insert("jvisualvm", std::shared_ptr(new JVisualVMFactory())); - for (auto profiler : m_profilers.values()) - { + for (auto profiler : m_profilers.values()) { profiler->registerSettings(m_settings); } @@ -860,19 +826,15 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) } #ifdef Q_OS_MACOS - connect(this, &Application::clickedOnDock, [this]() { - this->showMainWindow(); - }); + connect(this, &Application::clickedOnDock, [this]() { this->showMainWindow(); }); #endif - connect(this, &Application::aboutToQuit, [this](){ - if(m_instances) - { + connect(this, &Application::aboutToQuit, [this]() { + if (m_instances) { // save any remaining instance state m_instances->saveNow(); } - if(logFile) - { + if (logFile) { logFile->flush(); logFile->close(); } @@ -882,8 +844,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) updateCapabilities(); - if(createSetupWizard()) - { + if (createSetupWizard()) { return; } @@ -892,23 +853,20 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) bool Application::createSetupWizard() { - bool javaRequired = [&]() - { + bool javaRequired = [&]() { bool ignoreJavaWizard = m_settings->get("IgnoreJavaWizard").toBool(); - if(ignoreJavaWizard) { + if (ignoreJavaWizard) { return false; } QString currentHostName = QHostInfo::localHostName(); QString oldHostName = settings()->get("LastHostname").toString(); - if (currentHostName != oldHostName) - { + if (currentHostName != oldHostName) { settings()->set("LastHostname", currentHostName); return true; } QString currentJavaPath = settings()->get("JavaPath").toString(); QString actualPath = FS::ResolveExecutable(currentJavaPath); - if (actualPath.isNull()) - { + if (actualPath.isNull()) { return true; } return false; @@ -918,27 +876,22 @@ bool Application::createSetupWizard() bool themeInterventionRequired = settings()->get("ApplicationTheme") == ""; bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired; - if(wizardRequired) - { + if (wizardRequired) { m_setupWizard = new SetupWizard(nullptr); - if (languageRequired) - { + if (languageRequired) { m_setupWizard->addPage(new LanguageWizardPage(m_setupWizard)); } - if (javaRequired) - { + if (javaRequired) { m_setupWizard->addPage(new JavaWizardPage(m_setupWizard)); } - if (pasteInterventionRequired) - { + if (pasteInterventionRequired) { m_setupWizard->addPage(new PasteWizardPage(m_setupWizard)); } - if (themeInterventionRequired) - { - settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard + if (themeInterventionRequired) { + settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard)); } connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished); @@ -978,26 +931,22 @@ void Application::setupWizardFinished(int status) void Application::performMainStartupAction() { m_status = Application::Initialized; - if(!m_instanceIdToLaunch.isEmpty()) - { + if (!m_instanceIdToLaunch.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToLaunch); - if(inst) - { + if (inst) { MinecraftServerTargetPtr serverToJoin = nullptr; MinecraftAccountPtr accountToUse = nullptr; qDebug() << "<> Instance" << m_instanceIdToLaunch << "launching"; - if(!m_serverToJoin.isEmpty()) - { + if (!m_serverToJoin.isEmpty()) { // FIXME: validate the server string serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(m_serverToJoin))); qDebug() << " Launching with server" << m_serverToJoin; } - if(!m_profileToUse.isEmpty()) - { + if (!m_profileToUse.isEmpty()) { accountToUse = accounts()->getAccountByProfileName(m_profileToUse); - if(!accountToUse) { + if (!accountToUse) { return; } qDebug() << " Launching with account" << m_profileToUse; @@ -1007,26 +956,22 @@ void Application::performMainStartupAction() return; } } - if(!m_instanceIdToShowWindowOf.isEmpty()) - { + if (!m_instanceIdToShowWindowOf.isEmpty()) { auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf); - if(inst) - { + if (inst) { qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf; showInstanceWindow(inst); return; } } - if(!m_mainWindow) - { + if (!m_mainWindow) { // normal main window showMainWindow(false); qDebug() << "<> Main window shown."; } - if(!m_zipsToImport.isEmpty()) - { + if (!m_zipsToImport.isEmpty()) { qDebug() << "<> Importing from zip:" << m_zipsToImport; - m_mainWindow->processURLs( m_zipsToImport ); + m_mainWindow->processURLs(m_zipsToImport); } } @@ -1044,8 +989,7 @@ Application::~Application() #if defined Q_OS_WIN32 // Detach from Windows console - if(consoleAttached) - { + if (consoleAttached) { fclose(stdout); fclose(stdin); fclose(stderr); @@ -1056,8 +1000,7 @@ Application::~Application() void Application::messageReceived(const QByteArray& message) { - if(status() != Initialized) - { + if (status() != Initialized) { qDebug() << "Received message" << message << "while still initializing. It will be ignored."; return; } @@ -1065,66 +1008,51 @@ void Application::messageReceived(const QByteArray& message) ApplicationMessage received; received.parse(message); - auto & command = received.command; + auto& command = received.command; - if(command == "activate") - { + if (command == "activate") { showMainWindow(); - } - else if(command == "import") - { + } else if (command == "import") { QString path = received.args["path"]; - if(path.isEmpty()) - { + if (path.isEmpty()) { qWarning() << "Received" << command << "message without a zip path/URL."; return; } m_mainWindow->processURLs({ QUrl::fromLocalFile(QFileInfo(path).absoluteFilePath()) }); - } - else if(command == "launch") - { + } else if (command == "launch") { QString id = received.args["id"]; QString server = received.args["server"]; QString profile = received.args["profile"]; InstancePtr instance; - if(!id.isEmpty()) { + if (!id.isEmpty()) { instance = instances()->getInstanceById(id); - if(!instance) { + if (!instance) { qWarning() << "Launch command requires an valid instance ID. " << id << "resolves to nothing."; return; } - } - else { + } else { qWarning() << "Launch command called without an instance ID..."; return; } MinecraftServerTargetPtr serverObject = nullptr; - if(!server.isEmpty()) { + if (!server.isEmpty()) { serverObject = std::make_shared(MinecraftServerTarget::parse(server)); } MinecraftAccountPtr accountObject; - if(!profile.isEmpty()) { + if (!profile.isEmpty()) { accountObject = accounts()->getAccountByProfileName(profile); - if(!accountObject) { - qWarning() << "Launch command requires the specified profile to be valid. " << profile << "does not resolve to any account."; + if (!accountObject) { + qWarning() << "Launch command requires the specified profile to be valid. " << profile + << "does not resolve to any account."; return; } } - launch( - instance, - true, - false, - nullptr, - serverObject, - accountObject - ); - } - else - { + launch(instance, true, false, nullptr, serverObject, accountObject); + } else { qWarning() << "Received invalid message" << message; } } @@ -1136,8 +1064,7 @@ std::shared_ptr Application::translations() std::shared_ptr Application::javalist() { - if (!m_javalist) - { + if (!m_javalist) { m_javalist.reset(new JavaInstallList()); } return m_javalist; @@ -1165,7 +1092,7 @@ void Application::setIconTheme(const QString& name) QIcon Application::getThemedIcon(const QString& name) { - if(name == "logo") { + if (name == "logo") { return QIcon(":/" + BuildConfig.LAUNCHER_SVGFILENAME); } return QIcon::fromTheme(name); @@ -1184,41 +1111,32 @@ QString Application::getCatPack(QString catName) bool Application::openJsonEditor(const QString& filename) { const QString file = QDir::current().absoluteFilePath(filename); - if (m_settings->get("JsonEditor").toString().isEmpty()) - { + if (m_settings->get("JsonEditor").toString().isEmpty()) { return DesktopServices::openUrl(QUrl::fromLocalFile(file)); - } - else - { - //return DesktopServices::openFile(m_settings->get("JsonEditor").toString(), file); - return DesktopServices::run(m_settings->get("JsonEditor").toString(), {file}); + } else { + // return DesktopServices::openFile(m_settings->get("JsonEditor").toString(), file); + return DesktopServices::run(m_settings->get("JsonEditor").toString(), { file }); } } -bool Application::launch( - InstancePtr instance, - bool online, - bool demo, - BaseProfilerFactory *profiler, - MinecraftServerTargetPtr serverToJoin, - MinecraftAccountPtr accountToUse -) { - if(m_updateRunning) - { +bool Application::launch(InstancePtr instance, + bool online, + bool demo, + BaseProfilerFactory* profiler, + MinecraftServerTargetPtr serverToJoin, + MinecraftAccountPtr accountToUse) +{ + if (m_updateRunning) { qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; - } - else if(instance->canLaunch()) - { - auto & extras = m_instanceExtras[instance->id()]; - auto & window = extras.window; - if(window) - { - if(!window->saveAll()) - { + } else if (instance->canLaunch()) { + auto& extras = m_instanceExtras[instance->id()]; + auto& window = extras.window; + if (window) { + if (!window->saveAll()) { return false; } } - auto & controller = extras.controller; + auto& controller = extras.controller; controller.reset(new LaunchController()); controller->setInstance(instance); controller->setOnline(online); @@ -1226,30 +1144,21 @@ bool Application::launch( controller->setProfiler(profiler); controller->setServerToJoin(serverToJoin); controller->setAccountToUse(accountToUse); - if(window) - { + if (window) { controller->setParentWidget(window); - } - else if(m_mainWindow) - { + } else if (m_mainWindow) { controller->setParentWidget(m_mainWindow); } connect(controller.get(), &LaunchController::succeeded, this, &Application::controllerSucceeded); connect(controller.get(), &LaunchController::failed, this, &Application::controllerFailed); - connect(controller.get(), &LaunchController::aborted, this, [this] { - controllerFailed(tr("Aborted")); - }); + connect(controller.get(), &LaunchController::aborted, this, [this] { controllerFailed(tr("Aborted")); }); addRunningInstance(); controller->start(); return true; - } - else if (instance->isRunning()) - { + } else if (instance->isRunning()) { showInstanceWindow(instance, "console"); return true; - } - else if (instance->canEdit()) - { + } else if (instance->canEdit()) { showInstanceWindow(instance); return true; } @@ -1258,16 +1167,14 @@ bool Application::launch( bool Application::kill(InstancePtr instance) { - if (!instance->isRunning()) - { + if (!instance->isRunning()) { qWarning() << "Attempted to kill instance" << instance->id() << ", which isn't running."; return false; } - auto & extras = m_instanceExtras[instance->id()]; + auto& extras = m_instanceExtras[instance->id()]; // NOTE: copy of the shared pointer keeps it alive auto controller = extras.controller; - if(controller) - { + if (controller) { return controller->abort(); } return true; @@ -1281,23 +1188,20 @@ void Application::closeCurrentWindow() void Application::addRunningInstance() { - m_runningInstances ++; - if(m_runningInstances == 1) - { + m_runningInstances++; + if (m_runningInstances == 1) { emit updateAllowedChanged(false); } } void Application::subRunningInstance() { - if(m_runningInstances == 0) - { + if (m_runningInstances == 0) { qCritical() << "Something went really wrong and we now have less than 0 running instances... WTF"; return; } - m_runningInstances --; - if(m_runningInstances == 0) - { + m_runningInstances--; + if (m_runningInstances == 0) { emit updateAllowedChanged(true); } } @@ -1317,20 +1221,17 @@ void Application::updateIsRunning(bool running) m_updateRunning = running; } - void Application::controllerSucceeded() { - auto controller = qobject_cast(QObject::sender()); - if(!controller) + auto controller = qobject_cast(QObject::sender()); + if (!controller) return; auto id = controller->id(); - auto & extras = m_instanceExtras[id]; + auto& extras = m_instanceExtras[id]; // on success, do... - if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) - { - if(extras.window) - { + if (controller->instance()->settings()->get("AutoCloseConsole").toBool()) { + if (extras.window) { extras.window->close(); } } @@ -1338,8 +1239,7 @@ void Application::controllerSucceeded() subRunningInstance(); // quit when there are no more windows. - if(shouldExitNow()) - { + if (shouldExitNow()) { m_status = Status::Succeeded; exit(0); } @@ -1348,19 +1248,18 @@ void Application::controllerSucceeded() void Application::controllerFailed(const QString& error) { Q_UNUSED(error); - auto controller = qobject_cast(QObject::sender()); - if(!controller) + auto controller = qobject_cast(QObject::sender()); + if (!controller) return; auto id = controller->id(); - auto & extras = m_instanceExtras[id]; + auto& extras = m_instanceExtras[id]; // on failure, do... nothing extras.controller.reset(); subRunningInstance(); // quit when there are no more windows. - if(shouldExitNow()) - { + if (shouldExitNow()) { m_status = Status::Failed; exit(1); } @@ -1368,7 +1267,7 @@ void Application::controllerFailed(const QString& error) void Application::ShowGlobalSettings(class QWidget* parent, QString open_page) { - if(!m_globalSettingsProvider) { + if (!m_globalSettingsProvider) { return; } emit globalSettingsAboutToOpen(); @@ -1382,24 +1281,18 @@ void Application::ShowGlobalSettings(class QWidget* parent, QString open_page) MainWindow* Application::showMainWindow(bool minimized) { - if(m_mainWindow) - { + if (m_mainWindow) { m_mainWindow->setWindowState(m_mainWindow->windowState() & ~Qt::WindowMinimized); m_mainWindow->raise(); m_mainWindow->activateWindow(); - } - else - { + } else { m_mainWindow = new MainWindow(); m_mainWindow->restoreState(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowState").toByteArray())); m_mainWindow->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("MainWindowGeometry").toByteArray())); - if(minimized) - { + if (minimized) { m_mainWindow->showMinimized(); - } - else - { + } else { m_mainWindow->show(); } @@ -1411,31 +1304,26 @@ MainWindow* Application::showMainWindow(bool minimized) return m_mainWindow; } -InstanceWindow *Application::showInstanceWindow(InstancePtr instance, QString page) +InstanceWindow* Application::showInstanceWindow(InstancePtr instance, QString page) { - if(!instance) + if (!instance) return nullptr; auto id = instance->id(); - auto & extras = m_instanceExtras[id]; - auto & window = extras.window; + auto& extras = m_instanceExtras[id]; + auto& window = extras.window; - if(window) - { + if (window) { window->raise(); window->activateWindow(); - } - else - { + } else { window = new InstanceWindow(instance); - m_openWindows ++; + m_openWindows++; connect(window, &InstanceWindow::isClosing, this, &Application::on_windowClose); } - if(!page.isEmpty()) - { + if (!page.isEmpty()) { window->selectPage(page); } - if(extras.controller) - { + if (extras.controller) { extras.controller->setParentWidget(window); } return window; @@ -1444,24 +1332,20 @@ InstanceWindow *Application::showInstanceWindow(InstancePtr instance, QString pa void Application::on_windowClose() { m_openWindows--; - auto instWindow = qobject_cast(QObject::sender()); - if(instWindow) - { - auto & extras = m_instanceExtras[instWindow->instanceId()]; + auto instWindow = qobject_cast(QObject::sender()); + if (instWindow) { + auto& extras = m_instanceExtras[instWindow->instanceId()]; extras.window = nullptr; - if(extras.controller) - { + if (extras.controller) { extras.controller->setParentWidget(m_mainWindow); } } - auto mainWindow = qobject_cast(QObject::sender()); - if(mainWindow) - { + auto mainWindow = qobject_cast(QObject::sender()); + if (mainWindow) { m_mainWindow = nullptr; } // quit when there are no more windows. - if(shouldExitNow()) - { + if (shouldExitNow()) { exit(0); } } @@ -1469,23 +1353,14 @@ void Application::on_windowClose() void Application::updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password) { // Set the application proxy settings. - if (proxyTypeStr == "SOCKS5") - { - QNetworkProxy::setApplicationProxy( - QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password)); - } - else if (proxyTypeStr == "HTTP") - { - QNetworkProxy::setApplicationProxy( - QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password)); - } - else if (proxyTypeStr == "None") - { + if (proxyTypeStr == "SOCKS5") { + QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password)); + } else if (proxyTypeStr == "HTTP") { + QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password)); + } else if (proxyTypeStr == "None") { // If we have no proxy set, set no proxy and return. QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy)); - } - else - { + } else { // If we have "Default" selected, set Qt to use the system proxy settings. QNetworkProxyFactory::setUseSystemConfiguration(true); } @@ -1495,39 +1370,35 @@ void Application::updateProxySettings(QString proxyTypeStr, QString addr, int po m_network->setProxy(proxy); QString proxyDesc; - if (proxy.type() == QNetworkProxy::NoProxy) - { + if (proxy.type() == QNetworkProxy::NoProxy) { qDebug() << "Using no proxy is an option!"; return; } - switch (proxy.type()) - { - case QNetworkProxy::DefaultProxy: - proxyDesc = "Default proxy: "; - break; - case QNetworkProxy::Socks5Proxy: - proxyDesc = "Socks5 proxy: "; - break; - case QNetworkProxy::HttpProxy: - proxyDesc = "HTTP proxy: "; - break; - case QNetworkProxy::HttpCachingProxy: - proxyDesc = "HTTP caching: "; - break; - case QNetworkProxy::FtpCachingProxy: - proxyDesc = "FTP caching: "; - break; - default: - proxyDesc = "DERP proxy: "; - break; + switch (proxy.type()) { + case QNetworkProxy::DefaultProxy: + proxyDesc = "Default proxy: "; + break; + case QNetworkProxy::Socks5Proxy: + proxyDesc = "Socks5 proxy: "; + break; + case QNetworkProxy::HttpProxy: + proxyDesc = "HTTP proxy: "; + break; + case QNetworkProxy::HttpCachingProxy: + proxyDesc = "HTTP caching: "; + break; + case QNetworkProxy::FtpCachingProxy: + proxyDesc = "FTP caching: "; + break; + default: + proxyDesc = "DERP proxy: "; + break; } - proxyDesc += QString("%1:%2") - .arg(proxy.hostName()) - .arg(proxy.port()); + proxyDesc += QString("%1:%2").arg(proxy.hostName()).arg(proxy.port()); qDebug() << proxyDesc; } -shared_qobject_ptr< HttpMetaCache > Application::metacache() +shared_qobject_ptr Application::metacache() { return m_metacache; } @@ -1539,8 +1410,7 @@ shared_qobject_ptr Application::network() shared_qobject_ptr Application::metadataIndex() { - if (!m_metadataIndex) - { + if (!m_metadataIndex) { m_metadataIndex.reset(new Meta::Index()); } return m_metadataIndex; @@ -1571,10 +1441,9 @@ QString Application::getJarPath(QString jarFile) #endif FS::PathCombine(m_rootPath, "jars"), FS::PathCombine(applicationDirPath(), "jars"), - FS::PathCombine(applicationDirPath(), "..", "jars") // from inside build dir, for debuging + FS::PathCombine(applicationDirPath(), "..", "jars") // from inside build dir, for debuging }; - for(QString p : potentialPaths) - { + for (QString p : potentialPaths) { QString jarPath = FS::PathCombine(p, jarFile); if (QFileInfo(jarPath).isFile()) return jarPath; @@ -1639,7 +1508,7 @@ int Application::suitableMaxMem() // If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB if (totalRAM < (4096 * 1.5)) - maxMemoryAlloc = (int) (totalRAM / 1.5); + maxMemoryAlloc = (int)(totalRAM / 1.5); else maxMemoryAlloc = 4096; diff --git a/launcher/Application.h b/launcher/Application.h index c0a980b2e..cf7967a56 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -38,12 +38,12 @@ #pragma once #include -#include +#include #include #include #include -#include #include +#include #include @@ -73,25 +73,19 @@ class MCEditTool; class ThemeManager; namespace Meta { - class Index; +class Index; } #if defined(APPLICATION) #undef APPLICATION #endif -#define APPLICATION (static_cast(QCoreApplication::instance())) +#define APPLICATION (static_cast(QCoreApplication::instance())) -class Application : public QApplication -{ +class Application : public QApplication { // friends for the purpose of limiting access to deprecated stuff Q_OBJECT -public: - enum Status { - StartingUp, - Failed, - Succeeded, - Initialized - }; + public: + enum Status { StartingUp, Failed, Succeeded, Initialized }; enum Capability { None = 0, @@ -103,19 +97,15 @@ public: }; Q_DECLARE_FLAGS(Capabilities, Capability) -public: - Application(int &argc, char **argv); + public: + Application(int& argc, char** argv); virtual ~Application(); bool event(QEvent* event) override; - std::shared_ptr settings() const { - return m_settings; - } + std::shared_ptr settings() const { return m_settings; } - qint64 timeSinceStart() const { - return startTime.msecsTo(QDateTime::currentDateTime()); - } + qint64 timeSinceStart() const { return startTime.msecsTo(QDateTime::currentDateTime()); } QIcon getThemedIcon(const QString& name); @@ -139,29 +129,17 @@ public: std::shared_ptr javalist(); - std::shared_ptr instances() const { - return m_instances; - } + std::shared_ptr instances() const { return m_instances; } - std::shared_ptr icons() const { - return m_icons; - } + std::shared_ptr icons() const { return m_icons; } - MCEditTool *mcedit() const { - return m_mcedit.get(); - } + MCEditTool* mcedit() const { return m_mcedit.get(); } - shared_qobject_ptr accounts() const { - return m_accounts; - } + shared_qobject_ptr accounts() const { return m_accounts; } - Status status() const { - return m_status; - } + Status status() const { return m_status; } - const QMap> &profilers() const { - return m_profilers; - } + const QMap>& profilers() const { return m_profilers; } void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password); @@ -186,35 +164,29 @@ public: QString getUserAgentUncached(); /// this is the root of the 'installation'. Used for automatic updates - const QString &root() { - return m_rootPath; - } + const QString& root() { return m_rootPath; } - bool isPortable() { - return m_portable; - } + bool isPortable() { return m_portable; } - const Capabilities capabilities() { - return m_capabilities; - } + const Capabilities capabilities() { return m_capabilities; } /*! * Opens a json file using either a system default editor, or, if not empty, the editor * specified in the settings */ - bool openJsonEditor(const QString &filename); + bool openJsonEditor(const QString& filename); - InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString()); - MainWindow *showMainWindow(bool minimized = false); + InstanceWindow* showInstanceWindow(InstancePtr instance, QString page = QString()); + MainWindow* showMainWindow(bool minimized = false); void updateIsRunning(bool running); bool updatesAreAllowed(); - void ShowGlobalSettings(class QWidget * parent, QString open_page = QString()); + void ShowGlobalSettings(class QWidget* parent, QString open_page = QString()); int suitableMaxMem(); -signals: + signals: void updateAllowedChanged(bool status); void globalSettingsAboutToOpen(); void globalSettingsClosed(); @@ -224,39 +196,37 @@ signals: void clickedOnDock(); #endif -public slots: - bool launch( - InstancePtr instance, - bool online = true, - bool demo = false, - BaseProfilerFactory *profiler = nullptr, - MinecraftServerTargetPtr serverToJoin = nullptr, - MinecraftAccountPtr accountToUse = nullptr - ); + public slots: + bool launch(InstancePtr instance, + bool online = true, + bool demo = false, + BaseProfilerFactory* profiler = nullptr, + MinecraftServerTargetPtr serverToJoin = nullptr, + MinecraftAccountPtr accountToUse = nullptr); bool kill(InstancePtr instance); void closeCurrentWindow(); -private slots: + private slots: void on_windowClose(); - void messageReceived(const QByteArray & message); + void messageReceived(const QByteArray& message); void controllerSucceeded(); - void controllerFailed(const QString & error); + void controllerFailed(const QString& error); void setupWizardFinished(int status); -private: - bool handleDataMigration(const QString & currentData, const QString & oldData, const QString & name, const QString & configFile) const; + private: + bool handleDataMigration(const QString& currentData, const QString& oldData, const QString& name, const QString& configFile) const; bool createSetupWizard(); void performMainStartupAction(); // sets the fatal error message and m_status to Failed. - void showFatalErrorMessage(const QString & title, const QString & content); + void showFatalErrorMessage(const QString& title, const QString& content); -private: + private: void addRunningInstance(); void subRunningInstance(); bool shouldExitNow() const; -private: + private: QDateTime startTime; shared_qobject_ptr m_network; @@ -282,7 +252,7 @@ private: QString m_rootPath; Status m_status = Application::StartingUp; Capabilities m_capabilities; - bool m_portable = false; + bool m_portable = false; #ifdef Q_OS_MACOS Qt::ApplicationState m_prevAppState = Qt::ApplicationInactive; @@ -295,7 +265,7 @@ private: // FIXME: attach to instances instead. struct InstanceXtras { - InstanceWindow * window = nullptr; + InstanceWindow* window = nullptr; shared_qobject_ptr controller; }; std::map m_instanceExtras; @@ -306,13 +276,14 @@ private: bool m_updateRunning = false; // main window, if any - MainWindow * m_mainWindow = nullptr; + MainWindow* m_mainWindow = nullptr; // peer launcher instance connector - used to implement single instance launcher and signalling - LocalPeer * m_peerInstance = nullptr; + LocalPeer* m_peerInstance = nullptr; - SetupWizard * m_setupWizard = nullptr; -public: + SetupWizard* m_setupWizard = nullptr; + + public: QString m_instanceIdToLaunch; QString m_serverToJoin; QString m_profileToUse; diff --git a/launcher/ApplicationMessage.cpp b/launcher/ApplicationMessage.cpp index 700e43ced..8d75ecc8f 100644 --- a/launcher/ApplicationMessage.cpp +++ b/launcher/ApplicationMessage.cpp @@ -39,7 +39,8 @@ #include #include "Json.h" -void ApplicationMessage::parse(const QByteArray & input) { +void ApplicationMessage::parse(const QByteArray& input) +{ auto doc = Json::requireDocument(input, "ApplicationMessage"); auto root = Json::requireObject(doc, "ApplicationMessage"); @@ -47,12 +48,13 @@ void ApplicationMessage::parse(const QByteArray & input) { args.clear(); auto parsedArgs = root.value("args").toObject(); - for(auto iter = parsedArgs.constBegin(); iter != parsedArgs.constEnd(); iter++) { + for (auto iter = parsedArgs.constBegin(); iter != parsedArgs.constEnd(); iter++) { args.insert(iter.key(), iter.value().toString()); } } -QByteArray ApplicationMessage::serialize() { +QByteArray ApplicationMessage::serialize() +{ QJsonObject root; root.insert("command", command); QJsonObject outArgs; diff --git a/launcher/ApplicationMessage.h b/launcher/ApplicationMessage.h index d66456ebd..7ad674330 100644 --- a/launcher/ApplicationMessage.h +++ b/launcher/ApplicationMessage.h @@ -1,13 +1,13 @@ #pragma once -#include -#include #include +#include +#include struct ApplicationMessage { QString command; QHash args; QByteArray serialize(); - void parse(const QByteArray & input); + void parse(const QByteArray& input); }; diff --git a/launcher/BaseInstaller.cpp b/launcher/BaseInstaller.cpp index d61c3fe90..1ff86ed40 100644 --- a/launcher/BaseInstaller.cpp +++ b/launcher/BaseInstaller.cpp @@ -18,27 +18,21 @@ #include "BaseInstaller.h" #include "minecraft/MinecraftInstance.h" -BaseInstaller::BaseInstaller() -{ +BaseInstaller::BaseInstaller() {} -} - -bool BaseInstaller::isApplied(MinecraftInstance *on) +bool BaseInstaller::isApplied(MinecraftInstance* on) { return QFile::exists(filename(on->instanceRoot())); } -bool BaseInstaller::add(MinecraftInstance *to) +bool BaseInstaller::add(MinecraftInstance* to) { - if (!patchesDir(to->instanceRoot()).exists()) - { + if (!patchesDir(to->instanceRoot()).exists()) { QDir(to->instanceRoot()).mkdir("patches"); } - if (isApplied(to)) - { - if (!remove(to)) - { + if (isApplied(to)) { + if (!remove(to)) { return false; } } @@ -46,16 +40,16 @@ bool BaseInstaller::add(MinecraftInstance *to) return true; } -bool BaseInstaller::remove(MinecraftInstance *from) +bool BaseInstaller::remove(MinecraftInstance* from) { return QFile::remove(filename(from->instanceRoot())); } -QString BaseInstaller::filename(const QString &root) const +QString BaseInstaller::filename(const QString& root) const { return patchesDir(root).absoluteFilePath(id() + ".json"); } -QDir BaseInstaller::patchesDir(const QString &root) const +QDir BaseInstaller::patchesDir(const QString& root) const { return QDir(root + "/patches/"); } diff --git a/launcher/BaseInstaller.h b/launcher/BaseInstaller.h index a1b80e93f..6244ced7d 100644 --- a/launcher/BaseInstaller.h +++ b/launcher/BaseInstaller.h @@ -26,20 +26,19 @@ class QObject; class Task; class BaseVersion; -class BaseInstaller -{ -public: +class BaseInstaller { + public: BaseInstaller(); virtual ~BaseInstaller(){}; - bool isApplied(MinecraftInstance *on); + bool isApplied(MinecraftInstance* on); - virtual bool add(MinecraftInstance *to); - virtual bool remove(MinecraftInstance *from); + virtual bool add(MinecraftInstance* to); + virtual bool remove(MinecraftInstance* from); - virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersion::Ptr version, QObject *parent) = 0; + virtual Task* createInstallTask(MinecraftInstance* instance, BaseVersion::Ptr version, QObject* parent) = 0; -protected: + protected: virtual QString id() const = 0; - QString filename(const QString &root) const; - QDir patchesDir(const QString &root) const; + QString filename(const QString& root) const; + QDir patchesDir(const QString& root) const; }; diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp index a8fce879c..67fc150a4 100644 --- a/launcher/BaseInstance.cpp +++ b/launcher/BaseInstance.cpp @@ -36,23 +36,22 @@ #include "BaseInstance.h" -#include -#include #include -#include +#include +#include #include #include +#include #include "settings/INISettingsObject.h" -#include "settings/Setting.h" #include "settings/OverrideSetting.h" +#include "settings/Setting.h" -#include "FileSystem.h" -#include "Commandline.h" #include "BuildConfig.h" +#include "Commandline.h" +#include "FileSystem.h" -BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) - : QObject() +BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) : QObject() { m_settings = settings; m_global_settings = globalSettings; @@ -79,7 +78,7 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s m_settings->registerSetting("InstanceType", ""); // Custom Commands - auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false); + auto commandSetting = m_settings->registerSetting({ "OverrideCommands", "OverrideLaunchCmd" }, false); m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"), commandSetting); m_settings->registerOverride(globalSettings->getSetting("WrapperCommand"), commandSetting); m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"), commandSetting); @@ -148,7 +147,11 @@ QString BaseInstance::getManagedPackVersionName() const return m_settings->get("ManagedPackVersionName").toString(); } -void BaseInstance::setManagedPack(const QString& type, const QString& id, const QString& name, const QString& versionId, const QString& version) +void BaseInstance::setManagedPack(const QString& type, + const QString& id, + const QString& name, + const QString& versionId, + const QString& version) { m_settings->set("ManagedPack", true); m_settings->set("ManagedPackType", type); @@ -173,8 +176,7 @@ int BaseInstance::getConsoleMaxLines() const auto lineSetting = m_settings->getSetting("ConsoleMaxLines"); bool conversionOk = false; int maxLines = lineSetting->get().toInt(&conversionOk); - if(!conversionOk) - { + if (!conversionOk) { maxLines = lineSetting->defValue().toInt(); qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines; } @@ -220,8 +222,7 @@ bool BaseInstance::isLinkedToInstanceId(const QString& id) const void BaseInstance::iconUpdated(QString key) { - if(iconKey() == key) - { + if (iconKey() == key) { emit propertiesChanged(this); } } @@ -235,8 +236,7 @@ void BaseInstance::invalidate() void BaseInstance::changeStatus(BaseInstance::Status newStatus) { Status status = currentStatus(); - if(status != newStatus) - { + if (status != newStatus) { m_status = newStatus; emit statusChanged(status, newStatus); } @@ -259,23 +259,19 @@ bool BaseInstance::isRunning() const void BaseInstance::setRunning(bool running) { - if(running == m_isRunning) + if (running == m_isRunning) return; m_isRunning = running; - if(!m_settings->get("RecordGameTime").toBool()) - { + if (!m_settings->get("RecordGameTime").toBool()) { emit runningStatusChanged(running); return; } - if(running) - { + if (running) { m_timeStarted = QDateTime::currentDateTime(); - } - else - { + } else { QDateTime timeEnded = QDateTime::currentDateTime(); qint64 current = settings()->get("totalTimePlayed").toLongLong(); @@ -291,8 +287,7 @@ void BaseInstance::setRunning(bool running) int64_t BaseInstance::totalTimePlayed() const { qint64 current = m_settings->get("totalTimePlayed").toLongLong(); - if(m_isRunning) - { + if (m_isRunning) { QDateTime timeNow = QDateTime::currentDateTime(); return current + m_timeStarted.secsTo(timeNow); } @@ -301,8 +296,7 @@ int64_t BaseInstance::totalTimePlayed() const int64_t BaseInstance::lastTimePlayed() const { - if(m_isRunning) - { + if (m_isRunning) { QDateTime timeNow = QDateTime::currentDateTime(); return m_timeStarted.secsTo(timeNow); } @@ -349,14 +343,14 @@ qint64 BaseInstance::lastLaunch() const void BaseInstance::setLastLaunch(qint64 val) { - //FIXME: if no change, do not set. setting involves saving a file. + // FIXME: if no change, do not set. setting involves saving a file. m_settings->set("lastLaunchTime", val); emit propertiesChanged(this); } void BaseInstance::setNotes(QString val) { - //FIXME: if no change, do not set. setting involves saving a file. + // FIXME: if no change, do not set. setting involves saving a file. m_settings->set("notes", val); } @@ -367,7 +361,7 @@ QString BaseInstance::notes() const void BaseInstance::setIconKey(QString val) { - //FIXME: if no change, do not set. setting involves saving a file. + // FIXME: if no change, do not set. setting involves saving a file. m_settings->set("iconKey", val); emit propertiesChanged(this); } @@ -379,7 +373,7 @@ QString BaseInstance::iconKey() const void BaseInstance::setName(QString val) { - //FIXME: if no change, do not set. setting involves saving a file. + // FIXME: if no change, do not set. setting involves saving a file. m_settings->set("name", val); emit propertiesChanged(this); } diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index f6b5a7a56..1560bd258 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -37,24 +37,24 @@ #pragma once #include -#include -#include "QObjectPtr.h" #include -#include +#include #include +#include +#include "QObjectPtr.h" #include "settings/SettingsObject.h" -#include "settings/INIFile.h" #include "BaseVersionList.h" -#include "minecraft/auth/MinecraftAccount.h" #include "MessageLevel.h" +#include "minecraft/auth/MinecraftAccount.h" #include "pathmatcher/IPathMatcher.h" +#include "settings/INIFile.h" #include "net/Mode.h" -#include "minecraft/launch/MinecraftServerTarget.h" #include "RuntimeContext.h" +#include "minecraft/launch/MinecraftServerTarget.h" class QDir; class Task; @@ -72,21 +72,19 @@ typedef std::shared_ptr InstancePtr; * To create a new instance type, create a new class inheriting from this class * and implement the pure virtual functions. */ -class BaseInstance : public QObject, public std::enable_shared_from_this -{ +class BaseInstance : public QObject, public std::enable_shared_from_this { Q_OBJECT -protected: + protected: /// no-touchy! - BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir); + BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir); -public: /* types */ - enum class Status - { + public: /* types */ + enum class Status { Present, - Gone // either nuked or invalidated + Gone // either nuked or invalidated }; -public: + public: /// virtual destructor to make sure the destruction is COMPLETE virtual ~BaseInstance() {} @@ -117,10 +115,7 @@ public: QString instanceRoot() const; /// Path to the instance's game root directory. - virtual QString gameRoot() const - { - return instanceRoot(); - } + virtual QString gameRoot() const { return instanceRoot(); } /// Path to the instance's mods directory. virtual QString modsRoot() const = 0; @@ -151,15 +146,12 @@ public: void copyManagedPack(BaseInstance& other); /// guess log level from a line of game log - virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString &line, MessageLevel::Enum level) - { - return level; - } + virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString& line, MessageLevel::Enum level) { return level; } virtual QStringList extraArguments(); /// Traits. Normally inside the version, depends on instance implementation. - virtual QSet traits() const = 0; + virtual QSet traits() const = 0; /** * Gets the time that the instance was last launched. @@ -189,8 +181,7 @@ public: virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0; /// returns a valid launcher (task container) - virtual shared_qobject_ptr createLaunchTask( - AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0; + virtual shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0; /// returns the current launch task (if any) shared_qobject_ptr getLaunchTask(); @@ -222,45 +213,30 @@ public: virtual QString typeName() const = 0; void updateRuntimeContext(); - RuntimeContext runtimeContext() const - { - return m_runtimeContext; - } + RuntimeContext runtimeContext() const { return m_runtimeContext; } - bool hasVersionBroken() const - { - return m_hasBrokenVersion; - } + bool hasVersionBroken() const { return m_hasBrokenVersion; } void setVersionBroken(bool value) { - if(m_hasBrokenVersion != value) - { + if (m_hasBrokenVersion != value) { m_hasBrokenVersion = value; emit propertiesChanged(this); } } - bool hasUpdateAvailable() const - { - return m_hasUpdate; - } + bool hasUpdateAvailable() const { return m_hasUpdate; } void setUpdateAvailable(bool value) { - if(m_hasUpdate != value) - { + if (m_hasUpdate != value) { m_hasUpdate = value; emit propertiesChanged(this); } } - bool hasCrashed() const - { - return m_crashed; - } + bool hasCrashed() const { return m_crashed; } void setCrashed(bool value) { - if(m_crashed != value) - { + if (m_crashed != value) { m_crashed = value; emit propertiesChanged(this); } @@ -288,7 +264,7 @@ public: bool removeLinkedInstanceId(const QString& id); bool isLinkedToInstanceId(const QString& id) const; -protected: + protected: void changeStatus(Status newStatus); SettingsObjectPtr globalSettings() const { return m_global_settings.lock(); } @@ -296,11 +272,11 @@ protected: bool isSpecificSettingsLoaded() const { return m_specific_settings_loaded; } void setSpecificSettingsLoaded(bool loaded) { m_specific_settings_loaded = loaded; } -signals: + signals: /*! * \brief Signal emitted when properties relevant to the instance view change */ - void propertiesChanged(BaseInstance *inst); + void propertiesChanged(BaseInstance* inst); void launchTaskChanged(shared_qobject_ptr); @@ -308,10 +284,10 @@ signals: void statusChanged(Status from, Status to); -protected slots: + protected slots: void iconUpdated(QString key); -protected: /* data */ + protected: /* data */ QString m_rootDir; SettingsObjectPtr m_settings; // InstanceFlags m_flags; @@ -320,7 +296,7 @@ protected: /* data */ QDateTime m_timeStarted; RuntimeContext m_runtimeContext; -private: /* data */ + private: /* data */ Status m_status = Status::Present; bool m_crashed = false; bool m_hasUpdate = false; @@ -328,9 +304,8 @@ private: /* data */ SettingsObjectWeakPtr m_global_settings; bool m_specific_settings_loaded = false; - }; Q_DECLARE_METATYPE(shared_qobject_ptr) -//Q_DECLARE_METATYPE(BaseInstance::InstanceFlag) -//Q_DECLARE_OPERATORS_FOR_FLAGS(BaseInstance::InstanceFlags) +// Q_DECLARE_METATYPE(BaseInstance::InstanceFlag) +// Q_DECLARE_OPERATORS_FOR_FLAGS(BaseInstance::InstanceFlags) diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index dc95e7ea5..d817926ef 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -36,14 +36,11 @@ #include "BaseVersionList.h" #include "BaseVersion.h" -BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent) -{ -} +BaseVersionList::BaseVersionList(QObject* parent) : QAbstractListModel(parent) {} -BaseVersion::Ptr BaseVersionList::findVersion(const QString &descriptor) +BaseVersion::Ptr BaseVersionList::findVersion(const QString& descriptor) { - for (int i = 0; i < count(); i++) - { + for (int i = 0; i < count(); i++) { if (at(i)->descriptor() == descriptor) return at(i); } @@ -58,7 +55,7 @@ BaseVersion::Ptr BaseVersionList::getRecommended() const return at(0); } -QVariant BaseVersionList::data(const QModelIndex &index, int role) const +QVariant BaseVersionList::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); @@ -68,37 +65,36 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const BaseVersion::Ptr version = at(index.row()); - switch (role) - { - case VersionPointerRole: - return QVariant::fromValue(version); + switch (role) { + case VersionPointerRole: + return QVariant::fromValue(version); - case VersionRole: - return version->name(); + case VersionRole: + return version->name(); - case VersionIdRole: - return version->descriptor(); + case VersionIdRole: + return version->descriptor(); - case TypeRole: - return version->typeString(); + case TypeRole: + return version->typeString(); - default: - return QVariant(); + default: + return QVariant(); } } BaseVersionList::RoleList BaseVersionList::providesRoles() const { - return {VersionPointerRole, VersionRole, VersionIdRole, TypeRole}; + return { VersionPointerRole, VersionRole, VersionIdRole, TypeRole }; } -int BaseVersionList::rowCount(const QModelIndex &parent) const +int BaseVersionList::rowCount(const QModelIndex& parent) const { // Return count return parent.isValid() ? 0 : count(); } -int BaseVersionList::columnCount(const QModelIndex &parent) const +int BaseVersionList::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : 1; } diff --git a/launcher/BaseVersionList.h b/launcher/BaseVersionList.h index 31f29022a..fe1550c21 100644 --- a/launcher/BaseVersionList.h +++ b/launcher/BaseVersionList.h @@ -15,13 +15,13 @@ #pragma once +#include #include #include -#include #include "BaseVersion.h" -#include "tasks/Task.h" #include "QObjectPtr.h" +#include "tasks/Task.h" /*! * \brief Class that each instance type's version list derives from. @@ -35,12 +35,10 @@ * all have a default implementation, but they can be overridden by plugins to * change the behavior of the list. */ -class BaseVersionList : public QAbstractListModel -{ +class BaseVersionList : public QAbstractListModel { Q_OBJECT -public: - enum ModelRoles - { + public: + enum ModelRoles { VersionPointerRole = Qt::UserRole, VersionRole, VersionIdRole, @@ -55,7 +53,7 @@ public: }; typedef QList RoleList; - explicit BaseVersionList(QObject *parent = 0); + explicit BaseVersionList(QObject* parent = 0); /*! * \brief Gets a task that will reload the version list. @@ -66,7 +64,7 @@ public: virtual Task::Ptr getLoadTask() = 0; //! Checks whether or not the list is loaded. If this returns false, the list should be - //loaded. + // loaded. virtual bool isLoaded() = 0; //! Gets the version at the given index. @@ -76,9 +74,9 @@ public: virtual int count() const = 0; //////// List Model Functions //////// - QVariant data(const QModelIndex &index, int role) const override; - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex& index, int role) const override; + int rowCount(const QModelIndex& parent) const override; + int columnCount(const QModelIndex& parent) const override; QHash roleNames() const override; //! which roles are provided by this version list? @@ -90,7 +88,7 @@ public: * \return A const pointer to the version with the given descriptor. NULL if * one doesn't exist. */ - virtual BaseVersion::Ptr findVersion(const QString &descriptor); + virtual BaseVersion::Ptr findVersion(const QString& descriptor); /*! * \brief Gets the recommended version from this list @@ -103,8 +101,7 @@ public: */ virtual void sortVersions() = 0; -protected -slots: + protected slots: /*! * Updates this list with the given list of versions. * This is done by copying each version in the given list and inserting it diff --git a/launcher/Commandline.cpp b/launcher/Commandline.cpp index 6d97918de..4fac024ac 100644 --- a/launcher/Commandline.cpp +++ b/launcher/Commandline.cpp @@ -41,8 +41,7 @@ * @file libutil/src/cmdutils.cpp */ -namespace Commandline -{ +namespace Commandline { // commandline splitter QStringList splitArgs(QString args) @@ -51,19 +50,15 @@ QStringList splitArgs(QString args) QString current; bool escape = false; QChar inquotes; - for (int i = 0; i < args.length(); i++) - { + for (int i = 0; i < args.length(); i++) { QChar cchar = args.at(i); // \ escaped - if (escape) - { + if (escape) { current += cchar; escape = false; // in "quotes" - } - else if (!inquotes.isNull()) - { + } else if (!inquotes.isNull()) { if (cchar == '\\') escape = true; else if (cchar == inquotes) @@ -71,18 +66,13 @@ QStringList splitArgs(QString args) else current += cchar; // otherwise - } - else - { - if (cchar == ' ') - { - if (!current.isEmpty()) - { + } else { + if (cchar == ' ') { + if (!current.isEmpty()) { argv << current; current.clear(); } - } - else if (cchar == '"' || cchar == '\'') + } else if (cchar == '"' || cchar == '\'') inquotes = cchar; else current += cchar; @@ -92,4 +82,4 @@ QStringList splitArgs(QString args) argv << current; return argv; } -} +} // namespace Commandline diff --git a/launcher/Commandline.h b/launcher/Commandline.h index 8bd791808..77c557de2 100644 --- a/launcher/Commandline.h +++ b/launcher/Commandline.h @@ -25,8 +25,7 @@ * @brief commandline parsing and processing utilities */ -namespace Commandline -{ +namespace Commandline { /** * @brief split a string into argv items like a shell would do @@ -34,4 +33,4 @@ namespace Commandline * @return a QStringList containing all arguments */ QStringList splitArgs(QString args); -} +} // namespace Commandline diff --git a/launcher/DefaultVariable.h b/launcher/DefaultVariable.h index 5c069bd38..b082091c7 100644 --- a/launcher/DefaultVariable.h +++ b/launcher/DefaultVariable.h @@ -1,33 +1,21 @@ #pragma once template -class DefaultVariable -{ -public: - DefaultVariable(const T & value) - { - defaultValue = value; - } - DefaultVariable & operator =(const T & value) +class DefaultVariable { + public: + DefaultVariable(const T& value) { defaultValue = value; } + DefaultVariable& operator=(const T& value) { currentValue = value; is_default = currentValue == defaultValue; is_explicit = true; return *this; } - operator const T &() const - { - return is_default ? defaultValue : currentValue; - } - bool isDefault() const - { - return is_default; - } - bool isExplicit() const - { - return is_explicit; - } -private: + operator const T&() const { return is_default ? defaultValue : currentValue; } + bool isDefault() const { return is_default; } + bool isExplicit() const { return is_explicit; } + + private: T currentValue; T defaultValue; bool is_default = true; diff --git a/launcher/DesktopServices.cpp b/launcher/DesktopServices.cpp index 0a0934fb4..62f04f162 100644 --- a/launcher/DesktopServices.cpp +++ b/launcher/DesktopServices.cpp @@ -33,40 +33,37 @@ * limitations under the License. */ #include "DesktopServices.h" -#include -#include -#include #include +#include +#include +#include /** * This shouldn't exist, but until QTBUG-9328 and other unreported bugs are fixed, it needs to be a thing. */ #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) -#include #include #include #include +#include template -bool IndirectOpen(T callable, qint64 *pid_forked = nullptr) +bool IndirectOpen(T callable, qint64* pid_forked = nullptr) { auto pid = fork(); - if(pid_forked) - { - if(pid > 0) + if (pid_forked) { + if (pid > 0) *pid_forked = pid; else *pid_forked = 0; } - if(pid == -1) - { + if (pid == -1) { qWarning() << "IndirectOpen failed to fork: " << errno; return false; } // child - do the stuff - if(pid == 0) - { + if (pid == 0) { // unset all this garbage so it doesn't get passed to the child process qunsetenv("LD_PRELOAD"); qunsetenv("LD_LIBRARY_PATH"); @@ -82,19 +79,14 @@ bool IndirectOpen(T callable, qint64 *pid_forked = nullptr) // die. now. do not clean up anything, it would just hang forever. _exit(status ? 0 : 1); - } - else - { - //parent - assume it worked. + } else { + // parent - assume it worked. int status; - while (waitpid(pid, &status, 0)) - { - if(WIFEXITED(status)) - { + while (waitpid(pid, &status, 0)) { + if (WIFEXITED(status)) { return WEXITSTATUS(status) == 0; } - if(WIFSIGNALED(status)) - { + if (WIFSIGNALED(status)) { return false; } } @@ -104,26 +96,19 @@ bool IndirectOpen(T callable, qint64 *pid_forked = nullptr) #endif namespace DesktopServices { -bool openDirectory(const QString &path, [[maybe_unused]] bool ensureExists) +bool openDirectory(const QString& path, [[maybe_unused]] bool ensureExists) { qDebug() << "Opening directory" << path; QDir parentPath; QDir dir(path); - if (!dir.exists()) - { + if (!dir.exists()) { parentPath.mkpath(dir.absolutePath()); } - auto f = [&]() - { - return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); - }; + auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); }; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!isSandbox()) - { + if (!isSandbox()) { return IndirectOpen(f); - } - else - { + } else { return f(); } #else @@ -131,20 +116,14 @@ bool openDirectory(const QString &path, [[maybe_unused]] bool ensureExists) #endif } -bool openFile(const QString &path) +bool openFile(const QString& path) { qDebug() << "Opening file" << path; - auto f = [&]() - { - return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); - }; + auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!isSandbox()) - { + if (!isSandbox()) { return IndirectOpen(f); - } - else - { + } else { return f(); } #else @@ -152,41 +131,29 @@ bool openFile(const QString &path) #endif } -bool openFile(const QString &application, const QString &path, const QString &workingDirectory, qint64 *pid) +bool openFile(const QString& application, const QString& path, const QString& workingDirectory, qint64* pid) { qDebug() << "Opening file" << path << "using" << application; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave - if(!isSandbox()) - { - return IndirectOpen([&]() - { - return QProcess::startDetached(application, QStringList() << path, workingDirectory); - }, pid); - } - else - { - return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid); + if (!isSandbox()) { + return IndirectOpen([&]() { return QProcess::startDetached(application, QStringList() << path, workingDirectory); }, pid); + } else { + return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid); } #else return QProcess::startDetached(application, QStringList() << path, workingDirectory, pid); #endif } -bool run(const QString &application, const QStringList &args, const QString &workingDirectory, qint64 *pid) +bool run(const QString& application, const QStringList& args, const QString& workingDirectory, qint64* pid) { qDebug() << "Running" << application << "with args" << args.join(' '); #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!isSandbox()) - { - // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave - return IndirectOpen([&]() - { - return QProcess::startDetached(application, args, workingDirectory); - }, pid); - } - else - { + if (!isSandbox()) { + // FIXME: the pid here is fake. So if something depends on it, it will likely misbehave + return IndirectOpen([&]() { return QProcess::startDetached(application, args, workingDirectory); }, pid); + } else { return QProcess::startDetached(application, args, workingDirectory, pid); } #else @@ -194,20 +161,14 @@ bool run(const QString &application, const QStringList &args, const QString &wor #endif } -bool openUrl(const QUrl &url) +bool openUrl(const QUrl& url) { qDebug() << "Opening URL" << url.toString(); - auto f = [&]() - { - return QDesktopServices::openUrl(url); - }; + auto f = [&]() { return QDesktopServices::openUrl(url); }; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) - if(!isSandbox()) - { + if (!isSandbox()) { return IndirectOpen(f); - } - else - { + } else { return f(); } #else @@ -238,4 +199,4 @@ bool isSandbox() return isSnap() || isFlatpak(); } -} +} // namespace DesktopServices diff --git a/launcher/DesktopServices.h b/launcher/DesktopServices.h index b1948cc2b..151db5557 100644 --- a/launcher/DesktopServices.h +++ b/launcher/DesktopServices.h @@ -1,51 +1,50 @@ #pragma once -#include #include +#include /** * This wraps around QDesktopServices and adds workarounds where needed * Use this instead of QDesktopServices! */ -namespace DesktopServices -{ - /** - * Open a file in whatever application is applicable - */ - bool openFile(const QString &path); +namespace DesktopServices { +/** + * Open a file in whatever application is applicable + */ +bool openFile(const QString& path); - /** - * Open a file in the specified application - */ - bool openFile(const QString &application, const QString &path, const QString & workingDirectory = QString(), qint64 *pid = 0); +/** + * Open a file in the specified application + */ +bool openFile(const QString& application, const QString& path, const QString& workingDirectory = QString(), qint64* pid = 0); - /** - * Run an application - */ - bool run(const QString &application,const QStringList &args, const QString & workingDirectory = QString(), qint64 *pid = 0); +/** + * Run an application + */ +bool run(const QString& application, const QStringList& args, const QString& workingDirectory = QString(), qint64* pid = 0); - /** - * Open a directory - */ - bool openDirectory(const QString &path, bool ensureExists = false); +/** + * Open a directory + */ +bool openDirectory(const QString& path, bool ensureExists = false); - /** - * Open the URL, most likely in a browser. Maybe. - */ - bool openUrl(const QUrl &url); +/** + * Open the URL, most likely in a browser. Maybe. + */ +bool openUrl(const QUrl& url); - /** - * Determine whether the launcher is running in a Flatpak environment - */ - bool isFlatpak(); +/** + * Determine whether the launcher is running in a Flatpak environment + */ +bool isFlatpak(); - /** - * Determine whether the launcher is running in a Snap environment - */ - bool isSnap(); +/** + * Determine whether the launcher is running in a Snap environment + */ +bool isSnap(); - /** - * Determine whether the launcher is running in a sandboxed (Flatpak or Snap) environment - */ - bool isSandbox(); -} +/** + * Determine whether the launcher is running in a sandboxed (Flatpak or Snap) environment + */ +bool isSandbox(); +} // namespace DesktopServices diff --git a/launcher/Exception.h b/launcher/Exception.h index fe0b86b5f..ef1e4e0d8 100644 --- a/launcher/Exception.h +++ b/launcher/Exception.h @@ -2,31 +2,18 @@ #pragma once -#include #include +#include #include -class Exception : public std::exception -{ -public: - Exception(const QString &message) : std::exception(), m_message(message) - { - qCritical() << "Exception:" << message; - } - Exception(const Exception &other) - : std::exception(), m_message(other.cause()) - { - } +class Exception : public std::exception { + public: + Exception(const QString& message) : std::exception(), m_message(message) { qCritical() << "Exception:" << message; } + Exception(const Exception& other) : std::exception(), m_message(other.cause()) {} virtual ~Exception() noexcept {} - const char *what() const noexcept - { - return m_message.toLatin1().constData(); - } - QString cause() const - { - return m_message; - } + const char* what() const noexcept { return m_message.toLatin1().constData(); } + QString cause() const { return m_message; } -private: + private: QString m_message; }; diff --git a/launcher/ExponentialSeries.h b/launcher/ExponentialSeries.h index a9487f0a3..b1fca4359 100644 --- a/launcher/ExponentialSeries.h +++ b/launcher/ExponentialSeries.h @@ -4,31 +4,24 @@ template inline void clamp(T& current, T min, T max) { - if (current < min) - { + if (current < min) { current = min; - } - else if(current > max) - { + } else if (current > max) { current = max; } } // List of numbers from min to max. Next is exponent times bigger than previous. -class ExponentialSeries -{ -public: +class ExponentialSeries { + public: ExponentialSeries(unsigned min, unsigned max, unsigned exponent = 2) { m_current = m_min = min; m_max = max; m_exponent = exponent; } - void reset() - { - m_current = m_min; - } + void reset() { m_current = m_min; } unsigned operator()() { unsigned retval = m_current; diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 4538702f2..defb2cb9e 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -779,7 +779,8 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri } #if defined(Q_OS_MACOS) // Create the Application - QDir applicationDirectory = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/"; + QDir applicationDirectory = + QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/"; if (!applicationDirectory.mkpath(".")) { qWarning() << "Couldn't create application directory"; @@ -843,7 +844,9 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri " CFBundleIconFile\n" " Icon.icns\n" " CFBundleName\n" - " " << name << "\n" // Name of the application + " " + << name + << "\n" // Name of the application " CFBundlePackageType\n" " APPL\n" " CFBundleShortVersionString\n" diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index 2a4b26209..bfed576c1 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -43,10 +43,10 @@ #include #include -#include #include #include #include +#include #include namespace FS { @@ -365,25 +365,24 @@ enum class FilesystemType { * QMap is ordered * */ -static const QMap s_filesystem_type_names = { - {FilesystemType::FAT, { "FAT" }}, - {FilesystemType::NTFS, { "NTFS" }}, - {FilesystemType::REFS, { "REFS" }}, - {FilesystemType::EXT_2_OLD, { "EXT_2_OLD", "EXT2_OLD" }}, - {FilesystemType::EXT_2_3_4, { "EXT2/3/4", "EXT_2_3_4", "EXT2", "EXT3", "EXT4" }}, - {FilesystemType::EXT, { "EXT" }}, - {FilesystemType::XFS, { "XFS" }}, - {FilesystemType::BTRFS, { "BTRFS" }}, - {FilesystemType::NFS, { "NFS" }}, - {FilesystemType::ZFS, { "ZFS" }}, - {FilesystemType::APFS, { "APFS" }}, - {FilesystemType::HFS, { "HFS" }}, - {FilesystemType::HFSPLUS, { "HFSPLUS" }}, - {FilesystemType::HFSX, { "HFSX" }}, - {FilesystemType::FUSEBLK, { "FUSEBLK" }}, - {FilesystemType::F2FS, { "F2FS" }}, - {FilesystemType::UNKNOWN, { "UNKNOWN" }} -}; +static const QMap s_filesystem_type_names = { { FilesystemType::FAT, { "FAT" } }, + { FilesystemType::NTFS, { "NTFS" } }, + { FilesystemType::REFS, { "REFS" } }, + { FilesystemType::EXT_2_OLD, { "EXT_2_OLD", "EXT2_OLD" } }, + { FilesystemType::EXT_2_3_4, + { "EXT2/3/4", "EXT_2_3_4", "EXT2", "EXT3", "EXT4" } }, + { FilesystemType::EXT, { "EXT" } }, + { FilesystemType::XFS, { "XFS" } }, + { FilesystemType::BTRFS, { "BTRFS" } }, + { FilesystemType::NFS, { "NFS" } }, + { FilesystemType::ZFS, { "ZFS" } }, + { FilesystemType::APFS, { "APFS" } }, + { FilesystemType::HFS, { "HFS" } }, + { FilesystemType::HFSPLUS, { "HFSPLUS" } }, + { FilesystemType::HFSX, { "HFSX" } }, + { FilesystemType::FUSEBLK, { "FUSEBLK" } }, + { FilesystemType::F2FS, { "F2FS" } }, + { FilesystemType::UNKNOWN, { "UNKNOWN" } } }; /** * @brief Get the string name of Filesystem enum object diff --git a/launcher/Filter.cpp b/launcher/Filter.cpp index f95305977..fc1c42344 100644 --- a/launcher/Filter.cpp +++ b/launcher/Filter.cpp @@ -1,16 +1,16 @@ #include "Filter.h" -Filter::~Filter(){} +Filter::~Filter() {} -ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern){} -ContainsFilter::~ContainsFilter(){} +ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern) {} +ContainsFilter::~ContainsFilter() {} bool ContainsFilter::accepts(const QString& value) { return value.contains(pattern); } -ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern){} -ExactFilter::~ExactFilter(){} +ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern) {} +ExactFilter::~ExactFilter() {} bool ExactFilter::accepts(const QString& value) { return value == pattern; @@ -22,13 +22,12 @@ bool ExactIfPresentFilter::accepts(const QString& value) return value.isEmpty() || value == pattern; } -RegexpFilter::RegexpFilter(const QString& regexp, bool invert) - :invert(invert) +RegexpFilter::RegexpFilter(const QString& regexp, bool invert) : invert(invert) { pattern.setPattern(regexp); pattern.optimize(); } -RegexpFilter::~RegexpFilter(){} +RegexpFilter::~RegexpFilter() {} bool RegexpFilter::accepts(const QString& value) { auto match = pattern.match(value); diff --git a/launcher/Filter.h b/launcher/Filter.h index d3cee2d8d..089c844d4 100644 --- a/launcher/Filter.h +++ b/launcher/Filter.h @@ -1,52 +1,51 @@ #pragma once -#include #include +#include -class Filter -{ -public: - virtual ~Filter(); - virtual bool accepts(const QString & value) = 0; -}; - -class ContainsFilter: public Filter -{ -public: - ContainsFilter(const QString &pattern); - virtual ~ContainsFilter(); - bool accepts(const QString & value) override; -private: - QString pattern; -}; - -class ExactFilter: public Filter -{ -public: - ExactFilter(const QString &pattern); - virtual ~ExactFilter(); - bool accepts(const QString & value) override; -private: - QString pattern; -}; - -class ExactIfPresentFilter: public Filter -{ +class Filter { public: - ExactIfPresentFilter(const QString& pattern); - ~ExactIfPresentFilter() override = default; + virtual ~Filter(); + virtual bool accepts(const QString& value) = 0; +}; + +class ContainsFilter : public Filter { + public: + ContainsFilter(const QString& pattern); + virtual ~ContainsFilter(); bool accepts(const QString& value) override; + private: QString pattern; }; -class RegexpFilter: public Filter -{ -public: - RegexpFilter(const QString ®exp, bool invert); +class ExactFilter : public Filter { + public: + ExactFilter(const QString& pattern); + virtual ~ExactFilter(); + bool accepts(const QString& value) override; + + private: + QString pattern; +}; + +class ExactIfPresentFilter : public Filter { + public: + ExactIfPresentFilter(const QString& pattern); + ~ExactIfPresentFilter() override = default; + bool accepts(const QString& value) override; + + private: + QString pattern; +}; + +class RegexpFilter : public Filter { + public: + RegexpFilter(const QString& regexp, bool invert); virtual ~RegexpFilter(); - bool accepts(const QString & value) override; -private: + bool accepts(const QString& value) override; + + private: QRegularExpression pattern; bool invert = false; }; diff --git a/launcher/GZip.cpp b/launcher/GZip.cpp index e36dc8a49..292fab294 100644 --- a/launcher/GZip.cpp +++ b/launcher/GZip.cpp @@ -37,10 +37,9 @@ #include #include -bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes) +bool GZip::unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes) { - if (compressedBytes.size() == 0) - { + if (compressedBytes.size() == 0) { uncompressedBytes = compressedBytes; return true; } @@ -51,42 +50,37 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte z_stream strm; memset(&strm, 0, sizeof(strm)); - strm.next_in = (Bytef *)compressedBytes.data(); + strm.next_in = (Bytef*)compressedBytes.data(); strm.avail_in = compressedBytes.size(); bool done = false; - if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) - { + if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) { return false; } int err = Z_OK; - while (!done) - { + while (!done) { // If our output buffer is too small - if (strm.total_out >= uncompLength) - { + if (strm.total_out >= uncompLength) { uncompressedBytes.resize(uncompLength * 2); uncompLength *= 2; } - strm.next_out = reinterpret_cast((uncompressedBytes.data() + strm.total_out)); + strm.next_out = reinterpret_cast((uncompressedBytes.data() + strm.total_out)); strm.avail_out = uncompLength - strm.total_out; // Inflate another chunk. err = inflate(&strm, Z_SYNC_FLUSH); if (err == Z_STREAM_END) done = true; - else if (err != Z_OK) - { + else if (err != Z_OK) { break; } } - if (inflateEnd(&strm) != Z_OK || !done) - { + if (inflateEnd(&strm) != Z_OK || !done) { return false; } @@ -94,10 +88,9 @@ bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedByte return true; } -bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) +bool GZip::zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes) { - if (uncompressedBytes.size() == 0) - { + if (uncompressedBytes.size() == 0) { compressedBytes = uncompressedBytes; return true; } @@ -109,8 +102,7 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) z_stream zs; memset(&zs, 0, sizeof(zs)); - if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK) - { + if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK) { return false; } @@ -122,11 +114,9 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) unsigned offset = 0; unsigned temp = 0; - do - { + do { auto remaining = compressedBytes.size() - offset; - if(remaining < 1) - { + if (remaining < 1) { compressedBytes.resize(compressedBytes.size() * 2); } zs.next_out = reinterpret_cast((compressedBytes.data() + offset)); @@ -137,13 +127,11 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes) compressedBytes.resize(offset); - if (deflateEnd(&zs) != Z_OK) - { + if (deflateEnd(&zs) != Z_OK) { return false; } - if (ret != Z_STREAM_END) - { + if (ret != Z_STREAM_END) { return false; } return true; diff --git a/launcher/GZip.h b/launcher/GZip.h index 7d4b1c332..0bdb70407 100644 --- a/launcher/GZip.h +++ b/launcher/GZip.h @@ -1,10 +1,8 @@ #pragma once #include -class GZip -{ -public: - static bool unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes); - static bool zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes); +class GZip { + public: + static bool unzip(const QByteArray& compressedBytes, QByteArray& uncompressedBytes); + static bool zip(const QByteArray& uncompressedBytes, QByteArray& compressedBytes); }; - diff --git a/launcher/InstanceCopyPrefs.cpp b/launcher/InstanceCopyPrefs.cpp index 0650002b8..63c200cc4 100644 --- a/launcher/InstanceCopyPrefs.cpp +++ b/launcher/InstanceCopyPrefs.cpp @@ -6,17 +6,10 @@ bool InstanceCopyPrefs::allTrue() const { - return copySaves && - keepPlaytime && - copyGameOptions && - copyResourcePacks && - copyShaderPacks && - copyServers && - copyMods && - copyScreenshots; + return copySaves && keepPlaytime && copyGameOptions && copyResourcePacks && copyShaderPacks && copyServers && copyMods && + copyScreenshots; } - // Returns a single RegEx string of the selected folders/files to filter out (ex: ".minecraft/saves|.minecraft/server.dat") QString InstanceCopyPrefs::getSelectedFiltersAsRegex() const { @@ -26,25 +19,30 @@ QString InstanceCopyPrefs::getSelectedFiltersAsRegex(const QStringList& addition { QStringList filters; - if(!copySaves) + if (!copySaves) filters << "saves"; - if(!copyGameOptions) + if (!copyGameOptions) filters << "options.txt"; - if(!copyResourcePacks) - filters << "resourcepacks" << "texturepacks"; + if (!copyResourcePacks) + filters << "resourcepacks" + << "texturepacks"; - if(!copyShaderPacks) + if (!copyShaderPacks) filters << "shaderpacks"; - if(!copyServers) - filters << "servers.dat" << "servers.dat_old" << "server-resource-packs"; + if (!copyServers) + filters << "servers.dat" + << "servers.dat_old" + << "server-resource-packs"; - if(!copyMods) - filters << "coremods" << "mods" << "config"; + if (!copyMods) + filters << "coremods" + << "mods" + << "config"; - if(!copyScreenshots) + if (!copyScreenshots) filters << "screenshots"; for (auto filter : additionalFilters) { diff --git a/launcher/InstanceCopyPrefs.h b/launcher/InstanceCopyPrefs.h index c7bde0682..61c51b3b7 100644 --- a/launcher/InstanceCopyPrefs.h +++ b/launcher/InstanceCopyPrefs.h @@ -40,7 +40,7 @@ struct InstanceCopyPrefs { void enableDontLinkSaves(bool b); void enableUseClone(bool b); - protected: // data + protected: // data bool copySaves = true; bool keepPlaytime = true; bool copyGameOptions = true; diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp index 57a3143a1..8abf30640 100644 --- a/launcher/InstanceCopyTask.cpp +++ b/launcher/InstanceCopyTask.cpp @@ -156,8 +156,9 @@ void InstanceCopyTask::copyFinished() allowed_symlinks.append(m_origInstance->gameRoot().toUtf8()); allowed_symlinks.append("\n"); if (allowed_symlinks_file.isSymLink()) - FS::deletePath(allowed_symlinks_file - .filePath()); // we dont want to modify the original. also make sure the resulting file is not itself a link. + FS::deletePath( + allowed_symlinks_file + .filePath()); // we dont want to modify the original. also make sure the resulting file is not itself a link. FS::write(allowed_symlinks_file.filePath(), allowed_symlinks); } diff --git a/launcher/InstanceCopyTask.h b/launcher/InstanceCopyTask.h index aea9d99a1..357c6df0b 100644 --- a/launcher/InstanceCopyTask.h +++ b/launcher/InstanceCopyTask.h @@ -11,19 +11,18 @@ #include "settings/SettingsObject.h" #include "tasks/Task.h" -class InstanceCopyTask : public InstanceTask -{ +class InstanceCopyTask : public InstanceTask { Q_OBJECT -public: + public: explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs); -protected: + protected: //! Entry point for tasks. virtual void executeTask() override; void copyFinished(); void copyAborted(); -private: + private: /* data */ InstancePtr m_origInstance; QFuture m_copyFuture; diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 98ed14b97..2bc945d7b 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -45,9 +45,9 @@ #include "icons/IconList.h" #include "icons/IconUtils.h" -#include "modplatform/technic/TechnicPackProcessor.h" -#include "modplatform/modrinth/ModrinthInstanceCreationTask.h" #include "modplatform/flame/FlameInstanceCreationTask.h" +#include "modplatform/modrinth/ModrinthInstanceCreationTask.h" +#include "modplatform/technic/TechnicPackProcessor.h" #include "settings/INISettingsObject.h" @@ -140,8 +140,7 @@ void InstanceImportTask::processZipPack() // open the zip and find relevant files in it m_packZip.reset(new QuaZip(m_archivePath)); - if (!m_packZip->open(QuaZip::mdUnzip)) - { + if (!m_packZip->open(QuaZip::mdUnzip)) { emitFailed(tr("Unable to open supplied modpack zip file.")); return; } @@ -155,44 +154,40 @@ void InstanceImportTask::processZipPack() // NOTE: Prioritize modpack platforms that aren't searched for recursively. // Especially Flame has a very common filename for its manifest, which may appear inside overrides for example - if(modrinthFound) - { + if (modrinthFound) { // process as Modrinth pack qDebug() << "Modrinth:" << modrinthFound; m_modpackType = ModpackType::Modrinth; - } - else if (technicFound) - { + } else if (technicFound) { // process as Technic pack qDebug() << "Technic:" << technicFound; extractDir.mkpath(".minecraft"); extractDir.cd(".minecraft"); m_modpackType = ModpackType::Technic; - } - else - { - QStringList paths_to_ignore { "overrides/" }; + } else { + QStringList paths_to_ignore{ "overrides/" }; if (QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg", paths_to_ignore); !mmcRoot.isNull()) { // process as MultiMC instance/pack qDebug() << "MultiMC:" << mmcRoot; root = mmcRoot; m_modpackType = ModpackType::MultiMC; - } else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore); !flameRoot.isNull()) { + } else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore); + !flameRoot.isNull()) { // process as Flame pack qDebug() << "Flame:" << flameRoot; root = flameRoot; m_modpackType = ModpackType::Flame; } } - if(m_modpackType == ModpackType::Unknown) - { + if (m_modpackType == ModpackType::Unknown) { emitFailed(tr("Archive does not contain a recognized modpack type.")); return; } // make sure we extract just the pack - m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath()); + m_extractFuture = + QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath()); connect(&m_extractFutureWatcher, &QFutureWatcher::finished, this, &InstanceImportTask::extractFinished); m_extractFutureWatcher.setFuture(m_extractFuture); } @@ -212,37 +207,28 @@ void InstanceImportTask::extractFinished() qDebug() << "Fixing permissions for extracted pack files..."; QDirIterator it(extractDir, QDirIterator::Subdirectories); - while (it.hasNext()) - { + while (it.hasNext()) { auto filepath = it.next(); QFileInfo file(filepath); auto permissions = QFile::permissions(filepath); auto origPermissions = permissions; - if(file.isDir()) - { + if (file.isDir()) { // Folder +rwx for current user permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser; - } - else - { + } else { // File +rw for current user permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser; } - if(origPermissions != permissions) - { - if(!QFile::setPermissions(filepath, permissions)) - { + if (origPermissions != permissions) { + if (!QFile::setPermissions(filepath, permissions)) { logWarning(tr("Could not fix permissions for %1").arg(filepath)); - } - else - { + } else { qDebug() << "Fixed" << filepath; } } } - switch(m_modpackType) - { + switch (m_modpackType) { case ModpackType::MultiMC: processMultiMC(); return; @@ -278,7 +264,8 @@ void InstanceImportTask::processFlame() if (original_instance_id_it != m_extra_info.constEnd()) original_instance_id = original_instance_id_it.value(); - inst_creation_task = makeShared(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); + inst_creation_task = + makeShared(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); } else { // FIXME: Find a way to get IDs in directly imported ZIPs inst_creation_task = makeShared(m_stagingPath, m_globalSettings, m_parent, QString(), QString()); @@ -288,7 +275,7 @@ void InstanceImportTask::processFlame() inst_creation_task->setIcon(m_instIcon); inst_creation_task->setGroup(m_instGroup); inst_creation_task->setConfirmUpdate(shouldConfirmUpdate()); - + connect(inst_creation_task.get(), &Task::succeeded, this, [this, inst_creation_task] { setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID()); emitSucceeded(); @@ -364,7 +351,8 @@ void InstanceImportTask::processModrinth() if (original_instance_id_it != m_extra_info.constEnd()) original_instance_id = original_instance_id_it.value(); - inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); + inst_creation_task = + new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); } else { QString pack_id; if (!m_sourceUrl.isEmpty()) { @@ -380,7 +368,7 @@ void InstanceImportTask::processModrinth() inst_creation_task->setIcon(m_instIcon); inst_creation_task->setGroup(m_instGroup); inst_creation_task->setConfirmUpdate(shouldConfirmUpdate()); - + connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID()); emitSucceeded(); diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h index 7fda439fc..582a9ded0 100644 --- a/launcher/InstanceImportTask.h +++ b/launcher/InstanceImportTask.h @@ -35,54 +35,49 @@ #pragma once -#include "InstanceTask.h" -#include "net/NetJob.h" -#include #include #include -#include "settings/SettingsObject.h" +#include +#include "InstanceTask.h" #include "QObjectPtr.h" #include "modplatform/flame/PackManifest.h" +#include "net/NetJob.h" +#include "settings/SettingsObject.h" #include class QuaZip; -namespace Flame -{ - class FileResolvingTask; +namespace Flame { +class FileResolvingTask; } -class InstanceImportTask : public InstanceTask -{ +class InstanceImportTask : public InstanceTask { Q_OBJECT -public: + public: explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap&& extra_info = {}); bool abort() override; - const QVector &getBlockedFiles() const - { - return m_blockedMods; - } + const QVector& getBlockedFiles() const { return m_blockedMods; } -protected: + protected: //! Entry point for tasks. virtual void executeTask() override; -private: + private: void processZipPack(); void processMultiMC(); void processTechnic(); void processFlame(); void processModrinth(); -private slots: + private slots: void downloadSucceeded(); void downloadFailed(QString reason); void downloadProgressChanged(qint64 current, qint64 total); void downloadAborted(); void extractFinished(); -private: /* data */ + private: /* data */ NetJob::Ptr m_filesNetJob; shared_qobject_ptr m_modIdResolver; QUrl m_sourceUrl; @@ -92,7 +87,7 @@ private: /* data */ QFuture> m_extractFuture; QFutureWatcher> m_extractFutureWatcher; QVector m_blockedMods; - enum class ModpackType{ + enum class ModpackType { Unknown, MultiMC, Technic, @@ -104,6 +99,6 @@ private: /* data */ // the source URL / the resource it points to alone. QMap m_extra_info; - //FIXME: nuke + // FIXME: nuke QWidget* m_parent; }; diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index a5950659a..8dc0231b8 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -759,7 +759,7 @@ void InstanceList::instanceDirContentsChanged(const QString& path) emit instancesChanged(); } -void InstanceList::on_InstFolderChanged( [[maybe_unused]] const Setting& setting, QVariant value) +void InstanceList::on_InstFolderChanged([[maybe_unused]] const Setting& setting, QVariant value) { QString newInstDir = QDir(value.toString()).canonicalPath(); if (newInstDir != m_instDir) { diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h index 48bede07d..ee4578ffd 100644 --- a/launcher/InstanceList.h +++ b/launcher/InstanceList.h @@ -15,12 +15,12 @@ #pragma once -#include #include -#include #include -#include +#include #include +#include +#include #include "BaseInstance.h" @@ -32,21 +32,9 @@ using InstanceId = QString; using GroupId = QString; using InstanceLocator = std::pair; -enum class InstCreateError -{ - NoCreateError = 0, - NoSuchVersion, - UnknownCreateError, - InstExists, - CantCreateDir -}; +enum class InstCreateError { NoCreateError = 0, NoSuchVersion, UnknownCreateError, InstExists, CantCreateDir }; -enum class GroupsState -{ - NotLoaded, - Steady, - Dirty -}; +enum class GroupsState { NotLoaded, Steady, Dirty }; struct TrashHistoryItem { QString id; @@ -55,48 +43,36 @@ struct TrashHistoryItem { QString groupName; }; -class InstanceList : public QAbstractListModel -{ +class InstanceList : public QAbstractListModel { Q_OBJECT -public: - explicit InstanceList(SettingsObjectPtr settings, const QString & instDir, QObject *parent = 0); + public: + explicit InstanceList(SettingsObjectPtr settings, const QString& instDir, QObject* parent = 0); virtual ~InstanceList(); -public: - QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; + public: + QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; - bool setData(const QModelIndex & index, const QVariant & value, int role) override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; - enum AdditionalRoles - { + enum AdditionalRoles { GroupRole = Qt::UserRole, - InstancePointerRole = 0x34B1CB48, ///< Return pointer to real instance - InstanceIDRole = 0x34B1CB49 ///< Return id if the instance + InstancePointerRole = 0x34B1CB48, ///< Return pointer to real instance + InstanceIDRole = 0x34B1CB49 ///< Return id if the instance }; /*! * \brief Error codes returned by functions in the InstanceList class. * NoError Indicates that no error occurred. * UnknownError indicates that an unspecified error occurred. */ - enum InstListError - { - NoError = 0, - UnknownError - }; + enum InstListError { NoError = 0, UnknownError }; - InstancePtr at(int i) const - { - return m_instances.at(i); - } + InstancePtr at(int i) const { return m_instances.at(i); } - int count() const - { - return m_instances.count(); - } + int count() const { return m_instances.count(); } InstListError loadList(); void saveNow(); @@ -105,21 +81,21 @@ public: InstancePtr getInstanceById(QString id) const; /* O(n) */ InstancePtr getInstanceByManagedName(const QString& managed_name) const; - QModelIndex getInstanceIndexById(const QString &id) const; + QModelIndex getInstanceIndexById(const QString& id) const; QStringList getGroups(); - bool isGroupCollapsed(const QString &groupName); + bool isGroupCollapsed(const QString& groupName); - GroupId getInstanceGroup(const InstanceId & id) const; - void setInstanceGroup(const InstanceId & id, const GroupId& name); + GroupId getInstanceGroup(const InstanceId& id) const; + void setInstanceGroup(const InstanceId& id, const GroupId& name); - void deleteGroup(const GroupId & name); - bool trashInstance(const InstanceId &id); + void deleteGroup(const GroupId& name); + bool trashInstance(const InstanceId& id); bool trashedSomething(); void undoTrashInstance(); - void deleteInstance(const InstanceId & id); + void deleteInstance(const InstanceId& id); // Wrap an instance creation task in some more task machinery and make it ready to be used - Task * wrapInstanceTask(InstanceTask * task); + Task* wrapInstanceTask(InstanceTask* task); /** * Create a new empty staging area for instance creation and @return a path/key top commit it later. @@ -139,7 +115,7 @@ public: * Destroy a previously created staging area given by @keyPath - used when creation fails. * Used by instance manipulation tasks. */ - bool destroyStagingPath(const QString & keyPath); + bool destroyStagingPath(const QString& keyPath); int getTotalPlayTime(); @@ -147,42 +123,42 @@ public: Qt::DropActions supportedDropActions() const override; - bool canDropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) const override; + bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const override; - bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override; + bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; QStringList mimeTypes() const override; - QMimeData *mimeData(const QModelIndexList &indexes) const override; + QMimeData* mimeData(const QModelIndexList& indexes) const override; - QStringList getLinkedInstancesById(const QString &id) const; + QStringList getLinkedInstancesById(const QString& id) const; -signals: + signals: void dataIsInvalid(); void instancesChanged(); void instanceSelectRequest(QString instanceId); void groupsChanged(QSet groups); -public slots: - void on_InstFolderChanged(const Setting &setting, QVariant value); - void on_GroupStateChanged(const QString &group, bool collapsed); + public slots: + void on_InstFolderChanged(const Setting& setting, QVariant value); + void on_GroupStateChanged(const QString& group, bool collapsed); -private slots: - void propertiesChanged(BaseInstance *inst); + private slots: + void propertiesChanged(BaseInstance* inst); void providerUpdated(); - void instanceDirContentsChanged(const QString &path); + void instanceDirContentsChanged(const QString& path); -private: - int getInstIndex(BaseInstance *inst) const; + private: + int getInstIndex(BaseInstance* inst) const; void updateTotalPlayTime(); void suspendWatch(); void resumeWatch(); - void add(const QList &list); + void add(const QList& list); void loadGroupList(); void saveGroupList(); QList discoverInstances(); InstancePtr loadInstance(const InstanceId& id); -private: + private: int m_watchLevel = 0; int totalPlayTime = 0; bool m_dirty = false; @@ -191,7 +167,7 @@ private: SettingsObjectPtr m_globalSettings; QString m_instDir; - QFileSystemWatcher * m_watcher; + QFileSystemWatcher* m_watcher; // FIXME: this is so inefficient that looking at it is almost painful. QSet m_collapsedGroups; QMap m_instanceGroupIndex; diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h index d25cd330e..66d2b6750 100644 --- a/launcher/InstancePageProvider.h +++ b/launcher/InstancePageProvider.h @@ -1,35 +1,31 @@ #pragma once -#include "minecraft/MinecraftInstance.h" #include +#include "minecraft/MinecraftInstance.h" #include "ui/pages/BasePage.h" #include "ui/pages/BasePageProvider.h" +#include "ui/pages/instance/InstanceSettingsPage.h" #include "ui/pages/instance/LogPage.h" -#include "ui/pages/instance/VersionPage.h" #include "ui/pages/instance/ManagedPackPage.h" #include "ui/pages/instance/ModFolderPage.h" -#include "ui/pages/instance/ResourcePackPage.h" -#include "ui/pages/instance/TexturePackPage.h" -#include "ui/pages/instance/ShaderPackPage.h" #include "ui/pages/instance/NotesPage.h" -#include "ui/pages/instance/ScreenshotsPage.h" -#include "ui/pages/instance/InstanceSettingsPage.h" #include "ui/pages/instance/OtherLogsPage.h" -#include "ui/pages/instance/WorldListPage.h" +#include "ui/pages/instance/ResourcePackPage.h" +#include "ui/pages/instance/ScreenshotsPage.h" #include "ui/pages/instance/ServersPage.h" +#include "ui/pages/instance/ShaderPackPage.h" +#include "ui/pages/instance/TexturePackPage.h" +#include "ui/pages/instance/VersionPage.h" +#include "ui/pages/instance/WorldListPage.h" -class InstancePageProvider : protected QObject, public BasePageProvider -{ +class InstancePageProvider : protected QObject, public BasePageProvider { Q_OBJECT -public: - explicit InstancePageProvider(InstancePtr parent) - { - inst = parent; - } + public: + explicit InstancePageProvider(InstancePtr parent) { inst = parent; } - virtual ~InstancePageProvider() {}; - virtual QList getPages() override + virtual ~InstancePageProvider(){}; + virtual QList getPages() override { - QList values; + QList values; values.append(new LogPage(inst)); std::shared_ptr onesix = std::dynamic_pointer_cast(inst); values.append(new VersionPage(onesix.get())); @@ -49,18 +45,14 @@ public: values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); values.append(new InstanceSettingsPage(onesix.get())); auto logMatcher = inst->getLogFileMatcher(); - if(logMatcher) - { + if (logMatcher) { values.append(new OtherLogsPage(inst->getLogFileRoot(), logMatcher)); } return values; } - virtual QString dialogTitle() override - { - return tr("Edit Instance (%1)").arg(inst->name()); - } -protected: + virtual QString dialogTitle() override { return tr("Edit Instance (%1)").arg(inst->name()); } + + protected: InstancePtr inst; }; - diff --git a/launcher/InstanceTask.cpp b/launcher/InstanceTask.cpp index b16a40ba6..5b2398268 100644 --- a/launcher/InstanceTask.cpp +++ b/launcher/InstanceTask.cpp @@ -18,13 +18,14 @@ InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& ol return InstanceNameChange::ShouldKeep; } -ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name) +ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name) { auto info = CustomMessageBox::selectable( parent, QObject::tr("Similar modpack was found!"), - QObject::tr("One or more of your instances are from this same modpack%1. Do you want to create a " - "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " - "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") + QObject::tr( + "One or more of your instances are from this same modpack%1. Do you want to create a " + "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " + "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") .arg(original_version_name), QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort); info->setButtonText(QMessageBox::Ok, QObject::tr("Update existing instance")); @@ -38,7 +39,6 @@ ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name) if (info->clickedButton() == info->button(QMessageBox::Abort)) return ShouldUpdate::SkipUpdating; return ShouldUpdate::Cancel; - } QString InstanceName::name() const diff --git a/launcher/JavaCommon.cpp b/launcher/JavaCommon.cpp index 30a7dbacc..73bc96a43 100644 --- a/launcher/JavaCommon.cpp +++ b/launcher/JavaCommon.cpp @@ -39,43 +39,39 @@ #include -bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent) +bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget* parent) { - if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegularExpression("-Xm[sx]")) - || jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize")) - { + if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegularExpression("-Xm[sx]")) || jvmargs.contains("-XX-MaxHeapSize") || + jvmargs.contains("-XX:InitialHeapSize")) { auto warnStr = QObject::tr( - "You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" or \"-Xms\").\n" + "You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" " + "or \"-Xms\").\n" "There are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).\n" "This message will be displayed until you remove them from the JVM arguments."); - CustomMessageBox::selectable( - parent, QObject::tr("JVM arguments warning"), - warnStr, - QMessageBox::Warning)->exec(); + CustomMessageBox::selectable(parent, QObject::tr("JVM arguments warning"), warnStr, QMessageBox::Warning)->exec(); return false; } // block lunacy with passing required version to the JVM if (jvmargs.contains(QRegularExpression("-version:.*"))) { auto warnStr = QObject::tr( - "You tried to pass required Java version argument to the JVM (using \"-version:xxx\"). This is not safe and will not be allowed.\n" + "You tried to pass required Java version argument to the JVM (using \"-version:xxx\"). This is not safe and will not be " + "allowed.\n" "This message will be displayed until you remove this from the JVM arguments."); - CustomMessageBox::selectable( - parent, QObject::tr("JVM arguments warning"), - warnStr, - QMessageBox::Warning)->exec(); + CustomMessageBox::selectable(parent, QObject::tr("JVM arguments warning"), warnStr, QMessageBox::Warning)->exec(); return false; } return true; } -void JavaCommon::javaWasOk(QWidget *parent, const JavaCheckResult &result) +void JavaCommon::javaWasOk(QWidget* parent, const JavaCheckResult& result) { QString text; - text += QObject::tr("Java test succeeded!
Platform reported: %1
Java version " - "reported: %2
Java vendor " - "reported: %3
").arg(result.realPlatform, result.javaVersion.toString(), result.javaVendor); - if (result.errorLog.size()) - { + text += QObject::tr( + "Java test succeeded!
Platform reported: %1
Java version " + "reported: %2
Java vendor " + "reported: %3
") + .arg(result.realPlatform, result.javaVersion.toString(), result.javaVendor); + if (result.errorLog.size()) { auto htmlError = result.errorLog; htmlError.replace('\n', "
"); text += QObject::tr("
Warnings:
%1").arg(htmlError); @@ -83,7 +79,7 @@ void JavaCommon::javaWasOk(QWidget *parent, const JavaCheckResult &result) CustomMessageBox::selectable(parent, QObject::tr("Java test success"), text, QMessageBox::Information)->show(); } -void JavaCommon::javaArgsWereBad(QWidget *parent, const JavaCheckResult &result) +void JavaCommon::javaArgsWereBad(QWidget* parent, const JavaCheckResult& result) { auto htmlError = result.errorLog; QString text; @@ -93,7 +89,7 @@ void JavaCommon::javaArgsWereBad(QWidget *parent, const JavaCheckResult &result) CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show(); } -void JavaCommon::javaBinaryWasBad(QWidget *parent, const JavaCheckResult &result) +void JavaCommon::javaBinaryWasBad(QWidget* parent, const JavaCheckResult& result) { QString text; text += QObject::tr( @@ -102,7 +98,7 @@ void JavaCommon::javaBinaryWasBad(QWidget *parent, const JavaCheckResult &result CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show(); } -void JavaCommon::javaCheckNotFound(QWidget *parent) +void JavaCommon::javaCheckNotFound(QWidget* parent) { QString text; text += QObject::tr("Java checker library could not be found. Please check your installation."); @@ -111,8 +107,7 @@ void JavaCommon::javaCheckNotFound(QWidget *parent) void JavaCommon::TestCheck::run() { - if (!JavaCommon::checkJVMArgs(m_args, m_parent)) - { + if (!JavaCommon::checkJVMArgs(m_args, m_parent)) { emit finished(); return; } @@ -129,8 +124,7 @@ void JavaCommon::TestCheck::run() void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) { - if (result.validity != JavaCheckResult::Validity::Valid) - { + if (result.validity != JavaCheckResult::Validity::Valid) { javaBinaryWasBad(m_parent, result); emit finished(); return; @@ -141,8 +135,7 @@ void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) checker->m_args = m_args; checker->m_minMem = m_minMem; checker->m_maxMem = m_maxMem; - if (result.javaVersion.requiresPermGen()) - { + if (result.javaVersion.requiresPermGen()) { checker->m_permGen = m_permGen; } checker->performCheck(); @@ -150,8 +143,7 @@ void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result) { - if (result.validity == JavaCheckResult::Validity::Valid) - { + if (result.validity == JavaCheckResult::Validity::Valid) { javaWasOk(m_parent, result); emit finished(); return; @@ -159,4 +151,3 @@ void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result) javaArgsWereBad(m_parent, result); emit finished(); } - diff --git a/launcher/JavaCommon.h b/launcher/JavaCommon.h index 2ba64c0cd..c96f7a985 100644 --- a/launcher/JavaCommon.h +++ b/launcher/JavaCommon.h @@ -6,45 +6,42 @@ class QWidget; /** * Common UI bits for the java pages to use. */ -namespace JavaCommon -{ - bool checkJVMArgs(QString args, QWidget *parent); +namespace JavaCommon { +bool checkJVMArgs(QString args, QWidget* parent); - // Show a dialog saying that the Java binary was usable - void javaWasOk(QWidget *parent, const JavaCheckResult &result); - // Show a dialog saying that the Java binary was not usable because of bad options - void javaArgsWereBad(QWidget *parent, const JavaCheckResult &result); - // Show a dialog saying that the Java binary was not usable - void javaBinaryWasBad(QWidget *parent, const JavaCheckResult &result); - // Show a dialog if we couldn't find Java Checker - void javaCheckNotFound(QWidget *parent); +// Show a dialog saying that the Java binary was usable +void javaWasOk(QWidget* parent, const JavaCheckResult& result); +// Show a dialog saying that the Java binary was not usable because of bad options +void javaArgsWereBad(QWidget* parent, const JavaCheckResult& result); +// Show a dialog saying that the Java binary was not usable +void javaBinaryWasBad(QWidget* parent, const JavaCheckResult& result); +// Show a dialog if we couldn't find Java Checker +void javaCheckNotFound(QWidget* parent); - class TestCheck : public QObject - { - Q_OBJECT - public: - TestCheck(QWidget *parent, QString path, QString args, int minMem, int maxMem, int permGen) - :m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen) - { - } - virtual ~TestCheck() {}; +class TestCheck : public QObject { + Q_OBJECT + public: + TestCheck(QWidget* parent, QString path, QString args, int minMem, int maxMem, int permGen) + : m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen) + {} + virtual ~TestCheck(){}; - void run(); + void run(); - signals: - void finished(); + signals: + void finished(); - private slots: - void checkFinished(JavaCheckResult result); - void checkFinishedWithArgs(JavaCheckResult result); + private slots: + void checkFinished(JavaCheckResult result); + void checkFinishedWithArgs(JavaCheckResult result); - private: - std::shared_ptr checker; - QWidget *m_parent = nullptr; - QString m_path; - QString m_args; - int m_minMem = 0; - int m_maxMem = 0; - int m_permGen = 64; - }; -} + private: + std::shared_ptr checker; + QWidget* m_parent = nullptr; + QString m_path; + QString m_args; + int m_minMem = 0; + int m_maxMem = 0; + int m_permGen = 64; +}; +} // namespace JavaCommon diff --git a/launcher/Json.cpp b/launcher/Json.cpp index 06b3d3bd2..8db44f062 100644 --- a/launcher/Json.cpp +++ b/launcher/Json.cpp @@ -37,257 +37,246 @@ #include -#include "FileSystem.h" #include +#include "FileSystem.h" -namespace Json -{ -void write(const QJsonDocument &doc, const QString &filename) +namespace Json { +void write(const QJsonDocument& doc, const QString& filename) { FS::write(filename, doc.toJson()); } -void write(const QJsonObject &object, const QString &filename) +void write(const QJsonObject& object, const QString& filename) { write(QJsonDocument(object), filename); } -void write(const QJsonArray &array, const QString &filename) +void write(const QJsonArray& array, const QString& filename) { write(QJsonDocument(array), filename); } -QByteArray toText(const QJsonObject &obj) +QByteArray toText(const QJsonObject& obj) { return QJsonDocument(obj).toJson(QJsonDocument::Compact); } -QByteArray toText(const QJsonArray &array) +QByteArray toText(const QJsonArray& array) { return QJsonDocument(array).toJson(QJsonDocument::Compact); } -static bool isBinaryJson(const QByteArray &data) +static bool isBinaryJson(const QByteArray& data) { decltype(QJsonDocument::BinaryFormatTag) tag = QJsonDocument::BinaryFormatTag; return memcmp(data.constData(), &tag, sizeof(QJsonDocument::BinaryFormatTag)) == 0; } -QJsonDocument requireDocument(const QByteArray &data, const QString &what) +QJsonDocument requireDocument(const QByteArray& data, const QString& what) { - if (isBinaryJson(data)) - { + if (isBinaryJson(data)) { // FIXME: Is this needed? throw JsonException(what + ": Invalid JSON. Binary JSON unsupported"); - } - else - { + } else { QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(data, &error); - if (error.error != QJsonParseError::NoError) - { + if (error.error != QJsonParseError::NoError) { throw JsonException(what + ": Error parsing JSON: " + error.errorString()); } return doc; } } -QJsonDocument requireDocument(const QString &filename, const QString &what) +QJsonDocument requireDocument(const QString& filename, const QString& what) { return requireDocument(FS::read(filename), what); } -QJsonObject requireObject(const QJsonDocument &doc, const QString &what) +QJsonObject requireObject(const QJsonDocument& doc, const QString& what) { - if (!doc.isObject()) - { + if (!doc.isObject()) { throw JsonException(what + " is not an object"); } return doc.object(); } -QJsonArray requireArray(const QJsonDocument &doc, const QString &what) +QJsonArray requireArray(const QJsonDocument& doc, const QString& what) { - if (!doc.isArray()) - { + if (!doc.isArray()) { throw JsonException(what + " is not an array"); } return doc.array(); } -void writeString(QJsonObject &to, const QString &key, const QString &value) +void writeString(QJsonObject& to, const QString& key, const QString& value) { - if (!value.isEmpty()) - { + if (!value.isEmpty()) { to.insert(key, value); } } -void writeStringList(QJsonObject &to, const QString &key, const QStringList &values) +void writeStringList(QJsonObject& to, const QString& key, const QStringList& values) { - if (!values.isEmpty()) - { + if (!values.isEmpty()) { QJsonArray array; - for(auto value: values) - { + for (auto value : values) { array.append(value); } to.insert(key, array); } } -template<> -QJsonValue toJson(const QUrl &url) +template <> +QJsonValue toJson(const QUrl& url) { return QJsonValue(url.toString(QUrl::FullyEncoded)); } -template<> -QJsonValue toJson(const QByteArray &data) +template <> +QJsonValue toJson(const QByteArray& data) { return QJsonValue(QString::fromLatin1(data.toHex())); } -template<> -QJsonValue toJson(const QDateTime &datetime) +template <> +QJsonValue toJson(const QDateTime& datetime) { return QJsonValue(datetime.toString(Qt::ISODate)); } -template<> -QJsonValue toJson(const QDir &dir) +template <> +QJsonValue toJson(const QDir& dir) { return QDir::current().relativeFilePath(dir.absolutePath()); } -template<> -QJsonValue toJson(const QUuid &uuid) +template <> +QJsonValue toJson(const QUuid& uuid) { return uuid.toString(); } -template<> -QJsonValue toJson(const QVariant &variant) +template <> +QJsonValue toJson(const QVariant& variant) { return QJsonValue::fromVariant(variant); } - -template<> QByteArray requireIsType(const QJsonValue &value, const QString &what) +template <> +QByteArray requireIsType(const QJsonValue& value, const QString& what) { const QString string = ensureIsType(value, what); // ensure that the string can be safely cast to Latin1 - if (string != QString::fromLatin1(string.toLatin1())) - { + if (string != QString::fromLatin1(string.toLatin1())) { throw JsonException(what + " is not encodable as Latin1"); } return QByteArray::fromHex(string.toLatin1()); } -template<> QJsonArray requireIsType(const QJsonValue &value, const QString &what) +template <> +QJsonArray requireIsType(const QJsonValue& value, const QString& what) { - if (!value.isArray()) - { + if (!value.isArray()) { throw JsonException(what + " is not an array"); } return value.toArray(); } - -template<> QString requireIsType(const QJsonValue &value, const QString &what) +template <> +QString requireIsType(const QJsonValue& value, const QString& what) { - if (!value.isString()) - { + if (!value.isString()) { throw JsonException(what + " is not a string"); } return value.toString(); } -template<> bool requireIsType(const QJsonValue &value, const QString &what) +template <> +bool requireIsType(const QJsonValue& value, const QString& what) { - if (!value.isBool()) - { + if (!value.isBool()) { throw JsonException(what + " is not a bool"); } return value.toBool(); } -template<> double requireIsType(const QJsonValue &value, const QString &what) +template <> +double requireIsType(const QJsonValue& value, const QString& what) { - if (!value.isDouble()) - { + if (!value.isDouble()) { throw JsonException(what + " is not a double"); } return value.toDouble(); } -template<> int requireIsType(const QJsonValue &value, const QString &what) +template <> +int requireIsType(const QJsonValue& value, const QString& what) { const double doubl = requireIsType(value, what); - if (fmod(doubl, 1) != 0) - { + if (fmod(doubl, 1) != 0) { throw JsonException(what + " is not an integer"); } return int(doubl); } -template<> QDateTime requireIsType(const QJsonValue &value, const QString &what) +template <> +QDateTime requireIsType(const QJsonValue& value, const QString& what) { const QString string = requireIsType(value, what); const QDateTime datetime = QDateTime::fromString(string, Qt::ISODate); - if (!datetime.isValid()) - { + if (!datetime.isValid()) { throw JsonException(what + " is not a ISO formatted date/time value"); } return datetime; } -template<> QUrl requireIsType(const QJsonValue &value, const QString &what) +template <> +QUrl requireIsType(const QJsonValue& value, const QString& what) { const QString string = ensureIsType(value, what); - if (string.isEmpty()) - { + if (string.isEmpty()) { return QUrl(); } const QUrl url = QUrl(string, QUrl::StrictMode); - if (!url.isValid()) - { + if (!url.isValid()) { throw JsonException(what + " is not a correctly formatted URL"); } return url; } -template<> QDir requireIsType(const QJsonValue &value, const QString &what) +template <> +QDir requireIsType(const QJsonValue& value, const QString& what) { const QString string = requireIsType(value, what); // FIXME: does not handle invalid characters! return QDir::current().absoluteFilePath(string); } -template<> QUuid requireIsType(const QJsonValue &value, const QString &what) +template <> +QUuid requireIsType(const QJsonValue& value, const QString& what) { const QString string = requireIsType(value, what); const QUuid uuid = QUuid(string); - if (uuid.toString() != string) // converts back => valid + if (uuid.toString() != string) // converts back => valid { throw JsonException(what + " is not a valid UUID"); } return uuid; } -template<> QJsonObject requireIsType(const QJsonValue &value, const QString &what) +template <> +QJsonObject requireIsType(const QJsonValue& value, const QString& what) { - if (!value.isObject()) - { + if (!value.isObject()) { throw JsonException(what + " is not an object"); } return value.toObject(); } -template<> QVariant requireIsType(const QJsonValue &value, const QString &what) +template <> +QVariant requireIsType(const QJsonValue& value, const QString& what) { - if (value.isNull() || value.isUndefined()) - { + if (value.isNull() || value.isUndefined()) { throw JsonException(what + " is null or undefined"); } return value.toVariant(); } -template<> QJsonValue requireIsType(const QJsonValue &value, const QString &what) +template <> +QJsonValue requireIsType(const QJsonValue& value, const QString& what) { - if (value.isNull() || value.isUndefined()) - { + if (value.isNull() || value.isUndefined()) { throw JsonException(what + " is null or undefined"); } return value; } -} +} // namespace Json diff --git a/launcher/Json.h b/launcher/Json.h index b11a356cc..5a8504ef9 100644 --- a/launcher/Json.h +++ b/launcher/Json.h @@ -35,74 +35,71 @@ #pragma once -#include -#include -#include #include -#include #include +#include +#include +#include +#include #include #include #include #include "Exception.h" -namespace Json -{ -class JsonException : public ::Exception -{ -public: - JsonException(const QString &message) : Exception(message) {} +namespace Json { +class JsonException : public ::Exception { + public: + JsonException(const QString& message) : Exception(message) {} }; /// @throw FileSystemException -void write(const QJsonDocument &doc, const QString &filename); +void write(const QJsonDocument& doc, const QString& filename); /// @throw FileSystemException -void write(const QJsonObject &object, const QString &filename); +void write(const QJsonObject& object, const QString& filename); /// @throw FileSystemException -void write(const QJsonArray &array, const QString &filename); +void write(const QJsonArray& array, const QString& filename); -QByteArray toText(const QJsonObject &obj); -QByteArray toText(const QJsonArray &array); +QByteArray toText(const QJsonObject& obj); +QByteArray toText(const QJsonArray& array); /// @throw JsonException -QJsonDocument requireDocument(const QByteArray &data, const QString &what = "Document"); +QJsonDocument requireDocument(const QByteArray& data, const QString& what = "Document"); /// @throw JsonException -QJsonDocument requireDocument(const QString &filename, const QString &what = "Document"); +QJsonDocument requireDocument(const QString& filename, const QString& what = "Document"); /// @throw JsonException -QJsonObject requireObject(const QJsonDocument &doc, const QString &what = "Document"); +QJsonObject requireObject(const QJsonDocument& doc, const QString& what = "Document"); /// @throw JsonException -QJsonArray requireArray(const QJsonDocument &doc, const QString &what = "Document"); +QJsonArray requireArray(const QJsonDocument& doc, const QString& what = "Document"); /////////////////// WRITING //////////////////// -void writeString(QJsonObject & to, const QString &key, const QString &value); -void writeStringList(QJsonObject & to, const QString &key, const QStringList &values); +void writeString(QJsonObject& to, const QString& key, const QString& value); +void writeStringList(QJsonObject& to, const QString& key, const QStringList& values); -template -QJsonValue toJson(const T &t) +template +QJsonValue toJson(const T& t) { return QJsonValue(t); } -template<> -QJsonValue toJson(const QUrl &url); -template<> -QJsonValue toJson(const QByteArray &data); -template<> -QJsonValue toJson(const QDateTime &datetime); -template<> -QJsonValue toJson(const QDir &dir); -template<> -QJsonValue toJson(const QUuid &uuid); -template<> -QJsonValue toJson(const QVariant &variant); +template <> +QJsonValue toJson(const QUrl& url); +template <> +QJsonValue toJson(const QByteArray& data); +template <> +QJsonValue toJson(const QDateTime& datetime); +template <> +QJsonValue toJson(const QDir& dir); +template <> +QJsonValue toJson(const QUuid& uuid); +template <> +QJsonValue toJson(const QVariant& variant); -template -QJsonArray toJsonArray(const QList &container) +template +QJsonArray toJsonArray(const QList& container) { QJsonArray array; - for (const T item : container) - { + for (const T item : container) { array.append(toJson(item)); } return array; @@ -112,106 +109,110 @@ QJsonArray toJsonArray(const QList &container) /// @throw JsonException template -T requireIsType(const QJsonValue &value, const QString &what = "Value"); +T requireIsType(const QJsonValue& value, const QString& what = "Value"); /// @throw JsonException -template<> double requireIsType(const QJsonValue &value, const QString &what); +template <> +double requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> bool requireIsType(const QJsonValue &value, const QString &what); +template <> +bool requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> int requireIsType(const QJsonValue &value, const QString &what); +template <> +int requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QJsonObject requireIsType(const QJsonValue &value, const QString &what); +template <> +QJsonObject requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QJsonArray requireIsType(const QJsonValue &value, const QString &what); +template <> +QJsonArray requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QJsonValue requireIsType(const QJsonValue &value, const QString &what); +template <> +QJsonValue requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QByteArray requireIsType(const QJsonValue &value, const QString &what); +template <> +QByteArray requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QDateTime requireIsType(const QJsonValue &value, const QString &what); +template <> +QDateTime requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QVariant requireIsType(const QJsonValue &value, const QString &what); +template <> +QVariant requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QString requireIsType(const QJsonValue &value, const QString &what); +template <> +QString requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QUuid requireIsType(const QJsonValue &value, const QString &what); +template <> +QUuid requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QDir requireIsType(const QJsonValue &value, const QString &what); +template <> +QDir requireIsType(const QJsonValue& value, const QString& what); /// @throw JsonException -template<> QUrl requireIsType(const QJsonValue &value, const QString &what); +template <> +QUrl requireIsType(const QJsonValue& value, const QString& what); // the following functions are higher level functions, that make use of the above functions for // type conversion template -T ensureIsType(const QJsonValue &value, const T default_ = T(), const QString &what = "Value") +T ensureIsType(const QJsonValue& value, const T default_ = T(), const QString& what = "Value") { - if (value.isUndefined() || value.isNull()) - { + if (value.isUndefined() || value.isNull()) { return default_; } - try - { + try { return requireIsType(value, what); - } - catch (const JsonException &) - { + } catch (const JsonException&) { return default_; } } /// @throw JsonException template -T requireIsType(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__") +T requireIsType(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__") { const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); - if (!parent.contains(key)) - { + if (!parent.contains(key)) { throw JsonException(localWhat + "s parent does not contain " + localWhat); } return requireIsType(parent.value(key), localWhat); } template -T ensureIsType(const QJsonObject &parent, const QString &key, const T default_ = T(), const QString &what = "__placeholder__") +T ensureIsType(const QJsonObject& parent, const QString& key, const T default_ = T(), const QString& what = "__placeholder__") { const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); - if (!parent.contains(key)) - { + if (!parent.contains(key)) { return default_; } return ensureIsType(parent.value(key), default_, localWhat); } template -QVector requireIsArrayOf(const QJsonDocument &doc) +QVector requireIsArrayOf(const QJsonDocument& doc) { const QJsonArray array = requireArray(doc); QVector out; - for (const QJsonValue val : array) - { + for (const QJsonValue val : array) { out.append(requireIsType(val, "Document")); } return out; } template -QVector ensureIsArrayOf(const QJsonValue &value, const QString &what = "Value") +QVector ensureIsArrayOf(const QJsonValue& value, const QString& what = "Value") { const QJsonArray array = ensureIsType(value, QJsonArray(), what); QVector out; - for (const QJsonValue val : array) - { + for (const QJsonValue val : array) { out.append(requireIsType(val, what)); } return out; } template -QVector ensureIsArrayOf(const QJsonValue &value, const QVector default_, const QString &what = "Value") +QVector ensureIsArrayOf(const QJsonValue& value, const QVector default_, const QString& what = "Value") { - if (value.isUndefined()) - { + if (value.isUndefined()) { return default_; } return ensureIsArrayOf(value, what); @@ -219,45 +220,46 @@ QVector ensureIsArrayOf(const QJsonValue &value, const QVector default_, c /// @throw JsonException template -QVector requireIsArrayOf(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__") +QVector requireIsArrayOf(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__") { const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); - if (!parent.contains(key)) - { + if (!parent.contains(key)) { throw JsonException(localWhat + "s parent does not contain " + localWhat); } return ensureIsArrayOf(parent.value(key), localWhat); } template -QVector ensureIsArrayOf(const QJsonObject &parent, const QString &key, - const QVector &default_ = QVector(), const QString &what = "__placeholder__") +QVector ensureIsArrayOf(const QJsonObject& parent, + const QString& key, + const QVector& default_ = QVector(), + const QString& what = "__placeholder__") { const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\''); - if (!parent.contains(key)) - { + if (!parent.contains(key)) { return default_; } return ensureIsArrayOf(parent.value(key), default_, localWhat); } // this macro part could be replaced by variadic functions that just pass on their arguments, but that wouldn't work well with IDE helpers -#define JSON_HELPERFUNCTIONS(NAME, TYPE) \ - inline TYPE require##NAME(const QJsonValue &value, const QString &what = "Value") \ - { \ - return requireIsType(value, what); \ - } \ - inline TYPE ensure##NAME(const QJsonValue &value, const TYPE default_ = TYPE(), const QString &what = "Value") \ - { \ - return ensureIsType(value, default_, what); \ - } \ - inline TYPE require##NAME(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__") \ - { \ - return requireIsType(parent, key, what); \ - } \ - inline TYPE ensure##NAME(const QJsonObject &parent, const QString &key, const TYPE default_ = TYPE(), const QString &what = "__placeholder") \ - { \ - return ensureIsType(parent, key, default_, what); \ +#define JSON_HELPERFUNCTIONS(NAME, TYPE) \ + inline TYPE require##NAME(const QJsonValue& value, const QString& what = "Value") \ + { \ + return requireIsType(value, what); \ + } \ + inline TYPE ensure##NAME(const QJsonValue& value, const TYPE default_ = TYPE(), const QString& what = "Value") \ + { \ + return ensureIsType(value, default_, what); \ + } \ + inline TYPE require##NAME(const QJsonObject& parent, const QString& key, const QString& what = "__placeholder__") \ + { \ + return requireIsType(parent, key, what); \ + } \ + inline TYPE ensure##NAME(const QJsonObject& parent, const QString& key, const TYPE default_ = TYPE(), \ + const QString& what = "__placeholder") \ + { \ + return ensureIsType(parent, key, default_, what); \ } JSON_HELPERFUNCTIONS(Array, QJsonArray) @@ -276,5 +278,5 @@ JSON_HELPERFUNCTIONS(Variant, QVariant) #undef JSON_HELPERFUNCTIONS -} +} // namespace Json using JSONValidationError = Json::JsonException; diff --git a/launcher/KonamiCode.cpp b/launcher/KonamiCode.cpp index 46a2a0b2e..f9ec3b89d 100644 --- a/launcher/KonamiCode.cpp +++ b/launcher/KonamiCode.cpp @@ -1,42 +1,26 @@ #include "KonamiCode.h" -#include #include +#include namespace { -const std::array konamiCode = -{ - { - Qt::Key_Up, Qt::Key_Up, - Qt::Key_Down, Qt::Key_Down, - Qt::Key_Left, Qt::Key_Right, - Qt::Key_Left, Qt::Key_Right, - Qt::Key_B, Qt::Key_A - } -}; -} - -KonamiCode::KonamiCode(QObject* parent) : QObject(parent) -{ +const std::array konamiCode = { { Qt::Key_Up, Qt::Key_Up, Qt::Key_Down, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, + Qt::Key_Left, Qt::Key_Right, Qt::Key_B, Qt::Key_A } }; } +KonamiCode::KonamiCode(QObject* parent) : QObject(parent) {} void KonamiCode::input(QEvent* event) { - if( event->type() == QEvent::KeyPress ) - { - QKeyEvent *keyEvent = static_cast( event ); + if (event->type() == QEvent::KeyPress) { + QKeyEvent* keyEvent = static_cast(event); auto key = Qt::Key(keyEvent->key()); - if(key == konamiCode[m_progress]) - { - m_progress ++; - } - else - { + if (key == konamiCode[m_progress]) { + m_progress++; + } else { m_progress = 0; } - if(m_progress == static_cast(konamiCode.size())) - { + if (m_progress == static_cast(konamiCode.size())) { m_progress = 0; emit triggered(); } diff --git a/launcher/KonamiCode.h b/launcher/KonamiCode.h index 3d320ae7f..5c21e2ff3 100644 --- a/launcher/KonamiCode.h +++ b/launcher/KonamiCode.h @@ -2,16 +2,15 @@ #include -class KonamiCode : public QObject -{ +class KonamiCode : public QObject { Q_OBJECT -public: - KonamiCode(QObject *parent = 0); - void input(QEvent *event); + public: + KonamiCode(QObject* parent = 0); + void input(QEvent* event); -signals: + signals: void triggered(); -private: + private: int m_progress = 0; }; diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 2b52cac0b..720f8b91b 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -34,44 +34,41 @@ */ #include "LaunchController.h" -#include "minecraft/auth/AccountList.h" #include "Application.h" +#include "minecraft/auth/AccountList.h" -#include "ui/MainWindow.h" #include "ui/InstanceWindow.h" +#include "ui/MainWindow.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/dialogs/ProfileSelectDialog.h" -#include "ui/dialogs/ProgressDialog.h" #include "ui/dialogs/EditAccountDialog.h" +#include "ui/dialogs/ProfileSelectDialog.h" #include "ui/dialogs/ProfileSetupDialog.h" +#include "ui/dialogs/ProgressDialog.h" -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include #include "BuildConfig.h" #include "JavaCommon.h" -#include "tasks/Task.h" -#include "minecraft/auth/AccountTask.h" #include "launch/steps/TextPrint.h" +#include "minecraft/auth/AccountTask.h" +#include "tasks/Task.h" -LaunchController::LaunchController(QObject *parent) : Task(parent) -{ -} +LaunchController::LaunchController(QObject* parent) : Task(parent) {} void LaunchController::executeTask() { - if (!m_instance) - { + if (!m_instance) { emitFailed(tr("No instance specified!")); return; } - if(!JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget)) { + if (!JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget)) { emitFailed(tr("Invalid Java arguments specified. Please fix this first.")); return; } @@ -81,32 +78,25 @@ void LaunchController::executeTask() void LaunchController::decideAccount() { - if(m_accountToUse) { + if (m_accountToUse) { return; } // Find an account to use. auto accounts = APPLICATION->accounts(); - if (accounts->count() <= 0) - { + if (accounts->count() <= 0) { // Tell the user they need to log in at least one account in order to play. - auto reply = CustomMessageBox::selectable( - m_parentWidget, - tr("No Accounts"), - tr("In order to play Minecraft, you must have at least one Microsoft or Mojang " - "account logged in. Mojang accounts can only be used offline. " - "Would you like to open the account manager to add an account now?"), - QMessageBox::Information, - QMessageBox::Yes | QMessageBox::No - )->exec(); + auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"), + tr("In order to play Minecraft, you must have at least one Microsoft or Mojang " + "account logged in. Mojang accounts can only be used offline. " + "Would you like to open the account manager to add an account now?"), + QMessageBox::Information, QMessageBox::Yes | QMessageBox::No) + ->exec(); - if (reply == QMessageBox::Yes) - { + if (reply == QMessageBox::Yes) { // Open the account manager. APPLICATION->ShowGlobalSettings(m_parentWidget, "accounts"); - } - else if (reply == QMessageBox::No) - { + } else if (reply == QMessageBox::No) { // Do not open "profile select" dialog. return; } @@ -121,14 +111,10 @@ void LaunchController::decideAccount() m_accountToUse = accounts->at(instanceAccountIndex); } - if (!m_accountToUse) - { + if (!m_accountToUse) { // If no default account is set, ask the user which one to use. - ProfileSelectDialog selectDialog( - tr("Which account would you like to use?"), - ProfileSelectDialog::GlobalDefaultCheckbox, - m_parentWidget - ); + ProfileSelectDialog selectDialog(tr("Which account would you like to use?"), ProfileSelectDialog::GlobalDefaultCheckbox, + m_parentWidget); selectDialog.exec(); @@ -142,13 +128,12 @@ void LaunchController::decideAccount() } } - -void LaunchController::login() { +void LaunchController::login() +{ decideAccount(); // if no account is selected, we bail - if (!m_accountToUse) - { + if (!m_accountToUse) { emitFailed(tr("No account selected for launch.")); return; } @@ -157,15 +142,11 @@ void LaunchController::login() { bool tryagain = true; unsigned int tries = 0; - while (tryagain) - { + while (tryagain) { if (tries > 0 && tries % 3 == 0) { - auto result = QMessageBox::question( - m_parentWidget, - tr("Continue launch?"), - tr("It looks like we couldn't launch after %1 tries. Do you want to continue trying?") - .arg(tries) - ); + auto result = + QMessageBox::question(m_parentWidget, tr("Continue launch?"), + tr("It looks like we couldn't launch after %1 tries. Do you want to continue trying?").arg(tries)); if (result == QMessageBox::No) { emitAborted(); @@ -179,60 +160,48 @@ void LaunchController::login() { m_accountToUse->fillSession(m_session); // Launch immediately in true offline mode - if(m_accountToUse->isOffline()) { + if (m_accountToUse->isOffline()) { launchInstance(); return; } - switch(m_accountToUse->accountState()) { + switch (m_accountToUse->accountState()) { case AccountState::Offline: { m_session->wants_online = false; } /* fallthrough */ case AccountState::Online: { - if(!m_session->wants_online) { + if (!m_session->wants_online) { // we ask the user for a player name bool ok = false; QString message = tr("Choose your offline mode player name."); - if(m_session->demo) { + if (m_session->demo) { message = tr("Choose your demo mode player name."); } QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString(); QString usedname = lastOfflinePlayerName.isEmpty() ? m_session->player_name : lastOfflinePlayerName; - QString name = QInputDialog::getText( - m_parentWidget, - tr("Player name"), - message, - QLineEdit::Normal, - usedname, - &ok - ); - if (!ok) - { + QString name = QInputDialog::getText(m_parentWidget, tr("Player name"), message, QLineEdit::Normal, usedname, &ok); + if (!ok) { tryagain = false; break; } - if (name.length()) - { + if (name.length()) { usedname = name; APPLICATION->settings()->set("LastOfflinePlayerName", usedname); } m_session->MakeOffline(usedname); // offline flavored game from here :3 } - if(m_accountToUse->ownsMinecraft()) { - if(!m_accountToUse->hasProfile()) { + if (m_accountToUse->ownsMinecraft()) { + if (!m_accountToUse->hasProfile()) { // Now handle setting up a profile name here... ProfileSetupDialog dialog(m_accountToUse, m_parentWidget); - if (dialog.exec() == QDialog::Accepted) - { + if (dialog.exec() == QDialog::Accepted) { tryagain = true; continue; - } - else - { + } else { emitFailed(tr("Received undetermined session status during login.")); return; } @@ -240,24 +209,24 @@ void LaunchController::login() { // we own Minecraft, there is a profile, it's all ready to go! launchInstance(); return; - } - else { + } else { // play demo ? QMessageBox box(m_parentWidget); box.setWindowTitle(tr("Play demo?")); - box.setText(tr("This account does not own Minecraft.\nYou need to purchase the game first to play it.\n\nDo you want to play the demo?")); + box.setText( + tr("This account does not own Minecraft.\nYou need to purchase the game first to play it.\n\nDo you want to play " + "the demo?")); box.setIcon(QMessageBox::Warning); auto demoButton = box.addButton(tr("Play Demo"), QMessageBox::ButtonRole::YesRole); auto cancelButton = box.addButton(tr("Cancel"), QMessageBox::ButtonRole::NoRole); box.setDefaultButton(cancelButton); box.exec(); - if(box.clickedButton() == demoButton) { + if (box.clickedButton() == demoButton) { // play demo here m_session->MakeDemo(); launchInstance(); - } - else { + } else { emitFailed(tr("Launch cancelled - account does not own Minecraft.")); } } @@ -272,8 +241,7 @@ void LaunchController::login() { case AccountState::Working: { // refresh is in progress, we need to wait for it to finish to proceed. ProgressDialog progDialog(m_parentWidget); - if (m_online) - { + if (m_online) { progDialog.setSkipButton(true, tr("Play Offline")); } auto task = m_accountToUse->currentTask(); @@ -288,37 +256,24 @@ void LaunchController::login() { */ case AccountState::Expired: { auto errorString = tr("The account has expired and needs to be logged into manually again."); - QMessageBox::warning( - m_parentWidget, - tr("Account refresh failed"), - errorString, - QMessageBox::StandardButton::Ok, - QMessageBox::StandardButton::Ok - ); + QMessageBox::warning(m_parentWidget, tr("Account refresh failed"), errorString, QMessageBox::StandardButton::Ok, + QMessageBox::StandardButton::Ok); emitFailed(errorString); return; } case AccountState::Disabled: { auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again."); - QMessageBox::warning( - m_parentWidget, - tr("Client identification changed"), - errorString, - QMessageBox::StandardButton::Ok, - QMessageBox::StandardButton::Ok - ); + QMessageBox::warning(m_parentWidget, tr("Client identification changed"), errorString, QMessageBox::StandardButton::Ok, + QMessageBox::StandardButton::Ok); emitFailed(errorString); return; } case AccountState::Gone: { - auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to."); - QMessageBox::warning( - m_parentWidget, - tr("Account gone"), - errorString, - QMessageBox::StandardButton::Ok, - QMessageBox::StandardButton::Ok - ); + auto errorString = + tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account " + "you migrated this one to."); + QMessageBox::warning(m_parentWidget, tr("Account gone"), errorString, QMessageBox::StandardButton::Ok, + QMessageBox::StandardButton::Ok); emitFailed(errorString); return; } @@ -332,48 +287,45 @@ void LaunchController::launchInstance() Q_ASSERT_X(m_instance != NULL, "launchInstance", "instance is NULL"); Q_ASSERT_X(m_session.get() != nullptr, "launchInstance", "session is NULL"); - if(!m_instance->reloadSettings()) - { + if (!m_instance->reloadSettings()) { QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't load the instance profile.")); emitFailed(tr("Couldn't load the instance profile.")); return; } m_launcher = m_instance->createLaunchTask(m_session, m_serverToJoin); - if (!m_launcher) - { + if (!m_launcher) { emitFailed(tr("Couldn't instantiate a launcher.")); return; } - auto console = qobject_cast(m_parentWidget); + auto console = qobject_cast(m_parentWidget); auto showConsole = m_instance->settings()->get("ShowConsole").toBool(); - if(!console && showConsole) - { + if (!console && showConsole) { APPLICATION->showInstanceWindow(m_instance); } connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch); connect(m_launcher.get(), &LaunchTask::succeeded, this, &LaunchController::onSucceeded); - connect(m_launcher.get(), &LaunchTask::failed, this, &LaunchController::onFailed); + connect(m_launcher.get(), &LaunchTask::failed, this, &LaunchController::onFailed); connect(m_launcher.get(), &LaunchTask::requestProgress, this, &LaunchController::onProgressRequested); // Prepend Online and Auth Status QString online_mode; - if(m_session->wants_online) { + if (m_session->wants_online) { online_mode = "online"; // Prepend Server Status - QStringList servers = {"authserver.mojang.com", "session.minecraft.net", "textures.minecraft.net", "api.mojang.com"}; + QStringList servers = { "authserver.mojang.com", "session.minecraft.net", "textures.minecraft.net", "api.mojang.com" }; QString resolved_servers = ""; QHostInfo host_info; - for(QString server : servers) { + for (QString server : servers) { host_info = QHostInfo::fromName(server); resolved_servers = resolved_servers + server + " resolves to:\n ["; - if(!host_info.addresses().isEmpty()) { - for(QHostAddress address : host_info.addresses()) { + if (!host_info.addresses().isEmpty()) { + for (QHostAddress address : host_info.addresses()) { resolved_servers = resolved_servers + address.toString(); - if(!host_info.addresses().endsWith(address)) { + if (!host_info.addresses().endsWith(address)) { resolved_servers = resolved_servers + ", "; } } @@ -387,11 +339,13 @@ void LaunchController::launchInstance() online_mode = m_demo ? "demo" : "offline"; } - m_launcher->prependStep(makeShared(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher)); + m_launcher->prependStep( + makeShared(m_launcher.get(), "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher)); // Prepend Version { - auto versionString = QString("%1 version: %2 (%3)").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString(), BuildConfig.BUILD_PLATFORM); + auto versionString = QString("%1 version: %2 (%3)") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString(), BuildConfig.BUILD_PLATFORM); m_launcher->prependStep(makeShared(m_launcher.get(), versionString + "\n\n", MessageLevel::Launcher)); } m_launcher->start(); @@ -399,28 +353,26 @@ void LaunchController::launchInstance() void LaunchController::readyForLaunch() { - if (!m_profiler) - { + if (!m_profiler) { m_launcher->proceed(); return; } QString error; - if (!m_profiler->check(&error)) - { + if (!m_profiler->check(&error)) { m_launcher->abort(); QMessageBox::critical(m_parentWidget, tr("Error!"), tr("Couldn't start profiler: %1").arg(error)); emitFailed("Profiler startup failed!"); return; } - BaseProfiler *profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this); + BaseProfiler* profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this); - connect(profilerInstance, &BaseProfiler::readyToLaunch, [this](const QString & message) - { + connect(profilerInstance, &BaseProfiler::readyToLaunch, [this](const QString& message) { QMessageBox msg; msg.setText(tr("The game launch is delayed until you press the " - "button. This is the right time to setup the profiler, as the " - "profiler server is running now.\n\n%1").arg(message)); + "button. This is the right time to setup the profiler, as the " + "profiler server is running now.\n\n%1") + .arg(message)); msg.setWindowTitle(tr("Waiting.")); msg.setIcon(QMessageBox::Information); msg.addButton(tr("Launch"), QMessageBox::AcceptRole); @@ -428,8 +380,7 @@ void LaunchController::readyForLaunch() msg.exec(); m_launcher->proceed(); }); - connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString & message) - { + connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString& message) { QMessageBox msg; msg.setText(tr("Couldn't start the profiler: %1").arg(message)); msg.setWindowTitle(tr("Error")); @@ -450,8 +401,7 @@ void LaunchController::onSucceeded() void LaunchController::onFailed(QString reason) { - if(m_instance->settings()->get("ShowConsoleOnError").toBool()) - { + if (m_instance->settings()->get("ShowConsoleOnError").toBool()) { APPLICATION->showInstanceWindow(m_instance, "console"); } emitFailed(reason); @@ -467,21 +417,18 @@ void LaunchController::onProgressRequested(Task* task) bool LaunchController::abort() { - if(!m_launcher) - { + if (!m_launcher) { return true; } - if(!m_launcher->canAbort()) - { + if (!m_launcher->canAbort()) { return false; } - auto response = CustomMessageBox::selectable( - m_parentWidget, tr("Kill Minecraft?"), - tr("This can cause the instance to get corrupted and should only be used if Minecraft " - "is frozen for some reason"), - QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec(); - if (response == QMessageBox::Yes) - { + auto response = CustomMessageBox::selectable(m_parentWidget, tr("Kill Minecraft?"), + tr("This can cause the instance to get corrupted and should only be used if Minecraft " + "is frozen for some reason"), + QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) + ->exec(); + if (response == QMessageBox::Yes) { return m_launcher->abort(); } return false; diff --git a/launcher/LaunchController.h b/launcher/LaunchController.h index af6c98d18..b4138a062 100644 --- a/launcher/LaunchController.h +++ b/launcher/LaunchController.h @@ -34,81 +34,61 @@ */ #pragma once -#include #include #include +#include -#include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/auth/MinecraftAccount.h" +#include "minecraft/launch/MinecraftServerTarget.h" class InstanceWindow; -class LaunchController: public Task -{ +class LaunchController : public Task { Q_OBJECT -public: + public: void executeTask() override; - LaunchController(QObject * parent = nullptr); + LaunchController(QObject* parent = nullptr); virtual ~LaunchController(){}; - void setInstance(InstancePtr instance) { - m_instance = instance; - } + void setInstance(InstancePtr instance) { m_instance = instance; } - InstancePtr instance() { - return m_instance; - } + InstancePtr instance() { return m_instance; } - void setOnline(bool online) { - m_online = online; - } + void setOnline(bool online) { m_online = online; } - void setDemo(bool demo) { - m_demo = demo; - } + void setDemo(bool demo) { m_demo = demo; } - void setProfiler(BaseProfilerFactory *profiler) { - m_profiler = profiler; - } + void setProfiler(BaseProfilerFactory* profiler) { m_profiler = profiler; } - void setParentWidget(QWidget * widget) { - m_parentWidget = widget; - } + void setParentWidget(QWidget* widget) { m_parentWidget = widget; } - void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { - m_serverToJoin = std::move(serverToJoin); - } + void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { m_serverToJoin = std::move(serverToJoin); } - void setAccountToUse(MinecraftAccountPtr accountToUse) { - m_accountToUse = std::move(accountToUse); - } + void setAccountToUse(MinecraftAccountPtr accountToUse) { m_accountToUse = std::move(accountToUse); } - QString id() - { - return m_instance->id(); - } + QString id() { return m_instance->id(); } bool abort() override; -private: + private: void login(); void launchInstance(); void decideAccount(); -private slots: + private slots: void readyForLaunch(); void onSucceeded(); void onFailed(QString reason); - void onProgressRequested(Task *task); + void onProgressRequested(Task* task); -private: - BaseProfilerFactory *m_profiler = nullptr; + private: + BaseProfilerFactory* m_profiler = nullptr; bool m_online = true; bool m_demo = false; InstancePtr m_instance; - QWidget * m_parentWidget = nullptr; - InstanceWindow *m_console = nullptr; + QWidget* m_parentWidget = nullptr; + InstanceWindow* m_console = nullptr; MinecraftAccountPtr m_accountToUse = nullptr; AuthSessionPtr m_session; shared_qobject_ptr m_launcher; diff --git a/launcher/LoggedProcess.cpp b/launcher/LoggedProcess.cpp index d70f6d005..6978777e1 100644 --- a/launcher/LoggedProcess.cpp +++ b/launcher/LoggedProcess.cpp @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022,2023 Sefa Eyeoglu - * Copyright (c) 2023 flowln + * Copyright (c) 2023 flowln * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ #include #include "MessageLevel.h" -LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent) +LoggedProcess::LoggedProcess(QObject* parent) : QProcess(parent) { // QProcess has a strange interface... let's map a lot of those into a few. connect(this, &QProcess::readyReadStandardOutput, this, &LoggedProcess::on_stdOut); @@ -51,8 +51,7 @@ LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent) LoggedProcess::~LoggedProcess() { - if(m_is_detachable) - { + if (m_is_detachable) { setProcessState(QProcess::NotRunning); } } @@ -95,39 +94,31 @@ void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status) m_exit_code = exit_code; // based on state, send signals - if (!m_is_aborting) - { - if (status == QProcess::NormalExit) - { + if (!m_is_aborting) { + if (status == QProcess::NormalExit) { //: Message displayed on instance exit - emit log({tr("Process exited with code %1.").arg(exit_code)}, MessageLevel::Launcher); + emit log({ tr("Process exited with code %1.").arg(exit_code) }, MessageLevel::Launcher); changeState(LoggedProcess::Finished); - } - else - { + } else { //: Message displayed on instance crashed - if(exit_code == -1) - emit log({tr("Process crashed.")}, MessageLevel::Launcher); + if (exit_code == -1) + emit log({ tr("Process crashed.") }, MessageLevel::Launcher); else - emit log({tr("Process crashed with exitcode %1.").arg(exit_code)}, MessageLevel::Launcher); + emit log({ tr("Process crashed with exitcode %1.").arg(exit_code) }, MessageLevel::Launcher); changeState(LoggedProcess::Crashed); } - } - else - { + } else { //: Message displayed after the instance exits due to kill request - emit log({tr("Process was killed by user.")}, MessageLevel::Error); + emit log({ tr("Process was killed by user.") }, MessageLevel::Error); changeState(LoggedProcess::Aborted); } } void LoggedProcess::on_error(QProcess::ProcessError error) { - switch(error) - { - case QProcess::FailedToStart: - { - emit log({tr("The process failed to start.")}, MessageLevel::Fatal); + switch (error) { + case QProcess::FailedToStart: { + emit log({ tr("The process failed to start.") }, MessageLevel::Fatal); changeState(LoggedProcess::FailedToStart); break; } @@ -154,7 +145,7 @@ int LoggedProcess::exitCode() const void LoggedProcess::changeState(LoggedProcess::State state) { - if(state == m_state) + if (state == m_state) return; m_state = state; emit stateChanged(m_state); @@ -167,24 +158,19 @@ LoggedProcess::State LoggedProcess::state() const void LoggedProcess::on_stateChange(QProcess::ProcessState state) { - switch(state) - { + switch (state) { case QProcess::NotRunning: - break; // let's not - there are too many that handle this already. - case QProcess::Starting: - { - if(m_state != LoggedProcess::NotRunning) - { - qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Starting; + break; // let's not - there are too many that handle this already. + case QProcess::Starting: { + if (m_state != LoggedProcess::NotRunning) { + qWarning() << "Wrong state change for process from state" << m_state << "to" << (int)LoggedProcess::Starting; } changeState(LoggedProcess::Starting); return; } - case QProcess::Running: - { - if(m_state != LoggedProcess::Starting) - { - qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Running; + case QProcess::Running: { + if (m_state != LoggedProcess::Starting) { + qWarning() << "Wrong state change for process from state" << m_state << "to" << (int)LoggedProcess::Running; } changeState(LoggedProcess::Running); return; diff --git a/launcher/LoggedProcess.h b/launcher/LoggedProcess.h index af3ed79f4..46bdaa830 100644 --- a/launcher/LoggedProcess.h +++ b/launcher/LoggedProcess.h @@ -43,22 +43,12 @@ * This is a basic process. * It has line-based logging support and hides some of the nasty bits. */ -class LoggedProcess : public QProcess -{ -Q_OBJECT -public: - enum State - { - NotRunning, - Starting, - FailedToStart, - Running, - Finished, - Crashed, - Aborted - }; +class LoggedProcess : public QProcess { + Q_OBJECT + public: + enum State { NotRunning, Starting, FailedToStart, Running, Finished, Crashed, Aborted }; -public: + public: explicit LoggedProcess(QObject* parent = 0); virtual ~LoggedProcess(); @@ -67,30 +57,29 @@ public: void setDetachable(bool detachable); -signals: + signals: void log(QStringList lines, MessageLevel::Enum level); void stateChanged(LoggedProcess::State state); -public slots: + public slots: /** * @brief kill the process - equivalent to kill -9 */ void kill(); - -private slots: + private slots: void on_stdErr(); void on_stdOut(); void on_exit(int exit_code, QProcess::ExitStatus status); void on_error(QProcess::ProcessError error); void on_stateChange(QProcess::ProcessState); -private: + private: void changeState(LoggedProcess::State state); QStringList reprocess(const QByteArray& data, QTextDecoder& decoder); -private: + private: QTextDecoder m_err_decoder = QTextDecoder(QTextCodec::codecForLocale()); QTextDecoder m_out_decoder = QTextDecoder(QTextCodec::codecForLocale()); QString m_leftover_line; diff --git a/launcher/MMCTime.cpp b/launcher/MMCTime.cpp index 1702ec066..3972dbd53 100644 --- a/launcher/MMCTime.cpp +++ b/launcher/MMCTime.cpp @@ -17,30 +17,29 @@ #include -#include #include +#include #include -QString Time::prettifyDuration(int64_t duration) { - int seconds = (int) (duration % 60); +QString Time::prettifyDuration(int64_t duration) +{ + int seconds = (int)(duration % 60); duration /= 60; - int minutes = (int) (duration % 60); + int minutes = (int)(duration % 60); duration /= 60; - int hours = (int) (duration % 24); - int days = (int) (duration / 24); - if((hours == 0)&&(days == 0)) - { + int hours = (int)(duration % 24); + int days = (int)(duration / 24); + if ((hours == 0) && (days == 0)) { return QObject::tr("%1min %2s").arg(minutes).arg(seconds); } - if (days == 0) - { + if (days == 0) { return QObject::tr("%1h %2min").arg(hours).arg(minutes); } return QObject::tr("%1d %2h %3min").arg(days).arg(hours).arg(minutes); } -QString Time::humanReadableDuration(double duration, int precision) { - +QString Time::humanReadableDuration(double duration, int precision) +{ using days = std::chrono::duration>; QString outStr; @@ -48,10 +47,10 @@ QString Time::humanReadableDuration(double duration, int precision) { bool neg = false; if (duration < 0) { - neg = true; // flag - duration *= -1; // invert + neg = true; // flag + duration *= -1; // invert } - + auto std_duration = std::chrono::duration(duration); auto d = std::chrono::duration_cast(std_duration); std_duration -= d; @@ -78,22 +77,22 @@ QString Time::humanReadableDuration(double duration, int precision) { if (hc) { if (dc) os << " "; - os << qSetFieldWidth(2) << hc << QObject::tr("h"); // hours + os << qSetFieldWidth(2) << hc << QObject::tr("h"); // hours } if (mc) { if (dc || hc) os << " "; - os << qSetFieldWidth(2) << mc << QObject::tr("m"); // minutes + os << qSetFieldWidth(2) << mc << QObject::tr("m"); // minutes } if (dc || hc || mc || sc) { if (dc || hc || mc) os << " "; - os << qSetFieldWidth(2) << sc << QObject::tr("s"); // seconds + os << qSetFieldWidth(2) << sc << QObject::tr("s"); // seconds } if ((msc && (precision > 0)) || !(dc || hc || mc || sc)) { if (dc || hc || mc || sc) os << " "; - os << qSetFieldWidth(0) << qSetRealNumberPrecision(precision) << msc << QObject::tr("ms"); // miliseconds + os << qSetFieldWidth(0) << qSetRealNumberPrecision(precision) << msc << QObject::tr("ms"); // miliseconds } os.flush(); diff --git a/launcher/MMCTime.h b/launcher/MMCTime.h index 6a5780b44..b7d34b5d8 100644 --- a/launcher/MMCTime.h +++ b/launcher/MMCTime.h @@ -25,10 +25,10 @@ QString prettifyDuration(int64_t duration); /** * @brief Returns a string with short form time duration ie. `2days 1h3m4s56.0ms`. * miliseconds are only included if `precision` is greater than 0. - * + * * @param duration a number of seconds as floating point * @param precision number of decmial points to display on fractons of a second, defualts to 0. - * @return QString + * @return QString */ QString humanReadableDuration(double duration, int precision = 0); -} +} // namespace Time diff --git a/launcher/MTPixmapCache.h b/launcher/MTPixmapCache.h index 65cbe032a..1a3e52160 100644 --- a/launcher/MTPixmapCache.h +++ b/launcher/MTPixmapCache.h @@ -1,10 +1,10 @@ #pragma once #include +#include #include #include #include -#include #define GET_TYPE() \ Qt::ConnectionType type; \ @@ -94,8 +94,8 @@ class PixmapCache final : public QObject { return true; } - /** - * Mark that a cache miss occurred because of a eviction if too many of these occur too fast the cache size is increased + /** + * Mark that a cache miss occurred because of a eviction if too many of these occur too fast the cache size is increased * @return if the cache size was increased */ bool _markCacheMissByEviciton() diff --git a/launcher/MangoHud.cpp b/launcher/MangoHud.cpp index 90e48e298..5758da3aa 100644 --- a/launcher/MangoHud.cpp +++ b/launcher/MangoHud.cpp @@ -16,15 +16,15 @@ * along with this program. If not, see . */ -#include #include #include +#include #include #include -#include "MangoHud.h" #include "FileSystem.h" #include "Json.h" +#include "MangoHud.h" namespace MangoHud { diff --git a/launcher/Markdown.h b/launcher/Markdown.h index 6b261e60c..f91a016bd 100644 --- a/launcher/Markdown.h +++ b/launcher/Markdown.h @@ -18,7 +18,7 @@ #pragma once -#include #include +#include QString markdownToHTML(const QString& markdown); \ No newline at end of file diff --git a/launcher/MessageLevel.cpp b/launcher/MessageLevel.cpp index 135ef4632..116e70c4b 100644 --- a/launcher/MessageLevel.cpp +++ b/launcher/MessageLevel.cpp @@ -22,12 +22,11 @@ MessageLevel::Enum MessageLevel::getLevel(const QString& levelName) return MessageLevel::Unknown; } -MessageLevel::Enum MessageLevel::fromLine(QString &line) +MessageLevel::Enum MessageLevel::fromLine(QString& line) { // Level prefix int endmark = line.indexOf("]!"); - if (line.startsWith("!![") && endmark != -1) - { + if (line.startsWith("!![") && endmark != -1) { auto level = MessageLevel::getLevel(line.left(endmark).mid(3)); line = line.mid(endmark + 2); return level; diff --git a/launcher/MessageLevel.h b/launcher/MessageLevel.h index 227ad25d8..fd12583f2 100644 --- a/launcher/MessageLevel.h +++ b/launcher/MessageLevel.h @@ -6,23 +6,21 @@ * @brief the MessageLevel Enum * defines what level a log message is */ -namespace MessageLevel -{ -enum Enum -{ - Unknown, /**< No idea what this is or where it came from */ - StdOut, /**< Undetermined stderr messages */ - StdErr, /**< Undetermined stdout messages */ +namespace MessageLevel { +enum Enum { + Unknown, /**< No idea what this is or where it came from */ + StdOut, /**< Undetermined stderr messages */ + StdErr, /**< Undetermined stdout messages */ Launcher, /**< Launcher Messages */ - Debug, /**< Debug Messages */ - Info, /**< Info Messages */ - Message, /**< Standard Messages */ - Warning, /**< Warnings */ - Error, /**< Errors */ - Fatal, /**< Fatal Errors */ + Debug, /**< Debug Messages */ + Info, /**< Info Messages */ + Message, /**< Standard Messages */ + Warning, /**< Warnings */ + Error, /**< Errors */ + Fatal, /**< Fatal Errors */ }; -MessageLevel::Enum getLevel(const QString &levelName); +MessageLevel::Enum getLevel(const QString& levelName); /* Get message level from a line. Line is modified if it was successful. */ -MessageLevel::Enum fromLine(QString &line); -} +MessageLevel::Enum fromLine(QString& line); +} // namespace MessageLevel diff --git a/launcher/NullInstance.h b/launcher/NullInstance.h index 0f7434bb1..c7abfc587 100644 --- a/launcher/NullInstance.h +++ b/launcher/NullInstance.h @@ -37,88 +37,38 @@ #include "BaseInstance.h" #include "launch/LaunchTask.h" -class NullInstance: public BaseInstance -{ +class NullInstance : public BaseInstance { Q_OBJECT -public: + public: NullInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) - :BaseInstance(globalSettings, settings, rootDir) + : BaseInstance(globalSettings, settings, rootDir) { setVersionBroken(true); } - virtual ~NullInstance() {}; - void saveNow() override - { - } - void loadSpecificSettings() override - { - setSpecificSettingsLoaded(true); - } - QString getStatusbarDescription() override - { - return tr("Unknown instance type"); - }; - QSet< QString > traits() const override - { - return {}; - }; - QString instanceConfigFolder() const override - { - return instanceRoot(); - }; - shared_qobject_ptr createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override - { - return nullptr; - } - shared_qobject_ptr< Task > createUpdateTask([[maybe_unused]] Net::Mode mode) override - { - return nullptr; - } - QProcessEnvironment createEnvironment() override - { - return QProcessEnvironment(); - } - QProcessEnvironment createLaunchEnvironment() override - { - return QProcessEnvironment(); - } - QMap getVariables() override - { - return QMap(); - } - IPathMatcher::Ptr getLogFileMatcher() override - { - return nullptr; - } - QString getLogFileRoot() override - { - return instanceRoot(); - } - QString typeName() const override - { - return "Null"; - } - bool canExport() const override - { - return false; - } - bool canEdit() const override - { - return false; - } - bool canLaunch() const override - { - return false; - } + virtual ~NullInstance(){}; + void saveNow() override {} + void loadSpecificSettings() override { setSpecificSettingsLoaded(true); } + QString getStatusbarDescription() override { return tr("Unknown instance type"); }; + QSet traits() const override { return {}; }; + QString instanceConfigFolder() const override { return instanceRoot(); }; + shared_qobject_ptr createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override { return nullptr; } + shared_qobject_ptr createUpdateTask([[maybe_unused]] Net::Mode mode) override { return nullptr; } + QProcessEnvironment createEnvironment() override { return QProcessEnvironment(); } + QProcessEnvironment createLaunchEnvironment() override { return QProcessEnvironment(); } + QMap getVariables() override { return QMap(); } + IPathMatcher::Ptr getLogFileMatcher() override { return nullptr; } + QString getLogFileRoot() override { return instanceRoot(); } + QString typeName() const override { return "Null"; } + bool canExport() const override { return false; } + bool canEdit() const override { return false; } + bool canLaunch() const override { return false; } QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override { QStringList out; out << "Null instance - placeholder."; return out; } - QString modsRoot() const override { - return QString(); - } + QString modsRoot() const override { return QString(); } void updateRuntimeContext() { // NOOP diff --git a/launcher/ProblemProvider.h b/launcher/ProblemProvider.h index d7d4c4e57..9d1b0004e 100644 --- a/launcher/ProblemProvider.h +++ b/launcher/ProblemProvider.h @@ -3,48 +3,33 @@ #include #include -enum class ProblemSeverity -{ - None, - Warning, - Error -}; +enum class ProblemSeverity { None, Warning, Error }; -struct PatchProblem -{ +struct PatchProblem { ProblemSeverity m_severity; QString m_description; }; -class ProblemProvider -{ -public: +class ProblemProvider { + public: virtual ~ProblemProvider() {} virtual const QList getProblems() const = 0; virtual ProblemSeverity getProblemSeverity() const = 0; }; -class ProblemContainer : public ProblemProvider -{ -public: - const QList getProblems() const override +class ProblemContainer : public ProblemProvider { + public: + const QList getProblems() const override { return m_problems; } + ProblemSeverity getProblemSeverity() const override { return m_problemSeverity; } + virtual void addProblem(ProblemSeverity severity, const QString& description) { - return m_problems; - } - ProblemSeverity getProblemSeverity() const override - { - return m_problemSeverity; - } - virtual void addProblem(ProblemSeverity severity, const QString &description) - { - if(severity > m_problemSeverity) - { + if (severity > m_problemSeverity) { m_problemSeverity = severity; } - m_problems.append({severity, description}); + m_problems.append({ severity, description }); } -private: + private: QList m_problems; ProblemSeverity m_problemSeverity = ProblemSeverity::None; }; diff --git a/launcher/QVariantUtils.h b/launcher/QVariantUtils.h index 7e422c3e8..91f2ad29c 100644 --- a/launcher/QVariantUtils.h +++ b/launcher/QVariantUtils.h @@ -36,35 +36,34 @@ #pragma once - -#include #include +#include namespace QVariantUtils { -template -inline QList toList(QVariant src) { +template +inline QList toList(QVariant src) +{ QVariantList variantList = src.toList(); QList list_t; list_t.reserve(variantList.size()); - for (const QVariant& v : variantList) - { + for (const QVariant& v : variantList) { list_t.append(v.value()); } - return list_t; + return list_t; } -template -inline QVariant fromList(QList val) { +template +inline QVariant fromList(QList val) +{ QVariantList variantList; variantList.reserve(val.size()); - for (const T& v : val) - { + for (const T& v : val) { variantList.append(v); } return variantList; } -} \ No newline at end of file +} // namespace QVariantUtils \ No newline at end of file diff --git a/launcher/RWStorage.h b/launcher/RWStorage.h index 3028388e2..5764d7958 100644 --- a/launcher/RWStorage.h +++ b/launcher/RWStorage.h @@ -1,13 +1,12 @@ #pragma once -#include -#include #include +#include #include +#include template -class RWStorage -{ -public: +class RWStorage { + public: void add(K key, V value) { QWriteLocker l(&lock); @@ -17,21 +16,19 @@ public: V get(K key) { QReadLocker l(&lock); - if(cache.contains(key)) - { + if (cache.contains(key)) { return cache[key]; - } - else return V(); + } else + return V(); } bool get(K key, V& value) { QReadLocker l(&lock); - if(cache.contains(key)) - { + if (cache.contains(key)) { value = cache[key]; return true; - } - else return false; + } else + return false; } bool has(K key) { @@ -41,15 +38,14 @@ public: bool stale(K key) { QReadLocker l(&lock); - if(!cache.contains(key)) + if (!cache.contains(key)) return true; return stale_entries.contains(key); } void setStale(K key) { QWriteLocker l(&lock); - if(cache.contains(key)) - { + if (cache.contains(key)) { stale_entries.insert(key); } } @@ -59,7 +55,8 @@ public: cache.clear(); stale_entries.clear(); } -private: + + private: QReadWriteLock lock; QMap cache; QSet stale_entries; diff --git a/launcher/RecursiveFileSystemWatcher.cpp b/launcher/RecursiveFileSystemWatcher.cpp index be4d1fde6..8b28a03f1 100644 --- a/launcher/RecursiveFileSystemWatcher.cpp +++ b/launcher/RecursiveFileSystemWatcher.cpp @@ -1,25 +1,21 @@ #include "RecursiveFileSystemWatcher.h" -#include #include +#include -RecursiveFileSystemWatcher::RecursiveFileSystemWatcher(QObject *parent) - : QObject(parent), m_watcher(new QFileSystemWatcher(this)) +RecursiveFileSystemWatcher::RecursiveFileSystemWatcher(QObject* parent) : QObject(parent), m_watcher(new QFileSystemWatcher(this)) { - connect(m_watcher, &QFileSystemWatcher::fileChanged, this, - &RecursiveFileSystemWatcher::fileChange); - connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, - &RecursiveFileSystemWatcher::directoryChange); + connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &RecursiveFileSystemWatcher::fileChange); + connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &RecursiveFileSystemWatcher::directoryChange); } -void RecursiveFileSystemWatcher::setRootDir(const QDir &root) +void RecursiveFileSystemWatcher::setRootDir(const QDir& root) { bool wasEnabled = m_isEnabled; disable(); m_root = root; setFiles(scanRecursive(m_root)); - if (wasEnabled) - { + if (wasEnabled) { enable(); } } @@ -28,16 +24,14 @@ void RecursiveFileSystemWatcher::setWatchFiles(const bool watchFiles) bool wasEnabled = m_isEnabled; disable(); m_watchFiles = watchFiles; - if (wasEnabled) - { + if (wasEnabled) { enable(); } } void RecursiveFileSystemWatcher::enable() { - if (m_isEnabled) - { + if (m_isEnabled) { return; } Q_ASSERT(m_root != QDir::root()); @@ -46,8 +40,7 @@ void RecursiveFileSystemWatcher::enable() } void RecursiveFileSystemWatcher::disable() { - if (!m_isEnabled) - { + if (!m_isEnabled) { return; } m_isEnabled = false; @@ -55,53 +48,45 @@ void RecursiveFileSystemWatcher::disable() m_watcher->removePaths(m_watcher->directories()); } -void RecursiveFileSystemWatcher::setFiles(const QStringList &files) +void RecursiveFileSystemWatcher::setFiles(const QStringList& files) { - if (files != m_files) - { + if (files != m_files) { m_files = files; emit filesChanged(); } } -void RecursiveFileSystemWatcher::addFilesToWatcherRecursive(const QDir &dir) +void RecursiveFileSystemWatcher::addFilesToWatcherRecursive(const QDir& dir) { m_watcher->addPath(dir.absolutePath()); - for (const QString &directory : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) - { + for (const QString& directory : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { addFilesToWatcherRecursive(dir.absoluteFilePath(directory)); } - if (m_watchFiles) - { - for (const QFileInfo &info : dir.entryInfoList(QDir::Files)) - { + if (m_watchFiles) { + for (const QFileInfo& info : dir.entryInfoList(QDir::Files)) { m_watcher->addPath(info.absoluteFilePath()); } } } -QStringList RecursiveFileSystemWatcher::scanRecursive(const QDir &directory) +QStringList RecursiveFileSystemWatcher::scanRecursive(const QDir& directory) { QStringList ret; - if(!m_matcher) - { + if (!m_matcher) { return {}; } - for (const QString &dir : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden)) - { + for (const QString& dir : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden)) { ret.append(scanRecursive(directory.absoluteFilePath(dir))); } - for (const QString &file : directory.entryList(QDir::Files | QDir::Hidden)) - { + for (const QString& file : directory.entryList(QDir::Files | QDir::Hidden)) { auto relPath = m_root.relativeFilePath(directory.absoluteFilePath(file)); - if (m_matcher->matches(relPath)) - { + if (m_matcher->matches(relPath)) { ret.append(relPath); } } return ret; } -void RecursiveFileSystemWatcher::fileChange(const QString &path) +void RecursiveFileSystemWatcher::fileChange(const QString& path) { emit fileChanged(path); } diff --git a/launcher/RecursiveFileSystemWatcher.h b/launcher/RecursiveFileSystemWatcher.h index cc837d603..ec3ed804e 100644 --- a/launcher/RecursiveFileSystemWatcher.h +++ b/launcher/RecursiveFileSystemWatcher.h @@ -1,61 +1,48 @@ #pragma once -#include #include +#include #include "pathmatcher/IPathMatcher.h" -class RecursiveFileSystemWatcher : public QObject -{ +class RecursiveFileSystemWatcher : public QObject { Q_OBJECT -public: - RecursiveFileSystemWatcher(QObject *parent); + public: + RecursiveFileSystemWatcher(QObject* parent); - void setRootDir(const QDir &root); - QDir rootDir() const - { - return m_root; - } + void setRootDir(const QDir& root); + QDir rootDir() const { return m_root; } // WARNING: setting this to true may be bad for performance void setWatchFiles(const bool watchFiles); - bool watchFiles() const - { - return m_watchFiles; - } + bool watchFiles() const { return m_watchFiles; } - void setMatcher(IPathMatcher::Ptr matcher) - { - m_matcher = matcher; - } + void setMatcher(IPathMatcher::Ptr matcher) { m_matcher = matcher; } - QStringList files() const - { - return m_files; - } + QStringList files() const { return m_files; } -signals: + signals: void filesChanged(); - void fileChanged(const QString &path); + void fileChanged(const QString& path); -public slots: + public slots: void enable(); void disable(); -private: + private: QDir m_root; bool m_watchFiles = false; bool m_isEnabled = false; IPathMatcher::Ptr m_matcher; - QFileSystemWatcher *m_watcher; + QFileSystemWatcher* m_watcher; QStringList m_files; - void setFiles(const QStringList &files); + void setFiles(const QStringList& files); - void addFilesToWatcherRecursive(const QDir &dir); - QStringList scanRecursive(const QDir &dir); + void addFilesToWatcherRecursive(const QDir& dir); + QStringList scanRecursive(const QDir& dir); -private slots: - void fileChange(const QString &path); - void directoryChange(const QString &path); + private slots: + void fileChange(const QString& path); + void directoryChange(const QString& path); }; diff --git a/launcher/SeparatorPrefixTree.h b/launcher/SeparatorPrefixTree.h index 7a841cb76..df9dfe579 100644 --- a/launcher/SeparatorPrefixTree.h +++ b/launcher/SeparatorPrefixTree.h @@ -1,44 +1,32 @@ #pragma once -#include #include +#include #include template -class SeparatorPrefixTree -{ -public: - SeparatorPrefixTree(QStringList paths) - { - insert(paths); - } +class SeparatorPrefixTree { + public: + SeparatorPrefixTree(QStringList paths) { insert(paths); } - SeparatorPrefixTree(bool contained = false) - { - m_contained = contained; - } + SeparatorPrefixTree(bool contained = false) { m_contained = contained; } void insert(QStringList paths) { - for(auto &path: paths) - { + for (auto& path : paths) { insert(path); } } /// insert an exact path into the tree - SeparatorPrefixTree & insert(QString path) + SeparatorPrefixTree& insert(QString path) { auto sepIndex = path.indexOf(Tseparator); - if(sepIndex == -1) - { + if (sepIndex == -1) { children[path] = SeparatorPrefixTree(true); return children[path]; - } - else - { + } else { auto prefix = path.left(sepIndex); - if(!children.contains(prefix)) - { + if (!children.contains(prefix)) { children[prefix] = SeparatorPrefixTree(false); } return children[prefix].insert(path.mid(sepIndex + 1)); @@ -56,26 +44,20 @@ public: bool covers(QString path) const { // if we found some valid node, it's good enough. the tree covers the path - if(m_contained) - { + if (m_contained) { return true; } auto sepIndex = path.indexOf(Tseparator); - if(sepIndex == -1) - { + if (sepIndex == -1) { auto found = children.find(path); - if(found == children.end()) - { + if (found == children.end()) { return false; } return (*found).covers(QString()); - } - else - { + } else { auto prefix = path.left(sepIndex); auto found = children.find(prefix); - if(found == children.end()) - { + if (found == children.end()) { return false; } return (*found).covers(path.mid(sepIndex + 1)); @@ -86,41 +68,33 @@ public: QString cover(QString path) const { // if we found some valid node, it's good enough. the tree covers the path - if(m_contained) - { + if (m_contained) { return QString(""); } auto sepIndex = path.indexOf(Tseparator); - if(sepIndex == -1) - { + if (sepIndex == -1) { auto found = children.find(path); - if(found == children.end()) - { + if (found == children.end()) { return QString(); } auto nested = (*found).cover(QString()); - if(nested.isNull()) - { + if (nested.isNull()) { return nested; } - if(nested.isEmpty()) + if (nested.isEmpty()) return path; return path + Tseparator + nested; - } - else - { + } else { auto prefix = path.left(sepIndex); auto found = children.find(prefix); - if(found == children.end()) - { + if (found == children.end()) { return QString(); } auto nested = (*found).cover(path.mid(sepIndex + 1)); - if(nested.isNull()) - { + if (nested.isNull()) { return nested; } - if(nested.isEmpty()) + if (nested.isEmpty()) return prefix; return prefix + Tseparator + nested; } @@ -130,21 +104,16 @@ public: bool exists(QString path) const { auto sepIndex = path.indexOf(Tseparator); - if(sepIndex == -1) - { + if (sepIndex == -1) { auto found = children.find(path); - if(found == children.end()) - { + if (found == children.end()) { return false; } return true; - } - else - { + } else { auto prefix = path.left(sepIndex); auto found = children.find(prefix); - if(found == children.end()) - { + if (found == children.end()) { return false; } return (*found).exists(path.mid(sepIndex + 1)); @@ -152,24 +121,19 @@ public: } /// find a node in the tree by name - const SeparatorPrefixTree * find(QString path) const + const SeparatorPrefixTree* find(QString path) const { auto sepIndex = path.indexOf(Tseparator); - if(sepIndex == -1) - { + if (sepIndex == -1) { auto found = children.find(path); - if(found == children.end()) - { + if (found == children.end()) { return nullptr; } return &(*found); - } - else - { + } else { auto prefix = path.left(sepIndex); auto found = children.find(prefix); - if(found == children.end()) - { + if (found == children.end()) { return nullptr; } return (*found).find(path.mid(sepIndex + 1)); @@ -177,70 +141,48 @@ public: } /// is this a leaf node? - bool leaf() const - { - return children.isEmpty(); - } + bool leaf() const { return children.isEmpty(); } /// is this node actually contained in the tree, or is it purely structural? - bool contained() const - { - return m_contained; - } + bool contained() const { return m_contained; } /// Remove a path from the tree - bool remove(QString path) - { - return removeInternal(path) != Failed; - } + bool remove(QString path) { return removeInternal(path) != Failed; } /// Clear all children of this node tree node - void clear() - { - children.clear(); - } + void clear() { children.clear(); } QStringList toStringList() const { QStringList collected; // collecting these is more expensive. auto iter = children.begin(); - while(iter != children.end()) - { + while (iter != children.end()) { QStringList list = iter.value().toStringList(); - for(int i = 0; i < list.size(); i++) - { + for (int i = 0; i < list.size(); i++) { list[i] = iter.key() + Tseparator + list[i]; } collected.append(list); - if((*iter).m_contained) - { + if ((*iter).m_contained) { collected.append(iter.key()); } iter++; } return collected; } -private: - enum Removal - { - Failed, - Succeeded, - HasChildren - }; + + private: + enum Removal { Failed, Succeeded, HasChildren }; Removal removeInternal(QString path = QString()) { - if(path.isEmpty()) - { - if(!m_contained) - { + if (path.isEmpty()) { + if (!m_contained) { // remove all children - we are removing a prefix clear(); return Succeeded; } m_contained = false; - if(children.size()) - { + if (children.size()) { return HasChildren; } return Succeeded; @@ -248,42 +190,32 @@ private: Removal remStatus = Failed; QString childToRemove; auto sepIndex = path.indexOf(Tseparator); - if(sepIndex == -1) - { + if (sepIndex == -1) { childToRemove = path; auto found = children.find(childToRemove); - if(found == children.end()) - { + if (found == children.end()) { return Failed; } remStatus = (*found).removeInternal(); - } - else - { + } else { childToRemove = path.left(sepIndex); auto found = children.find(childToRemove); - if(found == children.end()) - { + if (found == children.end()) { return Failed; } remStatus = (*found).removeInternal(path.mid(sepIndex + 1)); } - switch (remStatus) - { + switch (remStatus) { case Failed: - case HasChildren: - { + case HasChildren: { return remStatus; } - case Succeeded: - { + case Succeeded: { children.remove(childToRemove); - if(m_contained) - { + if (m_contained) { return HasChildren; } - if(children.size()) - { + if (children.size()) { return HasChildren; } return Succeeded; @@ -292,7 +224,7 @@ private: return Failed; } -private: - QMap> children; + private: + QMap> children; bool m_contained = false; }; diff --git a/launcher/SkinUtils.cpp b/launcher/SkinUtils.cpp index 1fe0c896d..20d3b52e7 100644 --- a/launcher/SkinUtils.cpp +++ b/launcher/SkinUtils.cpp @@ -14,17 +14,16 @@ */ #include "SkinUtils.h" -#include "net/HttpMetaCache.h" #include "Application.h" +#include "net/HttpMetaCache.h" #include -#include +#include #include #include -#include +#include -namespace SkinUtils -{ +namespace SkinUtils { /* * Given a username, return a pixmap of the cached skin (if it exists), QPixmap() otherwise */ @@ -32,11 +31,9 @@ QPixmap getFaceFromCache(QString username, int height, int width) { QFile fskin(APPLICATION->metacache()->resolveEntry("skins", username + ".png")->getFullPath()); - if (fskin.exists()) - { + if (fskin.exists()) { QPixmap skinTexture(fskin.fileName()); - if(!skinTexture.isNull()) - { + if (!skinTexture.isNull()) { QPixmap skin = QPixmap(8, 8); QPainter painter(&skin); painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8)); @@ -47,4 +44,4 @@ QPixmap getFaceFromCache(QString username, int height, int width) return QPixmap(); } -} +} // namespace SkinUtils diff --git a/launcher/SkinUtils.h b/launcher/SkinUtils.h index c1f437ab0..11bc8bc6f 100644 --- a/launcher/SkinUtils.h +++ b/launcher/SkinUtils.h @@ -17,7 +17,6 @@ #include -namespace SkinUtils -{ +namespace SkinUtils { QPixmap getFaceFromCache(QString id, int height = 64, int width = 64); } diff --git a/launcher/StringUtils.h b/launcher/StringUtils.h index f90a6ac75..eac0d5a7d 100644 --- a/launcher/StringUtils.h +++ b/launcher/StringUtils.h @@ -68,15 +68,14 @@ inline QString fromStdString(string s) int naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs); /** - * @brief Truncate a url while keeping its readability py placing the `...` in the middle of the path + * @brief Truncate a url while keeping its readability py placing the `...` in the middle of the path * @param url Url to truncate * @param max_len max lenght of url in charaters * @param hard_limit if truncating the path can't get the url short enough, truncate it normaly. */ -QString truncateUrlHumanFriendly(QUrl &url, int max_len, bool hard_limit = false); +QString truncateUrlHumanFriendly(QUrl& url, int max_len, bool hard_limit = false); QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_points = 1); - QString getRandomAlphaNumeric(); } // namespace StringUtils diff --git a/launcher/Usable.h b/launcher/Usable.h index f5818cbb4..b0ecd4018 100644 --- a/launcher/Usable.h +++ b/launcher/Usable.h @@ -34,19 +34,15 @@ class Usable { * * @see Usable */ -class UseLock -{ -public: - UseLock(shared_qobject_ptr usable) - : m_usable(usable) +class UseLock { + public: + UseLock(shared_qobject_ptr usable) : m_usable(usable) { // this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate. m_usable->incrementUses(); } - ~UseLock() - { - m_usable->decrementUses(); - } -private: + ~UseLock() { m_usable->decrementUses(); } + + private: shared_qobject_ptr m_usable; }; diff --git a/launcher/Version.cpp b/launcher/Version.cpp index e4311f314..511aa9c35 100644 --- a/launcher/Version.cpp +++ b/launcher/Version.cpp @@ -117,12 +117,14 @@ QDebug operator<<(QDebug debug, const Version& v) bool first = true; for (auto s : v.m_sections) { - if (!first) debug.nospace() << ", "; + if (!first) + debug.nospace() << ", "; debug.nospace() << s.m_fullString; first = false; } - - debug.nospace() << " ]" << " }"; + + debug.nospace() << " ]" + << " }"; return debug; } diff --git a/launcher/Version.h b/launcher/Version.h index df379082c..31c7b2d8a 100644 --- a/launcher/Version.h +++ b/launcher/Version.h @@ -48,12 +48,12 @@ class Version { Version(QString str); Version() = default; - bool operator<(const Version &other) const; - bool operator<=(const Version &other) const; - bool operator>(const Version &other) const; - bool operator>=(const Version &other) const; - bool operator==(const Version &other) const; - bool operator!=(const Version &other) const; + bool operator<(const Version& other) const; + bool operator<=(const Version& other) const; + bool operator>(const Version& other) const; + bool operator>=(const Version& other) const; + bool operator==(const Version& other) const; + bool operator!=(const Version& other) const; QString toString() const { return m_string; } @@ -72,7 +72,7 @@ class Version { } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - auto numPart = QStringView{m_fullString}.left(cutoff); + auto numPart = QStringView{ m_fullString }.left(cutoff); #else auto numPart = m_fullString.leftRef(cutoff); #endif @@ -83,7 +83,7 @@ class Version { } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - auto stringPart = QStringView{m_fullString}.mid(cutoff); + auto stringPart = QStringView{ m_fullString }.mid(cutoff); #else auto stringPart = m_fullString.midRef(cutoff); #endif @@ -103,8 +103,14 @@ class Version { QString m_fullString; - [[nodiscard]] inline bool isAppendix() const { return m_stringPart.startsWith('+'); } - [[nodiscard]] inline bool isPreRelease() const { return m_stringPart.startsWith('-') && m_stringPart.length() > 1; } + [[nodiscard]] inline bool isAppendix() const + { + return m_stringPart.startsWith('+'); + } + [[nodiscard]] inline bool isPreRelease() const + { + return m_stringPart.startsWith('-') && m_stringPart.length() > 1; + } inline bool operator==(const Section& other) const { @@ -121,7 +127,7 @@ class Version { } inline bool operator<(const Section& other) const - { + { static auto unequal_is_less = [](Section const& non_null) -> bool { if (non_null.m_stringPart.isEmpty()) return non_null.m_numPart == 0; @@ -154,7 +160,7 @@ class Version { { return !(*this == other); } - inline bool operator>(const Section &other) const + inline bool operator>(const Section& other) const { return !(*this < other || *this == other); } @@ -166,5 +172,3 @@ class Version { void parse(); }; - - diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index e7c00fda2..0ab9ae2c3 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -35,53 +35,48 @@ */ #include "VersionProxyModel.h" -#include "Application.h" -#include -#include #include #include +#include +#include +#include "Application.h" -class VersionFilterModel : public QSortFilterProxyModel -{ +class VersionFilterModel : public QSortFilterProxyModel { Q_OBJECT -public: - VersionFilterModel(VersionProxyModel *parent) : QSortFilterProxyModel(parent) + public: + VersionFilterModel(VersionProxyModel* parent) : QSortFilterProxyModel(parent) { m_parent = parent; setSortRole(BaseVersionList::SortRole); sort(0, Qt::DescendingOrder); } - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { - const auto &filters = m_parent->filters(); - const QString &search = m_parent->search(); + const auto& filters = m_parent->filters(); + const QString& search = m_parent->search(); const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive)) return false; - for (auto it = filters.begin(); it != filters.end(); ++it) - { + for (auto it = filters.begin(); it != filters.end(); ++it) { auto data = sourceModel()->data(idx, it.key()); auto match = data.toString(); - if(!it.value()->accepts(match)) - { + if (!it.value()->accepts(match)) { return false; } } return true; } - void filterChanged() - { - invalidateFilter(); - } -private: - VersionProxyModel *m_parent; + void filterChanged() { invalidateFilter(); } + + private: + VersionProxyModel* m_parent; }; -VersionProxyModel::VersionProxyModel(QObject *parent) : QAbstractProxyModel(parent) +VersionProxyModel::VersionProxyModel(QObject* parent) : QAbstractProxyModel(parent) { filterModel = new VersionFilterModel(this); connect(filterModel, &QAbstractItemModel::dataChanged, this, &VersionProxyModel::sourceDataChanged); @@ -104,19 +99,17 @@ VersionProxyModel::VersionProxyModel(QObject *parent) : QAbstractProxyModel(pare QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, int role) const { - if(section < 0 || section >= m_columns.size()) + if (section < 0 || section >= m_columns.size()) return QVariant(); - if(orientation != Qt::Horizontal) + if (orientation != Qt::Horizontal) return QVariant(); auto column = m_columns[section]; - if(role == Qt::DisplayRole) - { - switch(column) - { + if (role == Qt::DisplayRole) { + switch (column) { case Name: return tr("Version"); case ParentVersion: - return tr("Minecraft"); //FIXME: this should come from metadata + return tr("Minecraft"); // FIXME: this should come from metadata case Branch: return tr("Branch"); case Type: @@ -128,15 +121,12 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, case Time: return tr("Released"); } - } - else if(role == Qt::ToolTipRole) - { - switch(column) - { + } else if (role == Qt::ToolTipRole) { + switch (column) { case Name: return tr("The name of the version."); case ParentVersion: - return tr("Minecraft version"); //FIXME: this should come from metadata + return tr("Minecraft version"); // FIXME: this should come from metadata case Branch: return tr("The version's branch"); case Type: @@ -152,25 +142,19 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, return QVariant(); } -QVariant VersionProxyModel::data(const QModelIndex &index, int role) const +QVariant VersionProxyModel::data(const QModelIndex& index, int role) const { - if(!index.isValid()) - { + if (!index.isValid()) { return QVariant(); } auto column = m_columns[index.column()]; auto parentIndex = mapToSource(index); - switch(role) - { - case Qt::DisplayRole: - { - switch(column) - { - case Name: - { + switch (role) { + case Qt::DisplayRole: { + switch (column) { + case Name: { QString version = sourceModel()->data(parentIndex, BaseVersionList::VersionRole).toString(); - if(version == m_currentVersion) - { + if (version == m_currentVersion) { return tr("%1 (installed)").arg(version); } return version; @@ -191,18 +175,14 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return QVariant(); } } - case Qt::ToolTipRole: - { - if(column == Name && hasRecommended) - { + case Qt::ToolTipRole: { + if (column == Name && hasRecommended) { auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { + if (value.toBool()) { return tr("Recommended"); - } else if(hasLatest) { + } else if (hasLatest) { auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { + if (value.toBool()) { return tr("Latest"); } } @@ -210,14 +190,10 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); } } - case Qt::DecorationRole: - { - switch(column) - { - case Name: - { - if(hasRecommended) - { + case Qt::DecorationRole: { + switch (column) { + case Name: { + if (hasRecommended) { auto recommenced = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); if (recommenced.toBool()) { return APPLICATION->getThemedIcon("star"); @@ -229,9 +205,8 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } QPixmap pixmap; QPixmapCache::find("placeholder", &pixmap); - if(!pixmap) - { - QPixmap px(16,16); + if (!pixmap) { + QPixmap px(16, 16); px.fill(Qt::transparent); QPixmapCache::insert("placeholder", px); return px; @@ -239,16 +214,13 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return pixmap; } } - default: - { + default: { return QVariant(); } } } - default: - { - if(roles.contains((BaseVersionList::ModelRoles)role)) - { + default: { + if (roles.contains((BaseVersionList::ModelRoles)role)) { return sourceModel()->data(parentIndex, role); } return QVariant(); @@ -261,56 +233,51 @@ QModelIndex VersionProxyModel::parent([[maybe_unused]] const QModelIndex& child) return QModelIndex(); } -QModelIndex VersionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const +QModelIndex VersionProxyModel::mapFromSource(const QModelIndex& sourceIndex) const { - if(sourceIndex.isValid()) - { + if (sourceIndex.isValid()) { return index(sourceIndex.row(), 0); } return QModelIndex(); } -QModelIndex VersionProxyModel::mapToSource(const QModelIndex &proxyIndex) const +QModelIndex VersionProxyModel::mapToSource(const QModelIndex& proxyIndex) const { - if(proxyIndex.isValid()) - { + if (proxyIndex.isValid()) { return sourceModel()->index(proxyIndex.row(), 0); } return QModelIndex(); } -QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex &parent) const +QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex& parent) const { // no trees here... shoo - if(parent.isValid()) - { + if (parent.isValid()) { return QModelIndex(); } - if(row < 0 || row >= sourceModel()->rowCount()) + if (row < 0 || row >= sourceModel()->rowCount()) return QModelIndex(); - if(column < 0 || column >= columnCount()) + if (column < 0 || column >= columnCount()) return QModelIndex(); return QAbstractItemModel::createIndex(row, column); } -int VersionProxyModel::columnCount(const QModelIndex &parent) const +int VersionProxyModel::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : m_columns.size(); } -int VersionProxyModel::rowCount(const QModelIndex &parent) const +int VersionProxyModel::rowCount(const QModelIndex& parent) const { - if(sourceModel()) - { + if (sourceModel()) { return sourceModel()->rowCount(parent); } return 0; } -void VersionProxyModel::sourceDataChanged(const QModelIndex &source_top_left, - const QModelIndex &source_bottom_right) +void VersionProxyModel::sourceDataChanged(const QModelIndex& source_top_left, const QModelIndex& source_bottom_right) { - if(source_top_left.parent() != source_bottom_right.parent()) + if (source_top_left.parent() != source_bottom_right.parent()) return; // whole row is getting changed @@ -319,22 +286,20 @@ void VersionProxyModel::sourceDataChanged(const QModelIndex &source_top_left, emit dataChanged(topLeft, bottomRight); } -void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw) +void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw) { - auto replacing = dynamic_cast(replacingRaw); + auto replacing = dynamic_cast(replacingRaw); beginResetModel(); m_columns.clear(); - if(!replacing) - { + if (!replacing) { roles.clear(); filterModel->setSourceModel(replacing); return; } roles = replacing->providesRoles(); - if(roles.contains(BaseVersionList::VersionRole)) - { + if (roles.contains(BaseVersionList::VersionRole)) { m_columns.push_back(Name); } /* @@ -343,32 +308,25 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw) m_columns.push_back(ParentVersion); } */ - if(roles.contains(BaseVersionList::ArchitectureRole)) - { + if (roles.contains(BaseVersionList::ArchitectureRole)) { m_columns.push_back(Architecture); } - if(roles.contains(BaseVersionList::PathRole)) - { + if (roles.contains(BaseVersionList::PathRole)) { m_columns.push_back(Path); } - if(roles.contains(Meta::VersionList::TimeRole)) - { + if (roles.contains(Meta::VersionList::TimeRole)) { m_columns.push_back(Time); } - if(roles.contains(BaseVersionList::BranchRole)) - { + if (roles.contains(BaseVersionList::BranchRole)) { m_columns.push_back(Branch); } - if(roles.contains(BaseVersionList::TypeRole)) - { + if (roles.contains(BaseVersionList::TypeRole)) { m_columns.push_back(Type); } - if(roles.contains(BaseVersionList::RecommendedRole)) - { + if (roles.contains(BaseVersionList::RecommendedRole)) { hasRecommended = true; } - if(roles.contains(BaseVersionList::LatestRole)) - { + if (roles.contains(BaseVersionList::LatestRole)) { hasLatest = true; } filterModel->setSourceModel(replacing); @@ -378,16 +336,13 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw) QModelIndex VersionProxyModel::getRecommended() const { - if(!roles.contains(BaseVersionList::RecommendedRole)) - { + if (!roles.contains(BaseVersionList::RecommendedRole)) { return index(0, 0); } int recommended = 0; - for (int i = 0; i < rowCount(); i++) - { + for (int i = 0; i < rowCount(); i++) { auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::RecommendedRole); - if (value.toBool()) - { + if (value.toBool()) { recommended = i; } } @@ -397,16 +352,13 @@ QModelIndex VersionProxyModel::getRecommended() const QModelIndex VersionProxyModel::getVersion(const QString& version) const { int found = -1; - for (int i = 0; i < rowCount(); i++) - { + for (int i = 0; i < rowCount(); i++) { auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::VersionRole); - if (value.toString() == version) - { + if (value.toString() == version) { found = i; } } - if(found == -1) - { + if (found == -1) { return QModelIndex(); } return index(found, 0); @@ -419,23 +371,24 @@ void VersionProxyModel::clearFilters() filterModel->filterChanged(); } -void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filter * f) +void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filter* f) { m_filters[column].reset(f); filterModel->filterChanged(); } -void VersionProxyModel::setSearch(const QString &search) { +void VersionProxyModel::setSearch(const QString& search) +{ m_search = search; filterModel->filterChanged(); } -const VersionProxyModel::FilterMap &VersionProxyModel::filters() const +const VersionProxyModel::FilterMap& VersionProxyModel::filters() const { return m_filters; } -const QString &VersionProxyModel::search() const +const QString& VersionProxyModel::search() const { return m_search; } @@ -472,7 +425,7 @@ void VersionProxyModel::sourceRowsRemoved([[maybe_unused]] const QModelIndex& pa endRemoveRows(); } -void VersionProxyModel::setCurrentVersion(const QString &version) +void VersionProxyModel::setCurrentVersion(const QString& version) { m_currentVersion = version; } diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 6434376c6..c7d5fd94e 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -6,64 +6,53 @@ class VersionFilterModel; -class VersionProxyModel: public QAbstractProxyModel -{ +class VersionProxyModel : public QAbstractProxyModel { Q_OBJECT -public: - - enum Column - { - Name, - ParentVersion, - Branch, - Type, - Architecture, - Path, - Time - }; + public: + enum Column { Name, ParentVersion, Branch, Type, Architecture, Path, Time }; typedef QHash> FilterMap; -public: - VersionProxyModel ( QObject* parent = 0 ); - virtual ~VersionProxyModel() {}; + public: + VersionProxyModel(QObject* parent = 0); + virtual ~VersionProxyModel(){}; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; - virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; - virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; - virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + virtual QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; + virtual QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; + virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual QModelIndex parent(const QModelIndex &child) const override; - virtual void setSourceModel(QAbstractItemModel *sourceModel) override; + virtual QModelIndex parent(const QModelIndex& child) const override; + virtual void setSourceModel(QAbstractItemModel* sourceModel) override; - const FilterMap &filters() const; - const QString &search() const; - void setFilter(const BaseVersionList::ModelRoles column, Filter * filter); - void setSearch(const QString &search); + const FilterMap& filters() const; + const QString& search() const; + void setFilter(const BaseVersionList::ModelRoles column, Filter* filter); + void setSearch(const QString& search); void clearFilters(); QModelIndex getRecommended() const; - QModelIndex getVersion(const QString & version) const; - void setCurrentVersion(const QString &version); -private slots: + QModelIndex getVersion(const QString& version) const; + void setCurrentVersion(const QString& version); + private slots: - void sourceDataChanged(const QModelIndex &source_top_left,const QModelIndex &source_bottom_right); + void sourceDataChanged(const QModelIndex& source_top_left, const QModelIndex& source_bottom_right); void sourceAboutToBeReset(); void sourceReset(); - void sourceRowsAboutToBeInserted(const QModelIndex &parent, int first, int last); - void sourceRowsInserted(const QModelIndex &parent, int first, int last); + void sourceRowsAboutToBeInserted(const QModelIndex& parent, int first, int last); + void sourceRowsInserted(const QModelIndex& parent, int first, int last); - void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); - void sourceRowsRemoved(const QModelIndex &parent, int first, int last); + void sourceRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last); + void sourceRowsRemoved(const QModelIndex& parent, int first, int last); -private: + private: QList m_columns; FilterMap m_filters; QString m_search; BaseVersionList::RoleList roles; - VersionFilterModel * filterModel; + VersionFilterModel* filterModel; bool hasRecommended = false; bool hasLatest = false; QString m_currentVersion; diff --git a/launcher/WatchLock.h b/launcher/WatchLock.h index 3e08b4137..ad74f251e 100644 --- a/launcher/WatchLock.h +++ b/launcher/WatchLock.h @@ -1,20 +1,15 @@ #pragma once -#include #include +#include -struct WatchLock -{ - WatchLock(QFileSystemWatcher * watcher, const QString& directory) - : m_watcher(watcher), m_directory(directory) +struct WatchLock { + WatchLock(QFileSystemWatcher* watcher, const QString& directory) : m_watcher(watcher), m_directory(directory) { m_watcher->removePath(m_directory); } - ~WatchLock() - { - m_watcher->addPath(m_directory); - } - QFileSystemWatcher * m_watcher; + ~WatchLock() { m_watcher->addPath(m_directory); } + QFileSystemWatcher* m_watcher; QString m_directory; }; diff --git a/launcher/WindowsConsole.cpp b/launcher/WindowsConsole.cpp index 860af01fd..83cad5afa 100644 --- a/launcher/WindowsConsole.cpp +++ b/launcher/WindowsConsole.cpp @@ -16,7 +16,6 @@ * */ - #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -26,8 +25,8 @@ #include #include -void RedirectHandle(DWORD handle, FILE* stream, const char* mode ) { - +void RedirectHandle(DWORD handle, FILE* stream, const char* mode) +{ HANDLE stdHandle = GetStdHandle(handle); if (stdHandle != INVALID_HANDLE_VALUE) { int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); @@ -41,7 +40,6 @@ void RedirectHandle(DWORD handle, FILE* stream, const char* mode ) { } } } - } // taken from https://stackoverflow.com/a/25927081 @@ -101,12 +99,12 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr } } - -bool AttachWindowsConsole() { +bool AttachWindowsConsole() +{ auto stdinType = GetFileType(GetStdHandle(STD_INPUT_HANDLE)); auto stdoutType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); auto stderrType = GetFileType(GetStdHandle(STD_ERROR_HANDLE)); - + bool bindStdIn = false; bool bindStdOut = false; bool bindStdErr = false; @@ -128,5 +126,3 @@ bool AttachWindowsConsole() { return false; } - - diff --git a/launcher/filelink/FileLink.cpp b/launcher/filelink/FileLink.cpp index 3774b3821..1ea0e382f 100644 --- a/launcher/filelink/FileLink.cpp +++ b/launcher/filelink/FileLink.cpp @@ -170,7 +170,7 @@ void FileLinkApp::runLink() FS::LinkResult result = { src_path, dst_path, QString::fromStdString(os_err.message()), os_err.value() }; m_path_results.append(result); } else { - FS::LinkResult result = { src_path, dst_path, "", 0}; + FS::LinkResult result = { src_path, dst_path, "", 0 }; m_path_results.append(result); } } diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index e4a686c27..f3207fdcf 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -35,26 +35,23 @@ #include "JavaChecker.h" -#include -#include -#include #include +#include +#include +#include -#include "JavaUtils.h" -#include "FileSystem.h" -#include "Commandline.h" #include "Application.h" +#include "Commandline.h" +#include "FileSystem.h" +#include "JavaUtils.h" -JavaChecker::JavaChecker(QObject *parent) : QObject(parent) -{ -} +JavaChecker::JavaChecker(QObject* parent) : QObject(parent) {} void JavaChecker::performCheck() { QString checkerJar = JavaUtils::getJavaCheckPath(); - if (checkerJar.isEmpty()) - { + if (checkerJar.isEmpty()) { qDebug() << "Java checker library could not be found. Please check your installation."; return; } @@ -62,25 +59,21 @@ void JavaChecker::performCheck() QStringList args; process.reset(new QProcess()); - if(m_args.size()) - { + if (m_args.size()) { auto extraArgs = Commandline::splitArgs(m_args); args.append(extraArgs); } - if(m_minMem != 0) - { + if (m_minMem != 0) { args << QString("-Xms%1m").arg(m_minMem); } - if(m_maxMem != 0) - { + if (m_maxMem != 0) { args << QString("-Xmx%1m").arg(m_maxMem); } - if(m_permGen != 64) - { + if (m_permGen != 64) { args << QString("-XX:PermSize=%1m").arg(m_permGen); } - args.append({"-jar", checkerJar}); + args.append({ "-jar", checkerJar }); process->setArguments(args); process->setProgram(m_path); process->setProcessChannelMode(QProcess::SeparateChannels); @@ -130,8 +123,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) qWarning() << "STDERR" << m_stderr; qDebug() << "Java checker finished with status" << status << "exit code" << exitcode; - if (status == QProcess::CrashExit || exitcode == 1) - { + if (status == QProcess::CrashExit || exitcode == 1) { result.validity = JavaCheckResult::Validity::Errored; emit checkFinished(result); return; @@ -146,8 +138,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) #else QStringList lines = m_stdout.split("\n", QString::SkipEmptyParts); #endif - for(QString line : lines) - { + for (QString line : lines) { line = line.trimmed(); // NOTE: workaround for GH-4125, where garbage is getting printed into stdout on bedrock linux if (line.contains("/bedrock/strata")) { @@ -159,18 +150,14 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) #else auto parts = line.split('=', QString::SkipEmptyParts); #endif - if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) - { + if (parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty()) { continue; - } - else - { + } else { results.insert(parts[0], parts[1]); } } - if(!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success) - { + if (!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success) { result.validity = JavaCheckResult::Validity::ReturnedInvalidData; emit checkFinished(result); return; @@ -181,7 +168,6 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) auto java_vendor = results["java.vendor"]; bool is_64 = os_arch == "x86_64" || os_arch == "amd64" || os_arch == "aarch64" || os_arch == "arm64"; - result.validity = JavaCheckResult::Validity::Valid; result.is_64bit = is_64; result.mojangPlatform = is_64 ? "64" : "32"; @@ -194,8 +180,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) void JavaChecker::error(QProcess::ProcessError err) { - if(err == QProcess::FailedToStart) - { + if (err == QProcess::FailedToStart) { qDebug() << "Java checker has failed to start."; qDebug() << "Process environment:"; qDebug() << process->environment(); @@ -216,8 +201,7 @@ void JavaChecker::error(QProcess::ProcessError err) void JavaChecker::timeout() { // NO MERCY. NO ABUSE. - if(process) - { + if (process) { qDebug() << "Java checker has been killed by timeout."; process->kill(); } diff --git a/launcher/java/JavaChecker.h b/launcher/java/JavaChecker.h index 122861cf7..743f49417 100644 --- a/launcher/java/JavaChecker.h +++ b/launcher/java/JavaChecker.h @@ -9,8 +9,7 @@ class JavaChecker; -struct JavaCheckResult -{ +struct JavaCheckResult { QString path; QString mojangPlatform; QString realPlatform; @@ -20,21 +19,15 @@ struct JavaCheckResult QString errorLog; bool is_64bit = false; int id; - enum class Validity - { - Errored, - ReturnedInvalidData, - Valid - } validity = Validity::Errored; + enum class Validity { Errored, ReturnedInvalidData, Valid } validity = Validity::Errored; }; typedef shared_qobject_ptr QProcessPtr; typedef shared_qobject_ptr JavaCheckerPtr; -class JavaChecker : public QObject -{ +class JavaChecker : public QObject { Q_OBJECT -public: - explicit JavaChecker(QObject *parent = 0); + public: + explicit JavaChecker(QObject* parent = 0); void performCheck(); QString m_path; @@ -44,15 +37,15 @@ public: int m_maxMem = 0; int m_permGen = 64; -signals: + signals: void checkFinished(JavaCheckResult result); -private: + + private: QProcessPtr process; QTimer killTimer; QString m_stdout; QString m_stderr; -public -slots: + public slots: void timeout(); void finished(int exitcode, QProcess::ExitStatus); void error(QProcess::ProcessError); diff --git a/launcher/java/JavaCheckerJob.cpp b/launcher/java/JavaCheckerJob.cpp index 48274974d..870e2a09a 100644 --- a/launcher/java/JavaCheckerJob.cpp +++ b/launcher/java/JavaCheckerJob.cpp @@ -20,14 +20,12 @@ void JavaCheckerJob::partFinished(JavaCheckResult result) { num_finished++; - qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/" - << javacheckers.size(); + qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/" << javacheckers.size(); setProgress(num_finished, javacheckers.size()); javaresults.replace(result.id, result); - if (num_finished == javacheckers.size()) - { + if (num_finished == javacheckers.size()) { emitSucceeded(); } } @@ -35,8 +33,7 @@ void JavaCheckerJob::partFinished(JavaCheckResult result) void JavaCheckerJob::executeTask() { qDebug() << m_job_name.toLocal8Bit() << " started."; - for (auto iter : javacheckers) - { + for (auto iter : javacheckers) { javaresults.append(JavaCheckResult()); connect(iter.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); iter->performCheck(); diff --git a/launcher/java/JavaCheckerJob.h b/launcher/java/JavaCheckerJob.h index c09864207..009687917 100644 --- a/launcher/java/JavaCheckerJob.h +++ b/launcher/java/JavaCheckerJob.h @@ -23,37 +23,32 @@ class JavaCheckerJob; typedef shared_qobject_ptr JavaCheckerJobPtr; // FIXME: this just seems horribly redundant -class JavaCheckerJob : public Task -{ +class JavaCheckerJob : public Task { Q_OBJECT -public: - explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name) {}; - virtual ~JavaCheckerJob() {}; + public: + explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name){}; + virtual ~JavaCheckerJob(){}; bool addJavaCheckerAction(JavaCheckerPtr base) { javacheckers.append(base); // if this is already running, the action needs to be started right away! - if (isRunning()) - { + if (isRunning()) { setProgress(num_finished, javacheckers.size()); connect(base.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); base->performCheck(); } return true; } - QList getResults() - { - return javaresults; - } + QList getResults() { return javaresults; } -private slots: + private slots: void partFinished(JavaCheckResult result); -protected: + protected: virtual void executeTask() override; -private: + private: QString m_job_name; QList javacheckers; QList javaresults; diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index 3407fdf72..d8be4963f 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -39,14 +39,12 @@ #include -#include "java/JavaInstallList.h" #include "java/JavaCheckerJob.h" +#include "java/JavaInstallList.h" #include "java/JavaUtils.h" #include "minecraft/VersionFilterData.h" -JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent) -{ -} +JavaInstallList::JavaInstallList(QObject* parent) : BaseVersionList(parent) {} Task::Ptr JavaInstallList::getLoadTask() { @@ -56,8 +54,7 @@ Task::Ptr JavaInstallList::getLoadTask() Task::Ptr JavaInstallList::getCurrentTask() { - if(m_status == Status::InProgress) - { + if (m_status == Status::InProgress) { return m_loadTask; } return nullptr; @@ -65,8 +62,7 @@ Task::Ptr JavaInstallList::getCurrentTask() void JavaInstallList::load() { - if(m_status != Status::InProgress) - { + if (m_status != Status::InProgress) { m_status = Status::InProgress; m_loadTask.reset(new JavaListLoadTask(this)); m_loadTask->start(); @@ -88,7 +84,7 @@ int JavaInstallList::count() const return m_vlist.count(); } -QVariant JavaInstallList::data(const QModelIndex &index, int role) const +QVariant JavaInstallList::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); @@ -97,8 +93,7 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const return QVariant(); auto version = std::dynamic_pointer_cast(m_vlist[index.row()]); - switch (role) - { + switch (role) { case SortRole: return -index.row(); case VersionPointerRole: @@ -120,17 +115,15 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const BaseVersionList::RoleList JavaInstallList::providesRoles() const { - return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole}; + return { VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole }; } - void JavaInstallList::updateListData(QList versions) { beginResetModel(); m_vlist = versions; sortVersions(); - if(m_vlist.size()) - { + if (m_vlist.size()) { auto best = std::dynamic_pointer_cast(m_vlist[0]); best->recommended = true; } @@ -153,15 +146,13 @@ void JavaInstallList::sortVersions() endResetModel(); } -JavaListLoadTask::JavaListLoadTask(JavaInstallList *vlist) : Task() +JavaListLoadTask::JavaListLoadTask(JavaInstallList* vlist) : Task() { m_list = vlist; m_currentRecommended = NULL; } -JavaListLoadTask::~JavaListLoadTask() -{ -} +JavaListLoadTask::~JavaListLoadTask() {} void JavaListLoadTask::executeTask() { @@ -176,8 +167,7 @@ void JavaListLoadTask::executeTask() qDebug() << "Probing the following Java paths: "; int id = 0; - for(QString candidate : candidate_paths) - { + for (QString candidate : candidate_paths) { qDebug() << " " << candidate; auto candidate_checker = new JavaChecker(); @@ -197,10 +187,8 @@ void JavaListLoadTask::javaCheckerFinished() auto results = m_job->getResults(); qDebug() << "Found the following valid Java installations:"; - for(JavaCheckResult result : results) - { - if(result.validity == JavaCheckResult::Validity::Valid) - { + for (JavaCheckResult result : results) { + if (result.validity == JavaCheckResult::Validity::Valid) { JavaInstallPtr javaVersion(new JavaInstall()); javaVersion->id = result.javaVersion; @@ -213,13 +201,11 @@ void JavaListLoadTask::javaCheckerFinished() } QList javas_bvp; - for (auto java : candidates) - { - //qDebug() << java->id << java->arch << " at " << java->path; + for (auto java : candidates) { + // qDebug() << java->id << java->arch << " at " << java->path; BaseVersion::Ptr bp_java = std::dynamic_pointer_cast(java); - if (bp_java) - { + if (bp_java) { javas_bvp.append(java); } } diff --git a/launcher/java/JavaInstallList.h b/launcher/java/JavaInstallList.h index 733dc7e1c..1eebadf23 100644 --- a/launcher/java/JavaInstallList.h +++ b/launcher/java/JavaInstallList.h @@ -15,8 +15,8 @@ #pragma once -#include #include +#include #include "BaseVersionList.h" #include "tasks/Task.h" @@ -28,17 +28,12 @@ class JavaListLoadTask; -class JavaInstallList : public BaseVersionList -{ +class JavaInstallList : public BaseVersionList { Q_OBJECT - enum class Status - { - NotDone, - InProgress, - Done - }; -public: - explicit JavaInstallList(QObject *parent = 0); + enum class Status { NotDone, InProgress, Done }; + + public: + explicit JavaInstallList(QObject* parent = 0); Task::Ptr getLoadTask() override; bool isLoaded() override; @@ -46,36 +41,35 @@ public: int count() const override; void sortVersions() override; - QVariant data(const QModelIndex &index, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; RoleList providesRoles() const override; -public slots: + public slots: void updateListData(QList versions) override; -protected: + protected: void load(); Task::Ptr getCurrentTask(); -protected: + protected: Status m_status = Status::NotDone; shared_qobject_ptr m_loadTask; QList m_vlist; }; -class JavaListLoadTask : public Task -{ +class JavaListLoadTask : public Task { Q_OBJECT -public: - explicit JavaListLoadTask(JavaInstallList *vlist); + public: + explicit JavaListLoadTask(JavaInstallList* vlist); virtual ~JavaListLoadTask(); void executeTask() override; -public slots: + public slots: void javaCheckerFinished(); -protected: + protected: shared_qobject_ptr m_job; - JavaInstallList *m_list; - JavaInstall *m_currentRecommended; + JavaInstallList* m_list; + JavaInstall* m_currentRecommended; }; diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index e55663aab..a44ebca25 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -33,24 +33,21 @@ * limitations under the License. */ -#include -#include #include +#include #include #include #include -#include "java/JavaUtils.h" -#include "java/JavaInstallList.h" -#include "FileSystem.h" #include "Application.h" +#include "FileSystem.h" +#include "java/JavaInstallList.h" +#include "java/JavaUtils.h" #define IBUS "@im=ibus" -JavaUtils::JavaUtils() -{ -} +JavaUtils::JavaUtils() {} QString stripVariableEntries(QString name, QString target, QString remove) { @@ -65,8 +62,7 @@ QString stripVariableEntries(QString name, QString target, QString remove) for (QString item : toRemove) { bool removed = targetItems.removeOne(item); if (!removed) - qWarning() << "Entry" << item - << "could not be stripped from variable" << name; + qWarning() << "Entry" << item << "could not be stripped from variable" << name; } return targetItems.join(delimiter); } @@ -77,20 +73,10 @@ QProcessEnvironment CleanEnviroment() QProcessEnvironment rawenv = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env; - QStringList ignored = - { - "JAVA_ARGS", - "CLASSPATH", - "CONFIGPATH", - "JAVA_HOME", - "JRE_HOME", - "_JAVA_OPTIONS", - "JAVA_OPTIONS", - "JAVA_TOOL_OPTIONS" - }; + QStringList ignored = { "JAVA_ARGS", "CLASSPATH", "CONFIGPATH", "JAVA_HOME", + "JRE_HOME", "_JAVA_OPTIONS", "JAVA_OPTIONS", "JAVA_TOOL_OPTIONS" }; - QStringList stripped = - { + QStringList stripped = { #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) "LD_LIBRARY_PATH", "LD_PRELOAD", @@ -98,12 +84,10 @@ QProcessEnvironment CleanEnviroment() "QT_PLUGIN_PATH", "QT_FONTPATH" }; - for(auto key: rawenv.keys()) - { + for (auto key : rawenv.keys()) { auto value = rawenv.value(key); // filter out dangerous java crap - if(ignored.contains(key)) - { + if (ignored.contains(key)) { qDebug() << "Env: ignoring" << key << value; continue; } @@ -111,13 +95,11 @@ QProcessEnvironment CleanEnviroment() // These are used to strip the original variables // If there is "LD_LIBRARY_PATH" and "LAUNCHER_LD_LIBRARY_PATH", we want to // remove all values in "LAUNCHER_LD_LIBRARY_PATH" from "LD_LIBRARY_PATH" - if(key.startsWith("LAUNCHER_")) - { + if (key.startsWith("LAUNCHER_")) { qDebug() << "Env: ignoring" << key << value; continue; } - if(stripped.contains(key)) - { + if (stripped.contains(key)) { QString newValue = stripVariableEntries(key, value, rawenv.value("LAUNCHER_" + key)); qDebug() << "Env: stripped" << key << value << "to" << newValue; @@ -125,8 +107,7 @@ QProcessEnvironment CleanEnviroment() #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) // Strip IBus // IBus is a Linux IME framework. For some reason, it breaks MC? - if (key == "XMODIFIERS" && value.contains(IBUS)) - { + if (key == "XMODIFIERS" && value.contains(IBUS)) { QString save = value; value.replace(IBUS, ""); qDebug() << "Env: stripped" << IBUS << "from" << save << ":" << value; @@ -137,8 +118,7 @@ QProcessEnvironment CleanEnviroment() } #ifdef Q_OS_LINUX // HACK: Workaround for QTBUG-42500 - if(!env.contains("LD_LIBRARY_PATH")) - { + if (!env.contains("LD_LIBRARY_PATH")) { env.insert("LD_LIBRARY_PATH", ""); } #endif @@ -177,7 +157,7 @@ QStringList addJavasFromEnv(QList javas) auto env = qEnvironmentVariable("PRISMLAUNCHER_JAVA_PATHS"); // FIXME: use launcher name from buildconfig #if defined(Q_OS_WIN32) QList javaPaths = env.replace("\\", "/").split(QLatin1String(";")); - + auto envPath = qEnvironmentVariable("PATH"); QList javaPathsfromPath = envPath.replace("\\", "/").split(QLatin1String(";")); for (QString string : javaPathsfromPath) { @@ -186,8 +166,7 @@ QStringList addJavasFromEnv(QList javas) #else QList javaPaths = env.split(QLatin1String(":")); #endif - for(QString i : javaPaths) - { + for (QString i : javaPaths) { javas.append(i); }; return javas; @@ -205,9 +184,8 @@ QList JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString archType = "32"; HKEY jreKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName.toStdWString().c_str(), 0, - KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS) - { + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName.toStdWString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == + ERROR_SUCCESS) { // Read the current type version from the registry. // This will be used to find any key that contains the JavaHome value. @@ -215,46 +193,36 @@ QList JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString DWORD subKeyNameSize, numSubKeys, retCode; // Get the number of subkeys - RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, - NULL, NULL); + RegQueryInfoKeyW(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); // Iterate until RegEnumKeyEx fails - if (numSubKeys > 0) - { - for (DWORD i = 0; i < numSubKeys; i++) - { + if (numSubKeys > 0) { + for (DWORD i = 0; i < numSubKeys; i++) { subKeyNameSize = 255; - retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, - NULL); + retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); QString newSubkeyName = QString::fromWCharArray(subKeyName); - if (retCode == ERROR_SUCCESS) - { + if (retCode == ERROR_SUCCESS) { // Now open the registry key for the version that we just got. QString newKeyName = keyName + "\\" + newSubkeyName + subkeySuffix; HKEY newKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, newKeyName.toStdWString().c_str(), 0, - KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS) - { + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, newKeyName.toStdWString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &newKey) == + ERROR_SUCCESS) { // Read the JavaHome value to find where Java is installed. DWORD valueSz = 0; - if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, - &valueSz) == ERROR_SUCCESS) - { - WCHAR *value = new WCHAR[valueSz]; - RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE *)value, - &valueSz); + if (RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, NULL, &valueSz) == ERROR_SUCCESS) { + WCHAR* value = new WCHAR[valueSz]; + RegQueryValueExW(newKey, keyJavaDir.toStdWString().c_str(), NULL, NULL, (BYTE*)value, &valueSz); QString newValue = QString::fromWCharArray(value); - delete [] value; + delete[] value; // Now, we construct the version object and add it to the list. JavaInstallPtr javaVersion(new JavaInstall()); javaVersion->id = newSubkeyName; javaVersion->arch = archType; - javaVersion->path = - QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); + javaVersion->path = QDir(FS::PathCombine(newValue, "bin")).absoluteFilePath("javaw.exe"); javas.append(javaVersion); } @@ -275,66 +243,56 @@ QList JavaUtils::FindJavaPaths() QList java_candidates; // Oracle - QList JRE64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); - QList JDK64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); - QList JRE32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); - QList JDK32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); + QList JRE64s = + this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); + QList JDK64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); + QList JRE32s = + this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome"); + QList JDK32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome"); // Oracle for Java 9 and newer - QList NEWJRE64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); - QList NEWJDK64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); - QList NEWJRE32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); - QList NEWJDK32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); + QList NEWJRE64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); + QList NEWJDK64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); + QList NEWJRE32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome"); + QList NEWJDK32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome"); // AdoptOpenJDK - QList ADOPTOPENJRE32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); - QList ADOPTOPENJRE64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); - QList ADOPTOPENJDK32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); - QList ADOPTOPENJDK64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); + QList ADOPTOPENJRE32s = + this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); + QList ADOPTOPENJRE64s = + this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI"); + QList ADOPTOPENJDK32s = + this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); + QList ADOPTOPENJDK64s = + this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI"); // Eclipse Foundation - QList FOUNDATIONJDK32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); - QList FOUNDATIONJDK64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); + QList FOUNDATIONJDK32s = + this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); + QList FOUNDATIONJDK64s = + this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI"); // Eclipse Adoptium - QList ADOPTIUMJRE32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); - QList ADOPTIUMJRE64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); - QList ADOPTIUMJDK32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); - QList ADOPTIUMJDK64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); + QList ADOPTIUMJRE32s = + this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); + QList ADOPTIUMJRE64s = + this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JRE", "Path", "\\hotspot\\MSI"); + QList ADOPTIUMJDK32s = + this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); + QList ADOPTIUMJDK64s = + this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI"); // Microsoft - QList MICROSOFTJDK64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\Microsoft\\JDK", "Path", "\\hotspot\\MSI"); + QList MICROSOFTJDK64s = + this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Microsoft\\JDK", "Path", "\\hotspot\\MSI"); // Azul Zulu - QList ZULU64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); - QList ZULU32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); + QList ZULU64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); + QList ZULU32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath"); // BellSoft Liberica - QList LIBERICA64s = this->FindJavaFromRegistryKey( - KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); - QList LIBERICA32s = this->FindJavaFromRegistryKey( - KEY_WOW64_32KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); + QList LIBERICA64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); + QList LIBERICA32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath"); // List x64 before x86 java_candidates.append(JRE64s); @@ -371,10 +329,8 @@ QList JavaUtils::FindJavaPaths() java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path)); QList candidates; - for(JavaInstallPtr java_candidate : java_candidates) - { - if(!candidates.contains(java_candidate->path)) - { + for (JavaInstallPtr java_candidate : java_candidates) { + if (!candidates.contains(java_candidate->path)) { candidates.append(java_candidate->path); } } @@ -394,13 +350,13 @@ QList JavaUtils::FindJavaPaths() javas.append("/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java"); QDir libraryJVMDir("/Library/Java/JavaVirtualMachines/"); QStringList libraryJVMJavas = libraryJVMDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - foreach (const QString &java, libraryJVMJavas) { + foreach (const QString& java, libraryJVMJavas) { javas.append(libraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java"); javas.append(libraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/jre/bin/java"); } QDir systemLibraryJVMDir("/System/Library/Java/JavaVirtualMachines/"); QStringList systemLibraryJVMJavas = systemLibraryJVMDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - foreach (const QString &java, systemLibraryJVMJavas) { + foreach (const QString& java, systemLibraryJVMJavas) { javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java"); javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java"); } @@ -414,14 +370,12 @@ QList JavaUtils::FindJavaPaths() { QList javas; javas.append(this->GetDefaultJava()->path); - auto scanJavaDir = [&](const QString & dirPath) - { + auto scanJavaDir = [&](const QString& dirPath) { QDir dir(dirPath); - if(!dir.exists()) + if (!dir.exists()) return; auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); - for(auto & entry: entries) - { + for (auto& entry : entries) { QString prefix; prefix = entry.canonicalFilePath(); javas.append(FS::PathCombine(prefix, "jre/bin/java")); @@ -430,8 +384,7 @@ QList JavaUtils::FindJavaPaths() }; // java installed in a snap is installed in the standard directory, but underneath $SNAP auto snap = qEnvironmentVariable("SNAP"); - auto scanJavaDirs = [&](const QString & dirPath) - { + auto scanJavaDirs = [&](const QString& dirPath) { scanJavaDir(dirPath); if (!snap.isNull()) { scanJavaDir(snap + dirPath); diff --git a/launcher/java/JavaUtils.h b/launcher/java/JavaUtils.h index 9b69b516e..616179706 100644 --- a/launcher/java/JavaUtils.h +++ b/launcher/java/JavaUtils.h @@ -27,10 +27,9 @@ QString stripVariableEntries(QString name, QString target, QString remove); QProcessEnvironment CleanEnviroment(); -class JavaUtils : public QObject -{ +class JavaUtils : public QObject { Q_OBJECT -public: + public: JavaUtils(); JavaInstallPtr MakeJavaPtr(QString path, QString id = "unknown", QString arch = "unknown"); diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp index 7124e22fb..f9ac47824 100644 --- a/launcher/java/JavaVersion.cpp +++ b/launcher/java/JavaVersion.cpp @@ -5,27 +5,22 @@ #include #include -JavaVersion & JavaVersion::operator=(const QString & javaVersionString) +JavaVersion& JavaVersion::operator=(const QString& javaVersionString) { m_string = javaVersionString; - auto getCapturedInteger = [](const QRegularExpressionMatch & match, const QString &what) -> int - { + auto getCapturedInteger = [](const QRegularExpressionMatch& match, const QString& what) -> int { auto str = match.captured(what); - if(str.isEmpty()) - { + if (str.isEmpty()) { return 0; } return str.toInt(); }; QRegularExpression pattern; - if(javaVersionString.startsWith("1.")) - { - pattern = QRegularExpression ("1[.](?[0-9]+)([.](?[0-9]+))?(_(?[0-9]+)?)?(-(?[a-zA-Z0-9]+))?"); - } - else - { + if (javaVersionString.startsWith("1.")) { + pattern = QRegularExpression("1[.](?[0-9]+)([.](?[0-9]+))?(_(?[0-9]+)?)?(-(?[a-zA-Z0-9]+))?"); + } else { pattern = QRegularExpression("(?[0-9]+)([.](?[0-9]+))?([.](?[0-9]+))?(-(?[a-zA-Z0-9]+))?"); } @@ -38,7 +33,7 @@ JavaVersion & JavaVersion::operator=(const QString & javaVersionString) return *this; } -JavaVersion::JavaVersion(const QString &rhs) +JavaVersion::JavaVersion(const QString& rhs) { operator=(rhs); } @@ -50,73 +45,65 @@ QString JavaVersion::toString() const bool JavaVersion::requiresPermGen() { - if(m_parseable) - { + if (m_parseable) { return m_major < 8; } return true; } -bool JavaVersion::operator<(const JavaVersion &rhs) +bool JavaVersion::operator<(const JavaVersion& rhs) { - if(m_parseable && rhs.m_parseable) - { + if (m_parseable && rhs.m_parseable) { auto major = m_major; auto rmajor = rhs.m_major; // HACK: discourage using java 9 - if(major > 8) + if (major > 8) major = -major; - if(rmajor > 8) + if (rmajor > 8) rmajor = -rmajor; - if(major < rmajor) + if (major < rmajor) return true; - if(major > rmajor) + if (major > rmajor) return false; - if(m_minor < rhs.m_minor) + if (m_minor < rhs.m_minor) return true; - if(m_minor > rhs.m_minor) + if (m_minor > rhs.m_minor) return false; - if(m_security < rhs.m_security) + if (m_security < rhs.m_security) return true; - if(m_security > rhs.m_security) + if (m_security > rhs.m_security) return false; // everything else being equal, consider prerelease status bool thisPre = !m_prerelease.isEmpty(); bool rhsPre = !rhs.m_prerelease.isEmpty(); - if(thisPre && !rhsPre) - { + if (thisPre && !rhsPre) { // this is a prerelease and the other one isn't -> lesser return true; - } - else if(!thisPre && rhsPre) - { + } else if (!thisPre && rhsPre) { // this isn't a prerelease and the other one is -> greater return false; - } - else if(thisPre && rhsPre) - { + } else if (thisPre && rhsPre) { // both are prereleases - use natural compare... return StringUtils::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0; } // neither is prerelease, so they are the same -> this cannot be less than rhs return false; - } - else return StringUtils::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0; + } else + return StringUtils::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0; } -bool JavaVersion::operator==(const JavaVersion &rhs) +bool JavaVersion::operator==(const JavaVersion& rhs) { - if(m_parseable && rhs.m_parseable) - { + if (m_parseable && rhs.m_parseable) { return m_major == rhs.m_major && m_minor == rhs.m_minor && m_security == rhs.m_security && m_prerelease == rhs.m_prerelease; } return m_string == rhs.m_string; } -bool JavaVersion::operator>(const JavaVersion &rhs) +bool JavaVersion::operator>(const JavaVersion& rhs) { return (!operator<(rhs)) && (!operator==(rhs)); } diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h index d74e0148d..7e66269cb 100644 --- a/launcher/java/JavaVersion.h +++ b/launcher/java/JavaVersion.h @@ -4,42 +4,34 @@ // NOTE: apparently the GNU C library pollutes the global namespace with these... undef them. #ifdef major - #undef major +#undef major #endif #ifdef minor - #undef minor +#undef minor #endif -class JavaVersion -{ +class JavaVersion { friend class JavaVersionTest; -public: + + public: JavaVersion() {} - JavaVersion(const QString & rhs); + JavaVersion(const QString& rhs); - JavaVersion & operator=(const QString & rhs); + JavaVersion& operator=(const QString& rhs); - bool operator<(const JavaVersion & rhs); - bool operator==(const JavaVersion & rhs); - bool operator>(const JavaVersion & rhs); + bool operator<(const JavaVersion& rhs); + bool operator==(const JavaVersion& rhs); + bool operator>(const JavaVersion& rhs); bool requiresPermGen(); QString toString() const; - int major() - { - return m_major; - } - int minor() - { - return m_minor; - } - int security() - { - return m_security; - } -private: + int major() { return m_major; } + int minor() { return m_minor; } + int security() { return m_security; } + + private: QString m_string; int m_major = 0; int m_minor = 0; diff --git a/launcher/launch/LaunchStep.cpp b/launcher/launch/LaunchStep.cpp index d6bb6e885..ebc534617 100644 --- a/launcher/launch/LaunchStep.cpp +++ b/launcher/launch/LaunchStep.cpp @@ -16,7 +16,7 @@ #include "LaunchStep.h" #include "LaunchTask.h" -void LaunchStep::bind(LaunchTask *parent) +void LaunchStep::bind(LaunchTask* parent) { m_parent = parent; connect(this, &LaunchStep::readyForLaunch, parent, &LaunchTask::onReadyForLaunch); diff --git a/launcher/launch/LaunchStep.h b/launcher/launch/LaunchStep.h index 3939f9604..b1bec2b4a 100644 --- a/launcher/launch/LaunchStep.h +++ b/launcher/launch/LaunchStep.h @@ -15,36 +15,32 @@ #pragma once -#include "tasks/Task.h" #include "MessageLevel.h" +#include "tasks/Task.h" #include class LaunchTask; -class LaunchStep: public Task -{ +class LaunchStep : public Task { Q_OBJECT -public: /* methods */ - explicit LaunchStep(LaunchTask *parent):Task(nullptr), m_parent(parent) - { - bind(parent); - }; - virtual ~LaunchStep() {}; + public: /* methods */ + explicit LaunchStep(LaunchTask* parent) : Task(nullptr), m_parent(parent) { bind(parent); }; + virtual ~LaunchStep(){}; -private: /* methods */ - void bind(LaunchTask *parent); + private: /* methods */ + void bind(LaunchTask* parent); -signals: + signals: void logLines(QStringList lines, MessageLevel::Enum level); void logLine(QString line, MessageLevel::Enum level); void readyForLaunch(); void progressReportingRequest(); -public slots: - virtual void proceed() {}; + public slots: + virtual void proceed(){}; // called in the opposite order than the Task launch(), used to clean up or otherwise undo things after the launch ends - virtual void finalize() {}; + virtual void finalize(){}; -protected: /* data */ - LaunchTask *m_parent; + protected: /* data */ + LaunchTask* m_parent; }; diff --git a/launcher/launch/LaunchTask.cpp b/launcher/launch/LaunchTask.cpp index 9e1794b34..902801a10 100644 --- a/launcher/launch/LaunchTask.cpp +++ b/launcher/launch/LaunchTask.cpp @@ -36,16 +36,16 @@ */ #include "launch/LaunchTask.h" -#include "MessageLevel.h" -#include "java/JavaChecker.h" -#include "tasks/Task.h" +#include +#include #include #include #include #include -#include #include -#include +#include "MessageLevel.h" +#include "java/JavaChecker.h" +#include "tasks/Task.h" void LaunchTask::init() { @@ -59,9 +59,7 @@ shared_qobject_ptr LaunchTask::create(InstancePtr inst) return proc; } -LaunchTask::LaunchTask(InstancePtr instance): m_instance(instance) -{ -} +LaunchTask::LaunchTask(InstancePtr instance) : m_instance(instance) {} void LaunchTask::appendStep(shared_qobject_ptr step) { @@ -76,8 +74,7 @@ void LaunchTask::prependStep(shared_qobject_ptr step) void LaunchTask::executeTask() { m_instance->setCrashed(false); - if(!m_steps.size()) - { + if (!m_steps.size()) { state = LaunchTask::Finished; emitSucceeded(); } @@ -94,46 +91,35 @@ void LaunchTask::onReadyForLaunch() void LaunchTask::onStepFinished() { // initial -> just start the first step - if(currentStep == -1) - { - currentStep ++; + if (currentStep == -1) { + currentStep++; m_steps[currentStep]->start(); return; } auto step = m_steps[currentStep]; - if(step->wasSuccessful()) - { + if (step->wasSuccessful()) { // end? - if(currentStep == m_steps.size() - 1) - { + if (currentStep == m_steps.size() - 1) { finalizeSteps(true, QString()); - } - else - { - currentStep ++; + } else { + currentStep++; step = m_steps[currentStep]; step->start(); } - } - else - { + } else { finalizeSteps(false, step->failReason()); } } void LaunchTask::finalizeSteps(bool successful, const QString& error) { - for(auto step = currentStep; step >= 0; step--) - { + for (auto step = currentStep; step >= 0; step--) { m_steps[step]->finalize(); } - if(successful) - { + if (successful) { emitSucceeded(); - } - else - { + } else { emitFailed(error); } } @@ -152,8 +138,7 @@ void LaunchTask::setCensorFilter(QMap filter) QString LaunchTask::censorPrivateInfo(QString in) { auto iter = m_censorFilter.begin(); - while (iter != m_censorFilter.end()) - { + while (iter != m_censorFilter.end()) { in.replace(iter.key(), iter.value()); iter++; } @@ -162,8 +147,7 @@ QString LaunchTask::censorPrivateInfo(QString in) void LaunchTask::proceed() { - if(state != LaunchTask::Waiting) - { + if (state != LaunchTask::Waiting) { return; } m_steps[currentStep]->proceed(); @@ -171,8 +155,7 @@ void LaunchTask::proceed() bool LaunchTask::canAbort() const { - switch(state) - { + switch (state) { case LaunchTask::Aborted: case LaunchTask::Failed: case LaunchTask::Finished: @@ -180,8 +163,7 @@ bool LaunchTask::canAbort() const case LaunchTask::NotStarted: return true; case LaunchTask::Running: - case LaunchTask::Waiting: - { + case LaunchTask::Waiting: { auto step = m_steps[currentStep]; return step->canAbort(); } @@ -191,28 +173,23 @@ bool LaunchTask::canAbort() const bool LaunchTask::abort() { - switch(state) - { + switch (state) { case LaunchTask::Aborted: case LaunchTask::Failed: case LaunchTask::Finished: return true; - case LaunchTask::NotStarted: - { + case LaunchTask::NotStarted: { state = LaunchTask::Aborted; emitFailed("Aborted"); return true; } case LaunchTask::Running: - case LaunchTask::Waiting: - { + case LaunchTask::Waiting: { auto step = m_steps[currentStep]; - if(!step->canAbort()) - { + if (!step->canAbort()) { return false; } - if(step->abort()) - { + if (step->abort()) { state = LaunchTask::Aborted; return true; } @@ -225,23 +202,22 @@ bool LaunchTask::abort() shared_qobject_ptr LaunchTask::getLogModel() { - if(!m_logModel) - { + if (!m_logModel) { m_logModel.reset(new LogModel()); m_logModel->setMaxLines(m_instance->getConsoleMaxLines()); m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow()); // FIXME: should this really be here? m_logModel->setOverflowMessage(tr("Stopped watching the game log because the log length surpassed %1 lines.\n" - "You may have to fix your mods because the game is still logging to files and" - " likely wasting harddrive space at an alarming rate!").arg(m_logModel->getMaxLines())); + "You may have to fix your mods because the game is still logging to files and" + " likely wasting harddrive space at an alarming rate!") + .arg(m_logModel->getMaxLines())); } return m_logModel; } -void LaunchTask::onLogLines(const QStringList &lines, MessageLevel::Enum defaultLevel) +void LaunchTask::onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel) { - for (auto & line: lines) - { + for (auto& line : lines) { onLogLine(line, defaultLevel); } } @@ -250,21 +226,19 @@ void LaunchTask::onLogLine(QString line, MessageLevel::Enum level) { // if the launcher part set a log level, use it auto innerLevel = MessageLevel::fromLine(line); - if(innerLevel != MessageLevel::Unknown) - { + if (innerLevel != MessageLevel::Unknown) { level = innerLevel; } // If the level is still undetermined, guess level - if (level == MessageLevel::StdErr || level == MessageLevel::StdOut || level == MessageLevel::Unknown) - { + if (level == MessageLevel::StdErr || level == MessageLevel::StdOut || level == MessageLevel::Unknown) { level = m_instance->guessLevel(line, level); } // censor private user info line = censorPrivateInfo(line); - auto &model = *getLogModel(); + auto& model = *getLogModel(); model.append(level, line); } @@ -281,22 +255,20 @@ void LaunchTask::emitFailed(QString reason) Task::emitFailed(reason); } -void LaunchTask::substituteVariables(QStringList &args) const +void LaunchTask::substituteVariables(QStringList& args) const { auto env = m_instance->createEnvironment(); - for (auto key : env.keys()) - { + for (auto key : env.keys()) { args.replaceInStrings("$" + key, env.value(key)); } } -void LaunchTask::substituteVariables(QString &cmd) const +void LaunchTask::substituteVariables(QString& cmd) const { auto env = m_instance->createEnvironment(); - for (auto key : env.keys()) - { + for (auto key : env.keys()) { cmd.replace("$" + key, env.value(key)); } } diff --git a/launcher/launch/LaunchTask.h b/launcher/launch/LaunchTask.h index 9c72b23f0..40a3324ba 100644 --- a/launcher/launch/LaunchTask.h +++ b/launcher/launch/LaunchTask.h @@ -36,54 +36,36 @@ */ #pragma once -#include #include -#include "LogModel.h" +#include #include "BaseInstance.h" -#include "MessageLevel.h" -#include "LoggedProcess.h" #include "LaunchStep.h" +#include "LogModel.h" +#include "LoggedProcess.h" +#include "MessageLevel.h" -class LaunchTask: public Task -{ +class LaunchTask : public Task { Q_OBJECT -protected: + protected: explicit LaunchTask(InstancePtr instance); void init(); -public: - enum State - { - NotStarted, - Running, - Waiting, - Failed, - Aborted, - Finished - }; + public: + enum State { NotStarted, Running, Waiting, Failed, Aborted, Finished }; -public: /* methods */ + public: /* methods */ static shared_qobject_ptr create(InstancePtr inst); - virtual ~LaunchTask() {}; + virtual ~LaunchTask(){}; void appendStep(shared_qobject_ptr step); void prependStep(shared_qobject_ptr step); void setCensorFilter(QMap filter); - InstancePtr instance() - { - return m_instance; - } + InstancePtr instance() { return m_instance; } - void setPid(qint64 pid) - { - m_pid = pid; - } + void setPid(qint64 pid) { m_pid = pid; } - qint64 pid() - { - return m_pid; - } + qint64 pid() { return m_pid; } /** * @brief prepare the process for launch (for multi-stage launch) @@ -104,39 +86,39 @@ public: /* methods */ shared_qobject_ptr getLogModel(); -public: - void substituteVariables(QStringList &args) const; - void substituteVariables(QString &cmd) const; + public: + void substituteVariables(QStringList& args) const; + void substituteVariables(QString& cmd) const; QString censorPrivateInfo(QString in); -protected: /* methods */ + protected: /* methods */ virtual void emitFailed(QString reason) override; virtual void emitSucceeded() override; -signals: + signals: /** * @brief emitted when the launch preparations are done */ void readyForLaunch(); - void requestProgress(Task *task); + void requestProgress(Task* task); void requestLogging(); -public slots: + public slots: void onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel = MessageLevel::Launcher); void onLogLine(QString line, MessageLevel::Enum defaultLevel = MessageLevel::Launcher); void onReadyForLaunch(); void onStepFinished(); void onProgressReportingRequested(); -private: /*methods */ - void finalizeSteps(bool successful, const QString & error); + private: /*methods */ + void finalizeSteps(bool successful, const QString& error); -protected: /* data */ + protected: /* data */ InstancePtr m_instance; shared_qobject_ptr m_logModel; - QList > m_steps; + QList> m_steps; QMap m_censorFilter; int currentStep = -1; State state = NotStarted; diff --git a/launcher/launch/LogModel.cpp b/launcher/launch/LogModel.cpp index 92f9487a9..23a33ae18 100644 --- a/launcher/launch/LogModel.cpp +++ b/launcher/launch/LogModel.cpp @@ -1,11 +1,11 @@ #include "LogModel.h" -LogModel::LogModel(QObject *parent):QAbstractListModel(parent) +LogModel::LogModel(QObject* parent) : QAbstractListModel(parent) { m_content.resize(m_maxLines); } -int LogModel::rowCount(const QModelIndex &parent) const +int LogModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; @@ -13,19 +13,17 @@ int LogModel::rowCount(const QModelIndex &parent) const return m_numLines; } -QVariant LogModel::data(const QModelIndex &index, int role) const +QVariant LogModel::data(const QModelIndex& index, int role) const { if (index.row() < 0 || index.row() >= m_numLines) return QVariant(); auto row = index.row(); auto realRow = (row + m_firstLine) % m_maxLines; - if (role == Qt::DisplayRole || role == Qt::EditRole) - { + if (role == Qt::DisplayRole || role == Qt::EditRole) { return m_content[realRow].line; } - if(role == LevelRole) - { + if (role == LevelRole) { return m_content[realRow].level; } @@ -34,31 +32,26 @@ QVariant LogModel::data(const QModelIndex &index, int role) const void LogModel::append(MessageLevel::Enum level, QString line) { - if(m_suspended) - { + if (m_suspended) { return; } int lineNum = (m_firstLine + m_numLines) % m_maxLines; // overflow - if(m_numLines == m_maxLines) - { - if(m_stopOnOverflow) - { + if (m_numLines == m_maxLines) { + if (m_stopOnOverflow) { // nothing more to do, the buffer is full return; } beginRemoveRows(QModelIndex(), 0, 0); m_firstLine = (m_firstLine + 1) % m_maxLines; - m_numLines --; + m_numLines--; endRemoveRows(); - } - else if (m_numLines == m_maxLines - 1 && m_stopOnOverflow) - { + } else if (m_numLines == m_maxLines - 1 && m_stopOnOverflow) { level = MessageLevel::Fatal; line = m_overflowMessage; } beginInsertRows(QModelIndex(), m_numLines, m_numLines); - m_numLines ++; + m_numLines++; m_content[lineNum].level = level; m_content[lineNum].line = line; endInsertRows(); @@ -86,9 +79,8 @@ QString LogModel::toPlainText() { QString out; out.reserve(m_numLines * 80); - for(int i = 0; i < m_numLines; i++) - { - QString & line = m_content[(m_firstLine + i) % m_maxLines].line; + for (int i = 0; i < m_numLines; i++) { + QString& line = m_content[(m_firstLine + i) % m_maxLines].line; out.append(line + '\n'); } out.squeeze(); @@ -98,13 +90,11 @@ QString LogModel::toPlainText() void LogModel::setMaxLines(int maxLines) { // no-op - if(maxLines == m_maxLines) - { + if (maxLines == m_maxLines) { return; } // if it all still fits in the buffer, just resize it - if(m_firstLine + m_numLines < m_maxLines) - { + if (m_firstLine + m_numLines < m_maxLines) { m_maxLines = maxLines; m_content.resize(maxLines); return; @@ -112,22 +102,17 @@ void LogModel::setMaxLines(int maxLines) // otherwise, we need to reorganize the data because it crosses the wrap boundary QVector newContent; newContent.resize(maxLines); - if(m_numLines <= maxLines) - { + if (m_numLines <= maxLines) { // if it all fits in the new buffer, just copy it over - for(int i = 0; i < m_numLines; i++) - { + for (int i = 0; i < m_numLines; i++) { newContent[i] = m_content[(m_firstLine + i) % m_maxLines]; } m_content.swap(newContent); - } - else - { + } else { // if it doesn't fit, part of the data needs to be thrown away (the oldest log messages) int lead = m_numLines - maxLines; beginRemoveRows(QModelIndex(), 0, lead - 1); - for(int i = 0; i < maxLines; i++) - { + for (int i = 0; i < maxLines; i++) { newContent[i] = m_content[(m_firstLine + lead + i) % m_maxLines]; } m_numLines = m_maxLines; @@ -155,8 +140,7 @@ void LogModel::setOverflowMessage(const QString& overflowMessage) void LogModel::setLineWrap(bool state) { - if(m_lineWrap != state) - { + if (m_lineWrap != state) { m_lineWrap = state; } } diff --git a/launcher/launch/LogModel.h b/launcher/launch/LogModel.h index 6aabc8236..ba2e4054a 100644 --- a/launcher/launch/LogModel.h +++ b/launcher/launch/LogModel.h @@ -4,14 +4,13 @@ #include #include "MessageLevel.h" -class LogModel : public QAbstractListModel -{ +class LogModel : public QAbstractListModel { Q_OBJECT -public: - explicit LogModel(QObject *parent = 0); + public: + explicit LogModel(QObject* parent = 0); - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role) const; + int rowCount(const QModelIndex& parent = QModelIndex()) const; + QVariant data(const QModelIndex& index, int role) const; void append(MessageLevel::Enum, QString line); void clear(); @@ -24,25 +23,21 @@ public: int getMaxLines(); void setMaxLines(int maxLines); void setStopOnOverflow(bool stop); - void setOverflowMessage(const QString & overflowMessage); + void setOverflowMessage(const QString& overflowMessage); void setLineWrap(bool state); bool wrapLines() const; - enum Roles - { - LevelRole = Qt::UserRole - }; + enum Roles { LevelRole = Qt::UserRole }; -private /* types */: - struct entry - { + private /* types */: + struct entry { MessageLevel::Enum level; QString line; }; -private: /* data */ - QVector m_content; + private: /* data */ + QVector m_content; int m_maxLines = 1000; // first line in the circular buffer int m_firstLine = 0; @@ -53,6 +48,6 @@ private: /* data */ bool m_suspended = false; bool m_lineWrap = true; -private: + private: Q_DISABLE_COPY(LogModel) }; diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index 7d697ba96..7fd8fc331 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -34,12 +34,12 @@ */ #include "CheckJava.h" -#include "java/JavaUtils.h" -#include #include -#include -#include +#include #include +#include +#include +#include "java/JavaUtils.h" void CheckJava::executeTask() { @@ -49,32 +49,26 @@ void CheckJava::executeTask() bool perInstance = settings->get("OverrideJava").toBool() || settings->get("OverrideJavaLocation").toBool(); auto realJavaPath = QStandardPaths::findExecutable(m_javaPath); - if (realJavaPath.isEmpty()) - { - if (perInstance) - { - emit logLine( - QString("The java binary \"%1\" couldn't be found. Please fix the java path " - "override in the instance's settings or disable it.").arg(m_javaPath), - MessageLevel::Warning); - } - else - { + if (realJavaPath.isEmpty()) { + if (perInstance) { + emit logLine(QString("The java binary \"%1\" couldn't be found. Please fix the java path " + "override in the instance's settings or disable it.") + .arg(m_javaPath), + MessageLevel::Warning); + } else { emit logLine(QString("The java binary \"%1\" couldn't be found. Please set up java in " - "the settings.").arg(m_javaPath), + "the settings.") + .arg(m_javaPath), MessageLevel::Warning); } emitFailed(QString("Java path is not valid.")); return; - } - else - { + } else { emit logLine("Java path is:\n" + m_javaPath + "\n\n", MessageLevel::Launcher); } - if (JavaUtils::getJavaCheckPath().isEmpty()) - { - const char *reason = QT_TR_NOOP("Java checker library could not be found. Please check your installation."); + if (JavaUtils::getJavaCheckPath().isEmpty()) { + const char* reason = QT_TR_NOOP("Java checker library could not be found. Please check your installation."); emit logLine(tr(reason), MessageLevel::Fatal); emitFailed(tr(reason)); return; @@ -94,19 +88,15 @@ void CheckJava::executeTask() m_javaSignature = hash.result().toHex(); // if timestamps are not the same, or something is missing, check! - if (m_javaSignature != storedSignature || storedVersion.size() == 0 - || storedArchitecture.size() == 0 || storedRealArchitecture.size() == 0 - || storedVendor.size() == 0) - { + if (m_javaSignature != storedSignature || storedVersion.size() == 0 || storedArchitecture.size() == 0 || + storedRealArchitecture.size() == 0 || storedVendor.size() == 0) { m_JavaChecker.reset(new JavaChecker); emit logLine(QString("Checking Java version..."), MessageLevel::Launcher); connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished); m_JavaChecker->m_path = realJavaPath; m_JavaChecker->performCheck(); return; - } - else - { + } else { auto verString = instance->settings()->get("JavaVersion").toString(); auto archString = instance->settings()->get("JavaArchitecture").toString(); auto realArchString = settings->get("JavaRealArchitecture").toString(); @@ -118,10 +108,8 @@ void CheckJava::executeTask() void CheckJava::checkJavaFinished(JavaCheckResult result) { - switch (result.validity) - { - case JavaCheckResult::Validity::Errored: - { + switch (result.validity) { + case JavaCheckResult::Validity::Errored: { // Error message displayed if java can't start emit logLine(QString("Could not start java:"), MessageLevel::Error); emit logLines(result.errorLog.split('\n'), MessageLevel::Error); @@ -129,16 +117,14 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) emitFailed(QString("Could not start java!")); return; } - case JavaCheckResult::Validity::ReturnedInvalidData: - { + case JavaCheckResult::Validity::ReturnedInvalidData: { emit logLine(QString("Java checker returned some invalid data we don't understand:"), MessageLevel::Error); emit logLines(result.outLog.split('\n'), MessageLevel::Warning); emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher); emitSucceeded(); return; } - case JavaCheckResult::Validity::Valid: - { + case JavaCheckResult::Validity::Valid: { auto instance = m_parent->instance(); printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.realPlatform, result.javaVendor); instance->settings()->set("JavaVersion", result.javaVersion.toString()); @@ -152,8 +138,9 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) } } -void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString & vendor) +void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor) { - emit logLine(QString("Java is version %1, using %2 (%3) architecture, from %4.\n\n") - .arg(version, architecture, realArchitecture, vendor), MessageLevel::Launcher); + emit logLine( + QString("Java is version %1, using %2 (%3) architecture, from %4.\n\n").arg(version, architecture, realArchitecture, vendor), + MessageLevel::Launcher); } diff --git a/launcher/launch/steps/CheckJava.h b/launcher/launch/steps/CheckJava.h index bbf06b7c7..4436e2a55 100644 --- a/launcher/launch/steps/CheckJava.h +++ b/launcher/launch/steps/CheckJava.h @@ -15,30 +15,26 @@ #pragma once -#include #include #include +#include -class CheckJava: public LaunchStep -{ +class CheckJava : public LaunchStep { Q_OBJECT -public: - explicit CheckJava(LaunchTask *parent) :LaunchStep(parent){}; - virtual ~CheckJava() {}; + public: + explicit CheckJava(LaunchTask* parent) : LaunchStep(parent){}; + virtual ~CheckJava(){}; virtual void executeTask(); - virtual bool canAbort() const - { - return false; - } -private slots: + virtual bool canAbort() const { return false; } + private slots: void checkJavaFinished(JavaCheckResult result); -private: - void printJavaInfo(const QString & version, const QString & architecture, const QString & realArchitecture, const QString & vendor); + private: + void printJavaInfo(const QString& version, const QString& architecture, const QString& realArchitecture, const QString& vendor); void printSystemInfo(bool javaIsKnown, bool javaIs64bit); -private: + private: QString m_javaPath; QString m_javaSignature; JavaCheckerPtr m_JavaChecker; diff --git a/launcher/launch/steps/LookupServerAddress.cpp b/launcher/launch/steps/LookupServerAddress.cpp index c7b8cea47..9bdac203b 100644 --- a/launcher/launch/steps/LookupServerAddress.cpp +++ b/launcher/launch/steps/LookupServerAddress.cpp @@ -13,20 +13,18 @@ * limitations under the License. */ - #include "LookupServerAddress.h" #include -LookupServerAddress::LookupServerAddress(LaunchTask *parent) : - LaunchStep(parent), m_dnsLookup(new QDnsLookup(this)) +LookupServerAddress::LookupServerAddress(LaunchTask* parent) : LaunchStep(parent), m_dnsLookup(new QDnsLookup(this)) { connect(m_dnsLookup, &QDnsLookup::finished, this, &LookupServerAddress::on_dnsLookupFinished); m_dnsLookup->setType(QDnsLookup::SRV); } -void LookupServerAddress::setLookupAddress(const QString &lookupAddress) +void LookupServerAddress::setLookupAddress(const QString& lookupAddress) { m_lookupAddress = lookupAddress; m_dnsLookup->setName(QString("_minecraft._tcp.%1").arg(lookupAddress)); @@ -51,41 +49,40 @@ void LookupServerAddress::executeTask() void LookupServerAddress::on_dnsLookupFinished() { - if (isFinished()) - { + if (isFinished()) { // Aborted return; } - if (m_dnsLookup->error() != QDnsLookup::NoError) - { + if (m_dnsLookup->error() != QDnsLookup::NoError) { emit logLine(QString("Failed to resolve server address (this is NOT an error!) %1: %2\n") - .arg(m_dnsLookup->name(), m_dnsLookup->errorString()), MessageLevel::Launcher); - resolve(m_lookupAddress, 25565); // Technically the task failed, however, we don't abort the launch - // and leave it up to minecraft to fail (or maybe not) when connecting + .arg(m_dnsLookup->name(), m_dnsLookup->errorString()), + MessageLevel::Launcher); + resolve(m_lookupAddress, 25565); // Technically the task failed, however, we don't abort the launch + // and leave it up to minecraft to fail (or maybe not) when connecting return; } const auto records = m_dnsLookup->serviceRecords(); - if (records.empty()) - { - emit logLine( - QString("Failed to resolve server address %1: the DNS lookup succeeded, but no records were returned.\n") - .arg(m_dnsLookup->name()), MessageLevel::Warning); - resolve(m_lookupAddress, 25565); // Technically the task failed, however, we don't abort the launch - // and leave it up to minecraft to fail (or maybe not) when connecting + if (records.empty()) { + emit logLine(QString("Failed to resolve server address %1: the DNS lookup succeeded, but no records were returned.\n") + .arg(m_dnsLookup->name()), + MessageLevel::Warning); + resolve(m_lookupAddress, 25565); // Technically the task failed, however, we don't abort the launch + // and leave it up to minecraft to fail (or maybe not) when connecting return; } - const auto &firstRecord = records.at(0); + const auto& firstRecord = records.at(0); quint16 port = firstRecord.port(); - emit logLine(QString("Resolved server address %1 to %2 with port %3\n").arg( - m_dnsLookup->name(), firstRecord.target(), QString::number(port)),MessageLevel::Launcher); + emit logLine( + QString("Resolved server address %1 to %2 with port %3\n").arg(m_dnsLookup->name(), firstRecord.target(), QString::number(port)), + MessageLevel::Launcher); resolve(firstRecord.target(), port); } -void LookupServerAddress::resolve(const QString &address, quint16 port) +void LookupServerAddress::resolve(const QString& address, quint16 port) { m_output->address = address; m_output->port = port; diff --git a/launcher/launch/steps/LookupServerAddress.h b/launcher/launch/steps/LookupServerAddress.h index 5a5c3de17..abd92a5e8 100644 --- a/launcher/launch/steps/LookupServerAddress.h +++ b/launcher/launch/steps/LookupServerAddress.h @@ -15,35 +15,32 @@ #pragma once -#include #include +#include #include #include "minecraft/launch/MinecraftServerTarget.h" -class LookupServerAddress: public LaunchStep { -Q_OBJECT -public: - explicit LookupServerAddress(LaunchTask *parent); - virtual ~LookupServerAddress() {}; +class LookupServerAddress : public LaunchStep { + Q_OBJECT + public: + explicit LookupServerAddress(LaunchTask* parent); + virtual ~LookupServerAddress(){}; virtual void executeTask(); virtual bool abort(); - virtual bool canAbort() const - { - return true; - } + virtual bool canAbort() const { return true; } - void setLookupAddress(const QString &lookupAddress); + void setLookupAddress(const QString& lookupAddress); void setOutputAddressPtr(MinecraftServerTargetPtr output); -private slots: + private slots: void on_dnsLookupFinished(); -private: - void resolve(const QString &address, quint16 port); + private: + void resolve(const QString& address, quint16 port); - QDnsLookup *m_dnsLookup; + QDnsLookup* m_dnsLookup; QString m_lookupAddress; MinecraftServerTargetPtr m_output; }; diff --git a/launcher/launch/steps/PostLaunchCommand.cpp b/launcher/launch/steps/PostLaunchCommand.cpp index ccf07f220..2e59de630 100644 --- a/launcher/launch/steps/PostLaunchCommand.cpp +++ b/launcher/launch/steps/PostLaunchCommand.cpp @@ -36,7 +36,7 @@ #include "PostLaunchCommand.h" #include -PostLaunchCommand::PostLaunchCommand(LaunchTask *parent) : LaunchStep(parent) +PostLaunchCommand::PostLaunchCommand(LaunchTask* parent) : LaunchStep(parent) { auto instance = m_parent->instance(); m_command = instance->getPostExitCommand(); @@ -47,7 +47,7 @@ PostLaunchCommand::PostLaunchCommand(LaunchTask *parent) : LaunchStep(parent) void PostLaunchCommand::executeTask() { - //FIXME: where to put this? + // FIXME: where to put this? #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) auto args = QProcess::splitCommand(m_command); m_parent->substituteVariables(args); @@ -65,31 +65,22 @@ void PostLaunchCommand::executeTask() void PostLaunchCommand::on_state(LoggedProcess::State state) { - auto getError = [&]() - { - return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); - }; - switch(state) - { + auto getError = [&]() { return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); }; + switch (state) { case LoggedProcess::Aborted: case LoggedProcess::Crashed: - case LoggedProcess::FailedToStart: - { + case LoggedProcess::FailedToStart: { auto error = getError(); emit logLine(error, MessageLevel::Fatal); emitFailed(error); return; } - case LoggedProcess::Finished: - { - if(m_process.exitCode() != 0) - { + case LoggedProcess::Finished: { + if (m_process.exitCode() != 0) { auto error = getError(); emit logLine(error, MessageLevel::Fatal); emitFailed(error); - } - else - { + } else { emit logLine(tr("Post-Launch command ran successfully.\n\n"), MessageLevel::Launcher); emitSucceeded(); } @@ -99,7 +90,7 @@ void PostLaunchCommand::on_state(LoggedProcess::State state) } } -void PostLaunchCommand::setWorkingDirectory(const QString &wd) +void PostLaunchCommand::setWorkingDirectory(const QString& wd) { m_process.setWorkingDirectory(wd); } @@ -107,8 +98,7 @@ void PostLaunchCommand::setWorkingDirectory(const QString &wd) bool PostLaunchCommand::abort() { auto state = m_process.state(); - if (state == LoggedProcess::Running || state == LoggedProcess::Starting) - { + if (state == LoggedProcess::Running || state == LoggedProcess::Starting) { m_process.kill(); } return true; diff --git a/launcher/launch/steps/PostLaunchCommand.h b/launcher/launch/steps/PostLaunchCommand.h index ab4c494f5..578433b86 100644 --- a/launcher/launch/steps/PostLaunchCommand.h +++ b/launcher/launch/steps/PostLaunchCommand.h @@ -15,27 +15,23 @@ #pragma once -#include #include +#include -class PostLaunchCommand: public LaunchStep -{ +class PostLaunchCommand : public LaunchStep { Q_OBJECT -public: - explicit PostLaunchCommand(LaunchTask *parent); - virtual ~PostLaunchCommand() {}; + public: + explicit PostLaunchCommand(LaunchTask* parent); + virtual ~PostLaunchCommand(){}; virtual void executeTask(); virtual bool abort(); - virtual bool canAbort() const - { - return true; - } - void setWorkingDirectory(const QString &wd); -private slots: + virtual bool canAbort() const { return true; } + void setWorkingDirectory(const QString& wd); + private slots: void on_state(LoggedProcess::State state); -private: + private: LoggedProcess m_process; QString m_command; }; diff --git a/launcher/launch/steps/PreLaunchCommand.cpp b/launcher/launch/steps/PreLaunchCommand.cpp index 0b0392cbb..a7f36086b 100644 --- a/launcher/launch/steps/PreLaunchCommand.cpp +++ b/launcher/launch/steps/PreLaunchCommand.cpp @@ -36,7 +36,7 @@ #include "PreLaunchCommand.h" #include -PreLaunchCommand::PreLaunchCommand(LaunchTask *parent) : LaunchStep(parent) +PreLaunchCommand::PreLaunchCommand(LaunchTask* parent) : LaunchStep(parent) { auto instance = m_parent->instance(); m_command = instance->getPreLaunchCommand(); @@ -47,7 +47,7 @@ PreLaunchCommand::PreLaunchCommand(LaunchTask *parent) : LaunchStep(parent) void PreLaunchCommand::executeTask() { - //FIXME: where to put this? + // FIXME: where to put this? #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) auto args = QProcess::splitCommand(m_command); m_parent->substituteVariables(args); @@ -65,31 +65,22 @@ void PreLaunchCommand::executeTask() void PreLaunchCommand::on_state(LoggedProcess::State state) { - auto getError = [&]() - { - return tr("Pre-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); - }; - switch(state) - { + auto getError = [&]() { return tr("Pre-Launch command failed with code %1.\n\n").arg(m_process.exitCode()); }; + switch (state) { case LoggedProcess::Aborted: case LoggedProcess::Crashed: - case LoggedProcess::FailedToStart: - { + case LoggedProcess::FailedToStart: { auto error = getError(); emit logLine(error, MessageLevel::Fatal); emitFailed(error); return; } - case LoggedProcess::Finished: - { - if(m_process.exitCode() != 0) - { + case LoggedProcess::Finished: { + if (m_process.exitCode() != 0) { auto error = getError(); emit logLine(error, MessageLevel::Fatal); emitFailed(error); - } - else - { + } else { emit logLine(tr("Pre-Launch command ran successfully.\n\n"), MessageLevel::Launcher); emitSucceeded(); } @@ -99,7 +90,7 @@ void PreLaunchCommand::on_state(LoggedProcess::State state) } } -void PreLaunchCommand::setWorkingDirectory(const QString &wd) +void PreLaunchCommand::setWorkingDirectory(const QString& wd) { m_process.setWorkingDirectory(wd); } @@ -107,8 +98,7 @@ void PreLaunchCommand::setWorkingDirectory(const QString &wd) bool PreLaunchCommand::abort() { auto state = m_process.state(); - if (state == LoggedProcess::Running || state == LoggedProcess::Starting) - { + if (state == LoggedProcess::Running || state == LoggedProcess::Starting) { m_process.kill(); } return true; diff --git a/launcher/launch/steps/PreLaunchCommand.h b/launcher/launch/steps/PreLaunchCommand.h index dc069f71b..10568ea34 100644 --- a/launcher/launch/steps/PreLaunchCommand.h +++ b/launcher/launch/steps/PreLaunchCommand.h @@ -15,27 +15,23 @@ #pragma once -#include "launch/LaunchStep.h" #include "LoggedProcess.h" +#include "launch/LaunchStep.h" -class PreLaunchCommand: public LaunchStep -{ +class PreLaunchCommand : public LaunchStep { Q_OBJECT -public: - explicit PreLaunchCommand(LaunchTask *parent); - virtual ~PreLaunchCommand() {}; + public: + explicit PreLaunchCommand(LaunchTask* parent); + virtual ~PreLaunchCommand(){}; virtual void executeTask(); virtual bool abort(); - virtual bool canAbort() const - { - return true; - } - void setWorkingDirectory(const QString &wd); -private slots: + virtual bool canAbort() const { return true; } + void setWorkingDirectory(const QString& wd); + private slots: void on_state(LoggedProcess::State state); -private: + private: LoggedProcess m_process; QString m_command; }; diff --git a/launcher/launch/steps/QuitAfterGameStop.h b/launcher/launch/steps/QuitAfterGameStop.h index 1ce14da95..5f5e63048 100644 --- a/launcher/launch/steps/QuitAfterGameStop.h +++ b/launcher/launch/steps/QuitAfterGameStop.h @@ -20,16 +20,12 @@ #include -class QuitAfterGameStop: public LaunchStep -{ +class QuitAfterGameStop : public LaunchStep { Q_OBJECT -public: - explicit QuitAfterGameStop(LaunchTask *parent) :LaunchStep(parent){}; - virtual ~QuitAfterGameStop() {}; + public: + explicit QuitAfterGameStop(LaunchTask* parent) : LaunchStep(parent){}; + virtual ~QuitAfterGameStop(){}; virtual void executeTask(); - virtual bool canAbort() const - { - return false; - } + virtual bool canAbort() const { return false; } }; diff --git a/launcher/launch/steps/TextPrint.cpp b/launcher/launch/steps/TextPrint.cpp index 0c1f320c3..0dec35b79 100644 --- a/launcher/launch/steps/TextPrint.cpp +++ b/launcher/launch/steps/TextPrint.cpp @@ -1,11 +1,11 @@ #include "TextPrint.h" -TextPrint::TextPrint(LaunchTask * parent, const QStringList &lines, MessageLevel::Enum level) : LaunchStep(parent) +TextPrint::TextPrint(LaunchTask* parent, const QStringList& lines, MessageLevel::Enum level) : LaunchStep(parent) { m_lines = lines; m_level = level; } -TextPrint::TextPrint(LaunchTask *parent, const QString &line, MessageLevel::Enum level) : LaunchStep(parent) +TextPrint::TextPrint(LaunchTask* parent, const QString& line, MessageLevel::Enum level) : LaunchStep(parent) { m_lines.append(line); m_level = level; diff --git a/launcher/launch/steps/TextPrint.h b/launcher/launch/steps/TextPrint.h index 36fa7f9a9..bd6c28567 100644 --- a/launcher/launch/steps/TextPrint.h +++ b/launcher/launch/steps/TextPrint.h @@ -15,27 +15,26 @@ #pragma once -#include #include #include +#include /* * FIXME: maybe do not export */ -class TextPrint: public LaunchStep -{ +class TextPrint : public LaunchStep { Q_OBJECT -public: - explicit TextPrint(LaunchTask *parent, const QStringList &lines, MessageLevel::Enum level); - explicit TextPrint(LaunchTask *parent, const QString &line, MessageLevel::Enum level); + public: + explicit TextPrint(LaunchTask* parent, const QStringList& lines, MessageLevel::Enum level); + explicit TextPrint(LaunchTask* parent, const QString& line, MessageLevel::Enum level); virtual ~TextPrint(){}; virtual void executeTask(); virtual bool canAbort() const; virtual bool abort(); -private: + private: QStringList m_lines; MessageLevel::Enum m_level; }; diff --git a/launcher/launch/steps/Update.cpp b/launcher/launch/steps/Update.cpp index 8df2bc67c..f23c0bb4b 100644 --- a/launcher/launch/steps/Update.cpp +++ b/launcher/launch/steps/Update.cpp @@ -18,14 +18,12 @@ void Update::executeTask() { - if(m_aborted) - { + if (m_aborted) { emitFailed(tr("Task aborted.")); return; } m_updateTask.reset(m_parent->instance()->createUpdateTask(m_mode)); - if(m_updateTask) - { + if (m_updateTask) { connect(m_updateTask.get(), &Task::finished, this, &Update::updateFinished); connect(m_updateTask.get(), &Task::progress, this, &Update::setProgress); connect(m_updateTask.get(), &Task::stepProgress, this, &Update::propagateStepProgress); @@ -44,13 +42,10 @@ void Update::proceed() void Update::updateFinished() { - if(m_updateTask->wasSuccessful()) - { + if (m_updateTask->wasSuccessful()) { m_updateTask.reset(); emitSucceeded(); - } - else - { + } else { QString reason = tr("Instance update failed because: %1\n\n").arg(m_updateTask->failReason()); m_updateTask.reset(); emit logLine(reason, MessageLevel::Fatal); @@ -60,21 +55,17 @@ void Update::updateFinished() bool Update::canAbort() const { - if(m_updateTask) - { + if (m_updateTask) { return m_updateTask->canAbort(); } return true; } - bool Update::abort() { m_aborted = true; - if(m_updateTask) - { - if(m_updateTask->canAbort()) - { + if (m_updateTask) { + if (m_updateTask->canAbort()) { return m_updateTask->abort(); } } diff --git a/launcher/launch/steps/Update.h b/launcher/launch/steps/Update.h index ce40611e0..9262cdbe4 100644 --- a/launcher/launch/steps/Update.h +++ b/launcher/launch/steps/Update.h @@ -15,30 +15,29 @@ #pragma once -#include -#include #include +#include #include +#include #include // FIXME: stupid. should be defined by the instance type? or even completely abstracted away... -class Update: public LaunchStep -{ +class Update : public LaunchStep { Q_OBJECT -public: - explicit Update(LaunchTask *parent, Net::Mode mode):LaunchStep(parent), m_mode(mode) {}; - virtual ~Update() {}; + public: + explicit Update(LaunchTask* parent, Net::Mode mode) : LaunchStep(parent), m_mode(mode){}; + virtual ~Update(){}; void executeTask() override; bool canAbort() const override; void proceed() override; -public slots: + public slots: bool abort() override; -private slots: + private slots: void updateFinished(); -private: + private: Task::Ptr m_updateTask; bool m_aborted = false; Net::Mode m_mode = Net::Mode::Offline; diff --git a/launcher/main.cpp b/launcher/main.cpp index b63f8bfd0..31551f998 100644 --- a/launcher/main.cpp +++ b/launcher/main.cpp @@ -40,15 +40,14 @@ // #define BREAK_RETURN #ifdef BREAK_INFINITE_LOOP -#include #include +#include #endif -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { #ifdef BREAK_INFINITE_LOOP - while(true) - { + while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(250)); } #endif @@ -67,33 +66,31 @@ int main(int argc, char *argv[]) // initialize Qt Application app(argc, argv); - switch (app.status()) - { - case Application::StartingUp: - case Application::Initialized: - { - Q_INIT_RESOURCE(multimc); - Q_INIT_RESOURCE(backgrounds); - Q_INIT_RESOURCE(documents); - Q_INIT_RESOURCE(prismlauncher); + switch (app.status()) { + case Application::StartingUp: + case Application::Initialized: { + Q_INIT_RESOURCE(multimc); + Q_INIT_RESOURCE(backgrounds); + Q_INIT_RESOURCE(documents); + Q_INIT_RESOURCE(prismlauncher); - Q_INIT_RESOURCE(pe_dark); - Q_INIT_RESOURCE(pe_light); - Q_INIT_RESOURCE(pe_blue); - Q_INIT_RESOURCE(pe_colored); - Q_INIT_RESOURCE(breeze_dark); - Q_INIT_RESOURCE(breeze_light); - Q_INIT_RESOURCE(OSX); - Q_INIT_RESOURCE(iOS); - Q_INIT_RESOURCE(flat); - Q_INIT_RESOURCE(flat_white); - return app.exec(); - } - case Application::Failed: - return 1; - case Application::Succeeded: - return 0; - default: - return -1; + Q_INIT_RESOURCE(pe_dark); + Q_INIT_RESOURCE(pe_light); + Q_INIT_RESOURCE(pe_blue); + Q_INIT_RESOURCE(pe_colored); + Q_INIT_RESOURCE(breeze_dark); + Q_INIT_RESOURCE(breeze_light); + Q_INIT_RESOURCE(OSX); + Q_INIT_RESOURCE(iOS); + Q_INIT_RESOURCE(flat); + Q_INIT_RESOURCE(flat_white); + return app.exec(); + } + case Application::Failed: + return 1; + case Application::Succeeded: + return 0; + default: + return -1; } } diff --git a/launcher/meta/BaseEntity.cpp b/launcher/meta/BaseEntity.cpp index 7d83db2a8..5f9804e48 100644 --- a/launcher/meta/BaseEntity.cpp +++ b/launcher/meta/BaseEntity.cpp @@ -15,74 +15,55 @@ #include "BaseEntity.h" +#include "Json.h" #include "net/ApiDownload.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" -#include "Json.h" -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" -class ParsingValidator : public Net::Validator -{ -public: /* con/des */ - ParsingValidator(Meta::BaseEntity *entity) : m_entity(entity) - { - }; - virtual ~ParsingValidator() - { - }; +class ParsingValidator : public Net::Validator { + public: /* con/des */ + ParsingValidator(Meta::BaseEntity* entity) : m_entity(entity){}; + virtual ~ParsingValidator(){}; -public: /* methods */ - bool init(QNetworkRequest &) override - { - return true; - } - bool write(QByteArray & data) override + public: /* methods */ + bool init(QNetworkRequest&) override { return true; } + bool write(QByteArray& data) override { this->m_data.append(data); return true; } - bool abort() override - { - return true; - } - bool validate(QNetworkReply &) override + bool abort() override { return true; } + bool validate(QNetworkReply&) override { auto fname = m_entity->localFilename(); - try - { + try { auto doc = Json::requireDocument(m_data, fname); auto obj = Json::requireObject(doc, fname); m_entity->parse(obj); return true; - } - catch (const Exception &e) - { + } catch (const Exception& e) { qWarning() << "Unable to parse response:" << e.cause(); return false; } } -private: /* data */ + private: /* data */ QByteArray m_data; - Meta::BaseEntity *m_entity; + Meta::BaseEntity* m_entity; }; -Meta::BaseEntity::~BaseEntity() -{ -} +Meta::BaseEntity::~BaseEntity() {} QUrl Meta::BaseEntity::url() const { auto s = APPLICATION->settings(); QString metaOverride = s->get("MetaURLOverride").toString(); - if(metaOverride.isEmpty()) - { + if (metaOverride.isEmpty()) { return QUrl(BuildConfig.META_URL).resolved(localFilename()); - } - else - { + } else { return QUrl(metaOverride).resolved(localFilename()); } } @@ -90,20 +71,16 @@ QUrl Meta::BaseEntity::url() const bool Meta::BaseEntity::loadLocalFile() { const QString fname = QDir("meta").absoluteFilePath(localFilename()); - if (!QFile::exists(fname)) - { + if (!QFile::exists(fname)) { return false; } // TODO: check if the file has the expected checksum - try - { + try { auto doc = Json::requireDocument(fname, fname); auto obj = Json::requireObject(doc, fname); parse(obj); return true; - } - catch (const Exception &e) - { + } catch (const Exception& e) { qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause()); // just make sure it's gone and we never consider it again. QFile::remove(fname); @@ -114,16 +91,13 @@ bool Meta::BaseEntity::loadLocalFile() void Meta::BaseEntity::load(Net::Mode loadType) { // load local file if nothing is loaded yet - if(!isLoaded()) - { - if(loadLocalFile()) - { + if (!isLoaded()) { + if (loadLocalFile()) { m_loadStatus = LoadStatus::Local; } } // if we need remote update, run the update task - if(loadType == Net::Mode::Offline || !shouldStartRemoteUpdate()) - { + if (loadType == Net::Mode::Offline || !shouldStartRemoteUpdate()) { return; } m_updateTask.reset(new NetJob(QObject::tr("Download of meta file %1").arg(localFilename()), APPLICATION->network())); @@ -138,14 +112,12 @@ void Meta::BaseEntity::load(Net::Mode loadType) dl->addValidator(new ParsingValidator(this)); m_updateTask->addNetAction(dl); m_updateStatus = UpdateStatus::InProgress; - QObject::connect(m_updateTask.get(), &NetJob::succeeded, [&]() - { + QObject::connect(m_updateTask.get(), &NetJob::succeeded, [&]() { m_loadStatus = LoadStatus::Remote; m_updateStatus = UpdateStatus::Succeeded; m_updateTask.reset(); }); - QObject::connect(m_updateTask.get(), &NetJob::failed, [&]() - { + QObject::connect(m_updateTask.get(), &NetJob::failed, [&]() { m_updateStatus = UpdateStatus::Failed; m_updateTask.reset(); }); @@ -165,8 +137,7 @@ bool Meta::BaseEntity::shouldStartRemoteUpdate() const Task::Ptr Meta::BaseEntity::getCurrentTask() { - if(m_updateStatus == UpdateStatus::InProgress) - { + if (m_updateStatus == UpdateStatus::InProgress) { return m_updateTask; } return nullptr; diff --git a/launcher/meta/BaseEntity.h b/launcher/meta/BaseEntity.h index 75fa384ad..1336a5217 100644 --- a/launcher/meta/BaseEntity.h +++ b/launcher/meta/BaseEntity.h @@ -22,30 +22,17 @@ #include "net/Mode.h" #include "net/NetJob.h" -namespace Meta -{ -class BaseEntity -{ -public: /* types */ +namespace Meta { +class BaseEntity { + public: /* types */ using Ptr = std::shared_ptr; - enum class LoadStatus - { - NotLoaded, - Local, - Remote - }; - enum class UpdateStatus - { - NotDone, - InProgress, - Failed, - Succeeded - }; + enum class LoadStatus { NotLoaded, Local, Remote }; + enum class UpdateStatus { NotDone, InProgress, Failed, Succeeded }; -public: + public: virtual ~BaseEntity(); - virtual void parse(const QJsonObject &obj) = 0; + virtual void parse(const QJsonObject& obj) = 0; virtual QString localFilename() const = 0; virtual QUrl url() const; @@ -56,12 +43,12 @@ public: void load(Net::Mode loadType); Task::Ptr getCurrentTask(); -protected: /* methods */ + protected: /* methods */ bool loadLocalFile(); -private: + private: LoadStatus m_loadStatus = LoadStatus::NotLoaded; UpdateStatus m_updateStatus = UpdateStatus::NotDone; NetJob::Ptr m_updateTask; }; -} +} // namespace Meta diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 4dccccca8..657019f8a 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -15,84 +15,75 @@ #include "Index.h" -#include "VersionList.h" #include "JsonFormat.h" +#include "VersionList.h" -namespace Meta +namespace Meta { +Index::Index(QObject* parent) : QAbstractListModel(parent) {} +Index::Index(const QVector& lists, QObject* parent) : QAbstractListModel(parent), m_lists(lists) { -Index::Index(QObject *parent) - : QAbstractListModel(parent) -{ -} -Index::Index(const QVector &lists, QObject *parent) - : QAbstractListModel(parent), m_lists(lists) -{ - for (int i = 0; i < m_lists.size(); ++i) - { + for (int i = 0; i < m_lists.size(); ++i) { m_uids.insert(m_lists.at(i)->uid(), m_lists.at(i)); connectVersionList(i, m_lists.at(i)); } } -QVariant Index::data(const QModelIndex &index, int role) const +QVariant Index::data(const QModelIndex& index, int role) const { - if (index.parent().isValid() || index.row() < 0 || index.row() >= m_lists.size()) - { + if (index.parent().isValid() || index.row() < 0 || index.row() >= m_lists.size()) { return QVariant(); } VersionList::Ptr list = m_lists.at(index.row()); - switch (role) - { - case Qt::DisplayRole: - if (index.column() == 0) { - return list->humanReadable(); - } else { - break; - } - case UidRole: return list->uid(); - case NameRole: return list->name(); - case ListPtrRole: return QVariant::fromValue(list); + switch (role) { + case Qt::DisplayRole: + if (index.column() == 0) { + return list->humanReadable(); + } else { + break; + } + case UidRole: + return list->uid(); + case NameRole: + return list->name(); + case ListPtrRole: + return QVariant::fromValue(list); } return QVariant(); } -int Index::rowCount(const QModelIndex &parent) const +int Index::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : m_lists.size(); } -int Index::columnCount(const QModelIndex &parent) const +int Index::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : 1; } QVariant Index::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0) - { + if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0) { return tr("Name"); - } - else - { + } else { return QVariant(); } } -bool Index::hasUid(const QString &uid) const +bool Index::hasUid(const QString& uid) const { return m_uids.contains(uid); } -VersionList::Ptr Index::get(const QString &uid) +VersionList::Ptr Index::get(const QString& uid) { VersionList::Ptr out = m_uids.value(uid, nullptr); - if(!out) - { + if (!out) { out = std::make_shared(uid); m_uids[uid] = out; } return out; } -Version::Ptr Index::get(const QString &uid, const QString &version) +Version::Ptr Index::get(const QString& uid, const QString& version) { auto list = get(uid); return list->getVersion(version); @@ -103,31 +94,23 @@ void Index::parse(const QJsonObject& obj) parseIndex(obj, this); } -void Index::merge(const std::shared_ptr &other) +void Index::merge(const std::shared_ptr& other) { const QVector lists = std::dynamic_pointer_cast(other)->m_lists; // initial load, no need to merge - if (m_lists.isEmpty()) - { + if (m_lists.isEmpty()) { beginResetModel(); m_lists = lists; - for (int i = 0; i < lists.size(); ++i) - { + for (int i = 0; i < lists.size(); ++i) { m_uids.insert(lists.at(i)->uid(), lists.at(i)); connectVersionList(i, lists.at(i)); } endResetModel(); - } - else - { - for (const VersionList::Ptr &list : lists) - { - if (m_uids.contains(list->uid())) - { + } else { + for (const VersionList::Ptr& list : lists) { + if (m_uids.contains(list->uid())) { m_uids[list->uid()]->mergeFromIndex(list); - } - else - { + } else { beginInsertRows(QModelIndex(), m_lists.size(), m_lists.size()); connectVersionList(m_lists.size(), list); m_lists.append(list); @@ -138,11 +121,9 @@ void Index::merge(const std::shared_ptr &other) } } -void Index::connectVersionList(const int row, const VersionList::Ptr &list) +void Index::connectVersionList(const int row, const VersionList::Ptr& list) { - connect(list.get(), &VersionList::nameChanged, this, [this, row]() - { - emit dataChanged(index(row), index(row), QVector() << Qt::DisplayRole); - }); -} + connect(list.get(), &VersionList::nameChanged, this, + [this, row]() { emit dataChanged(index(row), index(row), QVector() << Qt::DisplayRole); }); } +} // namespace Meta diff --git a/launcher/meta/Index.h b/launcher/meta/Index.h index 06ea09dcf..41fdfcea9 100644 --- a/launcher/meta/Index.h +++ b/launcher/meta/Index.h @@ -23,46 +23,38 @@ class Task; -namespace Meta -{ +namespace Meta { -class Index : public QAbstractListModel, public BaseEntity -{ +class Index : public QAbstractListModel, public BaseEntity { Q_OBJECT -public: - explicit Index(QObject *parent = nullptr); - explicit Index(const QVector &lists, QObject *parent = nullptr); + public: + explicit Index(QObject* parent = nullptr); + explicit Index(const QVector& lists, QObject* parent = nullptr); - enum - { - UidRole = Qt::UserRole, - NameRole, - ListPtrRole - }; + enum { UidRole = Qt::UserRole, NameRole, ListPtrRole }; - QVariant data(const QModelIndex &index, int role) const override; - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex& index, int role) const override; + int rowCount(const QModelIndex& parent) const override; + int columnCount(const QModelIndex& parent) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QString localFilename() const override { return "index.json"; } // queries - VersionList::Ptr get(const QString &uid); - Version::Ptr get(const QString &uid, const QString &version); - bool hasUid(const QString &uid) const; + VersionList::Ptr get(const QString& uid); + Version::Ptr get(const QString& uid, const QString& version); + bool hasUid(const QString& uid) const; QVector lists() const { return m_lists; } -public: // for usage by parsers only - void merge(const std::shared_ptr &other); - void parse(const QJsonObject &obj) override; + public: // for usage by parsers only + void merge(const std::shared_ptr& other); + void parse(const QJsonObject& obj) override; -private: + private: QVector m_lists; QHash m_uids; - void connectVersionList(const int row, const VersionList::Ptr &list); + void connectVersionList(const int row, const VersionList::Ptr& list); }; -} - +} // namespace Meta diff --git a/launcher/meta/JsonFormat.cpp b/launcher/meta/JsonFormat.cpp index cb2d06ea0..6c993f720 100644 --- a/launcher/meta/JsonFormat.cpp +++ b/launcher/meta/JsonFormat.cpp @@ -16,8 +16,8 @@ #include "JsonFormat.h" // FIXME: remove this from here... somehow -#include "minecraft/OneSixVersionFormat.h" #include "Json.h" +#include "minecraft/OneSixVersionFormat.h" #include "Index.h" #include "Version.h" @@ -25,8 +25,7 @@ using namespace Json; -namespace Meta -{ +namespace Meta { MetadataVersion currentFormatVersion() { @@ -34,13 +33,12 @@ MetadataVersion currentFormatVersion() } // Index -static std::shared_ptr parseIndexInternal(const QJsonObject &obj) +static std::shared_ptr parseIndexInternal(const QJsonObject& obj) { const QVector objects = requireIsArrayOf(obj, "packages"); QVector lists; lists.reserve(objects.size()); - std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj) - { + std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject& obj) { VersionList::Ptr list = std::make_shared(requireString(obj, "uid")); list->setName(ensureString(obj, "name", QString())); return list; @@ -49,7 +47,7 @@ static std::shared_ptr parseIndexInternal(const QJsonObject &obj) } // Version -static Version::Ptr parseCommonVersion(const QString &uid, const QJsonObject &obj) +static Version::Ptr parseCommonVersion(const QString& uid, const QJsonObject& obj) { Version::Ptr version = std::make_shared(uid, requireString(obj, "version")); version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000); @@ -63,26 +61,24 @@ static Version::Ptr parseCommonVersion(const QString &uid, const QJsonObject &ob return version; } -static Version::Ptr parseVersionInternal(const QJsonObject &obj) +static Version::Ptr parseVersionInternal(const QJsonObject& obj) { Version::Ptr version = parseCommonVersion(requireString(obj, "uid"), obj); - version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj), - QString("%1/%2.json").arg(version->uid(), version->version()), - obj.contains("order"))); + version->setData(OneSixVersionFormat::versionFileFromJson( + QJsonDocument(obj), QString("%1/%2.json").arg(version->uid(), version->version()), obj.contains("order"))); return version; } // Version list / package -static VersionList::Ptr parseVersionListInternal(const QJsonObject &obj) +static VersionList::Ptr parseVersionListInternal(const QJsonObject& obj) { const QString uid = requireString(obj, "uid"); const QVector versionsRaw = requireIsArrayOf(obj, "versions"); QVector versions; versions.reserve(versionsRaw.size()); - std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj) - { + std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject& vObj) { auto version = parseCommonVersion(uid, vObj); version->setProvidesRecommendations(); return version; @@ -94,23 +90,18 @@ static VersionList::Ptr parseVersionListInternal(const QJsonObject &obj) return list; } - -MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required) +MetadataVersion parseFormatVersion(const QJsonObject& obj, bool required) { - if (!obj.contains("formatVersion")) - { - if(required) - { + if (!obj.contains("formatVersion")) { + if (required) { return MetadataVersion::Invalid; } return MetadataVersion::InitialRelease; } - if (!obj.value("formatVersion").isDouble()) - { + if (!obj.value("formatVersion").isDouble()) { return MetadataVersion::Invalid; } - switch(obj.value("formatVersion").toInt()) - { + switch (obj.value("formatVersion").toInt()) { case 0: case 1: return MetadataVersion::InitialRelease; @@ -121,49 +112,45 @@ MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required) void serializeFormatVersion(QJsonObject& obj, Meta::MetadataVersion version) { - if(version == MetadataVersion::Invalid) - { + if (version == MetadataVersion::Invalid) { return; } obj.insert("formatVersion", int(version)); } -void parseIndex(const QJsonObject &obj, Index *ptr) +void parseIndex(const QJsonObject& obj, Index* ptr) { const MetadataVersion version = parseFormatVersion(obj); - switch (version) - { - case MetadataVersion::InitialRelease: - ptr->merge(parseIndexInternal(obj)); - break; - case MetadataVersion::Invalid: - throw ParseException(QObject::tr("Unknown format version!")); + switch (version) { + case MetadataVersion::InitialRelease: + ptr->merge(parseIndexInternal(obj)); + break; + case MetadataVersion::Invalid: + throw ParseException(QObject::tr("Unknown format version!")); } } -void parseVersionList(const QJsonObject &obj, VersionList *ptr) +void parseVersionList(const QJsonObject& obj, VersionList* ptr) { const MetadataVersion version = parseFormatVersion(obj); - switch (version) - { - case MetadataVersion::InitialRelease: - ptr->merge(parseVersionListInternal(obj)); - break; - case MetadataVersion::Invalid: - throw ParseException(QObject::tr("Unknown format version!")); + switch (version) { + case MetadataVersion::InitialRelease: + ptr->merge(parseVersionListInternal(obj)); + break; + case MetadataVersion::Invalid: + throw ParseException(QObject::tr("Unknown format version!")); } } -void parseVersion(const QJsonObject &obj, Version *ptr) +void parseVersion(const QJsonObject& obj, Version* ptr) { const MetadataVersion version = parseFormatVersion(obj); - switch (version) - { - case MetadataVersion::InitialRelease: - ptr->merge(parseVersionInternal(obj)); - break; - case MetadataVersion::Invalid: - throw ParseException(QObject::tr("Unknown format version!")); + switch (version) { + case MetadataVersion::InitialRelease: + ptr->merge(parseVersionInternal(obj)); + break; + case MetadataVersion::Invalid: + throw ParseException(QObject::tr("Unknown format version!")); } } @@ -172,40 +159,34 @@ void parseVersion(const QJsonObject &obj, Version *ptr) {"uid":"foo", "equals":"version"} ] */ -void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char * keyName) +void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char* keyName) { - if(obj.contains(keyName)) - { + if (obj.contains(keyName)) { auto reqArray = requireArray(obj, keyName); auto iter = reqArray.begin(); - while(iter != reqArray.end()) - { + while (iter != reqArray.end()) { auto reqObject = requireObject(*iter); auto uid = requireString(reqObject, "uid"); auto equals = ensureString(reqObject, "equals", QString()); auto suggests = ensureString(reqObject, "suggests", QString()); - ptr->insert({uid, equals, suggests}); + ptr->insert({ uid, equals, suggests }); iter++; } } } -void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char * keyName) +void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char* keyName) { - if(!ptr || ptr->empty()) - { + if (!ptr || ptr->empty()) { return; } QJsonArray arrOut; - for(auto &iter: *ptr) - { + for (auto& iter : *ptr) { QJsonObject reqOut; reqOut.insert("uid", iter.uid); - if(!iter.equalsVersion.isEmpty()) - { + if (!iter.equalsVersion.isEmpty()) { reqOut.insert("equals", iter.equalsVersion); } - if(!iter.suggests.isEmpty()) - { + if (!iter.suggests.isEmpty()) { reqOut.insert("suggests", iter.suggests); } arrOut.append(reqOut); @@ -213,5 +194,4 @@ void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char * keyName) obj.insert(keyName, arrOut); } -} - +} // namespace Meta diff --git a/launcher/meta/JsonFormat.h b/launcher/meta/JsonFormat.h index 63128a4e6..d474bcc39 100644 --- a/launcher/meta/JsonFormat.h +++ b/launcher/meta/JsonFormat.h @@ -18,43 +18,25 @@ #include #include +#include #include "Exception.h" #include "meta/BaseEntity.h" -#include -namespace Meta -{ +namespace Meta { class Index; class Version; class VersionList; -enum class MetadataVersion -{ - Invalid = -1, - InitialRelease = 1 -}; +enum class MetadataVersion { Invalid = -1, InitialRelease = 1 }; -class ParseException : public Exception -{ -public: +class ParseException : public Exception { + public: using Exception::Exception; }; -struct Require -{ - bool operator==(const Require & rhs) const - { - return uid == rhs.uid; - } - bool operator<(const Require & rhs) const - { - return uid < rhs.uid; - } - bool deepEquals(const Require & rhs) const - { - return uid == rhs.uid - && equalsVersion == rhs.equalsVersion - && suggests == rhs.suggests; - } +struct Require { + bool operator==(const Require& rhs) const { return uid == rhs.uid; } + bool operator<(const Require& rhs) const { return uid < rhs.uid; } + bool deepEquals(const Require& rhs) const { return uid == rhs.uid && equalsVersion == rhs.equalsVersion && suggests == rhs.suggests; } QString uid; QString equalsVersion; QString suggests; @@ -62,17 +44,17 @@ struct Require using RequireSet = std::set; -void parseIndex(const QJsonObject &obj, Index *ptr); -void parseVersion(const QJsonObject &obj, Version *ptr); -void parseVersionList(const QJsonObject &obj, VersionList *ptr); +void parseIndex(const QJsonObject& obj, Index* ptr); +void parseVersion(const QJsonObject& obj, Version* ptr); +void parseVersionList(const QJsonObject& obj, VersionList* ptr); -MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required = true); -void serializeFormatVersion(QJsonObject &obj, MetadataVersion version); +MetadataVersion parseFormatVersion(const QJsonObject& obj, bool required = true); +void serializeFormatVersion(QJsonObject& obj, MetadataVersion version); // FIXME: this has a different shape than the others...FIX IT!? -void parseRequires(const QJsonObject &obj, RequireSet * ptr, const char * keyName = "requires"); -void serializeRequires(QJsonObject & objOut, RequireSet* ptr, const char * keyName = "requires"); +void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char* keyName = "requires"); +void serializeRequires(QJsonObject& objOut, RequireSet* ptr, const char* keyName = "requires"); MetadataVersion currentFormatVersion(); -} +} // namespace Meta Q_DECLARE_METATYPE(std::set) diff --git a/launcher/meta/Version.cpp b/launcher/meta/Version.cpp index 0718a4204..655a20b93 100644 --- a/launcher/meta/Version.cpp +++ b/launcher/meta/Version.cpp @@ -20,14 +20,9 @@ #include "JsonFormat.h" #include "minecraft/PackProfile.h" -Meta::Version::Version(const QString &uid, const QString &version) - : BaseVersion(), m_uid(uid), m_version(version) -{ -} +Meta::Version::Version(const QString& uid, const QString& version) : BaseVersion(), m_uid(uid), m_version(version) {} -Meta::Version::~Version() -{ -} +Meta::Version::~Version() {} QString Meta::Version::descriptor() { @@ -35,7 +30,7 @@ QString Meta::Version::descriptor() } QString Meta::Version::name() { - if(m_data) + if (m_data) return m_data->name; return m_uid; } @@ -56,40 +51,32 @@ void Meta::Version::parse(const QJsonObject& obj) void Meta::Version::mergeFromList(const Meta::Version::Ptr& other) { - if(other->m_providesRecommendations) - { - if(m_recommended != other->m_recommended) - { + if (other->m_providesRecommendations) { + if (m_recommended != other->m_recommended) { setRecommended(other->m_recommended); } } - if (m_type != other->m_type) - { + if (m_type != other->m_type) { setType(other->m_type); } - if (m_time != other->m_time) - { + if (m_time != other->m_time) { setTime(other->m_time); } - if (m_requires != other->m_requires) - { + if (m_requires != other->m_requires) { m_requires = other->m_requires; } - if (m_conflicts != other->m_conflicts) - { + if (m_conflicts != other->m_conflicts) { m_conflicts = other->m_conflicts; } - if(m_volatile != other->m_volatile) - { + if (m_volatile != other->m_volatile) { setVolatile(other->m_volatile); } } -void Meta::Version::merge(const Version::Ptr &other) +void Meta::Version::merge(const Version::Ptr& other) { mergeFromList(other); - if(other->m_data) - { + if (other->m_data) { setData(other->m_data); } } @@ -104,7 +91,7 @@ QString Meta::Version::localFilename() const return { const_cast(this)->descriptor() }; } -void Meta::Version::setType(const QString &type) +void Meta::Version::setType(const QString& type) { m_type = type; emit typeChanged(); @@ -116,7 +103,7 @@ void Meta::Version::setTime(const qint64 time) emit timeChanged(); } -void Meta::Version::setRequires(const Meta::RequireSet &reqs, const Meta::RequireSet &conflicts) +void Meta::Version::setRequires(const Meta::RequireSet& reqs, const Meta::RequireSet& conflicts) { m_requires = reqs; m_conflicts = conflicts; @@ -128,8 +115,7 @@ void Meta::Version::setVolatile(bool volatile_) m_volatile = volatile_; } - -void Meta::Version::setData(const VersionFilePtr &data) +void Meta::Version::setData(const VersionFilePtr& data) { m_data = data; } diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 59a96a68b..07dcafb01 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -15,8 +15,8 @@ #pragma once -#include "BaseVersion.h" #include "../Version.h" +#include "BaseVersion.h" #include #include @@ -29,80 +29,54 @@ #include "JsonFormat.h" -namespace Meta -{ +namespace Meta { -class Version : public QObject, public BaseVersion, public BaseEntity -{ +class Version : public QObject, public BaseVersion, public BaseEntity { Q_OBJECT -public: + public: using Ptr = std::shared_ptr; - explicit Version(const QString &uid, const QString &version); + explicit Version(const QString& uid, const QString& version); virtual ~Version(); QString descriptor() override; QString name() override; QString typeString() const override; - QString uid() const - { - return m_uid; - } - QString version() const - { - return m_version; - } - QString type() const - { - return m_type; - } + QString uid() const { return m_uid; } + QString version() const { return m_version; } + QString type() const { return m_type; } QDateTime time() const; - qint64 rawTime() const - { - return m_time; - } - const Meta::RequireSet &requiredSet() const - { - return m_requires; - } - VersionFilePtr data() const - { - return m_data; - } - bool isRecommended() const - { - return m_recommended; - } - bool isLoaded() const - { - return m_data != nullptr; - } + qint64 rawTime() const { return m_time; } + const Meta::RequireSet& requiredSet() const { return m_requires; } + VersionFilePtr data() const { return m_data; } + bool isRecommended() const { return m_recommended; } + bool isLoaded() const { return m_data != nullptr; } - void merge(const Version::Ptr &other); - void mergeFromList(const Version::Ptr &other); - void parse(const QJsonObject &obj) override; + void merge(const Version::Ptr& other); + void mergeFromList(const Version::Ptr& other); + void parse(const QJsonObject& obj) override; QString localFilename() const override; [[nodiscard]] ::Version toComparableVersion() const; -public: // for usage by format parsers only - void setType(const QString &type); + public: // for usage by format parsers only + void setType(const QString& type); void setTime(const qint64 time); - void setRequires(const Meta::RequireSet &reqs, const Meta::RequireSet &conflicts); + void setRequires(const Meta::RequireSet& reqs, const Meta::RequireSet& conflicts); void setVolatile(bool volatile_); void setRecommended(bool recommended); void setProvidesRecommendations(); - void setData(const VersionFilePtr &data); + void setData(const VersionFilePtr& data); -signals: + signals: void typeChanged(); void timeChanged(); void requiresChanged(); -private: + private: bool m_providesRecommendations = false; bool m_recommended = false; QString m_name; @@ -115,6 +89,6 @@ private: bool m_volatile = false; VersionFilePtr m_data; }; -} +} // namespace Meta Q_DECLARE_METATYPE(Meta::Version::Ptr) diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index 9f4482784..7b7ae1fa3 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -17,14 +17,11 @@ #include -#include "Version.h" #include "JsonFormat.h" #include "Version.h" -namespace Meta -{ -VersionList::VersionList(const QString &uid, QObject *parent) - : BaseVersionList(parent), m_uid(uid) +namespace Meta { +VersionList::VersionList(const QString& uid, QObject* parent) : BaseVersionList(parent), m_uid(uid) { setObjectName("Version list: " + uid); } @@ -52,61 +49,60 @@ int VersionList::count() const void VersionList::sortVersions() { beginResetModel(); - std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b) - { - return *a.get() < *b.get(); - }); + std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr& a, const Version::Ptr& b) { return *a.get() < *b.get(); }); endResetModel(); } -QVariant VersionList::data(const QModelIndex &index, int role) const +QVariant VersionList::data(const QModelIndex& index, int role) const { - if (!index.isValid() || index.row() < 0 || index.row() >= m_versions.size() || index.parent().isValid()) - { + if (!index.isValid() || index.row() < 0 || index.row() >= m_versions.size() || index.parent().isValid()) { return QVariant(); } Version::Ptr version = m_versions.at(index.row()); - switch (role) - { - case VersionPointerRole: return QVariant::fromValue(std::dynamic_pointer_cast(version)); - case VersionRole: - case VersionIdRole: - return version->version(); - case ParentVersionRole: - { - // FIXME: HACK: this should be generic and be replaced by something else. Anything that is a hard 'equals' dep is a 'parent uid'. - auto & reqs = version->requiredSet(); - auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Require & req) - { - return req.uid == "net.minecraft"; - }); - if (iter != reqs.end()) - { - return (*iter).equalsVersion; + switch (role) { + case VersionPointerRole: + return QVariant::fromValue(std::dynamic_pointer_cast(version)); + case VersionRole: + case VersionIdRole: + return version->version(); + case ParentVersionRole: { + // FIXME: HACK: this should be generic and be replaced by something else. Anything that is a hard 'equals' dep is a 'parent + // uid'. + auto& reqs = version->requiredSet(); + auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Require& req) { return req.uid == "net.minecraft"; }); + if (iter != reqs.end()) { + return (*iter).equalsVersion; + } + return QVariant(); } - return QVariant(); - } - case TypeRole: return version->type(); + case TypeRole: + return version->type(); - case UidRole: return version->uid(); - case TimeRole: return version->time(); - case RequiresRole: return QVariant::fromValue(version->requiredSet()); - case SortRole: return version->rawTime(); - case VersionPtrRole: return QVariant::fromValue(version); - case RecommendedRole: return version->isRecommended(); - // FIXME: this should be determined in whatever view/proxy is used... - // case LatestRole: return version == getLatestStable(); - default: return QVariant(); + case UidRole: + return version->uid(); + case TimeRole: + return version->time(); + case RequiresRole: + return QVariant::fromValue(version->requiredSet()); + case SortRole: + return version->rawTime(); + case VersionPtrRole: + return QVariant::fromValue(version); + case RecommendedRole: + return version->isRecommended(); + // FIXME: this should be determined in whatever view/proxy is used... + // case LatestRole: return version == getLatestStable(); + default: + return QVariant(); } } BaseVersionList::RoleList VersionList::providesRoles() const { - return {VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole, - TypeRole, UidRole, TimeRole, RequiresRole, SortRole, - RecommendedRole, LatestRole, VersionPtrRole}; + return { VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole, TypeRole, UidRole, + TimeRole, RequiresRole, SortRole, RecommendedRole, LatestRole, VersionPtrRole }; } QHash VersionList::roleNames() const @@ -129,11 +125,10 @@ QString VersionList::humanReadable() const return m_name.isEmpty() ? m_uid : m_name; } -Version::Ptr VersionList::getVersion(const QString &version) +Version::Ptr VersionList::getVersion(const QString& version) { Version::Ptr out = m_lookup.value(version, nullptr); - if(!out) - { + if (!out) { out = std::make_shared(m_uid, version); m_lookup[version] = out; } @@ -142,33 +137,31 @@ Version::Ptr VersionList::getVersion(const QString &version) bool VersionList::hasVersion(QString version) const { - auto ver = std::find_if(m_versions.constBegin(), m_versions.constEnd(), - [&](Meta::Version::Ptr const& a){ return a->version() == version; }); + auto ver = + std::find_if(m_versions.constBegin(), m_versions.constEnd(), [&](Meta::Version::Ptr const& a) { return a->version() == version; }); return (ver != m_versions.constEnd()); } -void VersionList::setName(const QString &name) +void VersionList::setName(const QString& name) { m_name = name; emit nameChanged(name); } -void VersionList::setVersions(const QVector &versions) +void VersionList::setVersions(const QVector& versions) { beginResetModel(); m_versions = versions; - std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b) - { - return a->rawTime() > b->rawTime(); - }); - for (int i = 0; i < m_versions.size(); ++i) - { + std::sort(m_versions.begin(), m_versions.end(), + [](const Version::Ptr& a, const Version::Ptr& b) { return a->rawTime() > b->rawTime(); }); + for (int i = 0; i < m_versions.size(); ++i) { m_lookup.insert(m_versions.at(i)->version(), m_versions.at(i)); setupAddedVersion(i, m_versions.at(i)); } // FIXME: this is dumb, we have 'recommended' as part of the metadata already... - auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const Version::Ptr &ptr) { return ptr->type() == "release"; }); + auto recommendedIt = + std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const Version::Ptr& ptr) { return ptr->type() == "release"; }); m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt; endResetModel(); } @@ -179,14 +172,13 @@ void VersionList::parse(const QJsonObject& obj) } // FIXME: this is dumb, we have 'recommended' as part of the metadata already... -static const Meta::Version::Ptr &getBetterVersion(const Meta::Version::Ptr &a, const Meta::Version::Ptr &b) +static const Meta::Version::Ptr& getBetterVersion(const Meta::Version::Ptr& a, const Meta::Version::Ptr& b) { - if(!a) + if (!a) return b; - if(!b) + if (!b) return a; - if(a->type() == b->type()) - { + if (a->type() == b->type()) { // newer of same type wins return (a->rawTime() > b->rawTime() ? a : b); } @@ -194,37 +186,30 @@ static const Meta::Version::Ptr &getBetterVersion(const Meta::Version::Ptr &a, c return (a->type() == "release" ? a : b); } -void VersionList::mergeFromIndex(const VersionList::Ptr &other) +void VersionList::mergeFromIndex(const VersionList::Ptr& other) { - if (m_name != other->m_name) - { + if (m_name != other->m_name) { setName(other->m_name); } } -void VersionList::merge(const VersionList::Ptr &other) +void VersionList::merge(const VersionList::Ptr& other) { - if (m_name != other->m_name) - { + if (m_name != other->m_name) { setName(other->m_name); } // TODO: do not reset the whole model. maybe? beginResetModel(); m_versions.clear(); - if(other->m_versions.isEmpty()) - { + if (other->m_versions.isEmpty()) { qWarning() << "Empty list loaded ..."; } - for (const Version::Ptr &version : other->m_versions) - { + for (const Version::Ptr& version : other->m_versions) { // we already have the version. merge the contents - if (m_lookup.contains(version->version())) - { + if (m_lookup.contains(version->version())) { m_lookup.value(version->version())->mergeFromList(version); - } - else - { + } else { m_lookup.insert(version->uid(), version); } // connect it. @@ -235,13 +220,16 @@ void VersionList::merge(const VersionList::Ptr &other) endResetModel(); } -void VersionList::setupAddedVersion(const int row, const Version::Ptr &version) +void VersionList::setupAddedVersion(const int row, const Version::Ptr& version) { // FIXME: do not disconnect from everythin, disconnect only the lambdas here version->disconnect(); - connect(version.get(), &Version::requiresChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector() << RequiresRole); }); - connect(version.get(), &Version::timeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector() << TimeRole << SortRole); }); - connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector() << TypeRole); }); + connect(version.get(), &Version::requiresChanged, this, + [this, row]() { emit dataChanged(index(row), index(row), QVector() << RequiresRole); }); + connect(version.get(), &Version::timeChanged, this, + [this, row]() { emit dataChanged(index(row), index(row), QVector() << TimeRole << SortRole); }); + connect(version.get(), &Version::typeChanged, this, + [this, row]() { emit dataChanged(index(row), index(row), QVector() << TypeRole); }); } BaseVersion::Ptr VersionList::getRecommended() const @@ -249,4 +237,4 @@ BaseVersion::Ptr VersionList::getRecommended() const return m_recommended; } -} +} // namespace Meta diff --git a/launcher/meta/VersionList.h b/launcher/meta/VersionList.h index a4d5603d9..5e587f204 100644 --- a/launcher/meta/VersionList.h +++ b/launcher/meta/VersionList.h @@ -15,33 +15,25 @@ #pragma once -#include "BaseEntity.h" -#include "BaseVersionList.h" #include #include +#include "BaseEntity.h" +#include "BaseVersionList.h" #include "meta/Version.h" -namespace Meta -{ +namespace Meta { -class VersionList : public BaseVersionList, public BaseEntity -{ +class VersionList : public BaseVersionList, public BaseEntity { Q_OBJECT Q_PROPERTY(QString uid READ uid CONSTANT) Q_PROPERTY(QString name READ name NOTIFY nameChanged) -public: - explicit VersionList(const QString &uid, QObject *parent = nullptr); + public: + explicit VersionList(const QString& uid, QObject* parent = nullptr); using Ptr = std::shared_ptr; - enum Roles - { - UidRole = Qt::UserRole + 100, - TimeRole, - RequiresRole, - VersionPtrRole - }; + enum Roles { UidRole = Qt::UserRole + 100, TimeRole, RequiresRole, VersionPtrRole }; Task::Ptr getLoadTask() override; bool isLoaded() override; @@ -51,46 +43,35 @@ public: BaseVersion::Ptr getRecommended() const override; - QVariant data(const QModelIndex &index, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; RoleList providesRoles() const override; QHash roleNames() const override; QString localFilename() const override; - QString uid() const - { - return m_uid; - } - QString name() const - { - return m_name; - } + QString uid() const { return m_uid; } + QString name() const { return m_name; } QString humanReadable() const; - Version::Ptr getVersion(const QString &version); + Version::Ptr getVersion(const QString& version); bool hasVersion(QString version) const; - QVector versions() const - { - return m_versions; - } + QVector versions() const { return m_versions; } -public: // for usage only by parsers - void setName(const QString &name); - void setVersions(const QVector &versions); - void merge(const VersionList::Ptr &other); - void mergeFromIndex(const VersionList::Ptr &other); - void parse(const QJsonObject &obj) override; + public: // for usage only by parsers + void setName(const QString& name); + void setVersions(const QVector& versions); + void merge(const VersionList::Ptr& other); + void mergeFromIndex(const VersionList::Ptr& other); + void parse(const QJsonObject& obj) override; -signals: - void nameChanged(const QString &name); + signals: + void nameChanged(const QString& name); -protected slots: - void updateListData(QList) override - { - } + protected slots: + void updateListData(QList) override {} -private: + private: QVector m_versions; QHash m_lookup; QString m_uid; @@ -98,7 +79,7 @@ private: Version::Ptr m_recommended; - void setupAddedVersion(const int row, const Version::Ptr &version); + void setupAddedVersion(const int row, const Version::Ptr& version); }; -} +} // namespace Meta Q_DECLARE_METATYPE(Meta::VersionList::Ptr) diff --git a/launcher/minecraft/Agent.h b/launcher/minecraft/Agent.h index 374e6e94e..8958521e5 100644 --- a/launcher/minecraft/Agent.h +++ b/launcher/minecraft/Agent.h @@ -9,28 +9,21 @@ class Agent; typedef std::shared_ptr AgentPtr; class Agent { -public: - Agent(LibraryPtr library, const QString &argument) + public: + Agent(LibraryPtr library, const QString& argument) { m_library = library; m_argument = argument; } -public: /* methods */ - - LibraryPtr library() { - return m_library; - } - QString argument() { - return m_argument; - } - -protected: /* data */ + public: /* methods */ + LibraryPtr library() { return m_library; } + QString argument() { return m_argument; } + protected: /* data */ /// The library pointing to the jar this Java agent is contained within LibraryPtr m_library; /// The argument to the Java agent, passed after an = if present QString m_argument; - }; diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp index 65ad6da69..21c3007eb 100644 --- a/launcher/minecraft/AssetsUtils.cpp +++ b/launcher/minecraft/AssetsUtils.cpp @@ -33,21 +33,21 @@ * limitations under the License. */ -#include +#include +#include #include #include -#include -#include +#include #include #include +#include #include -#include #include "AssetsUtils.h" +#include "BuildConfig.h" #include "FileSystem.h" #include "net/ApiDownload.h" #include "net/ChecksumValidator.h" -#include "BuildConfig.h" #include "Application.h" @@ -56,37 +56,32 @@ QSet collectPathsFromDir(QString dirPath) { QFileInfo dirInfo(dirPath); - if (!dirInfo.exists()) - { + if (!dirInfo.exists()) { return {}; } QSet out; QDirIterator iter(dirPath, QDirIterator::Subdirectories); - while (iter.hasNext()) - { + while (iter.hasNext()) { QString value = iter.next(); QFileInfo info(value); - if(info.isFile()) - { + if (info.isFile()) { out.insert(value); qDebug() << value; } } return out; } -} +} // namespace - -namespace AssetsUtils -{ +namespace AssetsUtils { /* * Returns true on success, with index populated * index is undefined otherwise */ -bool loadAssetsIndexJson(const QString &assetsId, const QString &path, AssetsIndex& index) +bool loadAssetsIndexJson(const QString& assetsId, const QString& path, AssetsIndex& index) { /* { @@ -105,8 +100,7 @@ bool loadAssetsIndexJson(const QString &assetsId, const QString &path, AssetsInd // Try to open the file and fail if we can't. // TODO: We should probably report this error to the user. - if (!file.open(QIODevice::ReadOnly)) - { + if (!file.open(QIODevice::ReadOnly)) { qCritical() << "Failed to read assets index file" << path; return false; } @@ -120,16 +114,14 @@ bool loadAssetsIndexJson(const QString &assetsId, const QString &path, AssetsInd QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError); // Fail if the JSON is invalid. - if (parseError.error != QJsonParseError::NoError) - { - qCritical() << "Failed to parse assets index file:" << parseError.errorString() - << "at offset " << QString::number(parseError.offset); + if (parseError.error != QJsonParseError::NoError) { + qCritical() << "Failed to parse assets index file:" << parseError.errorString() << "at offset " + << QString::number(parseError.offset); return false; } // Make sure the root is an object. - if (!jsonDoc.isObject()) - { + if (!jsonDoc.isObject()) { qCritical() << "Invalid assets index JSON: Root should be an array."; return false; } @@ -137,22 +129,19 @@ bool loadAssetsIndexJson(const QString &assetsId, const QString &path, AssetsInd QJsonObject root = jsonDoc.object(); QJsonValue isVirtual = root.value("virtual"); - if (!isVirtual.isUndefined()) - { + if (!isVirtual.isUndefined()) { index.isVirtual = isVirtual.toBool(false); } QJsonValue mapToResources = root.value("map_to_resources"); - if (!mapToResources.isUndefined()) - { + if (!mapToResources.isUndefined()) { index.mapToResources = mapToResources.toBool(false); } QJsonValue objects = root.value("objects"); QVariantMap map = objects.toVariant().toMap(); - for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) - { + for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) { // qDebug() << iter.key(); QVariant variant = iter.value(); @@ -160,19 +149,14 @@ bool loadAssetsIndexJson(const QString &assetsId, const QString &path, AssetsInd AssetObject object; - for (QVariantMap::const_iterator nested_iter = nested_objects.begin(); - nested_iter != nested_objects.end(); ++nested_iter) - { + for (QVariantMap::const_iterator nested_iter = nested_objects.begin(); nested_iter != nested_objects.end(); ++nested_iter) { // qDebug() << nested_iter.key() << nested_iter.value().toString(); QString key = nested_iter.key(); QVariant value = nested_iter.value(); - if (key == "hash") - { + if (key == "hash") { object.hash = value.toString(); - } - else if (key == "size") - { + } else if (key == "size") { object.size = value.toDouble(); } } @@ -184,7 +168,7 @@ bool loadAssetsIndexJson(const QString &assetsId, const QString &path, AssetsInd } // FIXME: ugly code duplication -QDir getAssetsDir(const QString &assetsId, const QString &resourcesFolder) +QDir getAssetsDir(const QString& assetsId, const QString& resourcesFolder) { QDir assetsDir = QDir("assets/"); QDir indexDir = QDir(FS::PathCombine(assetsDir.path(), "indexes")); @@ -195,26 +179,21 @@ QDir getAssetsDir(const QString &assetsId, const QString &resourcesFolder) QFile indexFile(indexPath); QDir virtualRoot(FS::PathCombine(virtualDir.path(), assetsId)); - if (!indexFile.exists()) - { + if (!indexFile.exists()) { qCritical() << "No assets index file" << indexPath << "; can't determine assets path!"; return virtualRoot; } AssetsIndex index; - if(!AssetsUtils::loadAssetsIndexJson(assetsId, indexPath, index)) - { + if (!AssetsUtils::loadAssetsIndexJson(assetsId, indexPath, index)) { qCritical() << "Failed to load asset index file" << indexPath << "; can't determine assets path!"; return virtualRoot; } QString targetPath; - if(index.isVirtual) - { + if (index.isVirtual) { return virtualRoot; - } - else if(index.mapToResources) - { + } else if (index.mapToResources) { return QDir(resourcesFolder); } return virtualRoot; @@ -232,8 +211,7 @@ bool reconstructAssets(QString assetsId, QString resourcesFolder) QFile indexFile(indexPath); QDir virtualRoot(FS::PathCombine(virtualDir.path(), assetsId)); - if (!indexFile.exists()) - { + if (!indexFile.exists()) { qCritical() << "No assets index file" << indexPath << "; can't reconstruct assets!"; return false; } @@ -241,31 +219,25 @@ bool reconstructAssets(QString assetsId, QString resourcesFolder) qDebug() << "reconstructAssets" << assetsDir.path() << indexDir.path() << objectDir.path() << virtualDir.path() << virtualRoot.path(); AssetsIndex index; - if(!AssetsUtils::loadAssetsIndexJson(assetsId, indexPath, index)) - { + if (!AssetsUtils::loadAssetsIndexJson(assetsId, indexPath, index)) { qCritical() << "Failed to load asset index file" << indexPath << "; can't reconstruct assets!"; return false; } QString targetPath; bool removeLeftovers = false; - if(index.isVirtual) - { + if (index.isVirtual) { targetPath = virtualRoot.path(); removeLeftovers = true; qDebug() << "Reconstructing virtual assets folder at" << targetPath; - } - else if(index.mapToResources) - { + } else if (index.mapToResources) { targetPath = resourcesFolder; qDebug() << "Reconstructing resources folder at" << targetPath; } - if (!targetPath.isNull()) - { + if (!targetPath.isNull()) { auto presentFiles = collectPathsFromDir(targetPath); - for (QString map : index.objects.keys()) - { + for (QString map : index.objects.keys()) { AssetObject asset_object = index.objects.value(map); QString target_path = FS::PathCombine(targetPath, map); QFile target(target_path); @@ -279,8 +251,7 @@ bool reconstructAssets(QString assetsId, QString resourcesFolder) presentFiles.remove(target_path); - if (!target.exists()) - { + if (!target.exists()) { QFileInfo info(target_path); QDir target_dir = info.dir(); @@ -293,10 +264,8 @@ bool reconstructAssets(QString assetsId, QString resourcesFolder) } // TODO: Write last used time to virtualRoot/.lastused - if(removeLeftovers) - { - for(auto & file: presentFiles) - { + if (removeLeftovers) { + for (auto& file : presentFiles) { qDebug() << "Would remove" << file; } } @@ -304,16 +273,14 @@ bool reconstructAssets(QString assetsId, QString resourcesFolder) return true; } -} +} // namespace AssetsUtils NetAction::Ptr AssetObject::getDownloadAction() { QFileInfo objectFile(getLocalPath()); - if ((!objectFile.isFile()) || (objectFile.size() != size)) - { + if ((!objectFile.isFile()) || (objectFile.size() != size)) { auto objectDL = Net::ApiDownload::makeFile(getUrl(), objectFile.filePath()); - if(hash.size()) - { + if (hash.size()) { auto rawHash = QByteArray::fromHex(hash.toLatin1()); objectDL->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawHash)); } @@ -341,15 +308,13 @@ QString AssetObject::getRelPath() NetJob::Ptr AssetsIndex::getDownloadJob() { auto job = makeShared(QObject::tr("Assets for %1").arg(id), APPLICATION->network()); - for (auto &object : objects.values()) - { + for (auto& object : objects.values()) { auto dl = object.getDownloadAction(); - if(dl) - { + if (dl) { job->addNetAction(dl); } } - if(job->size()) + if (job->size()) return job; return nullptr; } diff --git a/launcher/minecraft/AssetsUtils.h b/launcher/minecraft/AssetsUtils.h index 3dbf19ed6..87956e57a 100644 --- a/launcher/minecraft/AssetsUtils.h +++ b/launcher/minecraft/AssetsUtils.h @@ -15,13 +15,12 @@ #pragma once -#include #include +#include #include "net/NetAction.h" #include "net/NetJob.h" -struct AssetObject -{ +struct AssetObject { QString getRelPath(); QUrl getUrl(); QString getLocalPath(); @@ -31,8 +30,7 @@ struct AssetObject qint64 size; }; -struct AssetsIndex -{ +struct AssetsIndex { NetJob::Ptr getDownloadJob(); QString id; @@ -42,12 +40,11 @@ struct AssetsIndex }; /// FIXME: this is absolutely horrendous. REDO!!!! -namespace AssetsUtils -{ -bool loadAssetsIndexJson(const QString &id, const QString &file, AssetsIndex& index); +namespace AssetsUtils { +bool loadAssetsIndexJson(const QString& id, const QString& file, AssetsIndex& index); -QDir getAssetsDir(const QString &assetsId, const QString &resourcesFolder); +QDir getAssetsDir(const QString& assetsId, const QString& resourcesFolder); /// Reconstruct a virtual assets folder for the given assets ID and return the folder bool reconstructAssets(QString assetsId, QString resourcesFolder); -} +} // namespace AssetsUtils diff --git a/launcher/minecraft/Component.cpp b/launcher/minecraft/Component.cpp index ff81fcbb8..96d67a057 100644 --- a/launcher/minecraft/Component.cpp +++ b/launcher/minecraft/Component.cpp @@ -33,22 +33,22 @@ * limitations under the License. */ -#include -#include #include "Component.h" +#include +#include #include -#include "meta/Version.h" -#include "VersionFile.h" -#include "minecraft/PackProfile.h" +#include "Application.h" #include "FileSystem.h" #include "OneSixVersionFormat.h" -#include "Application.h" +#include "VersionFile.h" +#include "meta/Version.h" +#include "minecraft/PackProfile.h" #include -Component::Component(PackProfile * parent, const QString& uid) +Component::Component(PackProfile* parent, const QString& uid) { assert(parent); m_parent = parent; @@ -56,7 +56,7 @@ Component::Component(PackProfile * parent, const QString& uid) m_uid = uid; } -Component::Component(PackProfile * parent, std::shared_ptr version) +Component::Component(PackProfile* parent, std::shared_ptr version) { assert(parent); m_parent = parent; @@ -68,7 +68,7 @@ Component::Component(PackProfile * parent, std::shared_ptr versio m_loaded = version->isLoaded(); } -Component::Component(PackProfile * parent, const QString& uid, std::shared_ptr file) +Component::Component(PackProfile* parent, const QString& uid, std::shared_ptr file) { assert(parent); m_parent = parent; @@ -88,33 +88,25 @@ std::shared_ptr Component::getMeta() void Component::applyTo(LaunchProfile* profile) { // do not apply disabled components - if(!isEnabled()) - { + if (!isEnabled()) { return; } auto vfile = getVersionFile(); - if(vfile) - { + if (vfile) { vfile->applyTo(profile, m_parent->runtimeContext()); - } - else - { + } else { profile->applyProblemSeverity(getProblemSeverity()); } } std::shared_ptr Component::getVersionFile() const { - if(m_metaVersion) - { - if(!m_metaVersion->isLoaded()) - { + if (m_metaVersion) { + if (!m_metaVersion->isLoaded()) { m_metaVersion->load(Net::Mode::Online); } return m_metaVersion->data(); - } - else - { + } else { return m_file; } } @@ -122,8 +114,7 @@ std::shared_ptr Component::getVersionFile() const std::shared_ptr Component::getVersionList() const { // FIXME: what if the metadata index isn't loaded yet? - if(APPLICATION->metadataIndex()->hasUid(m_uid)) - { + if (APPLICATION->metadataIndex()->hasUid(m_uid)) { return APPLICATION->metadataIndex()->get(m_uid); } return nullptr; @@ -131,12 +122,11 @@ std::shared_ptr Component::getVersionList() const int Component::getOrder() { - if(m_orderOverride) + if (m_orderOverride) return m_order; auto vfile = getVersionFile(); - if(vfile) - { + if (vfile) { return vfile->order; } return 0; @@ -166,13 +156,11 @@ QString Component::getFilename() } QDateTime Component::getReleaseDateTime() { - if(m_metaVersion) - { + if (m_metaVersion) { return m_metaVersion->time(); } auto vfile = getVersionFile(); - if(vfile) - { + if (vfile) { return vfile->releaseTime; } // FIXME: fake @@ -192,12 +180,10 @@ bool Component::canBeDisabled() bool Component::setEnabled(bool state) { bool intendedDisabled = !state; - if (!canBeDisabled()) - { + if (!canBeDisabled()) { intendedDisabled = false; } - if(intendedDisabled != m_disabled) - { + if (intendedDisabled != m_disabled) { m_disabled = intendedDisabled; emit dataChanged(); return true; @@ -212,10 +198,8 @@ bool Component::isCustom() bool Component::isCustomizable() { - if(m_metaVersion) - { - if(getVersionFile()) - { + if (m_metaVersion) { + if (getVersionFile()) { return true; } } @@ -227,10 +211,8 @@ bool Component::isRemovable() } bool Component::isRevertible() { - if (isCustom()) - { - if(APPLICATION->metadataIndex()->hasUid(m_uid)) - { + if (isCustom()) { + if (APPLICATION->metadataIndex()->hasUid(m_uid)) { return true; } } @@ -244,10 +226,8 @@ bool Component::isMoveable() bool Component::isVersionChangeable() { auto list = getVersionList(); - if(list) - { - if(!list->isLoaded()) - { + if (list) { + if (!list->isLoaded()) { list->load(Net::Mode::Online); } return list->count() != 0; @@ -257,8 +237,7 @@ bool Component::isVersionChangeable() void Component::setImportant(bool state) { - if(m_important != state) - { + if (m_important != state) { m_important = state; emit dataChanged(); } @@ -267,8 +246,7 @@ void Component::setImportant(bool state) ProblemSeverity Component::getProblemSeverity() const { auto file = getVersionFile(); - if(file) - { + if (file) { return file->getProblemSeverity(); } return ProblemSeverity::Error; @@ -277,49 +255,38 @@ ProblemSeverity Component::getProblemSeverity() const const QList Component::getProblems() const { auto file = getVersionFile(); - if(file) - { + if (file) { return file->getProblems(); } - return {{ProblemSeverity::Error, QObject::tr("Patch is not loaded yet.")}}; + return { { ProblemSeverity::Error, QObject::tr("Patch is not loaded yet.") } }; } void Component::setVersion(const QString& version) { - if(version == m_version) - { + if (version == m_version) { return; } m_version = version; - if(m_loaded) - { + if (m_loaded) { // we are loaded and potentially have state to invalidate - if(m_file) - { + if (m_file) { // we have a file... explicit version has been changed and there is nothing else to do. - } - else - { + } else { // we don't have a file, therefore we are loaded with metadata m_cachedVersion = version; // see if the meta version is loaded auto metaVersion = APPLICATION->metadataIndex()->get(m_uid, version); - if(metaVersion->isLoaded()) - { + if (metaVersion->isLoaded()) { // if yes, we can continue with that. m_metaVersion = metaVersion; - } - else - { + } else { // if not, we need loading m_metaVersion.reset(); m_loaded = false; } updateCachedData(); } - } - else - { + } else { // not loaded... assume it will be sorted out later by the update task } emit dataChanged(); @@ -327,41 +294,33 @@ void Component::setVersion(const QString& version) bool Component::customize() { - if(isCustom()) - { + if (isCustom()) { return false; } auto filename = getFilename(); - if(!FS::ensureFilePathExists(filename)) - { + if (!FS::ensureFilePathExists(filename)) { return false; } // FIXME: get rid of this try-catch. - try - { + try { QSaveFile jsonFile(filename); - if(!jsonFile.open(QIODevice::WriteOnly)) - { + if (!jsonFile.open(QIODevice::WriteOnly)) { return false; } auto vfile = getVersionFile(); - if(!vfile) - { + if (!vfile) { return false; } auto document = OneSixVersionFormat::versionFileToJson(vfile); jsonFile.write(document.toJson()); - if(!jsonFile.commit()) - { + if (!jsonFile.commit()) { return false; } m_file = vfile; m_metaVersion.reset(); emit dataChanged(); - } - catch (const Exception &error) - { + } catch (const Exception& error) { qWarning() << "Version could not be loaded:" << error.cause(); } return true; @@ -369,31 +328,25 @@ bool Component::customize() bool Component::revert() { - if(!isCustom()) - { + if (!isCustom()) { // already not custom return true; } auto filename = getFilename(); bool result = true; // just kill the file and reload - if(QFile::exists(filename)) - { + if (QFile::exists(filename)) { result = QFile::remove(filename); } - if(result) - { + if (result) { // file gone... m_file.reset(); // check local cache for metadata... auto version = APPLICATION->metadataIndex()->get(m_uid, m_version); - if(version->isLoaded()) - { + if (version->isLoaded()) { m_metaVersion = version; - } - else - { + } else { m_metaVersion.reset(); m_loaded = false; } @@ -407,23 +360,19 @@ bool Component::revert() * By default, only uids are compared for set operations. * This compares all fields of the Require structs in the sets. */ -static bool deepCompare(const std::set & a, const std::set & b) +static bool deepCompare(const std::set& a, const std::set& b) { // NOTE: this needs to be rewritten if the type of Meta::RequireSet changes - if(a.size() != b.size()) - { + if (a.size() != b.size()) { return false; } - for(const auto & reqA :a) - { - const auto &iter2 = b.find(reqA); - if(iter2 == b.cend()) - { + for (const auto& reqA : a) { + const auto& iter2 = b.find(reqA); + if (iter2 == b.cend()) { return false; } - const auto & reqB = *iter2; - if(!reqA.deepEquals(reqB)) - { + const auto& reqB = *iter2; + if (!reqA.deepEquals(reqB)) { return false; } } @@ -433,41 +382,32 @@ static bool deepCompare(const std::set & a, const std::setname) - { + if (m_cachedName != file->name) { m_cachedName = file->name; changed = true; } - if(m_cachedVersion != file->version) - { + if (m_cachedVersion != file->version) { m_cachedVersion = file->version; changed = true; } - if(m_cachedVolatile != file->m_volatile) - { + if (m_cachedVolatile != file->m_volatile) { m_cachedVolatile = file->m_volatile; changed = true; } - if(!deepCompare(m_cachedRequires, file->m_requires)) - { + if (!deepCompare(m_cachedRequires, file->m_requires)) { m_cachedRequires = file->m_requires; changed = true; } - if(!deepCompare(m_cachedConflicts, file->conflicts)) - { + if (!deepCompare(m_cachedConflicts, file->conflicts)) { m_cachedConflicts = file->conflicts; changed = true; } - if(changed) - { + if (changed) { emit dataChanged(); } - } - else - { + } else { // in case we removed all the metadata m_cachedRequires.clear(); m_cachedConflicts.clear(); diff --git a/launcher/minecraft/Component.h b/launcher/minecraft/Component.h index e7419c41a..3474a22e0 100644 --- a/launcher/minecraft/Component.h +++ b/launcher/minecraft/Component.h @@ -1,38 +1,36 @@ #pragma once -#include -#include -#include #include -#include "meta/JsonFormat.h" +#include +#include +#include #include "ProblemProvider.h" #include "QObjectPtr.h" +#include "meta/JsonFormat.h" class PackProfile; class LaunchProfile; -namespace Meta -{ - class Version; - class VersionList; -} +namespace Meta { +class Version; +class VersionList; +} // namespace Meta class VersionFile; -class Component : public QObject, public ProblemProvider -{ -Q_OBJECT -public: - Component(PackProfile * parent, const QString &uid); +class Component : public QObject, public ProblemProvider { + Q_OBJECT + public: + Component(PackProfile* parent, const QString& uid); // DEPRECATED: remove these constructors? - Component(PackProfile * parent, std::shared_ptr version); - Component(PackProfile * parent, const QString & uid, std::shared_ptr file); + Component(PackProfile* parent, std::shared_ptr version); + Component(PackProfile* parent, const QString& uid, std::shared_ptr file); - virtual ~Component(){} + virtual ~Component() {} - void applyTo(LaunchProfile *profile); + void applyTo(LaunchProfile* profile); bool isEnabled(); - bool setEnabled (bool state); + bool setEnabled(bool state); bool canBeDisabled(); bool isMoveable(); @@ -57,23 +55,22 @@ public: std::shared_ptr getVersionFile() const; std::shared_ptr getVersionList() const; - void setImportant (bool state); - + void setImportant(bool state); const QList getProblems() const override; ProblemSeverity getProblemSeverity() const override; - void setVersion(const QString & version); + void setVersion(const QString& version); bool customize(); bool revert(); void updateCachedData(); -signals: + signals: void dataChanged(); -public: /* data */ - PackProfile * m_parent; + public: /* data */ + PackProfile* m_parent; // BEGIN: persistent component list properties /// ID of the component diff --git a/launcher/minecraft/ComponentUpdateTask.cpp b/launcher/minecraft/ComponentUpdateTask.cpp index d55bc17f2..0b85b81aa 100644 --- a/launcher/minecraft/ComponentUpdateTask.cpp +++ b/launcher/minecraft/ComponentUpdateTask.cpp @@ -1,16 +1,16 @@ #include "ComponentUpdateTask.h" -#include "PackProfile_p.h" -#include "PackProfile.h" #include "Component.h" -#include "meta/Index.h" -#include "meta/VersionList.h" -#include "meta/Version.h" #include "ComponentUpdateTask_p.h" -#include "cassert" -#include "Version.h" -#include "net/Mode.h" #include "OneSixVersionFormat.h" +#include "PackProfile.h" +#include "PackProfile_p.h" +#include "Version.h" +#include "cassert" +#include "meta/Index.h" +#include "meta/Version.h" +#include "meta/VersionList.h" +#include "net/Mode.h" #include "Application.h" @@ -32,8 +32,7 @@ * If the component list changes, start over. */ -ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list, QObject* parent) - : Task(parent) +ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list, QObject* parent) : Task(parent) { d.reset(new ComponentUpdateTaskData); d->m_list = list; @@ -41,9 +40,7 @@ ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfi d->netmode = netmode; } -ComponentUpdateTask::~ComponentUpdateTask() -{ -} +ComponentUpdateTask::~ComponentUpdateTask() {} void ComponentUpdateTask::executeTask() { @@ -51,19 +48,12 @@ void ComponentUpdateTask::executeTask() loadComponents(); } -namespace -{ -enum class LoadResult -{ - LoadedLocal, - RequiresRemote, - Failed -}; +namespace { +enum class LoadResult { LoadedLocal, RequiresRemote, Failed }; LoadResult composeLoadResult(LoadResult a, LoadResult b) { - if (a < b) - { + if (a < b) { return b; } return a; @@ -71,28 +61,24 @@ LoadResult composeLoadResult(LoadResult a, LoadResult b) static LoadResult loadComponent(ComponentPtr component, Task::Ptr& loadTask, Net::Mode netmode) { - if(component->m_loaded) - { + if (component->m_loaded) { qDebug() << component->getName() << "is already loaded"; return LoadResult::LoadedLocal; } LoadResult result = LoadResult::Failed; auto customPatchFilename = component->getFilename(); - if(QFile::exists(customPatchFilename)) - { + if (QFile::exists(customPatchFilename)) { // if local file exists... // check for uid problems inside... bool fileChanged = false; auto file = ProfileUtils::parseJsonFile(QFileInfo(customPatchFilename), false); - if(file->uid != component->m_uid) - { + if (file->uid != component->m_uid) { file->uid = component->m_uid; fileChanged = true; } - if(fileChanged) - { + if (fileChanged) { // FIXME: @QUALITY do not ignore return value ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), customPatchFilename); } @@ -100,21 +86,16 @@ static LoadResult loadComponent(ComponentPtr component, Task::Ptr& loadTask, Net component->m_file = file; component->m_loaded = true; result = LoadResult::LoadedLocal; - } - else - { + } else { auto metaVersion = APPLICATION->metadataIndex()->get(component->m_uid, component->m_version); component->m_metaVersion = metaVersion; - if(metaVersion->isLoaded()) - { + if (metaVersion->isLoaded()) { component->m_loaded = true; result = LoadResult::LoadedLocal; - } - else - { + } else { metaVersion->load(netmode); loadTask = metaVersion->getCurrentTask(); - if(loadTask) + if (loadTask) result = LoadResult::RequiresRemote; else if (metaVersion->isLoaded()) result = LoadResult::LoadedLocal; @@ -155,21 +136,19 @@ static LoadResult loadPackProfile(ComponentPtr component, Task::Ptr& loadTask, N static LoadResult loadIndex(Task::Ptr& loadTask, Net::Mode netmode) { // FIXME: DECIDE. do we want to run the update task anyway? - if(APPLICATION->metadataIndex()->isLoaded()) - { + if (APPLICATION->metadataIndex()->isLoaded()) { qDebug() << "Index is already loaded"; return LoadResult::LoadedLocal; } APPLICATION->metadataIndex()->load(netmode); loadTask = APPLICATION->metadataIndex()->getCurrentTask(); - if(loadTask) - { + if (loadTask) { return LoadResult::RequiresRemote; } // FIXME: this is assuming the load succeeded... did it really? return LoadResult::LoadedLocal; } -} +} // namespace void ComponentUpdateTask::loadComponents() { @@ -183,34 +162,24 @@ void ComponentUpdateTask::loadComponents() Task::Ptr indexLoadTask; auto singleResult = loadIndex(indexLoadTask, d->netmode); result = composeLoadResult(result, singleResult); - if(indexLoadTask) - { + if (indexLoadTask) { qDebug() << "Remote loading is being run for metadata index"; RemoteLoadStatus status; status.type = RemoteLoadStatus::Type::Index; d->remoteLoadStatusList.append(status); - connect(indexLoadTask.get(), &Task::succeeded, [=]() - { - remoteLoadSucceeded(taskIndex); - }); - connect(indexLoadTask.get(), &Task::failed, [=](const QString & error) - { - remoteLoadFailed(taskIndex, error); - }); - connect(indexLoadTask.get(), &Task::aborted, [=]() - { - remoteLoadFailed(taskIndex, tr("Aborted")); - }); + connect(indexLoadTask.get(), &Task::succeeded, [=]() { remoteLoadSucceeded(taskIndex); }); + connect(indexLoadTask.get(), &Task::failed, [=](const QString& error) { remoteLoadFailed(taskIndex, error); }); + connect(indexLoadTask.get(), &Task::aborted, [=]() { remoteLoadFailed(taskIndex, tr("Aborted")); }); taskIndex++; } } // load all the components OR their lists... - for (auto component: d->m_list->d->components) - { + for (auto component : d->m_list->d->components) { Task::Ptr loadTask; LoadResult singleResult; RemoteLoadStatus::Type loadType; - // FIXME: to do this right, we need to load the lists and decide on which versions to use during dependency resolution. For now, ignore all that... + // FIXME: to do this right, we need to load the lists and decide on which versions to use during dependency resolution. For now, + // ignore all that... #if 0 switch(d->mode) { @@ -231,26 +200,15 @@ void ComponentUpdateTask::loadComponents() singleResult = loadComponent(component, loadTask, d->netmode); loadType = RemoteLoadStatus::Type::Version; #endif - if(singleResult == LoadResult::LoadedLocal) - { + if (singleResult == LoadResult::LoadedLocal) { component->updateCachedData(); } result = composeLoadResult(result, singleResult); - if (loadTask) - { + if (loadTask) { qDebug() << "Remote loading is being run for" << component->getName(); - connect(loadTask.get(), &Task::succeeded, [=]() - { - remoteLoadSucceeded(taskIndex); - }); - connect(loadTask.get(), &Task::failed, [=](const QString & error) - { - remoteLoadFailed(taskIndex, error); - }); - connect(loadTask.get(), &Task::aborted, [=]() - { - remoteLoadFailed(taskIndex, tr("Aborted")); - }); + connect(loadTask.get(), &Task::succeeded, [=]() { remoteLoadSucceeded(taskIndex); }); + connect(loadTask.get(), &Task::failed, [=](const QString& error) { remoteLoadFailed(taskIndex, error); }); + connect(loadTask.get(), &Task::aborted, [=]() { remoteLoadFailed(taskIndex, tr("Aborted")); }); RemoteLoadStatus status; status.type = loadType; status.PackProfileIndex = componentIndex; @@ -260,95 +218,73 @@ void ComponentUpdateTask::loadComponents() componentIndex++; } d->remoteTasksInProgress = taskIndex; - switch(result) - { - case LoadResult::LoadedLocal: - { + switch (result) { + case LoadResult::LoadedLocal: { // Everything got loaded. Advance to dependency resolution. resolveDependencies(d->mode == Mode::Launch || d->netmode == Net::Mode::Offline); break; } - case LoadResult::RequiresRemote: - { + case LoadResult::RequiresRemote: { // we wait for signals. break; } - case LoadResult::Failed: - { + case LoadResult::Failed: { emitFailed(tr("Some component metadata load tasks failed.")); break; } } } -namespace -{ - struct RequireEx : public Meta::Require - { - size_t indexOfFirstDependee = 0; - }; - struct RequireCompositionResult - { - bool ok; - RequireEx outcome; - }; - using RequireExSet = std::set; -} +namespace { +struct RequireEx : public Meta::Require { + size_t indexOfFirstDependee = 0; +}; +struct RequireCompositionResult { + bool ok; + RequireEx outcome; +}; +using RequireExSet = std::set; +} // namespace -static RequireCompositionResult composeRequirement(const RequireEx & a, const RequireEx & b) +static RequireCompositionResult composeRequirement(const RequireEx& a, const RequireEx& b) { assert(a.uid == b.uid); RequireEx out; out.uid = a.uid; out.indexOfFirstDependee = std::min(a.indexOfFirstDependee, b.indexOfFirstDependee); - if(a.equalsVersion.isEmpty()) - { + if (a.equalsVersion.isEmpty()) { out.equalsVersion = b.equalsVersion; - } - else if (b.equalsVersion.isEmpty()) - { + } else if (b.equalsVersion.isEmpty()) { out.equalsVersion = a.equalsVersion; - } - else if (a.equalsVersion == b.equalsVersion) - { + } else if (a.equalsVersion == b.equalsVersion) { out.equalsVersion = a.equalsVersion; - } - else - { + } else { // FIXME: mark error as explicit version conflict - return {false, out}; + return { false, out }; } - if(a.suggests.isEmpty()) - { + if (a.suggests.isEmpty()) { out.suggests = b.suggests; - } - else if (b.suggests.isEmpty()) - { + } else if (b.suggests.isEmpty()) { out.suggests = a.suggests; - } - else - { + } else { Version aVer(a.suggests); Version bVer(b.suggests); out.suggests = (aVer < bVer ? b.suggests : a.suggests); } - return {true, out}; + return { true, out }; } // gather the requirements from all components, finding any obvious conflicts -static bool gatherRequirementsFromComponents(const ComponentContainer & input, RequireExSet & output) +static bool gatherRequirementsFromComponents(const ComponentContainer& input, RequireExSet& output) { bool succeeded = true; size_t componentNum = 0; - for(auto component: input) - { - auto &componentRequires = component->m_cachedRequires; - for(const auto & componentRequire: componentRequires) - { - auto found = std::find_if(output.cbegin(), output.cend(), [componentRequire](const Meta::Require & req){ - return req.uid == componentRequire.uid; - }); + for (auto component : input) { + auto& componentRequires = component->m_cachedRequires; + for (const auto& componentRequire : componentRequires) { + auto found = std::find_if(output.cbegin(), output.cend(), + [componentRequire](const Meta::Require& req) { return req.uid == componentRequire.uid; }); RequireEx componenRequireEx; componenRequireEx.uid = componentRequire.uid; @@ -356,29 +292,18 @@ static bool gatherRequirementsFromComponents(const ComponentContainer & input, R componenRequireEx.equalsVersion = componentRequire.equalsVersion; componenRequireEx.indexOfFirstDependee = componentNum; - if(found != output.cend()) - { + if (found != output.cend()) { // found... process it further auto result = composeRequirement(componenRequireEx, *found); - if(result.ok) - { + if (result.ok) { output.erase(componenRequireEx); output.insert(result.outcome); - } - else - { - qCritical() - << "Conflicting requirements:" - << componentRequire.uid - << "versions:" - << componentRequire.equalsVersion - << ";" - << (*found).equalsVersion; + } else { + qCritical() << "Conflicting requirements:" << componentRequire.uid << "versions:" << componentRequire.equalsVersion + << ";" << (*found).equalsVersion; } succeeded &= result.ok; - } - else - { + } else { // not found, accumulate output.insert(componenRequireEx); } @@ -389,19 +314,17 @@ static bool gatherRequirementsFromComponents(const ComponentContainer & input, R } /// Get list of uids that can be trivially removed because nothing is depending on them anymore (and they are installed as deps) -static void getTrivialRemovals(const ComponentContainer & components, const RequireExSet & reqs, QStringList &toRemove) +static void getTrivialRemovals(const ComponentContainer& components, const RequireExSet& reqs, QStringList& toRemove) { - for(const auto & component: components) - { - if(!component->m_dependencyOnly) + for (const auto& component : components) { + if (!component->m_dependencyOnly) continue; - if(!component->m_cachedVolatile) + if (!component->m_cachedVolatile) continue; RequireEx reqNeedle; reqNeedle.uid = component->m_uid; const auto iter = reqs.find(reqNeedle); - if(iter == reqs.cend()) - { + if (iter == reqs.cend()) { toRemove.append(component->m_uid); } } @@ -415,60 +338,40 @@ static void getTrivialRemovals(const ComponentContainer & components, const Requ * toAdd - set of requirements than mean adding a new component * toChange - set of requirements that mean changing version of an existing component */ -static bool getTrivialComponentChanges(const ComponentIndex & index, const RequireExSet & input, RequireExSet & toAdd, RequireExSet & toChange) +static bool getTrivialComponentChanges(const ComponentIndex& index, const RequireExSet& input, RequireExSet& toAdd, RequireExSet& toChange) { - enum class Decision - { - Undetermined, - Met, - Missing, - VersionNotSame, - LockedVersionNotSame - } decision = Decision::Undetermined; + enum class Decision { Undetermined, Met, Missing, VersionNotSame, LockedVersionNotSame } decision = Decision::Undetermined; QString reqStr; bool succeeded = true; // list the composed requirements and say if they are met or unmet - for(auto & req: input) - { - do - { - if(req.equalsVersion.isEmpty()) - { + for (auto& req : input) { + do { + if (req.equalsVersion.isEmpty()) { reqStr = QString("Req: %1").arg(req.uid); - if(index.contains(req.uid)) - { + if (index.contains(req.uid)) { decision = Decision::Met; - } - else - { + } else { toAdd.insert(req); decision = Decision::Missing; } break; - } - else - { + } else { reqStr = QString("Req: %1 == %2").arg(req.uid, req.equalsVersion); - const auto & compIter = index.find(req.uid); - if(compIter == index.cend()) - { + const auto& compIter = index.find(req.uid); + if (compIter == index.cend()) { toAdd.insert(req); decision = Decision::Missing; break; } - auto & comp = (*compIter); - if(comp->getVersion() != req.equalsVersion) - { - if(comp->isCustom()) { + auto& comp = (*compIter); + if (comp->getVersion() != req.equalsVersion) { + if (comp->isCustom()) { decision = Decision::LockedVersionNotSame; } else { - if(comp->m_dependencyOnly) - { + if (comp->m_dependencyOnly) { decision = Decision::VersionNotSame; - } - else - { + } else { decision = Decision::LockedVersionNotSame; } } @@ -476,9 +379,8 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi } decision = Decision::Met; } - } while(false); - switch(decision) - { + } while (false); + switch (decision) { case Decision::Undetermined: qCritical() << "No decision for" << reqStr; succeeded = false; @@ -520,26 +422,22 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly) * * NOTE: this is a placeholder and should eventually be replaced with something 'serious' */ - auto & components = d->m_list->d->components; - auto & componentIndex = d->m_list->d->componentIndex; + auto& components = d->m_list->d->components; + auto& componentIndex = d->m_list->d->componentIndex; RequireExSet allRequires; QStringList toRemove; - do - { + do { allRequires.clear(); toRemove.clear(); - if(!gatherRequirementsFromComponents(components, allRequires)) - { + if (!gatherRequirementsFromComponents(components, allRequires)) { emitFailed(tr("Conflicting requirements detected during dependency checking!")); return; } getTrivialRemovals(components, allRequires, toRemove); - if(!toRemove.isEmpty()) - { + if (!toRemove.isEmpty()) { qDebug() << "Removing obsolete components..."; - for(auto & remove : toRemove) - { + for (auto& remove : toRemove) { qDebug() << "Removing" << remove; d->m_list->remove(remove); } @@ -548,69 +446,50 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly) RequireExSet toAdd; RequireExSet toChange; bool succeeded = getTrivialComponentChanges(componentIndex, allRequires, toAdd, toChange); - if(!succeeded) - { + if (!succeeded) { emitFailed(tr("Instance has conflicting dependencies.")); return; } - if(checkOnly) - { - if(toAdd.size() || toChange.size()) - { + if (checkOnly) { + if (toAdd.size() || toChange.size()) { emitFailed(tr("Instance has unresolved dependencies while loading/checking for launch.")); - } - else - { + } else { emitSucceeded(); } return; } bool recursionNeeded = false; - if(toAdd.size()) - { + if (toAdd.size()) { // add stuff... - for(auto &add: toAdd) - { + for (auto& add : toAdd) { auto component = makeShared(d->m_list, add.uid); - if(!add.equalsVersion.isEmpty()) - { + if (!add.equalsVersion.isEmpty()) { // exact version qDebug() << "Adding" << add.uid << "version" << add.equalsVersion << "at position" << add.indexOfFirstDependee; component->m_version = add.equalsVersion; - } - else - { + } else { // version needs to be decided qDebug() << "Adding" << add.uid << "at position" << add.indexOfFirstDependee; -// ############################################################################################################ -// HACK HACK HACK HACK FIXME: this is a placeholder for deciding what version to use. For now, it is hardcoded. - if(!add.suggests.isEmpty()) - { + // ############################################################################################################ + // HACK HACK HACK HACK FIXME: this is a placeholder for deciding what version to use. For now, it is hardcoded. + if (!add.suggests.isEmpty()) { component->m_version = add.suggests; - } - else - { - if(add.uid == "org.lwjgl") - { + } else { + if (add.uid == "org.lwjgl") { component->m_version = "2.9.1"; - } - else if (add.uid == "org.lwjgl3") - { + } else if (add.uid == "org.lwjgl3") { component->m_version = "3.1.2"; - } - else if (add.uid == "net.fabricmc.intermediary" || add.uid == "org.quiltmc.hashed") - { - auto minecraft = std::find_if(components.begin(), components.end(), [](ComponentPtr & cmp){ - return cmp->getID() == "net.minecraft"; - }); - if(minecraft != components.end()) { + } else if (add.uid == "net.fabricmc.intermediary" || add.uid == "org.quiltmc.hashed") { + auto minecraft = std::find_if(components.begin(), components.end(), + [](ComponentPtr& cmp) { return cmp->getID() == "net.minecraft"; }); + if (minecraft != components.end()) { component->m_version = (*minecraft)->getVersion(); } } } -// HACK HACK HACK HACK FIXME: this is a placeholder for deciding what version to use. For now, it is hardcoded. -// ############################################################################################################ + // HACK HACK HACK HACK FIXME: this is a placeholder for deciding what version to use. For now, it is hardcoded. + // ############################################################################################################ } component->m_dependencyOnly = true; // FIXME: this should not work directly with the component list @@ -619,11 +498,9 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly) } recursionNeeded = true; } - if(toChange.size()) - { + if (toChange.size()) { // change a version of something that exists - for(auto &change: toChange) - { + for (auto& change : toChange) { // FIXME: this should not work directly with the component list qDebug() << "Setting version of " << change.uid << "to" << change.equalsVersion; auto component = componentIndex[change.uid]; @@ -632,31 +509,26 @@ void ComponentUpdateTask::resolveDependencies(bool checkOnly) recursionNeeded = true; } - if(recursionNeeded) - { + if (recursionNeeded) { loadComponents(); - } - else - { + } else { emitSucceeded(); } } void ComponentUpdateTask::remoteLoadSucceeded(size_t taskIndex) { - auto &taskSlot = d->remoteLoadStatusList[taskIndex]; - if(taskSlot.finished) - { + auto& taskSlot = d->remoteLoadStatusList[taskIndex]; + if (taskSlot.finished) { qWarning() << "Got multiple results from remote load task" << taskIndex; return; } qDebug() << "Remote task" << taskIndex << "succeeded"; taskSlot.succeeded = false; taskSlot.finished = true; - d->remoteTasksInProgress --; + d->remoteTasksInProgress--; // update the cached data of the component from the downloaded version file. - if (taskSlot.type == RemoteLoadStatus::Type::Version) - { + if (taskSlot.type == RemoteLoadStatus::Type::Version) { auto component = d->m_list->getComponent(taskSlot.PackProfileIndex); component->m_loaded = true; component->updateCachedData(); @@ -664,12 +536,10 @@ void ComponentUpdateTask::remoteLoadSucceeded(size_t taskIndex) checkIfAllFinished(); } - void ComponentUpdateTask::remoteLoadFailed(size_t taskIndex, const QString& msg) { - auto &taskSlot = d->remoteLoadStatusList[taskIndex]; - if(taskSlot.finished) - { + auto& taskSlot = d->remoteLoadStatusList[taskIndex]; + if (taskSlot.finished) { qWarning() << "Got multiple results from remote load task" << taskIndex; return; } @@ -678,31 +548,25 @@ void ComponentUpdateTask::remoteLoadFailed(size_t taskIndex, const QString& msg) taskSlot.succeeded = false; taskSlot.finished = true; taskSlot.error = msg; - d->remoteTasksInProgress --; + d->remoteTasksInProgress--; checkIfAllFinished(); } void ComponentUpdateTask::checkIfAllFinished() { - if(d->remoteTasksInProgress) - { + if (d->remoteTasksInProgress) { // not yet... return; } - if(d->remoteLoadSuccessful) - { + if (d->remoteLoadSuccessful) { // nothing bad happened... clear the temp load status and proceed with looking at dependencies d->remoteLoadStatusList.clear(); resolveDependencies(d->mode == Mode::Launch); - } - else - { + } else { // remote load failed... report error and bail QStringList allErrorsList; - for(auto & item: d->remoteLoadStatusList) - { - if(!item.succeeded) - { + for (auto& item : d->remoteLoadStatusList) { + if (!item.succeeded) { allErrorsList.append(item.error); } } diff --git a/launcher/minecraft/ComponentUpdateTask.h b/launcher/minecraft/ComponentUpdateTask.h index 4274cabb5..2f396a049 100644 --- a/launcher/minecraft/ComponentUpdateTask.h +++ b/launcher/minecraft/ComponentUpdateTask.h @@ -1,37 +1,32 @@ #pragma once -#include "tasks/Task.h" #include "net/Mode.h" +#include "tasks/Task.h" #include class PackProfile; struct ComponentUpdateTaskData; -class ComponentUpdateTask : public Task -{ +class ComponentUpdateTask : public Task { Q_OBJECT -public: - enum class Mode - { - Launch, - Resolution - }; + public: + enum class Mode { Launch, Resolution }; -public: - explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile * list, QObject *parent = 0); + public: + explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list, QObject* parent = 0); virtual ~ComponentUpdateTask(); -protected: + protected: void executeTask(); -private: + private: void loadComponents(); void resolveDependencies(bool checkOnly); void remoteLoadSucceeded(size_t index); - void remoteLoadFailed(size_t index, const QString &msg); + void remoteLoadFailed(size_t index, const QString& msg); void checkIfAllFinished(); -private: + private: std::unique_ptr d; }; diff --git a/launcher/minecraft/ComponentUpdateTask_p.h b/launcher/minecraft/ComponentUpdateTask_p.h index 5b02431b2..00e8f2fbe 100644 --- a/launcher/minecraft/ComponentUpdateTask_p.h +++ b/launcher/minecraft/ComponentUpdateTask_p.h @@ -1,29 +1,22 @@ #pragma once -#include -#include #include +#include +#include #include "net/Mode.h" class PackProfile; -struct RemoteLoadStatus -{ - enum class Type - { - Index, - List, - Version - } type = Type::Version; +struct RemoteLoadStatus { + enum class Type { Index, List, Version } type = Type::Version; size_t PackProfileIndex = 0; bool finished = false; bool succeeded = false; QString error; }; -struct ComponentUpdateTaskData -{ - PackProfile * m_list = nullptr; +struct ComponentUpdateTaskData { + PackProfile* m_list = nullptr; QList remoteLoadStatusList; bool remoteLoadSuccessful = true; size_t remoteTasksInProgress = 0; diff --git a/launcher/minecraft/GradleSpecifier.h b/launcher/minecraft/GradleSpecifier.h index 27514ab9d..53c31e8e0 100644 --- a/launcher/minecraft/GradleSpecifier.h +++ b/launcher/minecraft/GradleSpecifier.h @@ -35,22 +35,15 @@ #pragma once +#include #include #include -#include #include "DefaultVariable.h" -struct GradleSpecifier -{ - GradleSpecifier() - { - m_valid = false; - } - GradleSpecifier(QString value) - { - operator=(value); - } - GradleSpecifier & operator =(const QString & value) +struct GradleSpecifier { + GradleSpecifier() { m_valid = false; } + GradleSpecifier(QString value) { operator=(value); } + GradleSpecifier& operator=(const QString& value) { /* org.gradle.test.classifiers : service : 1.0 : jdk15 @ jar @@ -61,10 +54,13 @@ struct GradleSpecifier 4 "jdk15" 5 "jar" */ - QRegularExpression matcher(QRegularExpression::anchoredPattern("([^:@]+):([^:@]+):([^:@]+)" "(?::([^:@]+))?" "(?:@([^:@]+))?")); + QRegularExpression matcher( + QRegularExpression::anchoredPattern("([^:@]+):([^:@]+):([^:@]+)" + "(?::([^:@]+))?" + "(?:@([^:@]+))?")); QRegularExpressionMatch match = matcher.match(value); m_valid = match.hasMatch(); - if(!m_valid) { + if (!m_valid) { m_invalidValue = value; return *this; } @@ -73,53 +69,46 @@ struct GradleSpecifier m_artifactId = match.captured(2); m_version = match.captured(3); m_classifier = match.captured(4); - if(match.lastCapturedIndex() >= 5) - { + if (match.lastCapturedIndex() >= 5) { m_extension = match.captured(5); } return *this; } QString serialize() const { - if(!m_valid) { + if (!m_valid) { return m_invalidValue; } QString retval = m_groupId + ":" + m_artifactId + ":" + m_version; - if(!m_classifier.isEmpty()) - { + if (!m_classifier.isEmpty()) { retval += ":" + m_classifier; } - if(m_extension.isExplicit()) - { + if (m_extension.isExplicit()) { retval += "@" + m_extension; } return retval; } QString getFileName() const { - if(!m_valid) { + if (!m_valid) { return QString(); } QString filename = m_artifactId + '-' + m_version; - if(!m_classifier.isEmpty()) - { + if (!m_classifier.isEmpty()) { filename += "-" + m_classifier; } filename += "." + m_extension; return filename; } - QString toPath(const QString & filenameOverride = QString()) const + QString toPath(const QString& filenameOverride = QString()) const { - if(!m_valid) { + if (!m_valid) { return QString(); } QString filename; - if(filenameOverride.isEmpty()) - { + if (filenameOverride.isEmpty()) { filename = getFileName(); - } - else - { + } else { filename = filenameOverride; } QString path = m_groupId; @@ -127,57 +116,34 @@ struct GradleSpecifier path += '/' + m_artifactId + '/' + m_version + '/' + filename; return path; } - inline bool valid() const - { - return m_valid; - } - inline QString version() const - { - return m_version; - } - inline QString groupId() const - { - return m_groupId; - } - inline QString artifactId() const - { - return m_artifactId; - } - inline void setClassifier(const QString & classifier) - { - m_classifier = classifier; - } - inline QString classifier() const - { - return m_classifier; - } - inline QString extension() const - { - return m_extension; - } - inline QString artifactPrefix() const - { - return m_groupId + ":" + m_artifactId; - } - bool matchName(const GradleSpecifier & other) const + inline bool valid() const { return m_valid; } + inline QString version() const { return m_version; } + inline QString groupId() const { return m_groupId; } + inline QString artifactId() const { return m_artifactId; } + inline void setClassifier(const QString& classifier) { m_classifier = classifier; } + inline QString classifier() const { return m_classifier; } + inline QString extension() const { return m_extension; } + inline QString artifactPrefix() const { return m_groupId + ":" + m_artifactId; } + bool matchName(const GradleSpecifier& other) const { return other.artifactId() == artifactId() && other.groupId() == groupId() && other.classifier() == classifier(); } - bool operator==(const GradleSpecifier & other) const + bool operator==(const GradleSpecifier& other) const { - if(m_groupId != other.m_groupId) + if (m_groupId != other.m_groupId) return false; - if(m_artifactId != other.m_artifactId) + if (m_artifactId != other.m_artifactId) return false; - if(m_version != other.m_version) + if (m_version != other.m_version) return false; - if(m_classifier != other.m_classifier) + if (m_classifier != other.m_classifier) return false; - if(m_extension != other.m_extension) + if (m_extension != other.m_extension) return false; return true; } -private: + + private: QString m_invalidValue; QString m_groupId; QString m_artifactId; diff --git a/launcher/minecraft/LaunchProfile.cpp b/launcher/minecraft/LaunchProfile.cpp index 9a6cea11a..013c78ae3 100644 --- a/launcher/minecraft/LaunchProfile.cpp +++ b/launcher/minecraft/LaunchProfile.cpp @@ -55,9 +55,9 @@ void LaunchProfile::clear() m_problemSeverity = ProblemSeverity::None; } -static void applyString(const QString & from, QString & to) +static void applyString(const QString& from, QString& to) { - if(from.isEmpty()) + if (from.isEmpty()) return; to = from; } @@ -94,8 +94,7 @@ void LaunchProfile::applyMinecraftVersionType(const QString& type) void LaunchProfile::applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets) { - if(assets) - { + if (assets) { m_minecraftAssets = assets; } } @@ -109,10 +108,8 @@ void LaunchProfile::applyTweakers(const QStringList& tweakers) { // if the applied tweakers override an existing one, skip it. this effectively moves it later in the sequence QStringList newTweakers; - for(auto & tweaker: m_tweakers) - { - if (tweakers.contains(tweaker)) - { + for (auto& tweaker : m_tweakers) { + if (tweakers.contains(tweaker)) { continue; } newTweakers.append(tweaker); @@ -127,13 +124,11 @@ void LaunchProfile::applyJarMods(const QList& jarMods) this->m_jarMods.append(jarMods); } -static int findLibraryByName(QList *haystack, const GradleSpecifier &needle) +static int findLibraryByName(QList* haystack, const GradleSpecifier& needle) { int retval = -1; - for (int i = 0; i < haystack->size(); ++i) - { - if (haystack->at(i)->rawName().matchName(needle)) - { + for (int i = 0; i < haystack->size(); ++i) { + if (haystack->at(i)->rawName().matchName(needle)) { // only one is allowed. if (retval != -1) return -1; @@ -145,24 +140,21 @@ static int findLibraryByName(QList *haystack, const GradleSpecifier void LaunchProfile::applyMods(const QList& mods) { - QList * list = &m_mods; - for(auto & mod: mods) - { + QList* list = &m_mods; + for (auto& mod : mods) { auto modCopy = Library::limitedCopy(mod); // find the mod by name. const int index = findLibraryByName(list, mod->rawName()); // mod not found? just add it. - if (index < 0) - { + if (index < 0) { list->append(modCopy); return; } auto existingLibrary = list->at(index); // if we are higher it means we should update - if (Version(mod->version()) > Version(existingLibrary->version())) - { + if (Version(mod->version()) > Version(existingLibrary->version())) { list->replace(index, modCopy); } } @@ -173,16 +165,14 @@ void LaunchProfile::applyCompatibleJavaMajors(QList& javaMajor) m_compatibleJavaMajors.append(javaMajor); } -void LaunchProfile::applyLibrary(LibraryPtr library, const RuntimeContext & runtimeContext) +void LaunchProfile::applyLibrary(LibraryPtr library, const RuntimeContext& runtimeContext) { - if(!library->isActive(runtimeContext)) - { + if (!library->isActive(runtimeContext)) { return; } - QList * list = &m_libraries; - if(library->isNative()) - { + QList* list = &m_libraries; + if (library->isNative()) { list = &m_nativeLibraries; } @@ -191,29 +181,25 @@ void LaunchProfile::applyLibrary(LibraryPtr library, const RuntimeContext & runt // find the library by name. const int index = findLibraryByName(list, library->rawName()); // library not found? just add it. - if (index < 0) - { + if (index < 0) { list->append(libraryCopy); return; } auto existingLibrary = list->at(index); // if we are higher it means we should update - if (Version(library->version()) > Version(existingLibrary->version())) - { + if (Version(library->version()) > Version(existingLibrary->version())) { list->replace(index, libraryCopy); } } -void LaunchProfile::applyMavenFile(LibraryPtr mavenFile, const RuntimeContext & runtimeContext) +void LaunchProfile::applyMavenFile(LibraryPtr mavenFile, const RuntimeContext& runtimeContext) { - if(!mavenFile->isActive(runtimeContext)) - { + if (!mavenFile->isActive(runtimeContext)) { return; } - if(mavenFile->isNative()) - { + if (mavenFile->isNative()) { return; } @@ -221,16 +207,14 @@ void LaunchProfile::applyMavenFile(LibraryPtr mavenFile, const RuntimeContext & m_mavenFiles.append(Library::limitedCopy(mavenFile)); } -void LaunchProfile::applyAgent(AgentPtr agent, const RuntimeContext & runtimeContext) +void LaunchProfile::applyAgent(AgentPtr agent, const RuntimeContext& runtimeContext) { auto lib = agent->library(); - if(!lib->isActive(runtimeContext)) - { + if (!lib->isActive(runtimeContext)) { return; } - if(lib->isNative()) - { + if (lib->isNative()) { return; } @@ -244,16 +228,14 @@ const LibraryPtr LaunchProfile::getMainJar() const void LaunchProfile::applyMainJar(LibraryPtr jar) { - if(jar) - { + if (jar) { m_mainJar = jar; } } void LaunchProfile::applyProblemSeverity(ProblemSeverity severity) { - if (m_problemSeverity < severity) - { + if (m_problemSeverity < severity) { m_problemSeverity = severity; } } @@ -279,12 +261,12 @@ QString LaunchProfile::getMainClass() const return m_mainClass; } -const QSet &LaunchProfile::getTraits() const +const QSet& LaunchProfile::getTraits() const { return m_traits; } -const QStringList & LaunchProfile::getTweakers() const +const QStringList& LaunchProfile::getTweakers() const { return m_tweakers; } @@ -306,8 +288,7 @@ QString LaunchProfile::getMinecraftVersionType() const std::shared_ptr LaunchProfile::getMinecraftAssets() const { - if(!m_minecraftAssets) - { + if (!m_minecraftAssets) { return std::make_shared("legacy"); } return m_minecraftAssets; @@ -318,80 +299,69 @@ QString LaunchProfile::getMinecraftArguments() const return m_minecraftArguments; } -const QStringList & LaunchProfile::getAddnJvmArguments() const +const QStringList& LaunchProfile::getAddnJvmArguments() const { return m_addnJvmArguments; } -const QList & LaunchProfile::getJarMods() const +const QList& LaunchProfile::getJarMods() const { return m_jarMods; } -const QList & LaunchProfile::getLibraries() const +const QList& LaunchProfile::getLibraries() const { return m_libraries; } -const QList & LaunchProfile::getNativeLibraries() const +const QList& LaunchProfile::getNativeLibraries() const { return m_nativeLibraries; } -const QList & LaunchProfile::getMavenFiles() const +const QList& LaunchProfile::getMavenFiles() const { return m_mavenFiles; } -const QList & LaunchProfile::getAgents() const +const QList& LaunchProfile::getAgents() const { return m_agents; } -const QList & LaunchProfile::getCompatibleJavaMajors() const +const QList& LaunchProfile::getCompatibleJavaMajors() const { return m_compatibleJavaMajors; } -void LaunchProfile::getLibraryFiles( - const RuntimeContext & runtimeContext, - QStringList& jars, - QStringList& nativeJars, - const QString& overridePath, - const QString& tempPath -) const +void LaunchProfile::getLibraryFiles(const RuntimeContext& runtimeContext, + QStringList& jars, + QStringList& nativeJars, + const QString& overridePath, + const QString& tempPath) const { QStringList native32, native64; jars.clear(); nativeJars.clear(); - for (auto lib : getLibraries()) - { + for (auto lib : getLibraries()) { lib->getApplicableFiles(runtimeContext, jars, nativeJars, native32, native64, overridePath); } // NOTE: order is important here, add main jar last to the lists - if(m_mainJar) - { + if (m_mainJar) { // FIXME: HACK!! jar modding is weird and unsystematic! - if(m_jarMods.size()) - { + if (m_jarMods.size()) { QDir tempDir(tempPath); jars.append(tempDir.absoluteFilePath("minecraft.jar")); - } - else - { + } else { m_mainJar->getApplicableFiles(runtimeContext, jars, nativeJars, native32, native64, overridePath); } } - for (auto lib : getNativeLibraries()) - { + for (auto lib : getNativeLibraries()) { lib->getApplicableFiles(runtimeContext, jars, nativeJars, native32, native64, overridePath); } - if(runtimeContext.javaArchitecture == "32") - { + if (runtimeContext.javaArchitecture == "32") { nativeJars.append(native32); - } - else if(runtimeContext.javaArchitecture == "64") - { + } else if (runtimeContext.javaArchitecture == "64") { nativeJars.append(native64); } } diff --git a/launcher/minecraft/LaunchProfile.h b/launcher/minecraft/LaunchProfile.h index 79e688246..9f7bc812e 100644 --- a/launcher/minecraft/LaunchProfile.h +++ b/launcher/minecraft/LaunchProfile.h @@ -34,17 +34,16 @@ */ #pragma once -#include -#include "Library.h" -#include "Agent.h" #include +#include +#include "Agent.h" +#include "Library.h" -class LaunchProfile: public ProblemProvider -{ -public: +class LaunchProfile : public ProblemProvider { + public: virtual ~LaunchProfile() {} -public: /* application of profile variables from patches */ + public: /* application of profile variables from patches */ void applyMinecraftVersion(const QString& id); void applyMainClass(const QString& mainClass); void applyAppletClass(const QString& appletClass); @@ -52,48 +51,46 @@ public: /* application of profile variables from patches */ void applyAddnJvmArguments(const QStringList& minecraftArguments); void applyMinecraftVersionType(const QString& type); void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets); - void applyTraits(const QSet &traits); - void applyTweakers(const QStringList &tweakers); - void applyJarMods(const QList &jarMods); - void applyMods(const QList &jarMods); - void applyLibrary(LibraryPtr library, const RuntimeContext & runtimeContext); - void applyMavenFile(LibraryPtr library, const RuntimeContext & runtimeContext); - void applyAgent(AgentPtr agent, const RuntimeContext & runtimeContext); + void applyTraits(const QSet& traits); + void applyTweakers(const QStringList& tweakers); + void applyJarMods(const QList& jarMods); + void applyMods(const QList& jarMods); + void applyLibrary(LibraryPtr library, const RuntimeContext& runtimeContext); + void applyMavenFile(LibraryPtr library, const RuntimeContext& runtimeContext); + void applyAgent(AgentPtr agent, const RuntimeContext& runtimeContext); void applyCompatibleJavaMajors(QList& javaMajor); void applyMainJar(LibraryPtr jar); void applyProblemSeverity(ProblemSeverity severity); /// clear the profile void clear(); -public: /* getters for profile variables */ + public: /* getters for profile variables */ QString getMinecraftVersion() const; QString getMainClass() const; QString getAppletClass() const; QString getMinecraftVersionType() const; MojangAssetIndexInfo::Ptr getMinecraftAssets() const; QString getMinecraftArguments() const; - const QStringList & getAddnJvmArguments() const; - const QSet & getTraits() const; - const QStringList & getTweakers() const; - const QList & getJarMods() const; - const QList & getLibraries() const; - const QList & getNativeLibraries() const; - const QList & getMavenFiles() const; - const QList & getAgents() const; - const QList & getCompatibleJavaMajors() const; + const QStringList& getAddnJvmArguments() const; + const QSet& getTraits() const; + const QStringList& getTweakers() const; + const QList& getJarMods() const; + const QList& getLibraries() const; + const QList& getNativeLibraries() const; + const QList& getMavenFiles() const; + const QList& getAgents() const; + const QList& getCompatibleJavaMajors() const; const LibraryPtr getMainJar() const; - void getLibraryFiles( - const RuntimeContext & runtimeContext, - QStringList & jars, - QStringList & nativeJars, - const QString & overridePath, - const QString & tempPath - ) const; - bool hasTrait(const QString & trait) const; + void getLibraryFiles(const RuntimeContext& runtimeContext, + QStringList& jars, + QStringList& nativeJars, + const QString& overridePath, + const QString& tempPath) const; + bool hasTrait(const QString& trait) const; ProblemSeverity getProblemSeverity() const override; const QList getProblems() const override; -private: + private: /// the version of Minecraft - jar to use QString m_minecraftVersion; @@ -154,5 +151,4 @@ private: QList m_compatibleJavaMajors; ProblemSeverity m_problemSeverity = ProblemSeverity::None; - }; diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index e0318ef22..0bb618b40 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -36,106 +36,90 @@ #include "Library.h" #include "MinecraftInstance.h" +#include +#include #include #include -#include -#include - -void Library::getApplicableFiles(const RuntimeContext & runtimeContext, QStringList& jar, QStringList& native, QStringList& native32, - QStringList& native64, const QString &overridePath) const +void Library::getApplicableFiles(const RuntimeContext& runtimeContext, + QStringList& jar, + QStringList& native, + QStringList& native32, + QStringList& native64, + const QString& overridePath) const { bool local = isLocal(); - auto actualPath = [&](QString relPath) - { + auto actualPath = [&](QString relPath) { QFileInfo out(FS::PathCombine(storagePrefix(), relPath)); - if(local && !overridePath.isEmpty()) - { + if (local && !overridePath.isEmpty()) { QString fileName = out.fileName(); return QFileInfo(FS::PathCombine(overridePath, fileName)).absoluteFilePath(); } return out.absoluteFilePath(); }; QString raw_storage = storageSuffix(runtimeContext); - if(isNative()) - { - if (raw_storage.contains("${arch}")) - { + if (isNative()) { + if (raw_storage.contains("${arch}")) { auto nat32Storage = raw_storage; nat32Storage.replace("${arch}", "32"); auto nat64Storage = raw_storage; nat64Storage.replace("${arch}", "64"); native32 += actualPath(nat32Storage); native64 += actualPath(nat64Storage); - } - else - { + } else { native += actualPath(raw_storage); } - } - else - { + } else { jar += actualPath(raw_storage); } } -QList Library::getDownloads( - const RuntimeContext & runtimeContext, - class HttpMetaCache* cache, - QStringList& failedLocalFiles, - const QString & overridePath -) const +QList Library::getDownloads(const RuntimeContext& runtimeContext, + class HttpMetaCache* cache, + QStringList& failedLocalFiles, + const QString& overridePath) const { QList out; bool stale = isAlwaysStale(); bool local = isLocal(); - auto check_local_file = [&](QString storage) - { + auto check_local_file = [&](QString storage) { QFileInfo fileinfo(storage); QString fileName = fileinfo.fileName(); auto fullPath = FS::PathCombine(overridePath, fileName); QFileInfo localFileInfo(fullPath); - if(!localFileInfo.exists()) - { + if (!localFileInfo.exists()) { failedLocalFiles.append(localFileInfo.filePath()); return false; } return true; }; - auto add_download = [&](QString storage, QString url, QString sha1) - { - if(local) - { + auto add_download = [&](QString storage, QString url, QString sha1) { + if (local) { return check_local_file(storage); } auto entry = cache->resolveEntry("libraries", storage); - if(stale) - { + if (stale) { entry->setStale(true); } if (!entry->isStale()) return true; Net::Download::Options options; - if(stale) - { + if (stale) { options |= Net::Download::Option::AcceptLocalFiles; } // Don't add a time limit for the libraries cache entry validity options |= Net::Download::Option::MakeEternal; - if(sha1.size()) - { + if (sha1.size()) { auto rawSha1 = QByteArray::fromHex(sha1.toLatin1()); auto dl = Net::ApiDownload::makeCached(url, entry, options); dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1)); qDebug() << "Checksummed Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; out.append(dl); - } - else - { + } else { out.append(Net::ApiDownload::makeCached(url, entry, options)); qDebug() << "Download for:" << rawName().serialize() << "storage:" << storage << "url:" << url; } @@ -143,121 +127,89 @@ QList Library::getDownloads( }; QString raw_storage = storageSuffix(runtimeContext); - if(m_mojangDownloads) - { - if(isNative()) - { + if (m_mojangDownloads) { + if (isNative()) { auto nativeClassifier = getCompatibleNative(runtimeContext); - if(!nativeClassifier.isNull()) - { - if(nativeClassifier.contains("${arch}")) - { + if (!nativeClassifier.isNull()) { + if (nativeClassifier.contains("${arch}")) { auto nat32Classifier = nativeClassifier; nat32Classifier.replace("${arch}", "32"); auto nat64Classifier = nativeClassifier; nat64Classifier.replace("${arch}", "64"); auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier); - if(nat32info) - { + if (nat32info) { auto cooked_storage = raw_storage; cooked_storage.replace("${arch}", "32"); add_download(cooked_storage, nat32info->url, nat32info->sha1); } auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier); - if(nat64info) - { + if (nat64info) { auto cooked_storage = raw_storage; cooked_storage.replace("${arch}", "64"); add_download(cooked_storage, nat64info->url, nat64info->sha1); } - } - else - { + } else { auto info = m_mojangDownloads->getDownloadInfo(nativeClassifier); - if(info) - { + if (info) { add_download(raw_storage, info->url, info->sha1); } } - } - else - { + } else { qDebug() << "Ignoring native library" << m_name.serialize() << "because it has no classifier for current OS"; } - } - else - { - if(m_mojangDownloads->artifact) - { + } else { + if (m_mojangDownloads->artifact) { auto artifact = m_mojangDownloads->artifact; add_download(raw_storage, artifact->url, artifact->sha1); - } - else - { + } else { qDebug() << "Ignoring java library" << m_name.serialize() << "because it has no artifact"; } } - } - else - { - auto raw_dl = [&]() - { - if (!m_absoluteURL.isEmpty()) - { + } else { + auto raw_dl = [&]() { + if (!m_absoluteURL.isEmpty()) { return m_absoluteURL; } - if (m_repositoryURL.isEmpty()) - { + if (m_repositoryURL.isEmpty()) { return BuildConfig.LIBRARY_BASE + raw_storage; } - if(m_repositoryURL.endsWith('/')) - { + if (m_repositoryURL.endsWith('/')) { return m_repositoryURL + raw_storage; - } - else - { + } else { return m_repositoryURL + QChar('/') + raw_storage; } }(); - if (raw_storage.contains("${arch}")) - { + if (raw_storage.contains("${arch}")) { QString cooked_storage = raw_storage; QString cooked_dl = raw_dl; add_download(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"), QString()); cooked_storage = raw_storage; cooked_dl = raw_dl; add_download(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"), QString()); - } - else - { + } else { add_download(raw_storage, raw_dl, QString()); } } return out; } -bool Library::isActive(const RuntimeContext & runtimeContext) const +bool Library::isActive(const RuntimeContext& runtimeContext) const { bool result = true; - if (m_rules.empty()) - { + if (m_rules.empty()) { result = true; - } - else - { + } else { RuleAction ruleResult = Disallow; - for (auto rule : m_rules) - { + for (auto rule : m_rules) { RuleAction temp = rule->apply(this, runtimeContext); if (temp != Defer) ruleResult = temp; } result = result && (ruleResult == Allow); } - if (isNative()) - { + if (isNative()) { result = result && !getCompatibleNative(runtimeContext).isNull(); } return result; @@ -273,7 +225,8 @@ bool Library::isAlwaysStale() const return m_hint == "always-stale"; } -QString Library::getCompatibleNative(const RuntimeContext & runtimeContext) const { +QString Library::getCompatibleNative(const RuntimeContext& runtimeContext) const +{ // try to match precise classifier "[os]-[arch]" auto entry = m_nativeClassifiers.constFind(runtimeContext.getClassifier()); // try to match imprecise classifier on legacy architectures "[os]" @@ -298,63 +251,53 @@ QString Library::defaultStoragePrefix() QString Library::storagePrefix() const { - if(m_storagePrefix.isEmpty()) - { + if (m_storagePrefix.isEmpty()) { return defaultStoragePrefix(); } return m_storagePrefix; } -QString Library::filename(const RuntimeContext & runtimeContext) const +QString Library::filename(const RuntimeContext& runtimeContext) const { - if(!m_filename.isEmpty()) - { + if (!m_filename.isEmpty()) { return m_filename; } // non-native? use only the gradle specifier - if (!isNative()) - { + if (!isNative()) { return m_name.getFileName(); } // otherwise native, override classifiers. Mojang HACK! GradleSpecifier nativeSpec = m_name; QString nativeClassifier = getCompatibleNative(runtimeContext); - if (!nativeClassifier.isNull()) - { + if (!nativeClassifier.isNull()) { nativeSpec.setClassifier(nativeClassifier); - } - else - { + } else { nativeSpec.setClassifier("INVALID"); } return nativeSpec.getFileName(); } -QString Library::displayName(const RuntimeContext & runtimeContext) const +QString Library::displayName(const RuntimeContext& runtimeContext) const { - if(!m_displayname.isEmpty()) + if (!m_displayname.isEmpty()) return m_displayname; return filename(runtimeContext); } -QString Library::storageSuffix(const RuntimeContext & runtimeContext) const +QString Library::storageSuffix(const RuntimeContext& runtimeContext) const { // non-native? use only the gradle specifier - if (!isNative()) - { + if (!isNative()) { return m_name.toPath(m_filename); } // otherwise native, override classifiers. Mojang HACK! GradleSpecifier nativeSpec = m_name; QString nativeClassifier = getCompatibleNative(runtimeContext); - if (!nativeClassifier.isNull()) - { + if (!nativeClassifier.isNull()) { nativeSpec.setClassifier(nativeClassifier); - } - else - { + } else { nativeSpec.setClassifier("INVALID"); } return nativeSpec.toPath(m_filename); diff --git a/launcher/minecraft/Library.h b/launcher/minecraft/Library.h index 26dbf962d..a24c11215 100644 --- a/launcher/minecraft/Library.h +++ b/launcher/minecraft/Library.h @@ -34,20 +34,19 @@ */ #pragma once -#include #include -#include +#include #include +#include +#include #include #include -#include -#include #include #include -#include "Rule.h" #include "GradleSpecifier.h" #include "MojangDownloadInfo.h" +#include "Rule.h" #include "RuntimeContext.h" class Library; @@ -55,19 +54,14 @@ class MinecraftInstance; typedef std::shared_ptr LibraryPtr; -class Library -{ +class Library { friend class OneSixVersionFormat; friend class MojangVersionFormat; friend class LibraryTest; -public: - Library() - { - } - Library(const QString &name) - { - m_name = name; - } + + public: + Library() {} + Library(const QString& name) { m_name = name; } /// limited copy without some data. TODO: why? static LibraryPtr limitedCopy(LibraryPtr base) { @@ -85,98 +79,60 @@ public: return newlib; } -public: /* methods */ + public: /* methods */ /// Returns the raw name field - const GradleSpecifier & rawName() const - { - return m_name; - } + const GradleSpecifier& rawName() const { return m_name; } - void setRawName(const GradleSpecifier & spec) - { - m_name = spec; - } + void setRawName(const GradleSpecifier& spec) { m_name = spec; } - void setClassifier(const QString & spec) - { - m_name.setClassifier(spec); - } + void setClassifier(const QString& spec) { m_name.setClassifier(spec); } /// returns the full group and artifact prefix - QString artifactPrefix() const - { - return m_name.artifactPrefix(); - } + QString artifactPrefix() const { return m_name.artifactPrefix(); } /// get the artifact ID - QString artifactId() const - { - return m_name.artifactId(); - } + QString artifactId() const { return m_name.artifactId(); } /// get the artifact version - QString version() const - { - return m_name.version(); - } + QString version() const { return m_name.version(); } /// Returns true if the library is native - bool isNative() const - { - return m_nativeClassifiers.size() != 0; - } + bool isNative() const { return m_nativeClassifiers.size() != 0; } void setStoragePrefix(QString prefix = QString()); /// Set the url base for downloads - void setRepositoryURL(const QString &base_url) - { - m_repositoryURL = base_url; - } + void setRepositoryURL(const QString& base_url) { m_repositoryURL = base_url; } - void getApplicableFiles(const RuntimeContext & runtimeContext, QStringList & jar, QStringList & native, - QStringList & native32, QStringList & native64, const QString & overridePath) const; + void getApplicableFiles(const RuntimeContext& runtimeContext, + QStringList& jar, + QStringList& native, + QStringList& native32, + QStringList& native64, + const QString& overridePath) const; - void setAbsoluteUrl(const QString &absolute_url) - { - m_absoluteURL = absolute_url; - } + void setAbsoluteUrl(const QString& absolute_url) { m_absoluteURL = absolute_url; } - void setFilename(const QString &filename) - { - m_filename = filename; - } + void setFilename(const QString& filename) { m_filename = filename; } /// Get the file name of the library - QString filename(const RuntimeContext & runtimeContext) const; + QString filename(const RuntimeContext& runtimeContext) const; // DEPRECATED: set a display name, used by jar mods only - void setDisplayName(const QString & displayName) - { - m_displayname = displayName; - } + void setDisplayName(const QString& displayName) { m_displayname = displayName; } /// Get the file name of the library - QString displayName(const RuntimeContext & runtimeContext) const; + QString displayName(const RuntimeContext& runtimeContext) const; - void setMojangDownloadInfo(MojangLibraryDownloadInfo::Ptr info) - { - m_mojangDownloads = info; - } + void setMojangDownloadInfo(MojangLibraryDownloadInfo::Ptr info) { m_mojangDownloads = info; } - void setHint(const QString &hint) - { - m_hint = hint; - } + void setHint(const QString& hint) { m_hint = hint; } /// Set the load rules - void setRules(QList> rules) - { - m_rules = rules; - } + void setRules(QList> rules) { m_rules = rules; } /// Returns true if the library should be loaded (or extracted, in case of natives) - bool isActive(const RuntimeContext & runtimeContext) const; + bool isActive(const RuntimeContext& runtimeContext) const; /// Returns true if the library is contained in an instance and false if it is shared bool isLocal() const; @@ -188,12 +144,14 @@ public: /* methods */ bool isForge() const; // Get a list of downloads for this library - QList getDownloads(const RuntimeContext & runtimeContext, class HttpMetaCache * cache, - QStringList & failedLocalFiles, const QString & overridePath) const; + QList getDownloads(const RuntimeContext& runtimeContext, + class HttpMetaCache* cache, + QStringList& failedLocalFiles, + const QString& overridePath) const; - QString getCompatibleNative(const RuntimeContext & runtimeContext) const; + QString getCompatibleNative(const RuntimeContext& runtimeContext) const; -private: /* methods */ + private: /* methods */ /// the default storage prefix used by Prism Launcher static QString defaultStoragePrefix(); @@ -201,14 +159,11 @@ private: /* methods */ QString storagePrefix() const; /// Get the relative file path where the library should be saved - QString storageSuffix(const RuntimeContext & runtimeContext) const; + QString storageSuffix(const RuntimeContext& runtimeContext) const; - QString hint() const - { - return m_hint; - } + QString hint() const { return m_hint; } -protected: /* data */ + protected: /* data */ /// the basic gradle dependency specifier. GradleSpecifier m_name; @@ -253,4 +208,3 @@ protected: /* data */ /// MOJANG: container with Mojang style download info MojangLibraryDownloadInfo::Ptr m_mojangDownloads; }; - diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 07ed04f96..305bff67b 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -37,32 +37,32 @@ */ #include "MinecraftInstance.h" +#include "Application.h" #include "BuildConfig.h" #include "minecraft/launch/CreateGameFolders.h" #include "minecraft/launch/ExtractNatives.h" #include "minecraft/launch/PrintInstanceInfo.h" #include "settings/Setting.h" #include "settings/SettingsObject.h" -#include "Application.h" -#include "pathmatcher/RegexpMatcher.h" -#include "pathmatcher/MultiMatcher.h" #include "FileSystem.h" -#include "java/JavaVersion.h" #include "MMCTime.h" +#include "java/JavaVersion.h" +#include "pathmatcher/MultiMatcher.h" +#include "pathmatcher/RegexpMatcher.h" #include "launch/LaunchTask.h" +#include "launch/steps/CheckJava.h" #include "launch/steps/LookupServerAddress.h" #include "launch/steps/PostLaunchCommand.h" -#include "launch/steps/Update.h" #include "launch/steps/PreLaunchCommand.h" -#include "launch/steps/TextPrint.h" -#include "launch/steps/CheckJava.h" #include "launch/steps/QuitAfterGameStop.h" +#include "launch/steps/TextPrint.h" +#include "launch/steps/Update.h" +#include "minecraft/launch/ClaimAccount.h" #include "minecraft/launch/LauncherPartLaunch.h" #include "minecraft/launch/ModMinecraftJar.h" -#include "minecraft/launch/ClaimAccount.h" #include "minecraft/launch/ReconstructAssets.h" #include "minecraft/launch/ScanModFolders.h" #include "minecraft/launch/VerifyJavaInstall.h" @@ -81,10 +81,10 @@ #include "WorldList.h" -#include "PackProfile.h" #include "AssetsUtils.h" -#include "MinecraftUpdate.h" #include "MinecraftLoadAndCheck.h" +#include "MinecraftUpdate.h" +#include "PackProfile.h" #include "minecraft/gameoptions/GameOptions.h" #include "minecraft/update/FoldersTask.h" @@ -96,14 +96,10 @@ // all of this because keeping things compatible with deprecated old settings // if either of the settings {a, b} is true, this also resolves to true -class OrSetting : public Setting -{ +class OrSetting : public Setting { Q_OBJECT -public: - OrSetting(QString id, std::shared_ptr a, std::shared_ptr b) - :Setting({id}, false), m_a(a), m_b(b) - { - } + public: + OrSetting(QString id, std::shared_ptr a, std::shared_ptr b) : Setting({ id }, false), m_a(a), m_b(b) {} virtual QVariant get() const { bool a = m_a->get().toBool(); @@ -112,12 +108,13 @@ public: } virtual void reset() {} virtual void set(QVariant value) {} -private: + + private: std::shared_ptr m_a; std::shared_ptr m_b; }; -MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) +MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir) : BaseInstance(globalSettings, settings, rootDir) { m_components.reset(new PackProfile(this)); @@ -222,14 +219,12 @@ std::shared_ptr MinecraftInstance::getPackProfile() const QSet MinecraftInstance::traits() const { auto components = getPackProfile(); - if (!components) - { - return {"version-incomplete"}; + if (!components) { + return { "version-incomplete" }; } auto profile = components->getProfile(); - if (!profile) - { - return {"version-incomplete"}; + if (!profile) { + return { "version-incomplete" }; } return profile->getTraits(); } @@ -264,7 +259,7 @@ QString MinecraftInstance::getLocalLibraryPath() const bool MinecraftInstance::supportsDemo() const { - Version instance_ver { getPackProfile()->getComponentVersion("net.minecraft") }; + Version instance_ver{ getPackProfile()->getComponentVersion("net.minecraft") }; // Demo mode was introduced in 1.3.1: https://minecraft.fandom.com/wiki/Demo_mode#History // FIXME: Due to Version constraints atm, this can't handle well non-release versions return instance_ver >= Version("1.3.1"); @@ -375,21 +370,18 @@ QStringList MinecraftInstance::extraArguments() if (!version) return list; auto jarMods = getJarMods(); - if (!jarMods.isEmpty()) - { - list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true", - "-Dfml.ignorePatchDiscrepancies=true"}); + if (!jarMods.isEmpty()) { + list.append({ "-Dfml.ignoreInvalidMinecraftCertificates=true", "-Dfml.ignorePatchDiscrepancies=true" }); } auto addn = m_components->getProfile()->getAddnJvmArguments(); if (!addn.isEmpty()) { list.append(addn); } auto agents = m_components->getProfile()->getAgents(); - for (auto agent : agents) - { + for (auto agent : agents) { QStringList jar, temp1, temp2, temp3; agent->library()->getApplicableFiles(runtimeContext(), jar, temp1, temp2, temp3, getLocalLibraryPath()); - list.append("-javaagent:"+jar[0]+(agent->argument().isEmpty() ? "" : "="+agent->argument())); + list.append("-javaagent:" + jar[0] + (agent->argument().isEmpty() ? "" : "=" + agent->argument())); } { @@ -416,38 +408,33 @@ QStringList MinecraftInstance::javaArguments() // HACK: fix issues on macOS with 1.13 snapshots // NOTE: Oracle Java option. if there are alternate jvm implementations, this would be the place to customize this for them #ifdef Q_OS_MAC - if(traits_.contains("FirstThreadOnMacOS")) - { + if (traits_.contains("FirstThreadOnMacOS")) { args << QString("-XstartOnFirstThread"); } #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"); + args << QString( + "-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" + "minecraft.exe.heapdump"); #endif int min = settings()->get("MinMemAlloc").toInt(); int max = settings()->get("MaxMemAlloc").toInt(); - if(min < max) - { + if (min < max) { args << QString("-Xms%1m").arg(min); args << QString("-Xmx%1m").arg(max); - } - else - { + } else { args << QString("-Xms%1m").arg(max); args << QString("-Xmx%1m").arg(min); } // No PermGen in newer java. JavaVersion javaVersion = getJavaVersion(); - if(javaVersion.requiresPermGen()) - { + if (javaVersion.requiresPermGen()) { auto permgen = settings()->get("PermGen").toInt(); - if (permgen != 64) - { + if (permgen != 64) { args << QString("-XX:PermSize=%1m").arg(permgen); } } @@ -487,8 +474,7 @@ QProcessEnvironment MinecraftInstance::createEnvironment() // export some infos auto variables = getVariables(); - for (auto it = variables.begin(); it != variables.end(); ++it) - { + for (auto it = variables.begin(); it != variables.end(); ++it) { env.insert(it.key(), it.value()); } return env; @@ -500,15 +486,12 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment() QProcessEnvironment env = createEnvironment(); #ifdef Q_OS_LINUX - if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud) - { - + if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud) { auto preloadList = env.value("LD_PRELOAD").split(QLatin1String(":")); auto libPaths = env.value("LD_LIBRARY_PATH").split(QLatin1String(":")); auto mangoHudLibString = MangoHud::getLibraryString(); - if (!mangoHudLibString.isEmpty()) - { + if (!mangoHudLibString.isEmpty()) { QFileInfo mangoHudLib(mangoHudLibString); // dlsym variant is only needed for OpenGL and not included in the vulkan layer @@ -521,8 +504,7 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment() env.insert("MANGOHUD", "1"); } - if (settings()->get("UseDiscreteGpu").toBool()) - { + if (settings()->get("UseDiscreteGpu").toBool()) { // Open Source Drivers env.insert("DRI_PRIME", "1"); // Proprietary Nvidia Drivers @@ -543,14 +525,12 @@ static QString replaceTokensIn(QString text, QMap with) QStringList list; QRegularExpressionMatchIterator i = token_regexp.globalMatch(text); int lastCapturedEnd = 0; - while (i.hasNext()) - { + while (i.hasNext()) { QRegularExpressionMatch match = i.next(); result.append(text.mid(lastCapturedEnd, match.capturedStart())); QString key = match.captured(1); auto iter = with.find(key); - if (iter != with.end()) - { + if (iter != with.end()) { result.append(*iter); } lastCapturedEnd = match.capturedEnd(); @@ -559,25 +539,22 @@ static QString replaceTokensIn(QString text, QMap with) return result; } -QStringList MinecraftInstance::processMinecraftArgs( - AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) const +QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) const { auto profile = m_components->getProfile(); QString args_pattern = profile->getMinecraftArguments(); - for (auto tweaker : profile->getTweakers()) - { + for (auto tweaker : profile->getTweakers()) { args_pattern += " --tweakClass " + tweaker; } - if (serverToJoin && !serverToJoin->address.isEmpty()) - { + if (serverToJoin && !serverToJoin->address.isEmpty()) { args_pattern += " --server " + serverToJoin->address; args_pattern += " --port " + QString::number(serverToJoin->port); } QMap token_mapping; // yggdrasil! - if(session) { + if (session) { // token_mapping["auth_username"] = session->username; token_mapping["auth_session"] = session->session; token_mapping["auth_access_token"] = session->access_token; @@ -585,7 +562,7 @@ QStringList MinecraftInstance::processMinecraftArgs( token_mapping["auth_uuid"] = session->uuid; token_mapping["user_properties"] = session->serializeUserProperties(); token_mapping["user_type"] = session->user_type; - if(session->demo) { + if (session->demo) { args_pattern += " --demo"; } } @@ -609,8 +586,7 @@ QStringList MinecraftInstance::processMinecraftArgs( #else QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts); #endif - for (int i = 0; i < parts.length(); i++) - { + for (int i = 0; i < parts.length(); i++) { parts[i] = replaceTokensIn(parts[i], token_mapping); } return parts; @@ -623,32 +599,26 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS if (!m_components) return QString(); auto profile = m_components->getProfile(); - if(!profile) + if (!profile) return QString(); auto mainClass = getMainClass(); - if (!mainClass.isEmpty()) - { + if (!mainClass.isEmpty()) { launchScript += "mainClass " + mainClass + "\n"; } auto appletClass = profile->getAppletClass(); - if (!appletClass.isEmpty()) - { + if (!appletClass.isEmpty()) { launchScript += "appletClass " + appletClass + "\n"; } - if (serverToJoin && !serverToJoin->address.isEmpty()) - { + if (serverToJoin && !serverToJoin->address.isEmpty()) { launchScript += "serverAddress " + serverToJoin->address + "\n"; launchScript += "serverPort " + QString::number(serverToJoin->port) + "\n"; } // generic minecraft params - for (auto param : processMinecraftArgs( - session, - nullptr /* When using a launch script, the server parameters are handled by it*/ - )) - { + for (auto param : processMinecraftArgs(session, nullptr /* When using a launch script, the server parameters are handled by it*/ + )) { launchScript += "param " + param + "\n"; } @@ -658,22 +628,19 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS if (settings()->get("LaunchMaximized").toBool()) windowParams = "max"; else - windowParams = QString("%1x%2") - .arg(settings()->get("MinecraftWinWidth").toInt()) - .arg(settings()->get("MinecraftWinHeight").toInt()); + windowParams = + QString("%1x%2").arg(settings()->get("MinecraftWinWidth").toInt()).arg(settings()->get("MinecraftWinHeight").toInt()); launchScript += "windowTitle " + windowTitle() + "\n"; launchScript += "windowParams " + windowParams + "\n"; } // legacy auth - if(session) - { + if (session) { launchScript += "userName " + session->player_name + "\n"; launchScript += "sessionId " + session->session + "\n"; } - for (auto trait : profile->getTraits()) - { + for (auto trait : profile->getTraits()) { launchScript += "traits " + trait + "\n"; } @@ -686,17 +653,17 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) { QStringList out; - out << "Main Class:" << " " + getMainClass() << ""; - out << "Native path:" << " " + getNativePath() << ""; + out << "Main Class:" + << " " + getMainClass() << ""; + out << "Native path:" + << " " + getNativePath() << ""; auto profile = m_components->getProfile(); auto alltraits = traits(); - if(alltraits.size()) - { + if (alltraits.size()) { out << "Traits:"; - for (auto trait : alltraits) - { + for (auto trait : alltraits) { out << "traits " + trait; } out << ""; @@ -705,8 +672,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr auto settings = this->settings(); bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool(); bool nativeGLFW = settings->get("UseNativeGLFW").toBool(); - if (nativeOpenAL || nativeGLFW) - { + if (nativeOpenAL || nativeGLFW) { if (nativeOpenAL) out << "Using system OpenAL."; if (nativeGLFW) @@ -719,34 +685,27 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << "Libraries:"; QStringList jars, nativeJars; profile->getLibraryFiles(runtimeContext(), jars, nativeJars, getLocalLibraryPath(), binRoot()); - auto printLibFile = [&](const QString & path) - { + auto printLibFile = [&](const QString& path) { QFileInfo info(path); - if(info.exists()) - { + if (info.exists()) { out << " " + path; - } - else - { + } else { out << " " + path + " (missing)"; } }; - for(auto file: jars) - { + for (auto file : jars) { printLibFile(file); } out << ""; out << "Native libraries:"; - for(auto file: nativeJars) - { + for (auto file : nativeJars) { printLibFile(file); } out << ""; } - auto printModList = [&](const QString & label, ModFolderModel & model) { - if(model.size()) - { + auto printModList = [&](const QString& label, ModFolderModel& model) { + if (model.size()) { out << QString("%1:").arg(label); auto modList = model.allMods(); std::sort(modList.begin(), modList.end(), [](auto a, auto b) { @@ -754,21 +713,17 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr auto bName = b->fileinfo().completeBaseName(); return aName.localeAwareCompare(bName) < 0; }); - for(auto mod: modList) - { - if(mod->type() == ResourceType::FOLDER) - { + for (auto mod : modList) { + if (mod->type() == ResourceType::FOLDER) { out << u8" [🖿] " + mod->fileinfo().completeBaseName() + " (folder)"; continue; } - if(mod->enabled()) { + if (mod->enabled()) { out << u8" [✔] " + mod->fileinfo().completeBaseName(); - } - else { + } else { out << u8" [✘] " + mod->fileinfo().completeBaseName() + " (disabled)"; } - } out << ""; } @@ -777,20 +732,15 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr printModList("Mods", *(loaderModList().get())); printModList("Core Mods", *(coreModList().get())); - auto & jarMods = profile->getJarMods(); - if(jarMods.size()) - { + auto& jarMods = profile->getJarMods(); + if (jarMods.size()) { out << "Jar Mods:"; - for(auto & jarmod: jarMods) - { + for (auto& jarmod : jarMods) { auto displayname = jarmod->displayName(runtimeContext()); auto realname = jarmod->filename(runtimeContext()); - if(displayname != realname) - { + if (displayname != realname) { out << " " + displayname + " (" + realname + ")"; - } - else - { + } else { out << " " + realname; } } @@ -803,12 +753,9 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr out << ""; QString windowParams; - if (settings->get("LaunchMaximized").toBool()) - { + if (settings->get("LaunchMaximized").toBool()) { out << "Window size: max (if available)"; - } - else - { + } else { auto width = settings->get("MinecraftWinWidth").toInt(); auto height = settings->get("MinecraftWinHeight").toInt(); out << "Window size: " + QString::number(width) + " x " + QString::number(height); @@ -821,27 +768,23 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr QMap MinecraftInstance::createCensorFilterFromSession(AuthSessionPtr session) { - if(!session) - { + if (!session) { return QMap(); } - auto & sessionRef = *session.get(); + auto& sessionRef = *session.get(); QMap filter; - auto addToFilter = [&filter](QString key, QString value) - { - if(key.trimmed().size()) - { + auto addToFilter = [&filter](QString key, QString value) { + if (key.trimmed().size()) { filter[key] = value; } }; - if (sessionRef.session != "-") - { + if (sessionRef.session != "-") { addToFilter(sessionRef.session, tr("")); } if (sessionRef.access_token != "0") { addToFilter(sessionRef.access_token, tr("")); } - if(sessionRef.client_token.size()) { + if (sessionRef.client_token.size()) { addToFilter(sessionRef.client_token, tr("")); } addToFilter(sessionRef.uuid, tr("")); @@ -849,31 +792,28 @@ QMap MinecraftInstance::createCensorFilterFromSession(AuthSess return filter; } -MessageLevel::Enum MinecraftInstance::guessLevel(const QString &line, MessageLevel::Enum level) +MessageLevel::Enum MinecraftInstance::guessLevel(const QString& line, MessageLevel::Enum level) { QRegularExpression re("\\[(?[0-9:]+)\\] \\[[^/]+/(?[^\\]]+)\\]"); auto match = re.match(line); - if(match.hasMatch()) - { + if (match.hasMatch()) { // New style logs from log4j QString timestamp = match.captured("timestamp"); QString levelStr = match.captured("level"); - if(levelStr == "INFO") + if (levelStr == "INFO") level = MessageLevel::Message; - if(levelStr == "WARN") + if (levelStr == "WARN") level = MessageLevel::Warning; - if(levelStr == "ERROR") + if (levelStr == "ERROR") level = MessageLevel::Error; - if(levelStr == "FATAL") + if (levelStr == "FATAL") level = MessageLevel::Fatal; - if(levelStr == "TRACE" || levelStr == "DEBUG") + if (levelStr == "TRACE" || levelStr == "DEBUG") level = MessageLevel::Debug; - } - else - { + } else { // Old style forge logs - if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") || - line.contains("[FINER]") || line.contains("[FINEST]")) + 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; @@ -884,14 +824,12 @@ MessageLevel::Enum MinecraftInstance::guessLevel(const QString &line, MessageLev } if (line.contains("overwriting existing")) return MessageLevel::Fatal; - //NOTE: this diverges from the real regexp. no unicode, the first section is + instead of * + // NOTE: this diverges from the real regexp. no unicode, the first section is + instead of * static const QString javaSymbol = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*"; - if (line.contains("Exception in thread") - || line.contains(QRegularExpression("\\s+at " + javaSymbol)) - || line.contains(QRegularExpression("Caused by: " + javaSymbol)) - || line.contains(QRegularExpression("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)")) - || line.contains(QRegularExpression("... \\d+ more$")) - ) + if (line.contains("Exception in thread") || line.contains(QRegularExpression("\\s+at " + javaSymbol)) || + line.contains(QRegularExpression("Caused by: " + javaSymbol)) || + line.contains(QRegularExpression("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)")) || + line.contains(QRegularExpression("... \\d+ more$"))) return MessageLevel::Error; return level; } @@ -914,14 +852,12 @@ QString MinecraftInstance::getLogFileRoot() QString MinecraftInstance::getStatusbarDescription() { QStringList traits; - if (hasVersionBroken()) - { + if (hasVersionBroken()) { traits.append(tr("broken")); } QString mcVersion = m_components->getComponentVersion("net.minecraft"); - if (mcVersion.isEmpty()) - { + if (mcVersion.isEmpty()) { // Load component info if needed m_components->reload(Net::Mode::Offline); mcVersion = m_components->getComponentVersion("net.minecraft"); @@ -929,8 +865,7 @@ QString MinecraftInstance::getStatusbarDescription() QString description; description.append(tr("Minecraft %1").arg(mcVersion)); - if(m_settings->get("ShowGameTime").toBool()) - { + if (m_settings->get("ShowGameTime").toBool()) { if (lastTimePlayed() > 0) { QDateTime lastLaunchTime = QDateTime::fromMSecsSinceEpoch(lastLaunch()); description.append(tr(", last played on %1 for %2") @@ -942,8 +877,7 @@ QString MinecraftInstance::getStatusbarDescription() description.append(tr(", total played for %1").arg(Time::prettifyDuration(totalTimePlayed()))); } } - if(hasCrashed()) - { + if (hasCrashed()) { description.append(tr(", has crashed.")); } return description; @@ -952,14 +886,11 @@ QString MinecraftInstance::getStatusbarDescription() Task::Ptr MinecraftInstance::createUpdateTask(Net::Mode mode) { updateRuntimeContext(); - switch (mode) - { - case Net::Mode::Offline: - { + switch (mode) { + case Net::Mode::Offline: { return Task::Ptr(new MinecraftLoadAndCheck(this)); } - case Net::Mode::Online: - { + case Net::Mode::Online: { return Task::Ptr(new MinecraftUpdate(this)); } } @@ -990,14 +921,12 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt process->appendStep(makeShared(pptr)); } - if (!serverToJoin && settings()->get("JoinServerOnLaunch").toBool()) - { + if (!serverToJoin && settings()->get("JoinServerOnLaunch").toBool()) { QString fullAddress = settings()->get("JoinServerOnLaunchAddress").toString(); serverToJoin.reset(new MinecraftServerTarget(MinecraftServerTarget::parse(fullAddress))); } - if(serverToJoin && serverToJoin->port == 25565) - { + if (serverToJoin && serverToJoin->port == 25565) { // Resolve server address to join on launch auto step = makeShared(pptr); step->setLookupAddress(serverToJoin->address); @@ -1006,23 +935,19 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt } // run pre-launch command if that's needed - if(getPreLaunchCommand().size()) - { + if (getPreLaunchCommand().size()) { auto step = makeShared(pptr); step->setWorkingDirectory(gameRoot()); process->appendStep(step); } // if we aren't in offline mode,. - if(session->status != AuthSession::PlayableOffline) - { - if(!session->demo) { + if (session->status != AuthSession::PlayableOffline) { + if (!session->demo) { process->appendStep(makeShared(pptr, session)); } process->appendStep(makeShared(pptr, Net::Mode::Online)); - } - else - { + } else { process->appendStep(makeShared(pptr, Net::Mode::Offline)); } @@ -1066,18 +991,15 @@ shared_qobject_ptr MinecraftInstance::createLaunchTask(AuthSessionPt } // run post-exit command if that's needed - if(getPostExitCommand().size()) - { + if (getPostExitCommand().size()) { auto step = makeShared(pptr); step->setWorkingDirectory(gameRoot()); process->appendStep(step); } - if (session) - { + if (session) { process->setCensorFilter(createCensorFilterFromSession(session)); } - if(m_settings->get("QuitAfterGameStop").toBool()) - { + if (m_settings->get("QuitAfterGameStop").toBool()) { process->appendStep(makeShared(pptr)); } m_launchProcess = process; @@ -1119,8 +1041,7 @@ std::shared_ptr MinecraftInstance::nilModList() std::shared_ptr MinecraftInstance::resourcePackList() { - if (!m_resource_pack_list) - { + if (!m_resource_pack_list) { m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir(), this)); } return m_resource_pack_list; @@ -1128,8 +1049,7 @@ std::shared_ptr MinecraftInstance::resourcePackList() std::shared_ptr MinecraftInstance::texturePackList() { - if (!m_texture_pack_list) - { + if (!m_texture_pack_list) { m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir(), this)); } return m_texture_pack_list; @@ -1137,8 +1057,7 @@ std::shared_ptr MinecraftInstance::texturePackList() std::shared_ptr MinecraftInstance::shaderPackList() { - if (!m_shader_pack_list) - { + if (!m_shader_pack_list) { m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir(), this)); } return m_shader_pack_list; @@ -1146,8 +1065,7 @@ std::shared_ptr MinecraftInstance::shaderPackList() std::shared_ptr MinecraftInstance::worldList() { - if (!m_world_list) - { + if (!m_world_list) { m_world_list.reset(new WorldList(worldDir(), this)); } return m_world_list; @@ -1155,8 +1073,7 @@ std::shared_ptr MinecraftInstance::worldList() std::shared_ptr MinecraftInstance::gameOptionsModel() { - if (!m_game_options) - { + if (!m_game_options) { m_game_options.reset(new GameOptions(FS::PathCombine(gameRoot(), "options.txt"))); } return m_game_options; @@ -1166,8 +1083,7 @@ QList MinecraftInstance::getJarMods() const { auto profile = m_components->getProfile(); QList mods; - for (auto jarmod : profile->getJarMods()) - { + for (auto jarmod : profile->getJarMods()) { QStringList jar, temp1, temp2, temp3; jarmod->getApplicableFiles(runtimeContext(), jar, temp1, temp2, temp3, jarmodsPath().absolutePath()); // QString filePath = jarmodsPath().absoluteFilePath(jarmod->filename(currentSystem)); @@ -1176,5 +1092,4 @@ QList MinecraftInstance::getJarMods() const return mods; } - #include "MinecraftInstance.moc" diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 4afcf04b8..c331cc6f5 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -35,12 +35,12 @@ */ #pragma once -#include "BaseInstance.h" #include -#include "minecraft/mod/Mod.h" -#include #include +#include +#include "BaseInstance.h" #include "minecraft/launch/MinecraftServerTarget.h" +#include "minecraft/mod/Mod.h" class ModFolderModel; class ResourceFolderModel; @@ -52,12 +52,11 @@ class GameOptions; class LaunchStep; class PackProfile; -class MinecraftInstance: public BaseInstance -{ +class MinecraftInstance : public BaseInstance { Q_OBJECT -public: - MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir); - virtual ~MinecraftInstance() {}; + public: + MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir); + virtual ~MinecraftInstance(){}; virtual void saveNow() override; void loadSpecificSettings() override; @@ -67,15 +66,9 @@ public: // FIXME: remove QSet traits() const override; - bool canEdit() const override - { - return true; - } + bool canEdit() const override { return true; } - bool canExport() const override - { - return true; - } + bool canExport() const override { return true; } ////// Directories and files ////// QString jarModsDir() const; @@ -143,7 +136,7 @@ public: QProcessEnvironment createLaunchEnvironment() override; /// guess log level from a line of minecraft log - MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level) override; + MessageLevel::Enum guessLevel(const QString& line, MessageLevel::Enum level) override; IPathMatcher::Ptr getLogFileMatcher() override; @@ -163,10 +156,10 @@ public: virtual JavaVersion getJavaVersion(); -protected: + protected: QMap createCensorFilterFromSession(AuthSessionPtr session); -protected: // data + protected: // data std::shared_ptr m_components; mutable std::shared_ptr m_loader_mod_list; mutable std::shared_ptr m_core_mod_list; diff --git a/launcher/minecraft/MinecraftLoadAndCheck.cpp b/launcher/minecraft/MinecraftLoadAndCheck.cpp index 2a3698798..818e90cfc 100644 --- a/launcher/minecraft/MinecraftLoadAndCheck.cpp +++ b/launcher/minecraft/MinecraftLoadAndCheck.cpp @@ -2,9 +2,7 @@ #include "MinecraftInstance.h" #include "PackProfile.h" -MinecraftLoadAndCheck::MinecraftLoadAndCheck(MinecraftInstance *inst, QObject *parent) : Task(parent), m_inst(inst) -{ -} +MinecraftLoadAndCheck::MinecraftLoadAndCheck(MinecraftInstance* inst, QObject* parent) : Task(parent), m_inst(inst) {} void MinecraftLoadAndCheck::executeTask() { @@ -13,14 +11,13 @@ void MinecraftLoadAndCheck::executeTask() components->reload(Net::Mode::Offline); m_task = components->getCurrentTask(); - if(!m_task) - { + if (!m_task) { emitSucceeded(); return; } connect(m_task.get(), &Task::succeeded, this, &MinecraftLoadAndCheck::subtaskSucceeded); connect(m_task.get(), &Task::failed, this, &MinecraftLoadAndCheck::subtaskFailed); - connect(m_task.get(), &Task::aborted, this, [this]{ subtaskFailed(tr("Aborted")); }); + connect(m_task.get(), &Task::aborted, this, [this] { subtaskFailed(tr("Aborted")); }); connect(m_task.get(), &Task::progress, this, &MinecraftLoadAndCheck::progress); connect(m_task.get(), &Task::stepProgress, this, &MinecraftLoadAndCheck::propagateStepProgress); connect(m_task.get(), &Task::status, this, &MinecraftLoadAndCheck::setStatus); @@ -28,8 +25,7 @@ void MinecraftLoadAndCheck::executeTask() void MinecraftLoadAndCheck::subtaskSucceeded() { - if(isFinished()) - { + if (isFinished()) { qCritical() << "MinecraftUpdate: Subtask" << sender() << "succeeded, but work was already done!"; return; } @@ -38,8 +34,7 @@ void MinecraftLoadAndCheck::subtaskSucceeded() void MinecraftLoadAndCheck::subtaskFailed(QString error) { - if(isFinished()) - { + if (isFinished()) { qCritical() << "MinecraftUpdate: Subtask" << sender() << "failed, but work was already done!"; return; } diff --git a/launcher/minecraft/MinecraftLoadAndCheck.h b/launcher/minecraft/MinecraftLoadAndCheck.h index d9af3ace2..9556c1d6a 100644 --- a/launcher/minecraft/MinecraftLoadAndCheck.h +++ b/launcher/minecraft/MinecraftLoadAndCheck.h @@ -15,34 +15,32 @@ #pragma once -#include #include +#include #include -#include "tasks/Task.h" #include +#include "tasks/Task.h" #include "QObjectPtr.h" class MinecraftVersion; class MinecraftInstance; -class MinecraftLoadAndCheck : public Task -{ +class MinecraftLoadAndCheck : public Task { Q_OBJECT -public: - explicit MinecraftLoadAndCheck(MinecraftInstance *inst, QObject *parent = 0); - virtual ~MinecraftLoadAndCheck() {}; + public: + explicit MinecraftLoadAndCheck(MinecraftInstance* inst, QObject* parent = 0); + virtual ~MinecraftLoadAndCheck(){}; void executeTask() override; -private slots: + private slots: void subtaskSucceeded(); void subtaskFailed(QString error); -private: - MinecraftInstance *m_inst = nullptr; + private: + MinecraftInstance* m_inst = nullptr; Task::Ptr m_task; QString m_preFailure; QString m_fail_reason; }; - diff --git a/launcher/minecraft/MinecraftUpdate.cpp b/launcher/minecraft/MinecraftUpdate.cpp index 236d0224b..c009317a6 100644 --- a/launcher/minecraft/MinecraftUpdate.cpp +++ b/launcher/minecraft/MinecraftUpdate.cpp @@ -16,27 +16,25 @@ #include "MinecraftUpdate.h" #include "MinecraftInstance.h" +#include #include #include #include -#include -#include "BaseInstance.h" -#include "minecraft/PackProfile.h" -#include "minecraft/Library.h" #include +#include "BaseInstance.h" +#include "minecraft/Library.h" +#include "minecraft/PackProfile.h" +#include "update/AssetUpdateTask.h" +#include "update/FMLLibrariesTask.h" #include "update/FoldersTask.h" #include "update/LibrariesTask.h" -#include "update/FMLLibrariesTask.h" -#include "update/AssetUpdateTask.h" #include #include -MinecraftUpdate::MinecraftUpdate(MinecraftInstance *inst, QObject *parent) : Task(parent), m_inst(inst) -{ -} +MinecraftUpdate::MinecraftUpdate(MinecraftInstance* inst, QObject* parent) : Task(parent), m_inst(inst) {} void MinecraftUpdate::executeTask() { @@ -51,8 +49,7 @@ void MinecraftUpdate::executeTask() auto components = m_inst->getPackProfile(); components->reload(Net::Mode::Online); auto task = components->getCurrentTask(); - if(task) - { + if (task) { m_tasks.append(task); } } @@ -72,8 +69,7 @@ void MinecraftUpdate::executeTask() m_tasks.append(makeShared(m_inst)); } - if(!m_preFailure.isEmpty()) - { + if (!m_preFailure.isEmpty()) { emitFailed(m_preFailure); return; } @@ -82,19 +78,16 @@ void MinecraftUpdate::executeTask() void MinecraftUpdate::next() { - if(m_abort) - { + if (m_abort) { emitFailed(tr("Aborted by user.")); return; } - if(m_failed_out_of_order) - { + if (m_failed_out_of_order) { emitFailed(m_fail_reason); return; } - m_currentTask ++; - if(m_currentTask > 0) - { + m_currentTask++; + if (m_currentTask > 0) { auto task = m_tasks[m_currentTask - 1]; disconnect(task.get(), &Task::succeeded, this, &MinecraftUpdate::subtaskSucceeded); disconnect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed); @@ -104,15 +97,13 @@ void MinecraftUpdate::next() disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); } - if(m_currentTask == m_tasks.size()) - { + if (m_currentTask == m_tasks.size()) { emitSucceeded(); return; } auto task = m_tasks[m_currentTask]; // if the task is already finished by the time we look at it, skip it - if(task->isFinished()) - { + if (task->isFinished()) { qCritical() << "MinecraftUpdate: Skipping finished subtask" << m_currentTask << ":" << task.get(); next(); } @@ -124,23 +115,20 @@ void MinecraftUpdate::next() connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus); connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails); // if the task is already running, do not start it again - if(!task->isRunning()) - { + if (!task->isRunning()) { task->start(); } } void MinecraftUpdate::subtaskSucceeded() { - if(isFinished()) - { + if (isFinished()) { qCritical() << "MinecraftUpdate: Subtask" << sender() << "succeeded, but work was already done!"; return; } auto senderTask = QObject::sender(); auto currentTask = m_tasks[m_currentTask].get(); - if(senderTask != currentTask) - { + if (senderTask != currentTask) { qDebug() << "MinecraftUpdate: Subtask" << sender() << "succeeded out of order."; return; } @@ -149,15 +137,13 @@ void MinecraftUpdate::subtaskSucceeded() void MinecraftUpdate::subtaskFailed(QString error) { - if(isFinished()) - { + if (isFinished()) { qCritical() << "MinecraftUpdate: Subtask" << sender() << "failed, but work was already done!"; return; } auto senderTask = QObject::sender(); auto currentTask = m_tasks[m_currentTask].get(); - if(senderTask != currentTask) - { + if (senderTask != currentTask) { qDebug() << "MinecraftUpdate: Subtask" << sender() << "failed out of order."; m_failed_out_of_order = true; m_fail_reason = error; @@ -166,15 +152,12 @@ void MinecraftUpdate::subtaskFailed(QString error) emitFailed(error); } - bool MinecraftUpdate::abort() { - if(!m_abort) - { + if (!m_abort) { m_abort = true; auto task = m_tasks[m_currentTask]; - if(task->canAbort()) - { + if (task->canAbort()) { return task->abort(); } } diff --git a/launcher/minecraft/MinecraftUpdate.h b/launcher/minecraft/MinecraftUpdate.h index c9cf8624b..9c41d7f56 100644 --- a/launcher/minecraft/MinecraftUpdate.h +++ b/launcher/minecraft/MinecraftUpdate.h @@ -15,41 +15,39 @@ #pragma once -#include #include +#include #include +#include +#include "minecraft/VersionFilterData.h" #include "net/NetJob.h" #include "tasks/Task.h" -#include "minecraft/VersionFilterData.h" -#include class MinecraftVersion; class MinecraftInstance; // FIXME: This looks very similar to a SequentialTask. Maybe we can reduce code duplications? :^) -class MinecraftUpdate : public Task -{ +class MinecraftUpdate : public Task { Q_OBJECT -public: - explicit MinecraftUpdate(MinecraftInstance *inst, QObject *parent = 0); - virtual ~MinecraftUpdate() {}; + public: + explicit MinecraftUpdate(MinecraftInstance* inst, QObject* parent = 0); + virtual ~MinecraftUpdate(){}; void executeTask() override; bool canAbort() const override; -private -slots: + private slots: bool abort() override; void subtaskSucceeded(); void subtaskFailed(QString error); -private: + private: void next(); -private: - MinecraftInstance *m_inst = nullptr; + private: + MinecraftInstance* m_inst = nullptr; QList m_tasks; QString m_preFailure; int m_currentTask = -1; diff --git a/launcher/minecraft/MojangDownloadInfo.h b/launcher/minecraft/MojangDownloadInfo.h index 6831d8d87..855dbe005 100644 --- a/launcher/minecraft/MojangDownloadInfo.h +++ b/launcher/minecraft/MojangDownloadInfo.h @@ -1,10 +1,9 @@ #pragma once -#include #include +#include #include -struct MojangDownloadInfo -{ +struct MojangDownloadInfo { // types typedef std::shared_ptr Ptr; @@ -19,24 +18,20 @@ struct MojangDownloadInfo int size; }; - - -struct MojangLibraryDownloadInfo -{ - MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact_): artifact(artifact_) {} +struct MojangLibraryDownloadInfo { + MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact_) : artifact(artifact_) {} MojangLibraryDownloadInfo() {} // types typedef std::shared_ptr Ptr; // methods - MojangDownloadInfo *getDownloadInfo(QString classifier) + MojangDownloadInfo* getDownloadInfo(QString classifier) { - if (classifier.isNull()) - { + if (classifier.isNull()) { return artifact.get(); } - + return classifiers[classifier].get(); } @@ -45,17 +40,12 @@ struct MojangLibraryDownloadInfo QMap classifiers; }; - - -struct MojangAssetIndexInfo : public MojangDownloadInfo -{ +struct MojangAssetIndexInfo : public MojangDownloadInfo { // types typedef std::shared_ptr Ptr; // methods - MojangAssetIndexInfo() - { - } + MojangAssetIndexInfo() {} MojangAssetIndexInfo(QString id_) { @@ -63,13 +53,11 @@ struct MojangAssetIndexInfo : public MojangDownloadInfo // HACK: ignore assets from other version files than Minecraft // workaround for stupid assets issue caused by amazon: // https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/ - if(id_ == "legacy") - { + if (id_ == "legacy") { url = "https://piston-meta.mojang.com/mc/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/legacy.json"; } // HACK - else - { + else { url = "https://s3.amazonaws.com/Minecraft.Download/indexes/" + id_ + ".json"; } known = false; diff --git a/launcher/minecraft/MojangVersionFormat.cpp b/launcher/minecraft/MojangVersionFormat.cpp index 623dcdfa6..d7393cf4a 100644 --- a/launcher/minecraft/MojangVersionFormat.cpp +++ b/launcher/minecraft/MojangVersionFormat.cpp @@ -34,34 +34,32 @@ */ #include "MojangVersionFormat.h" -#include "OneSixVersionFormat.h" #include "MojangDownloadInfo.h" +#include "OneSixVersionFormat.h" #include "Json.h" using namespace Json; -#include "ParseUtils.h" #include +#include "ParseUtils.h" static const int CURRENT_MINIMUM_LAUNCHER_VERSION = 18; -static MojangAssetIndexInfo::Ptr assetIndexFromJson (const QJsonObject &obj); -static MojangDownloadInfo::Ptr downloadInfoFromJson (const QJsonObject &obj); -static MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson (const QJsonObject &libObj); -static QJsonObject assetIndexToJson (MojangAssetIndexInfo::Ptr assetidxinfo); -static QJsonObject libDownloadInfoToJson (MojangLibraryDownloadInfo::Ptr libinfo); -static QJsonObject downloadInfoToJson (MojangDownloadInfo::Ptr info); +static MojangAssetIndexInfo::Ptr assetIndexFromJson(const QJsonObject& obj); +static MojangDownloadInfo::Ptr downloadInfoFromJson(const QJsonObject& obj); +static MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson(const QJsonObject& libObj); +static QJsonObject assetIndexToJson(MojangAssetIndexInfo::Ptr assetidxinfo); +static QJsonObject libDownloadInfoToJson(MojangLibraryDownloadInfo::Ptr libinfo); +static QJsonObject downloadInfoToJson(MojangDownloadInfo::Ptr info); -namespace Bits +namespace Bits { +static void readString(const QJsonObject& root, const QString& key, QString& variable) { -static void readString(const QJsonObject &root, const QString &key, QString &variable) -{ - if (root.contains(key)) - { + if (root.contains(key)) { variable = requireString(root.value(key)); } } -static void readDownloadInfo(MojangDownloadInfo::Ptr out, const QJsonObject &obj) +static void readDownloadInfo(MojangDownloadInfo::Ptr out, const QJsonObject& obj) { // optional, not used readString(obj, "path", out->path); @@ -71,22 +69,22 @@ static void readDownloadInfo(MojangDownloadInfo::Ptr out, const QJsonObject &obj out->size = requireInteger(obj, "size"); } -static void readAssetIndex(MojangAssetIndexInfo::Ptr out, const QJsonObject &obj) +static void readAssetIndex(MojangAssetIndexInfo::Ptr out, const QJsonObject& obj) { out->totalSize = requireInteger(obj, "totalSize"); out->id = requireString(obj, "id"); // out->known = true; } -} +} // namespace Bits -MojangDownloadInfo::Ptr downloadInfoFromJson(const QJsonObject &obj) +MojangDownloadInfo::Ptr downloadInfoFromJson(const QJsonObject& obj) { auto out = std::make_shared(); Bits::readDownloadInfo(out, obj); return out; } -MojangAssetIndexInfo::Ptr assetIndexFromJson(const QJsonObject &obj) +MojangAssetIndexInfo::Ptr assetIndexFromJson(const QJsonObject& obj) { auto out = std::make_shared(); Bits::readDownloadInfo(out, obj); @@ -97,8 +95,7 @@ MojangAssetIndexInfo::Ptr assetIndexFromJson(const QJsonObject &obj) QJsonObject downloadInfoToJson(MojangDownloadInfo::Ptr info) { QJsonObject out; - if(!info->path.isNull()) - { + if (!info->path.isNull()) { out.insert("path", info->path); } out.insert("sha1", info->sha1); @@ -107,19 +104,16 @@ QJsonObject downloadInfoToJson(MojangDownloadInfo::Ptr info) return out; } -MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson(const QJsonObject &libObj) +MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson(const QJsonObject& libObj) { auto out = std::make_shared(); auto dlObj = requireObject(libObj.value("downloads")); - if(dlObj.contains("artifact")) - { + if (dlObj.contains("artifact")) { out->artifact = downloadInfoFromJson(requireObject(dlObj, "artifact")); } - if(dlObj.contains("classifiers")) - { + if (dlObj.contains("classifiers")) { auto classifiersObj = requireObject(dlObj, "classifiers"); - for(auto iter = classifiersObj.begin(); iter != classifiersObj.end(); iter++) - { + for (auto iter = classifiersObj.begin(); iter != classifiersObj.end(); iter++) { auto classifier = iter.key(); auto classifierObj = requireObject(iter.value()); out->classifiers[classifier] = downloadInfoFromJson(classifierObj); @@ -131,15 +125,12 @@ MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson(const QJsonObject &libObj QJsonObject libDownloadInfoToJson(MojangLibraryDownloadInfo::Ptr libinfo) { QJsonObject out; - if(libinfo->artifact) - { + if (libinfo->artifact) { out.insert("artifact", downloadInfoToJson(libinfo->artifact)); } - if(!libinfo->classifiers.isEmpty()) - { + if (!libinfo->classifiers.isEmpty()) { QJsonObject classifiersOut; - for(auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++) - { + for (auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++) { classifiersOut.insert(iter.key(), downloadInfoToJson(iter.value())); } out.insert("classifiers", classifiersOut); @@ -150,8 +141,7 @@ QJsonObject libDownloadInfoToJson(MojangLibraryDownloadInfo::Ptr libinfo) QJsonObject assetIndexToJson(MojangAssetIndexInfo::Ptr info) { QJsonObject out; - if(!info->path.isNull()) - { + if (!info->path.isNull()) { out.insert("path", info->path); } out.insert("sha1", info->sha1); @@ -162,76 +152,57 @@ QJsonObject assetIndexToJson(MojangAssetIndexInfo::Ptr info) return out; } -void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFile *out) +void MojangVersionFormat::readVersionProperties(const QJsonObject& in, VersionFile* out) { Bits::readString(in, "id", out->minecraftVersion); Bits::readString(in, "mainClass", out->mainClass); Bits::readString(in, "minecraftArguments", out->minecraftArguments); - if(out->minecraftArguments.isEmpty()) - { + if (out->minecraftArguments.isEmpty()) { QString processArguments; Bits::readString(in, "processArguments", processArguments); QString toCompare = processArguments.toLower(); - if (toCompare == "legacy") - { + if (toCompare == "legacy") { out->minecraftArguments = " ${auth_player_name} ${auth_session}"; - } - else if (toCompare == "username_session") - { + } else if (toCompare == "username_session") { out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}"; - } - else if (toCompare == "username_session_version") - { + } else if (toCompare == "username_session_version") { out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}"; - } - else if (!toCompare.isEmpty()) - { + } else if (!toCompare.isEmpty()) { out->addProblem(ProblemSeverity::Error, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments)); } } Bits::readString(in, "type", out->type); Bits::readString(in, "assets", out->assets); - if(in.contains("assetIndex")) - { + if (in.contains("assetIndex")) { out->mojangAssetIndex = assetIndexFromJson(requireObject(in, "assetIndex")); - } - else if (!out->assets.isNull()) - { + } else if (!out->assets.isNull()) { out->mojangAssetIndex = std::make_shared(out->assets); } out->releaseTime = timeFromS3Time(in.value("releaseTime").toString("")); out->updateTime = timeFromS3Time(in.value("time").toString("")); - if (in.contains("minimumLauncherVersion")) - { + if (in.contains("minimumLauncherVersion")) { out->minimumLauncherVersion = requireInteger(in.value("minimumLauncherVersion")); - if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION) - { - out->addProblem( - ProblemSeverity::Warning, - QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than supported by %3 (%2). It might not work properly!") - .arg(out->minimumLauncherVersion) - .arg(CURRENT_MINIMUM_LAUNCHER_VERSION) - .arg(BuildConfig.LAUNCHER_DISPLAYNAME) - ); + if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION) { + out->addProblem(ProblemSeverity::Warning, QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than " + "supported by %3 (%2). It might not work properly!") + .arg(out->minimumLauncherVersion) + .arg(CURRENT_MINIMUM_LAUNCHER_VERSION) + .arg(BuildConfig.LAUNCHER_DISPLAYNAME)); } } - if (in.contains("compatibleJavaMajors")) - { - for (auto compatible : requireArray(in.value("compatibleJavaMajors"))) - { + if (in.contains("compatibleJavaMajors")) { + for (auto compatible : requireArray(in.value("compatibleJavaMajors"))) { out->compatibleJavaMajors.append(requireInteger(compatible)); } } - if(in.contains("downloads")) - { + if (in.contains("downloads")) { auto downloadsObj = requireObject(in, "downloads"); - for(auto iter = downloadsObj.begin(); iter != downloadsObj.end(); iter++) - { + for (auto iter = downloadsObj.begin(); iter != downloadsObj.end(); iter++) { auto classifier = iter.key(); auto classifierObj = requireObject(iter.value()); out->mojangDownloads[classifier] = downloadInfoFromJson(classifierObj); @@ -239,15 +210,13 @@ void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFi } } -VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument &doc, const QString &filename) +VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument& doc, const QString& filename) { VersionFilePtr out(new VersionFile()); - if (doc.isEmpty() || doc.isNull()) - { + if (doc.isEmpty() || doc.isNull()) { throw JSONValidationError(filename + " is empty or null"); } - if (!doc.isObject()) - { + if (!doc.isObject()) { throw JSONValidationError(filename + " is not an object"); } @@ -260,11 +229,8 @@ VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument &doc out->version = out->minecraftVersion; // out->filename = filename; - - if (root.contains("libraries")) - { - for (auto libVal : requireArray(root.value("libraries"))) - { + if (root.contains("libraries")) { + for (auto libVal : requireArray(root.value("libraries"))) { auto libObj = requireObject(libVal); auto lib = MojangVersionFormat::libraryFromJson(*out, libObj, filename); @@ -280,52 +246,42 @@ void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObj writeString(out, "mainClass", in->mainClass); writeString(out, "minecraftArguments", in->minecraftArguments); writeString(out, "type", in->type); - if(!in->releaseTime.isNull()) - { + if (!in->releaseTime.isNull()) { writeString(out, "releaseTime", timeToS3Time(in->releaseTime)); } - if(!in->updateTime.isNull()) - { + if (!in->updateTime.isNull()) { writeString(out, "time", timeToS3Time(in->updateTime)); } - if(in->minimumLauncherVersion != -1) - { + if (in->minimumLauncherVersion != -1) { out.insert("minimumLauncherVersion", in->minimumLauncherVersion); } writeString(out, "assets", in->assets); - if(in->mojangAssetIndex && in->mojangAssetIndex->known) - { + if (in->mojangAssetIndex && in->mojangAssetIndex->known) { out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex)); } - if(!in->mojangDownloads.isEmpty()) - { + if (!in->mojangDownloads.isEmpty()) { QJsonObject downloadsOut; - for(auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++) - { + for (auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++) { downloadsOut.insert(iter.key(), downloadInfoToJson(iter.value())); } out.insert("downloads", downloadsOut); } - if(!in->compatibleJavaMajors.isEmpty()) - { + if (!in->compatibleJavaMajors.isEmpty()) { QJsonArray compatibleJavaMajorsOut; - for(auto compatibleJavaMajor : in->compatibleJavaMajors) - { + for (auto compatibleJavaMajor : in->compatibleJavaMajors) { compatibleJavaMajorsOut.append(compatibleJavaMajor); } out.insert("compatibleJavaMajors", compatibleJavaMajorsOut); } } -QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr &patch) +QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr& patch) { QJsonObject root; writeVersionProperties(patch.get(), root); - if (!patch->libraries.isEmpty()) - { + if (!patch->libraries.isEmpty()) { QJsonArray array; - for (auto value: patch->libraries) - { + for (auto value : patch->libraries) { array.append(MojangVersionFormat::libraryToJson(value.get())); } root.insert("libraries", array); @@ -339,96 +295,80 @@ QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr &patch } } -LibraryPtr MojangVersionFormat::libraryFromJson(ProblemContainer & problems, const QJsonObject &libObj, const QString &filename) +LibraryPtr MojangVersionFormat::libraryFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename) { LibraryPtr out(new Library()); - if (!libObj.contains("name")) - { + if (!libObj.contains("name")) { throw JSONValidationError(filename + "contains a library that doesn't have a 'name' field"); } auto rawName = libObj.value("name").toString(); out->m_name = rawName; - if(!out->m_name.valid()) { + if (!out->m_name.valid()) { problems.addProblem(ProblemSeverity::Error, QObject::tr("Library %1 name is broken and cannot be processed.").arg(rawName)); } Bits::readString(libObj, "url", out->m_repositoryURL); - if (libObj.contains("extract")) - { + if (libObj.contains("extract")) { out->m_hasExcludes = true; auto extractObj = requireObject(libObj.value("extract")); - for (auto excludeVal : requireArray(extractObj.value("exclude"))) - { + for (auto excludeVal : requireArray(extractObj.value("exclude"))) { out->m_extractExcludes.append(requireString(excludeVal)); } } - if (libObj.contains("natives")) - { + if (libObj.contains("natives")) { QJsonObject nativesObj = requireObject(libObj.value("natives")); - for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it) - { - if (!it.value().isString()) - { + for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it) { + if (!it.value().isString()) { qWarning() << filename << "contains an invalid native (skipping)"; } // FIXME: Skip unknown platforms out->m_nativeClassifiers[it.key()] = it.value().toString(); } } - if (libObj.contains("rules")) - { + if (libObj.contains("rules")) { out->applyRules = true; out->m_rules = rulesFromJsonV4(libObj); } - if (libObj.contains("downloads")) - { + if (libObj.contains("downloads")) { out->m_mojangDownloads = libDownloadInfoFromJson(libObj); } return out; } -QJsonObject MojangVersionFormat::libraryToJson(Library *library) +QJsonObject MojangVersionFormat::libraryToJson(Library* library) { QJsonObject libRoot; libRoot.insert("name", library->m_name.serialize()); - if (!library->m_repositoryURL.isEmpty()) - { + if (!library->m_repositoryURL.isEmpty()) { libRoot.insert("url", library->m_repositoryURL); } - if (library->isNative()) - { + if (library->isNative()) { QJsonObject nativeList; auto iter = library->m_nativeClassifiers.begin(); - while (iter != library->m_nativeClassifiers.end()) - { + while (iter != library->m_nativeClassifiers.end()) { nativeList.insert(iter.key(), iter.value()); iter++; } libRoot.insert("natives", nativeList); - if (!library->m_extractExcludes.isEmpty()) - { + if (!library->m_extractExcludes.isEmpty()) { QJsonArray excludes; QJsonObject extract; - for (auto exclude : library->m_extractExcludes) - { + for (auto exclude : library->m_extractExcludes) { excludes.append(exclude); } extract.insert("exclude", excludes); libRoot.insert("extract", extract); } } - if (!library->m_rules.isEmpty()) - { + if (!library->m_rules.isEmpty()) { QJsonArray allRules; - for (auto &rule : library->m_rules) - { + for (auto& rule : library->m_rules) { QJsonObject ruleObj = rule->toJson(); allRules.append(ruleObj); } libRoot.insert("rules", allRules); } - if(library->m_mojangDownloads) - { + if (library->m_mojangDownloads) { auto downloadsObj = libDownloadInfoToJson(library->m_mojangDownloads); libRoot.insert("downloads", downloadsObj); } diff --git a/launcher/minecraft/MojangVersionFormat.h b/launcher/minecraft/MojangVersionFormat.h index d38f0a2ff..88d8a206d 100644 --- a/launcher/minecraft/MojangVersionFormat.h +++ b/launcher/minecraft/MojangVersionFormat.h @@ -1,24 +1,25 @@ #pragma once -#include -#include -#include #include +#include +#include +#include -class MojangVersionFormat -{ -friend class OneSixVersionFormat; -protected: +class MojangVersionFormat { + friend class OneSixVersionFormat; + + protected: // does not include libraries static void readVersionProperties(const QJsonObject& in, VersionFile* out); // does not include libraries static void writeVersionProperties(const VersionFile* in, QJsonObject& out); -public: + + public: // version files / profile patches - static VersionFilePtr versionFileFromJson(const QJsonDocument &doc, const QString &filename); - static QJsonDocument versionFileToJson(const VersionFilePtr &patch); + static VersionFilePtr versionFileFromJson(const QJsonDocument& doc, const QString& filename); + static QJsonDocument versionFileToJson(const VersionFilePtr& patch); // libraries - static LibraryPtr libraryFromJson(ProblemContainer & problems, const QJsonObject &libObj, const QString &filename); - static QJsonObject libraryToJson(Library *library); + static LibraryPtr libraryFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename); + static QJsonObject libraryToJson(Library* library); }; diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp index ddd98110c..91b58c96c 100644 --- a/launcher/minecraft/OneSixVersionFormat.cpp +++ b/launcher/minecraft/OneSixVersionFormat.cpp @@ -35,23 +35,22 @@ #include "OneSixVersionFormat.h" #include +#include #include "minecraft/Agent.h" #include "minecraft/ParseUtils.h" -#include #include using namespace Json; -static void readString(const QJsonObject &root, const QString &key, QString &variable) +static void readString(const QJsonObject& root, const QString& key, QString& variable) { - if (root.contains(key)) - { + if (root.contains(key)) { variable = requireString(root.value(key)); } } -LibraryPtr OneSixVersionFormat::libraryFromJson(ProblemContainer & problems, const QJsonObject &libObj, const QString &filename) +LibraryPtr OneSixVersionFormat::libraryFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename) { LibraryPtr out = MojangVersionFormat::libraryFromJson(problems, libObj, filename); readString(libObj, "MMC-hint", out->m_hint); @@ -62,7 +61,7 @@ LibraryPtr OneSixVersionFormat::libraryFromJson(ProblemContainer & problems, con return out; } -QJsonObject OneSixVersionFormat::libraryToJson(Library *library) +QJsonObject OneSixVersionFormat::libraryToJson(Library* library) { QJsonObject libRoot = MojangVersionFormat::libraryToJson(library); if (!library->m_absoluteURL.isEmpty()) @@ -76,37 +75,30 @@ QJsonObject OneSixVersionFormat::libraryToJson(Library *library) return libRoot; } -VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder) +VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument& doc, const QString& filename, const bool requireOrder) { VersionFilePtr out(new VersionFile()); - if (doc.isEmpty() || doc.isNull()) - { + if (doc.isEmpty() || doc.isNull()) { throw JSONValidationError(filename + " is empty or null"); } - if (!doc.isObject()) - { + if (!doc.isObject()) { throw JSONValidationError(filename + " is not an object"); } QJsonObject root = doc.object(); Meta::MetadataVersion formatVersion = Meta::parseFormatVersion(root, false); - switch(formatVersion) - { + switch (formatVersion) { case Meta::MetadataVersion::InitialRelease: break; case Meta::MetadataVersion::Invalid: throw JSONValidationError(filename + " does not contain a recognizable version of the metadata format."); } - if (requireOrder) - { - if (root.contains("order")) - { + if (requireOrder) { + if (root.contains("order")) { out->order = requireInteger(root.value("order")); - } - else - { + } else { // FIXME: evaluate if we don't want to throw exceptions here instead qCritical() << filename << "doesn't contain an order field"; } @@ -114,22 +106,18 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc out->name = root.value("name").toString(); - if(root.contains("uid")) - { + if (root.contains("uid")) { out->uid = root.value("uid").toString(); - } - else - { + } else { out->uid = root.value("fileId").toString(); } - const QRegularExpression valid_uid_regex{ QRegularExpression::anchoredPattern(QStringLiteral(R"([a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]+)*)")) }; + const QRegularExpression valid_uid_regex{ QRegularExpression::anchoredPattern( + QStringLiteral(R"([a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]+)*)")) }; if (!valid_uid_regex.match(out->uid).hasMatch()) { qCritical() << "The component's 'uid' contains illegal characters! UID:" << out->uid; - out->addProblem( - ProblemSeverity::Error, - QObject::tr("The component's 'uid' contains illegal characters! This can cause security issues.") - ); + out->addProblem(ProblemSeverity::Error, + QObject::tr("The component's 'uid' contains illegal characters! This can cause security issues.")); } out->version = root.value("version").toString(); @@ -139,46 +127,35 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc // added for legacy Minecraft window embedding, TODO: remove readString(root, "appletClass", out->appletClass); - if (root.contains("+tweakers")) - { - for (auto tweakerVal : requireArray(root.value("+tweakers"))) - { + if (root.contains("+tweakers")) { + for (auto tweakerVal : requireArray(root.value("+tweakers"))) { out->addTweakers.append(requireString(tweakerVal)); } } - if (root.contains("+traits")) - { - for (auto tweakerVal : requireArray(root.value("+traits"))) - { + if (root.contains("+traits")) { + for (auto tweakerVal : requireArray(root.value("+traits"))) { out->traits.insert(requireString(tweakerVal)); } } - if (root.contains("+jvmArgs")) - { - for (auto arg : requireArray(root.value("+jvmArgs"))) - { + if (root.contains("+jvmArgs")) { + for (auto arg : requireArray(root.value("+jvmArgs"))) { out->addnJvmArguments.append(requireString(arg)); } } - - if (root.contains("jarMods")) - { - for (auto libVal : requireArray(root.value("jarMods"))) - { + if (root.contains("jarMods")) { + for (auto libVal : requireArray(root.value("jarMods"))) { QJsonObject libObj = requireObject(libVal); // parse the jarmod auto lib = OneSixVersionFormat::jarModFromJson(*out, libObj, filename); // and add to jar mods out->jarMods.append(lib); } - } - else if (root.contains("+jarMods")) // DEPRECATED: old style '+jarMods' are only here for backwards compatibility + } else if (root.contains("+jarMods")) // DEPRECATED: old style '+jarMods' are only here for backwards compatibility { - for (auto libVal : requireArray(root.value("+jarMods"))) - { + for (auto libVal : requireArray(root.value("+jarMods"))) { QJsonObject libObj = requireObject(libVal); // parse the jarmod auto lib = OneSixVersionFormat::plusJarModFromJson(*out, libObj, filename, out->name); @@ -187,10 +164,8 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc } } - if (root.contains("mods")) - { - for (auto libVal : requireArray(root.value("mods"))) - { + if (root.contains("mods")) { + for (auto libVal : requireArray(root.value("mods"))) { QJsonObject libObj = requireObject(libVal); // parse the jarmod auto lib = OneSixVersionFormat::modFromJson(*out, libObj, filename); @@ -199,10 +174,8 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc } } - auto readLibs = [&](const char * which, QList & outList) - { - for (auto libVal : requireArray(root.value(which))) - { + auto readLibs = [&](const char* which, QList& outList) { + for (auto libVal : requireArray(root.value(which))) { QJsonObject libObj = requireObject(libVal); // parse the library auto lib = libraryFromJson(*out, libObj, filename); @@ -211,29 +184,23 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc }; bool hasPlusLibs = root.contains("+libraries"); bool hasLibs = root.contains("libraries"); - if (hasPlusLibs && hasLibs) - { + if (hasPlusLibs && hasLibs) { out->addProblem(ProblemSeverity::Warning, QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported.")); readLibs("libraries", out->libraries); readLibs("+libraries", out->libraries); - } - else if (hasLibs) - { + } else if (hasLibs) { readLibs("libraries", out->libraries); - } - else if(hasPlusLibs) - { + } else if (hasPlusLibs) { readLibs("+libraries", out->libraries); } - if(root.contains("mavenFiles")) { + if (root.contains("mavenFiles")) { readLibs("mavenFiles", out->mavenFiles); } - if(root.contains("+agents")) { - for (auto agentVal : requireArray(root.value("+agents"))) - { + if (root.contains("+agents")) { + for (auto agentVal : requireArray(root.value("+agents"))) { QJsonObject agentObj = requireObject(agentVal); auto lib = libraryFromJson(*out, agentObj, filename); @@ -246,83 +213,68 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc } // if we have mainJar, just use it - if(root.contains("mainJar")) - { + if (root.contains("mainJar")) { QJsonObject libObj = requireObject(root, "mainJar"); out->mainJar = libraryFromJson(*out, libObj, filename); } // else reconstruct it from downloads and id ... if that's available - else if(!out->minecraftVersion.isEmpty()) - { + else if (!out->minecraftVersion.isEmpty()) { auto lib = std::make_shared(); lib->setRawName(GradleSpecifier(QString("com.mojang:minecraft:%1:client").arg(out->minecraftVersion))); // we have a reliable client download, use it. - if(out->mojangDownloads.contains("client")) - { + if (out->mojangDownloads.contains("client")) { auto LibDLInfo = std::make_shared(); LibDLInfo->artifact = out->mojangDownloads["client"]; lib->setMojangDownloadInfo(LibDLInfo); } // we got nothing... - else - { + else { out->addProblem( ProblemSeverity::Error, - QObject::tr("URL for the main jar could not be determined - Mojang removed the server that we used as fallback.") - ); + QObject::tr("URL for the main jar could not be determined - Mojang removed the server that we used as fallback.")); } out->mainJar = lib; } - if (root.contains("requires")) - { + if (root.contains("requires")) { Meta::parseRequires(root, &out->m_requires); } QString dependsOnMinecraftVersion = root.value("mcVersion").toString(); - if(!dependsOnMinecraftVersion.isEmpty()) - { + if (!dependsOnMinecraftVersion.isEmpty()) { Meta::Require mcReq; mcReq.uid = "net.minecraft"; mcReq.equalsVersion = dependsOnMinecraftVersion; - if (out->m_requires.count(mcReq) == 0) - { + if (out->m_requires.count(mcReq) == 0) { out->m_requires.insert(mcReq); } } - if (root.contains("conflicts")) - { + if (root.contains("conflicts")) { Meta::parseRequires(root, &out->conflicts); } - if (root.contains("volatile")) - { + if (root.contains("volatile")) { out->m_volatile = requireBoolean(root, "volatile"); } /* removed features that shouldn't be used */ - if (root.contains("tweakers")) - { + if (root.contains("tweakers")) { out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'")); } - if (root.contains("-libraries")) - { + if (root.contains("-libraries")) { out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-libraries'")); } - if (root.contains("-tweakers")) - { + if (root.contains("-tweakers")) { out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-tweakers'")); } - if (root.contains("-minecraftArguments")) - { + if (root.contains("-minecraftArguments")) { out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-minecraftArguments'")); } - if (root.contains("+minecraftArguments")) - { + if (root.contains("+minecraftArguments")) { out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '+minecraftArguments'")); } return out; } -QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch) +QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr& patch) { QJsonObject root; writeString(root, "name", patch->name); @@ -335,19 +287,16 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch MojangVersionFormat::writeVersionProperties(patch.get(), root); - if(patch->mainJar) - { + if (patch->mainJar) { root.insert("mainJar", libraryToJson(patch->mainJar.get())); } writeString(root, "appletClass", patch->appletClass); writeStringList(root, "+tweakers", patch->addTweakers); writeStringList(root, "+traits", patch->traits.values()); writeStringList(root, "+jvmArgs", patch->addnJvmArguments); - if (!patch->agents.isEmpty()) - { + if (!patch->agents.isEmpty()) { QJsonArray array; - for (auto value: patch->agents) - { + for (auto value : patch->agents) { QJsonObject agentOut = OneSixVersionFormat::libraryToJson(value->library().get()); if (!value->argument().isEmpty()) agentOut.insert("argument", value->argument()); @@ -356,52 +305,41 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch } root.insert("+agents", array); } - if (!patch->libraries.isEmpty()) - { + if (!patch->libraries.isEmpty()) { QJsonArray array; - for (auto value: patch->libraries) - { + for (auto value : patch->libraries) { array.append(OneSixVersionFormat::libraryToJson(value.get())); } root.insert("libraries", array); } - if (!patch->mavenFiles.isEmpty()) - { + if (!patch->mavenFiles.isEmpty()) { QJsonArray array; - for (auto value: patch->mavenFiles) - { + for (auto value : patch->mavenFiles) { array.append(OneSixVersionFormat::libraryToJson(value.get())); } root.insert("mavenFiles", array); } - if (!patch->jarMods.isEmpty()) - { + if (!patch->jarMods.isEmpty()) { QJsonArray array; - for (auto value: patch->jarMods) - { + for (auto value : patch->jarMods) { array.append(OneSixVersionFormat::jarModtoJson(value.get())); } root.insert("jarMods", array); } - if (!patch->mods.isEmpty()) - { + if (!patch->mods.isEmpty()) { QJsonArray array; - for (auto value: patch->jarMods) - { + for (auto value : patch->jarMods) { array.append(OneSixVersionFormat::modtoJson(value.get())); } root.insert("mods", array); } - if(!patch->m_requires.empty()) - { + if (!patch->m_requires.empty()) { Meta::serializeRequires(root, &patch->m_requires, "requires"); } - if(!patch->conflicts.empty()) - { + if (!patch->conflicts.empty()) { Meta::serializeRequires(root, &patch->conflicts, "conflicts"); } - if(patch->m_volatile) - { + if (patch->m_volatile) { root.insert("volatile", true); } // write the contents to a json document. @@ -412,17 +350,14 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch } } -LibraryPtr OneSixVersionFormat::plusJarModFromJson( - [[maybe_unused]] ProblemContainer & problems, - const QJsonObject &libObj, - const QString &filename, - const QString &originalName -) { +LibraryPtr OneSixVersionFormat::plusJarModFromJson([[maybe_unused]] ProblemContainer& problems, + const QJsonObject& libObj, + const QString& filename, + const QString& originalName) +{ LibraryPtr out(new Library()); - if (!libObj.contains("name")) - { - throw JSONValidationError(filename + - "contains a jarmod that doesn't have a 'name' field"); + if (!libObj.contains("name")) { + throw JSONValidationError(filename + "contains a jarmod that doesn't have a 'name' field"); } // just make up something unique on the spot for the library name. @@ -439,36 +374,32 @@ LibraryPtr OneSixVersionFormat::plusJarModFromJson( // read the original name if present - some versions did not set it // it is the original jar mod filename before it got renamed at the point of addition auto displayName = libObj.value("originalName").toString(); - if(displayName.isEmpty()) - { + if (displayName.isEmpty()) { auto fixed = originalName; fixed.remove(" (jar mod)"); out->setDisplayName(fixed); - } - else - { + } else { out->setDisplayName(displayName); } return out; } -LibraryPtr OneSixVersionFormat::jarModFromJson(ProblemContainer & problems, const QJsonObject& libObj, const QString& filename) +LibraryPtr OneSixVersionFormat::jarModFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename) { return libraryFromJson(problems, libObj, filename); } - -QJsonObject OneSixVersionFormat::jarModtoJson(Library *jarmod) +QJsonObject OneSixVersionFormat::jarModtoJson(Library* jarmod) { return libraryToJson(jarmod); } -LibraryPtr OneSixVersionFormat::modFromJson(ProblemContainer & problems, const QJsonObject& libObj, const QString& filename) +LibraryPtr OneSixVersionFormat::modFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename) { - return libraryFromJson(problems, libObj, filename); + return libraryFromJson(problems, libObj, filename); } -QJsonObject OneSixVersionFormat::modtoJson(Library *jarmod) +QJsonObject OneSixVersionFormat::modtoJson(Library* jarmod) { return libraryToJson(jarmod); } diff --git a/launcher/minecraft/OneSixVersionFormat.h b/launcher/minecraft/OneSixVersionFormat.h index 1a091d880..9bdc4a4a3 100644 --- a/launcher/minecraft/OneSixVersionFormat.h +++ b/launcher/minecraft/OneSixVersionFormat.h @@ -1,30 +1,32 @@ #pragma once -#include -#include -#include -#include #include +#include +#include +#include +#include -class OneSixVersionFormat -{ -public: +class OneSixVersionFormat { + public: // version files / profile patches - static VersionFilePtr versionFileFromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder); - static QJsonDocument versionFileToJson(const VersionFilePtr &patch); + static VersionFilePtr versionFileFromJson(const QJsonDocument& doc, const QString& filename, const bool requireOrder); + static QJsonDocument versionFileToJson(const VersionFilePtr& patch); // libraries - static LibraryPtr libraryFromJson(ProblemContainer & problems, const QJsonObject &libObj, const QString &filename); - static QJsonObject libraryToJson(Library *library); + static LibraryPtr libraryFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename); + static QJsonObject libraryToJson(Library* library); // DEPRECATED: old 'plus' jar mods generated by the application - static LibraryPtr plusJarModFromJson(ProblemContainer & problems, const QJsonObject &libObj, const QString &filename, const QString &originalName); + static LibraryPtr plusJarModFromJson(ProblemContainer& problems, + const QJsonObject& libObj, + const QString& filename, + const QString& originalName); // new jar mods derived from libraries - static LibraryPtr jarModFromJson(ProblemContainer & problems, const QJsonObject &libObj, const QString &filename); - static QJsonObject jarModtoJson(Library * jarmod); + static LibraryPtr jarModFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename); + static QJsonObject jarModtoJson(Library* jarmod); // mods, also derived from libraries - static LibraryPtr modFromJson(ProblemContainer & problems, const QJsonObject &libObj, const QString &filename); - static QJsonObject modtoJson(Library * jarmod); + static LibraryPtr modFromJson(ProblemContainer& problems, const QJsonObject& libObj, const QString& filename); + static QJsonObject modtoJson(Library* jarmod); }; diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 1f210d695..cf8270cd2 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -37,40 +37,37 @@ * limitations under the License. */ -#include -#include #include -#include -#include -#include +#include #include +#include +#include +#include +#include #include -#include #include +#include #include "Exception.h" -#include "minecraft/OneSixVersionFormat.h" #include "FileSystem.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/ProfileUtils.h" #include "Json.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/OneSixVersionFormat.h" +#include "minecraft/ProfileUtils.h" +#include "ComponentUpdateTask.h" #include "PackProfile.h" #include "PackProfile_p.h" -#include "ComponentUpdateTask.h" #include "Application.h" #include "modplatform/ResourceAPI.h" -static const QMap modloaderMapping{ - {"net.minecraftforge", ResourceAPI::Forge}, - {"net.fabricmc.fabric-loader", ResourceAPI::Fabric}, - {"org.quiltmc.quilt-loader", ResourceAPI::Quilt}, - {"com.mumfrey.liteloader", ResourceAPI::LiteLoader} -}; +static const QMap modloaderMapping{ { "net.minecraftforge", ResourceAPI::Forge }, + { "net.fabricmc.fabric-loader", ResourceAPI::Fabric }, + { "org.quiltmc.quilt-loader", ResourceAPI::Quilt }, + { "com.mumfrey.liteloader", ResourceAPI::LiteLoader } }; -PackProfile::PackProfile(MinecraftInstance * instance) - : QAbstractListModel() +PackProfile::PackProfile(MinecraftInstance* instance) : QAbstractListModel() { d.reset(new PackProfileData); d->m_instance = instance; @@ -95,42 +92,35 @@ static QJsonObject componentToJsonV1(ComponentPtr component) QJsonObject obj; // critical obj.insert("uid", component->m_uid); - if(!component->m_version.isEmpty()) - { + if (!component->m_version.isEmpty()) { obj.insert("version", component->m_version); } - if(component->m_dependencyOnly) - { + if (component->m_dependencyOnly) { obj.insert("dependencyOnly", true); } - if(component->m_important) - { + if (component->m_important) { obj.insert("important", true); } - if(component->m_disabled) - { + if (component->m_disabled) { obj.insert("disabled", true); } // cached - if(!component->m_cachedVersion.isEmpty()) - { + if (!component->m_cachedVersion.isEmpty()) { obj.insert("cachedVersion", component->m_cachedVersion); } - if(!component->m_cachedName.isEmpty()) - { + if (!component->m_cachedName.isEmpty()) { obj.insert("cachedName", component->m_cachedName); } Meta::serializeRequires(obj, &component->m_cachedRequires, "cachedRequires"); Meta::serializeRequires(obj, &component->m_cachedConflicts, "cachedConflicts"); - if(component->m_cachedVolatile) - { + if (component->m_cachedVolatile) { obj.insert("cachedVolatile", true); } return obj; } -static ComponentPtr componentFromJsonV1(PackProfile * parent, const QString & componentJsonPattern, const QJsonObject &obj) +static ComponentPtr componentFromJsonV1(PackProfile* parent, const QString& componentJsonPattern, const QJsonObject& obj) { // critical auto uid = Json::requireString(obj.value("uid")); @@ -153,51 +143,44 @@ static ComponentPtr componentFromJsonV1(PackProfile * parent, const QString & co } // Save the given component container data to a file -static bool savePackProfile(const QString & filename, const ComponentContainer & container) +static bool savePackProfile(const QString& filename, const ComponentContainer& container) { QJsonObject obj; obj.insert("formatVersion", currentComponentsFileVersion); QJsonArray orderArray; - for(auto component: container) - { + for (auto component : container) { orderArray.append(componentToJsonV1(component)); } obj.insert("components", orderArray); QSaveFile outFile(filename); - if (!outFile.open(QFile::WriteOnly)) - { - qCritical() << "Couldn't open" << outFile.fileName() - << "for writing:" << outFile.errorString(); + if (!outFile.open(QFile::WriteOnly)) { + qCritical() << "Couldn't open" << outFile.fileName() << "for writing:" << outFile.errorString(); return false; } auto data = QJsonDocument(obj).toJson(QJsonDocument::Indented); - if(outFile.write(data) != data.size()) - { - qCritical() << "Couldn't write all the data into" << outFile.fileName() - << "because:" << outFile.errorString(); + if (outFile.write(data) != data.size()) { + qCritical() << "Couldn't write all the data into" << outFile.fileName() << "because:" << outFile.errorString(); return false; } - if(!outFile.commit()) - { - qCritical() << "Couldn't save" << outFile.fileName() - << "because:" << outFile.errorString(); + if (!outFile.commit()) { + qCritical() << "Couldn't save" << outFile.fileName() << "because:" << outFile.errorString(); } return true; } // Read the given file into component containers -static bool loadPackProfile(PackProfile * parent, const QString & filename, const QString & componentJsonPattern, ComponentContainer & container) +static bool loadPackProfile(PackProfile* parent, + const QString& filename, + const QString& componentJsonPattern, + ComponentContainer& container) { QFile componentsFile(filename); - if (!componentsFile.exists()) - { + if (!componentsFile.exists()) { qWarning() << "Components file doesn't exist. This should never happen."; return false; } - if (!componentsFile.open(QFile::ReadOnly)) - { - qCritical() << "Couldn't open" << componentsFile.fileName() - << " for reading:" << componentsFile.errorString(); + if (!componentsFile.open(QFile::ReadOnly)) { + qCritical() << "Couldn't open" << componentsFile.fileName() << " for reading:" << componentsFile.errorString(); qWarning() << "Ignoring overriden order"; return false; } @@ -205,33 +188,26 @@ static bool loadPackProfile(PackProfile * parent, const QString & filename, cons // and it's valid JSON QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(componentsFile.readAll(), &error); - if (error.error != QJsonParseError::NoError) - { + if (error.error != QJsonParseError::NoError) { qCritical() << "Couldn't parse" << componentsFile.fileName() << ":" << error.errorString(); qWarning() << "Ignoring overriden order"; return false; } // and then read it and process it if all above is true. - try - { + try { auto obj = Json::requireObject(doc); // check order file version. auto version = Json::requireInteger(obj.value("formatVersion")); - if (version != currentComponentsFileVersion) - { - throw JSONValidationError(QObject::tr("Invalid component file version, expected %1") - .arg(currentComponentsFileVersion)); + if (version != currentComponentsFileVersion) { + throw JSONValidationError(QObject::tr("Invalid component file version, expected %1").arg(currentComponentsFileVersion)); } auto orderArray = Json::requireArray(obj.value("components")); - for(auto item: orderArray) - { + for (auto item : orderArray) { auto comp_obj = Json::requireObject(item, "Component must be an object."); container.append(componentFromJsonV1(parent, componentJsonPattern, comp_obj)); } - } - catch ([[maybe_unused]] const JSONValidationError &err) - { + } catch ([[maybe_unused]] const JSONValidationError& err) { qCritical() << "Couldn't parse" << componentsFile.fileName() << ": bad file format"; container.clear(); return false; @@ -245,8 +221,7 @@ static bool loadPackProfile(PackProfile * parent, const QString & filename, cons void PackProfile::saveNow() { - if(saveIsScheduled()) - { + if (saveIsScheduled()) { d->m_saveTimer.stop(); save_internal(); } @@ -265,13 +240,11 @@ void PackProfile::buildingFromScratch() void PackProfile::scheduleSave() { - if(!d->loaded) - { + if (!d->loaded) { qDebug() << "Component list should never save if it didn't successfully load, instance:" << d->m_instance->name(); return; } - if(!d->dirty) - { + if (!d->dirty) { d->dirty = true; qDebug() << "Component list save is scheduled for" << d->m_instance->name(); } @@ -312,26 +285,20 @@ bool PackProfile::load() // load the new component list and swap it with the current one... ComponentContainer newComponents; - if(!loadPackProfile(this, filename, patchesPattern(), newComponents)) - { + if (!loadPackProfile(this, filename, patchesPattern(), newComponents)) { qCritical() << "Failed to load the component config for instance" << d->m_instance->name(); return false; - } - else - { + } else { // FIXME: actually use fine-grained updates, not this... beginResetModel(); // disconnect all the old components - for(auto component: d->components) - { + for (auto component : d->components) { disconnect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged); } d->components.clear(); d->componentIndex.clear(); - for(auto component: newComponents) - { - if(d->componentIndex.contains(component->m_uid)) - { + for (auto component : newComponents) { + if (d->componentIndex.contains(component->m_uid)) { qWarning() << "Ignoring duplicate component entry" << component->m_uid; continue; } @@ -348,8 +315,7 @@ bool PackProfile::load() void PackProfile::reload(Net::Mode netmode) { // Do not reload when the update/resolve task is running. It is in control. - if(d->m_updateTask) - { + if (d->m_updateTask) { return; } @@ -359,8 +325,7 @@ void PackProfile::reload(Net::Mode netmode) // FIXME: differentiate when a reapply is required by propagating state from components invalidateLaunchProfile(); - if(load()) - { + if (load()) { resolve(netmode); } } @@ -376,11 +341,10 @@ void PackProfile::resolve(Net::Mode netmode) d->m_updateTask.reset(updateTask); connect(updateTask, &ComponentUpdateTask::succeeded, this, &PackProfile::updateSucceeded); connect(updateTask, &ComponentUpdateTask::failed, this, &PackProfile::updateFailed); - connect(updateTask, &ComponentUpdateTask::aborted, this, [this]{ updateFailed(tr("Aborted")); }); + connect(updateTask, &ComponentUpdateTask::aborted, this, [this] { updateFailed(tr("Aborted")); }); d->m_updateTask->start(); } - void PackProfile::updateSucceeded() { qDebug() << "Component list update/resolve task succeeded for" << d->m_instance->name(); @@ -405,13 +369,11 @@ void PackProfile::appendComponent(ComponentPtr component) void PackProfile::insertComponent(size_t index, ComponentPtr component) { auto id = component->getID(); - if(id.isEmpty()) - { + if (id.isEmpty()) { qWarning() << "Attempt to add a component with empty ID!"; return; } - if(d->componentIndex.contains(id)) - { + if (d->componentIndex.contains(id)) { qWarning() << "Attempt to add a component that is already present!"; return; } @@ -425,21 +387,18 @@ void PackProfile::insertComponent(size_t index, ComponentPtr component) void PackProfile::componentDataChanged() { - auto objPtr = qobject_cast(sender()); - if(!objPtr) - { + auto objPtr = qobject_cast(sender()); + if (!objPtr) { qWarning() << "PackProfile got dataChanged signal from a non-Component!"; return; } - if(objPtr->getID() == "net.minecraft") { + if (objPtr->getID() == "net.minecraft") { emit minecraftChanged(); } // figure out which one is it... in a seriously dumb way. int index = 0; - for (auto component: d->components) - { - if(component.get() == objPtr) - { + for (auto component : d->components) { + if (component.get() == objPtr) { emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1)); scheduleSave(); return; @@ -452,14 +411,12 @@ void PackProfile::componentDataChanged() bool PackProfile::remove(const int index) { auto patch = getComponent(index); - if (!patch->isRemovable()) - { + if (!patch->isRemovable()) { qWarning() << "Patch" << patch->getID() << "is non-removable"; return false; } - if(!removeComponent_internal(patch)) - { + if (!removeComponent_internal(patch)) { qCritical() << "Patch" << patch->getID() << "could not be removed"; return false; } @@ -476,10 +433,8 @@ bool PackProfile::remove(const int index) bool PackProfile::remove(const QString id) { int i = 0; - for (auto patch : d->components) - { - if (patch->getID() == id) - { + for (auto patch : d->components) { + if (patch->getID() == id) { return remove(i); } i++; @@ -490,13 +445,11 @@ bool PackProfile::remove(const QString id) bool PackProfile::customize(int index) { auto patch = getComponent(index); - if (!patch->isCustomizable()) - { + if (!patch->isCustomizable()) { qDebug() << "Patch" << patch->getID() << "is not customizable"; return false; } - if(!patch->customize()) - { + if (!patch->customize()) { qCritical() << "Patch" << patch->getID() << "could not be customized"; return false; } @@ -508,13 +461,11 @@ bool PackProfile::customize(int index) bool PackProfile::revertToBase(int index) { auto patch = getComponent(index); - if (!patch->isRevertible()) - { + if (!patch->isRevertible()) { qDebug() << "Patch" << patch->getID() << "is not revertible"; return false; } - if(!patch->revert()) - { + if (!patch->revert()) { qCritical() << "Patch" << patch->getID() << "could not be reverted"; return false; } @@ -523,11 +474,10 @@ bool PackProfile::revertToBase(int index) return true; } -ComponentPtr PackProfile::getComponent(const QString &id) +ComponentPtr PackProfile::getComponent(const QString& id) { auto iter = d->componentIndex.find(id); - if (iter == d->componentIndex.end()) - { + if (iter == d->componentIndex.end()) { return nullptr; } return (*iter); @@ -535,14 +485,13 @@ ComponentPtr PackProfile::getComponent(const QString &id) ComponentPtr PackProfile::getComponent(size_t index) { - if(index >= static_cast(d->components.size())) - { + if (index >= static_cast(d->components.size())) { return nullptr; } return d->components[index]; } -QVariant PackProfile::data(const QModelIndex &index, int role) const +QVariant PackProfile::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); @@ -555,72 +504,58 @@ QVariant PackProfile::data(const QModelIndex &index, int role) const auto patch = d->components.at(row); - switch (role) - { - case Qt::CheckStateRole: - { - switch (column) - { - case NameColumn: { - return patch->isEnabled() ? Qt::Checked : Qt::Unchecked; - } - default: - return QVariant(); - } - } - case Qt::DisplayRole: - { - switch (column) - { - case NameColumn: - return patch->getName(); - case VersionColumn: - { - if(patch->isCustom()) - { - return QString("%1 (Custom)").arg(patch->getVersion()); - } - else - { - return patch->getVersion(); - } - } - default: - return QVariant(); - } - } - case Qt::DecorationRole: - { - if (column == NameColumn) { - auto severity = patch->getProblemSeverity(); - switch (severity) - { - case ProblemSeverity::Warning: - return "warning"; - case ProblemSeverity::Error: - return "error"; + switch (role) { + case Qt::CheckStateRole: { + switch (column) { + case NameColumn: { + return patch->isEnabled() ? Qt::Checked : Qt::Unchecked; + } default: return QVariant(); } } - return QVariant(); - } + case Qt::DisplayRole: { + switch (column) { + case NameColumn: + return patch->getName(); + case VersionColumn: { + if (patch->isCustom()) { + return QString("%1 (Custom)").arg(patch->getVersion()); + } else { + return patch->getVersion(); + } + } + default: + return QVariant(); + } + } + case Qt::DecorationRole: { + if (column == NameColumn) { + auto severity = patch->getProblemSeverity(); + switch (severity) { + case ProblemSeverity::Warning: + return "warning"; + case ProblemSeverity::Error: + return "error"; + default: + return QVariant(); + } + } + return QVariant(); + } } return QVariant(); } bool PackProfile::setData(const QModelIndex& index, [[maybe_unused]] const QVariant& value, int role) { - if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index.parent())) - { + if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index.parent())) { return false; } - if (role == Qt::CheckStateRole) - { + if (role == Qt::CheckStateRole) { auto component = d->components[index.row()]; - if (component->setEnabled(!component->isEnabled())) - { + if (component->setEnabled(!component->isEnabled())) { return true; } } @@ -629,18 +564,15 @@ bool PackProfile::setData(const QModelIndex& index, [[maybe_unused]] const QVari QVariant PackProfile::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation == Qt::Horizontal) - { - if (role == Qt::DisplayRole) - { - switch (section) - { - case NameColumn: - return tr("Name"); - case VersionColumn: - return tr("Version"); - default: - return QVariant(); + if (orientation == Qt::Horizontal) { + if (role == Qt::DisplayRole) { + switch (section) { + case NameColumn: + return tr("Name"); + case VersionColumn: + return tr("Version"); + default: + return QVariant(); } } } @@ -648,7 +580,7 @@ QVariant PackProfile::headerData(int section, Qt::Orientation orientation, int r } // FIXME: zero precision mess -Qt::ItemFlags PackProfile::flags(const QModelIndex &index) const +Qt::ItemFlags PackProfile::flags(const QModelIndex& index) const { if (!index.isValid()) { return Qt::NoItemFlags; @@ -664,19 +596,18 @@ Qt::ItemFlags PackProfile::flags(const QModelIndex &index) const auto patch = d->components.at(row); // TODO: this will need fine-tuning later... - if(patch->canBeDisabled() && !d->interactionDisabled) - { + if (patch->canBeDisabled() && !d->interactionDisabled) { outFlags |= Qt::ItemIsUserCheckable; } return outFlags; } -int PackProfile::rowCount(const QModelIndex &parent) const +int PackProfile::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : d->components.size(); } -int PackProfile::columnCount(const QModelIndex &parent) const +int PackProfile::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : NUM_COLUMNS; } @@ -684,12 +615,9 @@ int PackProfile::columnCount(const QModelIndex &parent) const void PackProfile::move(const int index, const MoveDirection direction) { int theirIndex; - if (direction == MoveUp) - { + if (direction == MoveUp) { theirIndex = index - 1; - } - else - { + } else { theirIndex = index + 1; } @@ -706,8 +634,7 @@ void PackProfile::move(const int index, const MoveDirection direction) auto from = getComponent(index); auto to = getComponent(theirIndex); - if (!from || !to || !to->isMoveable() || !from->isMoveable()) - { + if (!from || !to || !to->isMoveable() || !from->isMoveable()) { return; } beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap); @@ -775,8 +702,7 @@ void PackProfile::installAgents(QStringList selectedFiles) bool PackProfile::installEmpty(const QString& uid, const QString& name) { QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches"); - if(!FS::ensureFolderPathExists(patchDir)) - { + if (!FS::ensureFolderPathExists(patchDir)) { return false; } auto f = std::make_shared(); @@ -785,10 +711,8 @@ bool PackProfile::installEmpty(const QString& uid, const QString& name) f->version = "1"; QString patchFileName = FS::PathCombine(patchDir, uid + ".json"); QFile file(patchFileName); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); + if (!file.open(QFile::WriteOnly)) { + qCritical() << "Error opening" << file.fileName() << "for reading:" << file.errorString(); return false; } file.write(OneSixVersionFormat::versionFileToJson(f).toJson()); @@ -805,31 +729,25 @@ bool PackProfile::removeComponent_internal(ComponentPtr patch) bool ok = true; // first, remove the patch file. this ensures it's not used anymore auto fileName = patch->getFilename(); - if(fileName.size()) - { + if (fileName.size()) { QFile patchFile(fileName); - if(patchFile.exists() && !patchFile.remove()) - { + if (patchFile.exists() && !patchFile.remove()) { qCritical() << "File" << fileName << "could not be removed because:" << patchFile.errorString(); return false; } } // FIXME: we need a generic way of removing local resources, not just jar mods... - auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool - { - if (!jarMod->isLocal()) - { + auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool { + if (!jarMod->isLocal()) { return true; } QStringList jar, temp1, temp2, temp3; jarMod->getApplicableFiles(d->m_instance->runtimeContext(), jar, temp1, temp2, temp3, d->m_instance->jarmodsPath().absolutePath()); - QFileInfo finfo (jar[0]); - if(finfo.exists()) - { + QFileInfo finfo(jar[0]); + if (finfo.exists()) { QFile jarModFile(jar[0]); - if(!jarModFile.remove()) - { + if (!jarModFile.remove()) { qCritical() << "File" << jar[0] << "could not be removed because:" << jarModFile.errorString(); return false; } @@ -839,11 +757,9 @@ bool PackProfile::removeComponent_internal(ComponentPtr patch) }; auto vFile = patch->getVersionFile(); - if(vFile) - { - auto &jarMods = vFile->jarMods; - for(auto &jarmod: jarMods) - { + if (vFile) { + auto& jarMods = vFile->jarMods; + for (auto& jarmod : jarMods) { ok &= preRemoveJarMod(jarmod); } } @@ -853,18 +769,15 @@ bool PackProfile::removeComponent_internal(ComponentPtr patch) bool PackProfile::installJarMods_internal(QStringList filepaths) { QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches"); - if(!FS::ensureFolderPathExists(patchDir)) - { + if (!FS::ensureFolderPathExists(patchDir)) { return false; } - if (!FS::ensureFolderPathExists(d->m_instance->jarModsDir())) - { + if (!FS::ensureFolderPathExists(d->m_instance->jarModsDir())) { return false; } - for(auto filepath:filepaths) - { + for (auto filepath : filepaths) { QFileInfo sourceInfo(filepath); QString id = QUuid::createUuid().toString(QUuid::WithoutBraces); QString target_filename = id + ".jar"; @@ -875,8 +788,7 @@ bool PackProfile::installJarMods_internal(QStringList filepaths) QFileInfo targetInfo(finalPath); Q_ASSERT(!targetInfo.exists()); - if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath())) - { + if (!QFile::copy(sourceInfo.absoluteFilePath(), QFileInfo(finalPath).absoluteFilePath())) { return false; } @@ -892,10 +804,8 @@ bool PackProfile::installJarMods_internal(QStringList filepaths) QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); QFile file(patchFileName); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); + if (!file.open(QFile::WriteOnly)) { + qCritical() << "Error opening" << file.fileName() << "for reading:" << file.errorString(); return false; } file.write(OneSixVersionFormat::versionFileToJson(f).toJson()); @@ -911,14 +821,12 @@ bool PackProfile::installJarMods_internal(QStringList filepaths) bool PackProfile::installCustomJar_internal(QString filepath) { QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches"); - if(!FS::ensureFolderPathExists(patchDir)) - { + if (!FS::ensureFolderPathExists(patchDir)) { return false; } QString libDir = d->m_instance->getLocalLibraryPath(); - if (!FS::ensureFolderPathExists(libDir)) - { + if (!FS::ensureFolderPathExists(libDir)) { return false; } @@ -930,15 +838,12 @@ bool PackProfile::installCustomJar_internal(QString filepath) QString finalPath = FS::PathCombine(libDir, target_filename); QFileInfo jarInfo(finalPath); - if (jarInfo.exists()) - { - if(!QFile::remove(finalPath)) - { + if (jarInfo.exists()) { + if (!QFile::remove(finalPath)) { return false; } } - if (!QFile::copy(filepath, finalPath)) - { + if (!QFile::copy(filepath, finalPath)) { return false; } @@ -953,10 +858,8 @@ bool PackProfile::installCustomJar_internal(QString filepath) QString patchFileName = FS::PathCombine(patchDir, target_id + ".json"); QFile file(patchFileName); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); + if (!file.open(QFile::WriteOnly)) { + qCritical() << "Error opening" << file.fileName() << "for reading:" << file.errorString(); return false; } file.write(OneSixVersionFormat::versionFileToJson(f).toJson()); @@ -1029,20 +932,15 @@ bool PackProfile::installAgents_internal(QStringList filepaths) std::shared_ptr PackProfile::getProfile() const { - if(!d->m_profile) - { - try - { + if (!d->m_profile) { + try { auto profile = std::make_shared(); - for(auto file: d->components) - { + for (auto file : d->components) { qDebug() << "Applying" << file->getID() << (file->getProblemSeverity() == ProblemSeverity::Error ? "ERROR" : "GOOD"); file->applyTo(profile.get()); } d->m_profile = profile; - } - catch (const Exception &error) - { + } catch (const Exception& error) { qWarning() << "Couldn't apply profile patches because: " << error.cause(); } } @@ -1052,20 +950,16 @@ std::shared_ptr PackProfile::getProfile() const bool PackProfile::setComponentVersion(const QString& uid, const QString& version, bool important) { auto iter = d->componentIndex.find(uid); - if(iter != d->componentIndex.end()) - { + if (iter != d->componentIndex.end()) { ComponentPtr component = *iter; // set existing - if(component->revert()) - { + if (component->revert()) { component->setVersion(version); component->setImportant(important); return true; } return false; - } - else - { + } else { // add new auto component = makeShared(this, uid); component->m_version = version; @@ -1078,8 +972,7 @@ bool PackProfile::setComponentVersion(const QString& uid, const QString& version QString PackProfile::getComponentVersion(const QString& uid) const { const auto iter = d->componentIndex.find(uid); - if (iter != d->componentIndex.end()) - { + if (iter != d->componentIndex.end()) { return (*iter)->getVersion(); } return QString(); @@ -1087,10 +980,10 @@ QString PackProfile::getComponentVersion(const QString& uid) const void PackProfile::disableInteraction(bool disable) { - if(d->interactionDisabled != disable) { + if (d->interactionDisabled != disable) { d->interactionDisabled = disable; auto size = d->components.size(); - if(size) { + if (size) { emit dataChanged(index(0), index(size - 1)); } } diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h index 06741c2d7..ce44fa588 100644 --- a/launcher/minecraft/PackProfile.h +++ b/launcher/minecraft/PackProfile.h @@ -41,44 +41,39 @@ #include -#include #include +#include #include -#include "Library.h" -#include "LaunchProfile.h" -#include "Component.h" -#include "ProfileUtils.h" #include "BaseVersion.h" +#include "Component.h" +#include "LaunchProfile.h" +#include "Library.h" #include "MojangDownloadInfo.h" -#include "net/Mode.h" +#include "ProfileUtils.h" #include "modplatform/ResourceAPI.h" +#include "net/Mode.h" class MinecraftInstance; struct PackProfileData; class ComponentUpdateTask; -class PackProfile : public QAbstractListModel -{ +class PackProfile : public QAbstractListModel { Q_OBJECT friend ComponentUpdateTask; -public: - enum Columns - { - NameColumn = 0, - VersionColumn, - NUM_COLUMNS - }; - explicit PackProfile(MinecraftInstance * instance); + public: + enum Columns { NameColumn = 0, VersionColumn, NUM_COLUMNS }; + + explicit PackProfile(MinecraftInstance* instance); virtual ~PackProfile(); - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex &parent) const override; - virtual Qt::ItemFlags flags(const QModelIndex &index) const override; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex& parent) const override; + virtual Qt::ItemFlags flags(const QModelIndex& index) const override; /// call this to explicitly mark the component list as loaded - this is used to build a new component list from scratch. void buildingFromScratch(); @@ -121,15 +116,15 @@ public: std::shared_ptr getProfile() const; // NOTE: used ONLY by MinecraftInstance to provide legacy version mappings from instance config - void setOldConfigVersion(const QString &uid, const QString &version); + void setOldConfigVersion(const QString& uid, const QString& version); - QString getComponentVersion(const QString &uid) const; + QString getComponentVersion(const QString& uid) const; - bool setComponentVersion(const QString &uid, const QString &version, bool important = false); + bool setComponentVersion(const QString& uid, const QString& version, bool important = false); - bool installEmpty(const QString &uid, const QString &name); + bool installEmpty(const QString& uid, const QString& name); - QString patchFilePathForUid(const QString &uid) const; + QString patchFilePathForUid(const QString& uid) const; /// if there is a save scheduled, do it now. void saveNow(); @@ -137,12 +132,12 @@ public: /// helper method, returns RuntimeContext of instance RuntimeContext runtimeContext(); -signals: + signals: void minecraftChanged(); -public: + public: /// get the profile component by id - ComponentPtr getComponent(const QString &id); + ComponentPtr getComponent(const QString& id); /// get the profile component by index ComponentPtr getComponent(size_t index); @@ -153,7 +148,7 @@ public: std::optional getModLoaders(); -private: + private: void scheduleSave(); bool saveIsScheduled() const; @@ -166,21 +161,20 @@ private: QString componentsFilePath() const; QString patchesPattern() const; -private slots: + private slots: void save_internal(); void updateSucceeded(); - void updateFailed(const QString & error); + void updateFailed(const QString& error); void componentDataChanged(); void disableInteraction(bool disable); -private: + private: bool load(); bool installJarMods_internal(QStringList filepaths); bool installCustomJar_internal(QString filepath); bool installAgents_internal(QStringList filepaths); bool removeComponent_internal(ComponentPtr patch); -private: /* data */ - + private: /* data */ std::unique_ptr d; }; diff --git a/launcher/minecraft/PackProfile_p.h b/launcher/minecraft/PackProfile_p.h index 715e04606..0cd4fb839 100644 --- a/launcher/minecraft/PackProfile_p.h +++ b/launcher/minecraft/PackProfile_p.h @@ -1,19 +1,18 @@ #pragma once -#include "Component.h" -#include -#include #include #include +#include +#include +#include "Component.h" class MinecraftInstance; using ComponentContainer = QList; using ComponentIndex = QMap; -struct PackProfileData -{ +struct PackProfileData { // the instance this belongs to - MinecraftInstance *m_instance; + MinecraftInstance* m_instance; // the launch profile (volatile, temporary thing created on demand) std::shared_ptr m_profile; @@ -27,4 +26,3 @@ struct PackProfileData bool loaded = false; bool interactionDisabled = true; }; - diff --git a/launcher/minecraft/ParseUtils.cpp b/launcher/minecraft/ParseUtils.cpp index c9640e776..fabc57a65 100644 --- a/launcher/minecraft/ParseUtils.cpp +++ b/launcher/minecraft/ParseUtils.cpp @@ -1,7 +1,7 @@ -#include -#include #include "ParseUtils.h" +#include #include +#include #include QDateTime timeFromS3Time(QString str) @@ -22,7 +22,7 @@ QString timeToS3Time(QDateTime time) int offsetMinutes = offsetAbs % 3600; offsetAbs -= offsetMinutes; offsetMinutes /= 60; - + int offsetHours = offsetAbs / 3600; QString raw = time.toString("yyyy-MM-ddTHH:mm:ss"); diff --git a/launcher/minecraft/ParseUtils.h b/launcher/minecraft/ParseUtils.h index aad82748d..c81d8f8bb 100644 --- a/launcher/minecraft/ParseUtils.h +++ b/launcher/minecraft/ParseUtils.h @@ -1,6 +1,6 @@ #pragma once -#include #include +#include /// take the timestamp used by S3 and turn it into QDateTime QDateTime timeFromS3Time(QString str); diff --git a/launcher/minecraft/ProfileUtils.cpp b/launcher/minecraft/ProfileUtils.cpp index 145570039..5b2fd090e 100644 --- a/launcher/minecraft/ProfileUtils.cpp +++ b/launcher/minecraft/ProfileUtils.cpp @@ -34,33 +34,29 @@ */ #include "ProfileUtils.h" -#include "minecraft/VersionFilterData.h" -#include "minecraft/OneSixVersionFormat.h" -#include "Json.h" #include +#include "Json.h" +#include "minecraft/OneSixVersionFormat.h" +#include "minecraft/VersionFilterData.h" -#include #include +#include #include #include -namespace ProfileUtils -{ +namespace ProfileUtils { static const int currentOrderFileVersion = 1; -bool readOverrideOrders(QString path, PatchOrder &order) +bool readOverrideOrders(QString path, PatchOrder& order) { QFile orderFile(path); - if (!orderFile.exists()) - { + if (!orderFile.exists()) { qWarning() << "Order file doesn't exist. Ignoring."; return false; } - if (!orderFile.open(QFile::ReadOnly)) - { - qCritical() << "Couldn't open" << orderFile.fileName() - << " for reading:" << orderFile.errorString(); + if (!orderFile.open(QFile::ReadOnly)) { + qCritical() << "Couldn't open" << orderFile.fileName() << " for reading:" << orderFile.errorString(); qWarning() << "Ignoring overriden order"; return false; } @@ -68,32 +64,25 @@ bool readOverrideOrders(QString path, PatchOrder &order) // and it's valid JSON QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error); - if (error.error != QJsonParseError::NoError) - { + if (error.error != QJsonParseError::NoError) { qCritical() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString(); qWarning() << "Ignoring overriden order"; return false; } // and then read it and process it if all above is true. - try - { + try { auto obj = Json::requireObject(doc); // check order file version. auto version = Json::requireInteger(obj.value("version")); - if (version != currentOrderFileVersion) - { - throw JSONValidationError(QObject::tr("Invalid order file version, expected %1") - .arg(currentOrderFileVersion)); + if (version != currentOrderFileVersion) { + throw JSONValidationError(QObject::tr("Invalid order file version, expected %1").arg(currentOrderFileVersion)); } auto orderArray = Json::requireArray(obj.value("order")); - for(auto item: orderArray) - { + for (auto item : orderArray) { order.append(Json::requireString(item)); } - } - catch ([[maybe_unused]] const JSONValidationError &err) - { + } catch ([[maybe_unused]] const JSONValidationError& err) { qCritical() << "Couldn't parse" << orderFile.fileName() << ": bad file format"; qWarning() << "Ignoring overriden order"; order.clear(); @@ -111,23 +100,19 @@ static VersionFilePtr createErrorVersionFile(QString fileId, QString filepath, Q return outError; } -static VersionFilePtr guardedParseJson(const QJsonDocument & doc,const QString &fileId,const QString &filepath,const bool &requireOrder) +static VersionFilePtr guardedParseJson(const QJsonDocument& doc, const QString& fileId, const QString& filepath, const bool& requireOrder) { - try - { + try { return OneSixVersionFormat::versionFileFromJson(doc, filepath, requireOrder); - } - catch (const Exception &e) - { + } catch (const Exception& e) { return createErrorVersionFile(fileId, filepath, e.cause()); } } -VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder) +VersionFilePtr parseJsonFile(const QFileInfo& fileInfo, const bool requireOrder) { QFile file(fileInfo.absoluteFilePath()); - if (!file.open(QFile::ReadOnly)) - { + if (!file.open(QFile::ReadOnly)) { auto errorStr = QObject::tr("Unable to open the version file %1: %2.").arg(fileInfo.fileName(), file.errorString()); return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr); } @@ -135,14 +120,11 @@ VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder) auto data = file.readAll(); QJsonDocument doc = QJsonDocument::fromJson(data, &error); file.close(); - if (error.error != QJsonParseError::NoError) - { + if (error.error != QJsonParseError::NoError) { int line = 1; int column = 0; - for(int i = 0; i < error.offset; i++) - { - if(data[i] == '\n') - { + for (int i = 0; i < error.offset; i++) { + if (data[i] == '\n') { line++; column = 0; continue; @@ -150,26 +132,25 @@ VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder) column++; } auto errorStr = QObject::tr("Unable to process the version file %1: %2 at line %3 column %4.") - .arg(fileInfo.fileName(), error.errorString()) - .arg(line).arg(column); + .arg(fileInfo.fileName(), error.errorString()) + .arg(line) + .arg(column); return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr); } return guardedParseJson(doc, fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), requireOrder); } -bool saveJsonFile(const QJsonDocument doc, const QString & filename) +bool saveJsonFile(const QJsonDocument doc, const QString& filename) { auto data = doc.toJson(); QSaveFile jsonFile(filename); - if(!jsonFile.open(QIODevice::WriteOnly)) - { + if (!jsonFile.open(QIODevice::WriteOnly)) { jsonFile.cancelWriting(); qWarning() << "Couldn't open" << filename << "for writing"; return false; } jsonFile.write(data); - if(!jsonFile.commit()) - { + if (!jsonFile.commit()) { qWarning() << "Couldn't save" << filename; return false; } @@ -178,13 +159,10 @@ bool saveJsonFile(const QJsonDocument doc, const QString & filename) void removeLwjglFromPatch(VersionFilePtr patch) { - auto filter = [](QList& libs) - { + auto filter = [](QList& libs) { QList filteredLibs; - for (auto lib : libs) - { - if (!g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix())) - { + for (auto lib : libs) { + if (!g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix())) { filteredLibs.append(lib); } } @@ -192,4 +170,4 @@ void removeLwjglFromPatch(VersionFilePtr patch) }; filter(patch->libraries); } -} +} // namespace ProfileUtils diff --git a/launcher/minecraft/ProfileUtils.h b/launcher/minecraft/ProfileUtils.h index 5b938784c..93cc3da07 100644 --- a/launcher/minecraft/ProfileUtils.h +++ b/launcher/minecraft/ProfileUtils.h @@ -37,24 +37,22 @@ #include "Library.h" #include "VersionFile.h" -namespace ProfileUtils -{ +namespace ProfileUtils { typedef QStringList PatchOrder; /// Read and parse a OneSix format order file -bool readOverrideOrders(QString path, PatchOrder &order); +bool readOverrideOrders(QString path, PatchOrder& order); /// Write a OneSix format order file -bool writeOverrideOrders(QString path, const PatchOrder &order); - +bool writeOverrideOrders(QString path, const PatchOrder& order); /// Parse a version file in JSON format -VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder); +VersionFilePtr parseJsonFile(const QFileInfo& fileInfo, const bool requireOrder); /// Save a JSON file (in any format) -bool saveJsonFile(const QJsonDocument doc, const QString & filename); +bool saveJsonFile(const QJsonDocument doc, const QString& filename); /// Remove LWJGL from a patch file. This is applied to all Mojang-like profile files. void removeLwjglFromPatch(VersionFilePtr patch); -} +} // namespace ProfileUtils diff --git a/launcher/minecraft/Rule.cpp b/launcher/minecraft/Rule.cpp index ff3d75f2e..74c12a0d2 100644 --- a/launcher/minecraft/Rule.cpp +++ b/launcher/minecraft/Rule.cpp @@ -33,8 +33,8 @@ * limitations under the License. */ -#include #include +#include #include "Rule.h" @@ -47,7 +47,7 @@ RuleAction RuleAction_fromString(QString name) return Defer; } -QList> rulesFromJsonV4(const QJsonObject &objectWithRules) +QList> rulesFromJsonV4(const QJsonObject& objectWithRules) { QList> rules; auto rulesVal = objectWithRules.value("rules"); @@ -55,8 +55,7 @@ QList> rulesFromJsonV4(const QJsonObject &objectWithRules) return rules; QJsonArray ruleList = rulesVal.toArray(); - for (auto ruleVal : ruleList) - { + for (auto ruleVal : ruleList) { std::shared_ptr rule; if (!ruleVal.isObject()) continue; @@ -69,8 +68,7 @@ QList> rulesFromJsonV4(const QJsonObject &objectWithRules) continue; auto osVal = ruleObj.value("os"); - if (!osVal.isObject()) - { + if (!osVal.isObject()) { // add a new implicit action rule rules.append(ImplicitRule::create(action)); continue; @@ -102,12 +100,10 @@ QJsonObject OsRule::toJson() QJsonObject osObj; { osObj.insert("name", m_system); - if(!m_version_regexp.isEmpty()) - { + if (!m_version_regexp.isEmpty()) { osObj.insert("version", m_version_regexp); } } ruleObj.insert("os", osObj); return ruleObj; } - diff --git a/launcher/minecraft/Rule.h b/launcher/minecraft/Rule.h index 70fd70b68..b1bf0eac7 100644 --- a/launcher/minecraft/Rule.h +++ b/launcher/minecraft/Rule.h @@ -35,37 +35,29 @@ #pragma once -#include -#include #include +#include +#include #include #include "RuntimeContext.h" class Library; class Rule; -enum RuleAction -{ - Allow, - Disallow, - Defer -}; +enum RuleAction { Allow, Disallow, Defer }; -QList> rulesFromJsonV4(const QJsonObject &objectWithRules); +QList> rulesFromJsonV4(const QJsonObject& objectWithRules); -class Rule -{ -protected: +class Rule { + protected: RuleAction m_result; - virtual bool applies(const Library *parent, const RuntimeContext & runtimeContext) = 0; + virtual bool applies(const Library* parent, const RuntimeContext& runtimeContext) = 0; -public: - Rule(RuleAction result) : m_result(result) - { - } + public: + Rule(RuleAction result) : m_result(result) {} virtual ~Rule() {} virtual QJsonObject toJson() = 0; - RuleAction apply(const Library *parent, const RuntimeContext & runtimeContext) + RuleAction apply(const Library* parent, const RuntimeContext& runtimeContext) { if (applies(parent, runtimeContext)) return m_result; @@ -74,48 +66,31 @@ public: } }; -class OsRule : public Rule -{ -private: +class OsRule : public Rule { + private: // the OS QString m_system; // the OS version regexp QString m_version_regexp; -protected: - virtual bool applies(const Library *, const RuntimeContext & runtimeContext) - { - return runtimeContext.classifierMatches(m_system); - } - OsRule(RuleAction result, QString system, QString version_regexp) - : Rule(result), m_system(system), m_version_regexp(version_regexp) - { - } + protected: + virtual bool applies(const Library*, const RuntimeContext& runtimeContext) { return runtimeContext.classifierMatches(m_system); } + OsRule(RuleAction result, QString system, QString version_regexp) : Rule(result), m_system(system), m_version_regexp(version_regexp) {} -public: + public: virtual QJsonObject toJson(); - static std::shared_ptr create(RuleAction result, QString system, - QString version_regexp) + static std::shared_ptr create(RuleAction result, QString system, QString version_regexp) { return std::shared_ptr(new OsRule(result, system, version_regexp)); } }; -class ImplicitRule : public Rule -{ -protected: - virtual bool applies(const Library *, [[maybe_unused]] const RuntimeContext & runtimeContext) - { - return true; - } - ImplicitRule(RuleAction result) : Rule(result) - { - } +class ImplicitRule : public Rule { + protected: + virtual bool applies(const Library*, [[maybe_unused]] const RuntimeContext& runtimeContext) { return true; } + ImplicitRule(RuleAction result) : Rule(result) {} -public: + public: virtual QJsonObject toJson(); - static std::shared_ptr create(RuleAction result) - { - return std::shared_ptr(new ImplicitRule(result)); - } + static std::shared_ptr create(RuleAction result) { return std::shared_ptr(new ImplicitRule(result)); } }; diff --git a/launcher/minecraft/VanillaInstanceCreationTask.cpp b/launcher/minecraft/VanillaInstanceCreationTask.cpp index 0bb92e876..ccbd8c677 100644 --- a/launcher/minecraft/VanillaInstanceCreationTask.cpp +++ b/launcher/minecraft/VanillaInstanceCreationTask.cpp @@ -8,7 +8,11 @@ #include "settings/INISettingsObject.h" VanillaCreationTask::VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version) - : InstanceCreationTask(), m_version(std::move(version)), m_using_loader(true), m_loader(std::move(loader)), m_loader_version(std::move(loader_version)) + : InstanceCreationTask() + , m_version(std::move(version)) + , m_using_loader(true) + , m_loader(std::move(loader)) + , m_loader_version(std::move(loader_version)) {} bool VanillaCreationTask::createInstance() @@ -22,7 +26,7 @@ bool VanillaCreationTask::createInstance() auto components = inst.getPackProfile(); components->buildingFromScratch(); components->setComponentVersion("net.minecraft", m_version->descriptor(), true); - if(m_using_loader) + if (m_using_loader) components->setComponentVersion(m_loader, m_loader_version->descriptor()); inst.setName(name()); diff --git a/launcher/minecraft/VersionFile.cpp b/launcher/minecraft/VersionFile.cpp index 76f41600f..b8aaee90f 100644 --- a/launcher/minecraft/VersionFile.cpp +++ b/launcher/minecraft/VersionFile.cpp @@ -39,23 +39,22 @@ #include -#include "minecraft/VersionFile.h" +#include "ParseUtils.h" #include "minecraft/Library.h" #include "minecraft/PackProfile.h" -#include "ParseUtils.h" +#include "minecraft/VersionFile.h" #include -static bool isMinecraftVersion(const QString &uid) +static bool isMinecraftVersion(const QString& uid) { return uid == "net.minecraft"; } -void VersionFile::applyTo(LaunchProfile *profile, const RuntimeContext & runtimeContext) +void VersionFile::applyTo(LaunchProfile* profile, const RuntimeContext& runtimeContext) { // Only real Minecraft can set those. Don't let anything override them. - if (isMinecraftVersion(uid)) - { + if (isMinecraftVersion(uid)) { profile->applyMinecraftVersion(version); profile->applyMinecraftVersionType(type); // HACK: ignore assets from other version files than Minecraft @@ -75,16 +74,13 @@ void VersionFile::applyTo(LaunchProfile *profile, const RuntimeContext & runtime profile->applyTraits(traits); profile->applyCompatibleJavaMajors(compatibleJavaMajors); - for (auto library : libraries) - { + for (auto library : libraries) { profile->applyLibrary(library, runtimeContext); } - for (auto mavenFile : mavenFiles) - { + for (auto mavenFile : mavenFiles) { profile->applyMavenFile(mavenFile, runtimeContext); } - for (auto agent : agents) - { + for (auto agent : agents) { profile->applyAgent(agent, runtimeContext); } profile->applyProblemSeverity(getProblemSeverity()); diff --git a/launcher/minecraft/VersionFile.h b/launcher/minecraft/VersionFile.h index 8e9dd1670..d8984a29e 100644 --- a/launcher/minecraft/VersionFile.h +++ b/launcher/minecraft/VersionFile.h @@ -35,17 +35,17 @@ #pragma once -#include -#include #include #include +#include +#include -#include -#include "minecraft/Rule.h" -#include "ProblemProvider.h" -#include "Library.h" -#include "Agent.h" #include +#include +#include "Agent.h" +#include "Library.h" +#include "ProblemProvider.h" +#include "minecraft/Rule.h" class PackProfile; class VersionFile; @@ -54,14 +54,14 @@ struct MojangDownloadInfo; struct MojangAssetIndexInfo; using VersionFilePtr = std::shared_ptr; -class VersionFile : public ProblemContainer -{ +class VersionFile : public ProblemContainer { friend class MojangVersionFormat; friend class OneSixVersionFormat; -public: /* methods */ - void applyTo(LaunchProfile* profile, const RuntimeContext & runtimeContext); -public: /* data */ + public: /* methods */ + void applyTo(LaunchProfile* profile, const RuntimeContext& runtimeContext); + + public: /* data */ /// Prism Launcher: order hint for this version file if no explicit order is set int order = 0; @@ -149,11 +149,10 @@ public: /* data */ /// is volatile -- may be removed as soon as it is no longer needed by something else bool m_volatile = false; -public: + public: // Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more. - QMap > mojangDownloads; + QMap> mojangDownloads; // Mojang: extended asset index download information std::shared_ptr mojangAssetIndex; }; - diff --git a/launcher/minecraft/VersionFilterData.cpp b/launcher/minecraft/VersionFilterData.cpp index c286d2662..3924e598f 100644 --- a/launcher/minecraft/VersionFilterData.cpp +++ b/launcher/minecraft/VersionFilterData.cpp @@ -6,19 +6,17 @@ VersionFilterData g_VersionFilterData = VersionFilterData(); VersionFilterData::VersionFilterData() { // 1.3.* - auto libs13 = - QList{{"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b"}, - {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f"}, - {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82"}}; + auto libs13 = QList{ { "argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b" }, + { "guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f" }, + { "asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82" } }; fmlLibsMapping["1.3.2"] = libs13; // 1.4.* - auto libs14 = QList{ - {"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b"}, - {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f"}, - {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82"}, - {"bcprov-jdk15on-147.jar", "b6f5d9926b0afbde9f4dbe3db88c5247be7794bb"}}; + auto libs14 = QList{ { "argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b" }, + { "guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f" }, + { "asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82" }, + { "bcprov-jdk15on-147.jar", "b6f5d9926b0afbde9f4dbe3db88c5247be7794bb" } }; fmlLibsMapping["1.4"] = libs14; fmlLibsMapping["1.4.1"] = libs14; @@ -30,43 +28,38 @@ VersionFilterData::VersionFilterData() fmlLibsMapping["1.4.7"] = libs14; // 1.5 - fmlLibsMapping["1.5"] = QList{ - {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51"}, - {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a"}, - {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58"}, - {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65"}, - {"deobfuscation_data_1.5.zip", "5f7c142d53776f16304c0bbe10542014abad6af8"}, - {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85"}}; + fmlLibsMapping["1.5"] = QList{ { "argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51" }, + { "guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a" }, + { "asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58" }, + { "bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65" }, + { "deobfuscation_data_1.5.zip", "5f7c142d53776f16304c0bbe10542014abad6af8" }, + { "scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85" } }; // 1.5.1 - fmlLibsMapping["1.5.1"] = QList{ - {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51"}, - {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a"}, - {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58"}, - {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65"}, - {"deobfuscation_data_1.5.1.zip", "22e221a0d89516c1f721d6cab056a7e37471d0a6"}, - {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85"}}; + fmlLibsMapping["1.5.1"] = QList{ { "argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51" }, + { "guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a" }, + { "asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58" }, + { "bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65" }, + { "deobfuscation_data_1.5.1.zip", "22e221a0d89516c1f721d6cab056a7e37471d0a6" }, + { "scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85" } }; // 1.5.2 - fmlLibsMapping["1.5.2"] = QList{ - {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51"}, - {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a"}, - {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58"}, - {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65"}, - {"deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9"}, - {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85"}}; + fmlLibsMapping["1.5.2"] = QList{ { "argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51" }, + { "guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a" }, + { "asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58" }, + { "bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65" }, + { "deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9" }, + { "scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85" } }; // don't use installers for those. - forgeInstallerBlacklist = QSet({"1.5.2"}); + forgeInstallerBlacklist = QSet({ "1.5.2" }); // FIXME: remove, used for deciding when core mods should display legacyCutoffDate = timeFromS3Time("2013-06-25T15:08:56+02:00"); - lwjglWhitelist = - QSet{"net.java.jinput:jinput", "net.java.jinput:jinput-platform", - "net.java.jutils:jutils", "org.lwjgl.lwjgl:lwjgl", - "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"}; + lwjglWhitelist = QSet{ "net.java.jinput:jinput", "net.java.jinput:jinput-platform", "net.java.jutils:jutils", + "org.lwjgl.lwjgl:lwjgl", "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform" }; - java8BeginsDate = timeFromS3Time("2017-03-30T09:32:19+00:00"); + java8BeginsDate = timeFromS3Time("2017-03-30T09:32:19+00:00"); java16BeginsDate = timeFromS3Time("2021-05-12T11:19:15+00:00"); java17BeginsDate = timeFromS3Time("2021-11-16T17:04:48+00:00"); } diff --git a/launcher/minecraft/VersionFilterData.h b/launcher/minecraft/VersionFilterData.h index 13445a517..bcd329b6c 100644 --- a/launcher/minecraft/VersionFilterData.h +++ b/launcher/minecraft/VersionFilterData.h @@ -1,17 +1,15 @@ #pragma once -#include -#include -#include #include +#include +#include +#include -struct FMLlib -{ +struct FMLlib { QString filename; QString checksum; }; -struct VersionFilterData -{ +struct VersionFilterData { VersionFilterData(); // mapping between minecraft versions and FML libraries required QMap> fmlLibsMapping; diff --git a/launcher/minecraft/World.cpp b/launcher/minecraft/World.cpp index 21f2c4398..1a680ac56 100644 --- a/launcher/minecraft/World.cpp +++ b/launcher/minecraft/World.cpp @@ -34,23 +34,23 @@ * limitations under the License. */ -#include -#include -#include -#include -#include #include "World.h" +#include +#include +#include +#include +#include -#include "GZip.h" -#include #include -#include +#include #include -#include -#include #include -#include #include +#include +#include +#include +#include +#include "GZip.h" #include @@ -58,16 +58,15 @@ #include "FileSystem.h" -using std::optional; using std::nullopt; +using std::optional; -GameType::GameType(std::optional original): - original(original) +GameType::GameType(std::optional original) : original(original) { - if(!original) { + if (!original) { return; } - switch(*original) { + switch (*original) { case 0: type = GameType::Survival; break; @@ -87,8 +86,7 @@ GameType::GameType(std::optional original): QString GameType::toTranslatedString() const { - switch (type) - { + switch (type) { case GameType::Survival: return QCoreApplication::translate("GameType", "Survival"); case GameType::Creative: @@ -100,7 +98,7 @@ QString GameType::toTranslatedString() const default: break; } - if(original) { + if (original) { return QCoreApplication::translate("GameType", "Unknown (%1)").arg(*original); } return QCoreApplication::translate("GameType", "Undefined"); @@ -108,8 +106,7 @@ QString GameType::toTranslatedString() const QString GameType::toLogString() const { - switch (type) - { + switch (type) { case GameType::Survival: return "Survival"; case GameType::Creative: @@ -121,108 +118,94 @@ QString GameType::toLogString() const default: break; } - if(original) { + if (original) { return QString("Unknown (%1)").arg(*original); } return "Undefined"; } -std::unique_ptr parseLevelDat(QByteArray data) +std::unique_ptr parseLevelDat(QByteArray data) { QByteArray output; - if(!GZip::unzip(data, output)) - { + if (!GZip::unzip(data, output)) { return nullptr; } std::istringstream foo(std::string(output.constData(), output.size())); try { auto pair = nbt::io::read_compound(foo); - if(pair.first != "") + if (pair.first != "") return nullptr; - if(pair.second == nullptr) + if (pair.second == nullptr) return nullptr; return std::move(pair.second); - } - catch (const nbt::io::input_error &e) - { + } catch (const nbt::io::input_error& e) { qWarning() << "Unable to parse level.dat:" << e.what(); return nullptr; } } -QByteArray serializeLevelDat(nbt::tag_compound * levelInfo) +QByteArray serializeLevelDat(nbt::tag_compound* levelInfo) { std::ostringstream s; nbt::io::write_tag("", *levelInfo, s); - QByteArray val( s.str().data(), (int) s.str().size() ); + QByteArray val(s.str().data(), (int)s.str().size()); return val; } -QString getLevelDatFromFS(const QFileInfo &file) +QString getLevelDatFromFS(const QFileInfo& file) { QDir worldDir(file.filePath()); - if(!file.isDir() || !worldDir.exists("level.dat")) - { + if (!file.isDir() || !worldDir.exists("level.dat")) { return QString(); } return worldDir.absoluteFilePath("level.dat"); } -QByteArray getLevelDatDataFromFS(const QFileInfo &file) +QByteArray getLevelDatDataFromFS(const QFileInfo& file) { auto fullFilePath = getLevelDatFromFS(file); - if(fullFilePath.isNull()) - { + if (fullFilePath.isNull()) { return QByteArray(); } QFile f(fullFilePath); - if(!f.open(QIODevice::ReadOnly)) - { + if (!f.open(QIODevice::ReadOnly)) { return QByteArray(); } return f.readAll(); } -bool putLevelDatDataToFS(const QFileInfo &file, QByteArray & data) +bool putLevelDatDataToFS(const QFileInfo& file, QByteArray& data) { - auto fullFilePath = getLevelDatFromFS(file); - if(fullFilePath.isNull()) - { + auto fullFilePath = getLevelDatFromFS(file); + if (fullFilePath.isNull()) { return false; } QSaveFile f(fullFilePath); - if(!f.open(QIODevice::WriteOnly)) - { + if (!f.open(QIODevice::WriteOnly)) { return false; } QByteArray compressed; - if(!GZip::zip(data, compressed)) - { + if (!GZip::zip(data, compressed)) { return false; } - if(f.write(compressed) != compressed.size()) - { + if (f.write(compressed) != compressed.size()) { f.cancelWriting(); return false; } return f.commit(); } -int64_t calculateWorldSize(const QFileInfo &file) +int64_t calculateWorldSize(const QFileInfo& file) { - if (file.isFile() && file.suffix() == "zip") - { + if (file.isFile() && file.suffix() == "zip") { return file.size(); - } - else if(file.isDir()) - { + } else if (file.isDir()) { QDirIterator it(file.absoluteFilePath(), QDir::Files, QDirIterator::Subdirectories); int64_t total = 0; - while (it.hasNext()) - { + while (it.hasNext()) { total += it.fileInfo().size(); it.next(); } @@ -231,25 +214,22 @@ int64_t calculateWorldSize(const QFileInfo &file) return -1; } -World::World(const QFileInfo &file) +World::World(const QFileInfo& file) { repath(file); } -void World::repath(const QFileInfo &file) +void World::repath(const QFileInfo& file) { m_containerFile = file; m_folderName = file.fileName(); m_size = calculateWorldSize(file); - if(file.isFile() && file.suffix() == "zip") - { + if (file.isFile() && file.suffix() == "zip") { m_iconFile = QString(); readFromZip(file); - } - else if(file.isDir()) - { + } else if (file.isDir()) { QFileInfo assumedIconPath(file.absoluteFilePath() + "/icon.png"); - if(assumedIconPath.exists()) { + if (assumedIconPath.exists()) { m_iconFile = assumedIconPath.absoluteFilePath(); } readFromFS(file); @@ -258,21 +238,20 @@ void World::repath(const QFileInfo &file) bool World::resetIcon() { - if(m_iconFile.isNull()) { + if (m_iconFile.isNull()) { return false; } - if(QFile(m_iconFile).remove()) { + if (QFile(m_iconFile).remove()) { m_iconFile = QString(); return true; } return false; } -void World::readFromFS(const QFileInfo &file) +void World::readFromFS(const QFileInfo& file) { auto bytes = getLevelDatDataFromFS(file); - if(bytes.isEmpty()) - { + if (bytes.isEmpty()) { is_valid = false; return; } @@ -280,104 +259,88 @@ void World::readFromFS(const QFileInfo &file) levelDatTime = file.lastModified(); } -void World::readFromZip(const QFileInfo &file) +void World::readFromZip(const QFileInfo& file) { QuaZip zip(file.absoluteFilePath()); is_valid = zip.open(QuaZip::mdUnzip); - if (!is_valid) - { + if (!is_valid) { return; } auto location = MMCZip::findFolderOfFileInZip(&zip, "level.dat"); is_valid = !location.isEmpty(); - if (!is_valid) - { + if (!is_valid) { return; } m_containerOffsetPath = location; QuaZipFile zippedFile(&zip); // read the install profile is_valid = zip.setCurrentFile(location + "level.dat"); - if (!is_valid) - { + if (!is_valid) { return; } is_valid = zippedFile.open(QIODevice::ReadOnly); QuaZipFileInfo64 levelDatInfo; zippedFile.getFileInfo(&levelDatInfo); auto modTime = levelDatInfo.getNTFSmTime(); - if(!modTime.isValid()) - { + if (!modTime.isValid()) { modTime = levelDatInfo.dateTime; } levelDatTime = modTime; - if (!is_valid) - { + if (!is_valid) { return; } loadFromLevelDat(zippedFile.readAll()); zippedFile.close(); } -bool World::install(const QString &to, const QString &name) +bool World::install(const QString& to, const QString& name) { auto finalPath = FS::PathCombine(to, FS::DirNameFromString(m_actualName, to)); - if(!FS::ensureFolderPathExists(finalPath)) - { + if (!FS::ensureFolderPathExists(finalPath)) { return false; } bool ok = false; - if(m_containerFile.isFile()) - { + if (m_containerFile.isFile()) { QuaZip zip(m_containerFile.absoluteFilePath()); - if (!zip.open(QuaZip::mdUnzip)) - { + if (!zip.open(QuaZip::mdUnzip)) { return false; } ok = !MMCZip::extractSubDir(&zip, m_containerOffsetPath, finalPath); - } - else if(m_containerFile.isDir()) - { + } else if (m_containerFile.isDir()) { QString from = m_containerFile.filePath(); ok = FS::copy(from, finalPath)(); } - if(ok && !name.isEmpty() && m_actualName != name) - { + if (ok && !name.isEmpty() && m_actualName != name) { QFileInfo finalPathInfo(finalPath); World newWorld(finalPathInfo); - if(newWorld.isValid()) - { + if (newWorld.isValid()) { newWorld.rename(name); } } return ok; } -bool World::rename(const QString &newName) +bool World::rename(const QString& newName) { - if(m_containerFile.isFile()) - { + if (m_containerFile.isFile()) { return false; } auto data = getLevelDatDataFromFS(m_containerFile); - if(data.isEmpty()) - { + if (data.isEmpty()) { return false; } auto worldData = parseLevelDat(data); - if(!worldData) - { + if (!worldData) { return false; } - auto &val = worldData->at("Data"); - if(val.get_type() != nbt::tag_type::Compound) - { + auto& val = worldData->at("Data"); + if (val.get_type() != nbt::tag_type::Compound) { return false; } - auto &dataCompound = val.as(); + auto& dataCompound = val.as(); dataCompound.put("LevelName", nbt::value_initializer(newName.toUtf8().data())); data = serializeLevelDat(worldData.get()); @@ -396,112 +359,93 @@ bool World::rename(const QString &newName) namespace { -optional read_string (nbt::value& parent, const char * name) +optional read_string(nbt::value& parent, const char* name) { - try - { - auto &namedValue = parent.at(name); - if(namedValue.get_type() != nbt::tag_type::String) - { + try { + auto& namedValue = parent.at(name); + if (namedValue.get_type() != nbt::tag_type::String) { return nullopt; } - auto & tag_str = namedValue.as(); + auto& tag_str = namedValue.as(); return QString::fromStdString(tag_str.get()); - } - catch ([[maybe_unused]] const std::out_of_range &e) - { + } catch ([[maybe_unused]] const std::out_of_range& e) { // fallback for old world formats qWarning() << "String NBT tag" << name << "could not be found."; return nullopt; - } - catch ([[maybe_unused]] const std::bad_cast &e) - { + } catch ([[maybe_unused]] const std::bad_cast& e) { // type mismatch qWarning() << "NBT tag" << name << "could not be converted to string."; return nullopt; } } -optional read_long (nbt::value& parent, const char * name) +optional read_long(nbt::value& parent, const char* name) { - try - { - auto &namedValue = parent.at(name); - if(namedValue.get_type() != nbt::tag_type::Long) - { + try { + auto& namedValue = parent.at(name); + if (namedValue.get_type() != nbt::tag_type::Long) { return nullopt; } - auto & tag_str = namedValue.as(); + auto& tag_str = namedValue.as(); return tag_str.get(); - } - catch ([[maybe_unused]] const std::out_of_range &e) - { + } catch ([[maybe_unused]] const std::out_of_range& e) { // fallback for old world formats qWarning() << "Long NBT tag" << name << "could not be found."; return nullopt; - } - catch ([[maybe_unused]] const std::bad_cast &e) - { + } catch ([[maybe_unused]] const std::bad_cast& e) { // type mismatch qWarning() << "NBT tag" << name << "could not be converted to long."; return nullopt; } } -optional read_int (nbt::value& parent, const char * name) +optional read_int(nbt::value& parent, const char* name) { - try - { - auto &namedValue = parent.at(name); - if(namedValue.get_type() != nbt::tag_type::Int) - { + try { + auto& namedValue = parent.at(name); + if (namedValue.get_type() != nbt::tag_type::Int) { return nullopt; } - auto & tag_str = namedValue.as(); + auto& tag_str = namedValue.as(); return tag_str.get(); - } - catch ([[maybe_unused]] const std::out_of_range &e) - { + } catch ([[maybe_unused]] const std::out_of_range& e) { // fallback for old world formats qWarning() << "Int NBT tag" << name << "could not be found."; return nullopt; - } - catch ([[maybe_unused]] const std::bad_cast &e) - { + } catch ([[maybe_unused]] const std::bad_cast& e) { // type mismatch qWarning() << "NBT tag" << name << "could not be converted to int."; return nullopt; } } -GameType read_gametype(nbt::value& parent, const char * name) { +GameType read_gametype(nbt::value& parent, const char* name) +{ return GameType(read_int(parent, name)); } -} +} // namespace void World::loadFromLevelDat(QByteArray data) { auto levelData = parseLevelDat(data); - if(!levelData) - { + if (!levelData) { is_valid = false; return; } - nbt::value * valPtr = nullptr; + nbt::value* valPtr = nullptr; try { valPtr = &levelData->at("Data"); - } - catch (const std::out_of_range &e) { + } catch (const std::out_of_range& e) { qWarning() << "Unable to read NBT tags from " << m_folderName << ":" << e.what(); is_valid = false; return; } - nbt::value &val = *valPtr; + nbt::value& val = *valPtr; is_valid = val.get_type() == nbt::tag_type::Compound; - if(!is_valid) + if (!is_valid) return; auto name = read_string(val, "LevelName"); @@ -514,31 +458,30 @@ void World::loadFromLevelDat(QByteArray data) optional randomSeed; try { - auto &WorldGen_val = val.at("WorldGenSettings"); + auto& WorldGen_val = val.at("WorldGenSettings"); randomSeed = read_long(WorldGen_val, "seed"); + } catch (const std::out_of_range&) { } - catch (const std::out_of_range &) {} - if(!randomSeed) { + if (!randomSeed) { randomSeed = read_long(val, "RandomSeed"); } m_randomSeed = randomSeed ? *randomSeed : 0; qDebug() << "World Name:" << m_actualName; qDebug() << "Last Played:" << m_lastPlayed.toString(); - if(randomSeed) { + if (randomSeed) { qDebug() << "Seed:" << *randomSeed; } qDebug() << "Size:" << m_size; qDebug() << "GameType:" << m_gameType.toLogString(); } -bool World::replace(World &with) +bool World::replace(World& with) { if (!destroy()) return false; bool success = FS::copy(with.m_containerFile.filePath(), m_containerFile.path())(); - if (success) - { + if (success) { m_folderName = with.m_folderName; m_containerFile.refresh(); } @@ -547,25 +490,23 @@ bool World::replace(World &with) bool World::destroy() { - if(!is_valid) return false; + if (!is_valid) + return false; if (FS::trash(m_containerFile.filePath())) return true; - if (m_containerFile.isDir()) - { + if (m_containerFile.isDir()) { QDir d(m_containerFile.filePath()); return d.removeRecursively(); - } - else if(m_containerFile.isFile()) - { + } else if (m_containerFile.isFile()) { QFile file(m_containerFile.absoluteFilePath()); return file.remove(); } return true; } -bool World::operator==(const World &other) const +bool World::operator==(const World& other) const { return is_valid == other.is_valid && folderName() == other.folderName(); } @@ -585,8 +526,7 @@ bool World::isSymLinkUnder(const QString& instPath) const bool World::isMoreThanOneHardLink() const { - if (m_containerFile.isDir()) - { + if (m_containerFile.isDir()) { return FS::hardLinkCount(QDir(m_containerFile.absoluteFilePath()).filePath("level.dat")) > 1; } return FS::hardLinkCount(m_containerFile.absoluteFilePath()) > 1; diff --git a/launcher/minecraft/World.h b/launcher/minecraft/World.h index dc3733d5f..4303dc553 100644 --- a/launcher/minecraft/World.h +++ b/launcher/minecraft/World.h @@ -14,95 +14,57 @@ */ #pragma once -#include #include +#include #include struct GameType { GameType() = default; - GameType (std::optional original); + GameType(std::optional original); QString toTranslatedString() const; QString toLogString() const; - enum - { - Unknown = -1, - Survival, - Creative, - Adventure, - Spectator - } type = Unknown; + enum { Unknown = -1, Survival, Creative, Adventure, Spectator } type = Unknown; std::optional original; }; -class World -{ -public: - World(const QFileInfo &file); - QString folderName() const - { - return m_folderName; - } - QString name() const - { - return m_actualName; - } - QString iconFile() const - { - return m_iconFile; - } - int64_t bytes() const - { - return m_size; - } - QDateTime lastPlayed() const - { - return m_lastPlayed; - } - GameType gameType() const - { - return m_gameType; - } - int64_t seed() const - { - return m_randomSeed; - } - bool isValid() const - { - return is_valid; - } - bool isOnFS() const - { - return m_containerFile.isDir(); - } - QFileInfo container() const - { - return m_containerFile; - } +class World { + public: + World(const QFileInfo& file); + QString folderName() const { return m_folderName; } + QString name() const { return m_actualName; } + QString iconFile() const { return m_iconFile; } + int64_t bytes() const { return m_size; } + QDateTime lastPlayed() const { return m_lastPlayed; } + GameType gameType() const { return m_gameType; } + int64_t seed() const { return m_randomSeed; } + bool isValid() const { return is_valid; } + bool isOnFS() const { return m_containerFile.isDir(); } + QFileInfo container() const { return m_containerFile; } // delete all the files of this world bool destroy(); // replace this world with a copy of the other - bool replace(World &with); + bool replace(World& with); // change the world's filesystem path (used by world lists for *MAGIC* purposes) - void repath(const QFileInfo &file); + void repath(const QFileInfo& file); // remove the icon file, if any bool resetIcon(); - bool rename(const QString &to); - bool install(const QString &to, const QString &name= QString()); + bool rename(const QString& to); + bool install(const QString& to, const QString& name = QString()); // WEAK compare operator - used for replacing worlds - bool operator==(const World &other) const; + bool operator==(const World& other) const; - [[nodiscard]] auto isSymLink() const -> bool{ return m_containerFile.isSymLink(); } + [[nodiscard]] auto isSymLink() const -> bool { return m_containerFile.isSymLink(); } /** * @brief Take a instance path, checks if the file pointed to by the resource is a symlink or under a symlink in that instance - * + * * @param instPath path to an instance directory - * @return true - * @return false + * @return true + * @return false */ [[nodiscard]] bool isSymLinkUnder(const QString& instPath) const; @@ -110,13 +72,12 @@ public: QString canonicalFilePath() const { return m_containerFile.canonicalFilePath(); } -private: - void readFromZip(const QFileInfo &file); - void readFromFS(const QFileInfo &file); + private: + void readFromZip(const QFileInfo& file); + void readFromFS(const QFileInfo& file); void loadFromLevelDat(QByteArray data); -protected: - + protected: QFileInfo m_containerFile; QString m_containerOffsetPath; QString m_folderName; diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index fe0893783..cdfbef5b8 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -35,18 +35,17 @@ #include "WorldList.h" -#include "Application.h" #include -#include +#include +#include #include +#include #include #include -#include -#include -#include +#include +#include "Application.h" -WorldList::WorldList(const QString &dir, BaseInstance* instance) - : QAbstractListModel(), m_instance(instance), m_dir(dir) +WorldList::WorldList(const QString& dir, BaseInstance* instance) : QAbstractListModel(), m_instance(instance), m_dir(dir) { FS::ensureFolderPathExists(m_dir.absolutePath()); m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); @@ -58,35 +57,27 @@ WorldList::WorldList(const QString &dir, BaseInstance* instance) void WorldList::startWatching() { - if(is_watching) - { + if (is_watching) { return; } update(); is_watching = m_watcher->addPath(m_dir.absolutePath()); - if (is_watching) - { + if (is_watching) { qDebug() << "Started watching " << m_dir.absolutePath(); - } - else - { + } else { qDebug() << "Failed to start watching " << m_dir.absolutePath(); } } void WorldList::stopWatching() { - if(!is_watching) - { + if (!is_watching) { return; } is_watching = !m_watcher->removePath(m_dir.absolutePath()); - if (!is_watching) - { + if (!is_watching) { qDebug() << "Stopped watching " << m_dir.absolutePath(); - } - else - { + } else { qDebug() << "Failed to stop watching " << m_dir.absolutePath(); } } @@ -100,14 +91,12 @@ bool WorldList::update() m_dir.refresh(); auto folderContents = m_dir.entryInfoList(); // if there are any untracked files... - for (QFileInfo entry : folderContents) - { - if(!entry.isDir()) + for (QFileInfo entry : folderContents) { + if (!entry.isDir()) continue; World w(entry); - if(w.isValid()) - { + if (w.isValid()) { newWorlds.append(w); } } @@ -127,7 +116,8 @@ bool WorldList::isValid() return m_dir.exists() && m_dir.isReadable(); } -QString WorldList::instDirPath() const { +QString WorldList::instDirPath() const +{ return QFileInfo(m_instance->instanceRoot()).absoluteFilePath(); } @@ -135,9 +125,8 @@ bool WorldList::deleteWorld(int index) { if (index >= worlds.size() || index < 0) return false; - World &m = worlds[index]; - if (m.destroy()) - { + World& m = worlds[index]; + if (m.destroy()) { beginRemoveRows(QModelIndex(), index, index); worlds.removeAt(index); endRemoveRows(); @@ -149,9 +138,8 @@ bool WorldList::deleteWorld(int index) bool WorldList::deleteWorlds(int first, int last) { - for (int i = first; i <= last; i++) - { - World &m = worlds[i]; + for (int i = first; i <= last; i++) { + World& m = worlds[i]; m.destroy(); } beginRemoveRows(QModelIndex(), first, last); @@ -165,21 +153,20 @@ bool WorldList::resetIcon(int row) { if (row >= worlds.size() || row < 0) return false; - World &m = worlds[row]; - if(m.resetIcon()) { - emit dataChanged(index(row), index(row), {WorldList::IconFileRole}); + World& m = worlds[row]; + if (m.resetIcon()) { + emit dataChanged(index(row), index(row), { WorldList::IconFileRole }); return true; } return false; } - -int WorldList::columnCount(const QModelIndex &parent) const +int WorldList::columnCount(const QModelIndex& parent) const { - return parent.isValid()? 0 : 5; + return parent.isValid() ? 0 : 5; } -QVariant WorldList::data(const QModelIndex &index, int role) const +QVariant WorldList::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); @@ -192,133 +179,120 @@ QVariant WorldList::data(const QModelIndex &index, int role) const QLocale locale; - auto & world = worlds[row]; - switch (role) - { - case Qt::DisplayRole: - switch (column) - { - case NameColumn: + auto& world = worlds[row]; + switch (role) { + case Qt::DisplayRole: + switch (column) { + case NameColumn: + return world.name(); + + case GameModeColumn: + return world.gameType().toTranslatedString(); + + case LastPlayedColumn: + return world.lastPlayed(); + + case SizeColumn: + return locale.formattedDataSize(world.bytes()); + + case InfoColumn: + if (world.isSymLinkUnder(instDirPath())) { + return tr("This world is symbolically linked from elsewhere."); + } + if (world.isMoreThanOneHardLink()) { + return tr("\nThis world is hard linked elsewhere."); + } + return ""; + default: + return QVariant(); + } + + case Qt::UserRole: + switch (column) { + case SizeColumn: + return QVariant::fromValue(world.bytes()); + + default: + return data(index, Qt::DisplayRole); + } + + case Qt::ToolTipRole: { + if (column == InfoColumn) { + if (world.isSymLinkUnder(instDirPath())) { + return tr("Warning: This world is symbolically linked from elsewhere. Editing it will also change the original." + "\nCanonical Path: %1") + .arg(world.canonicalFilePath()); + } + if (world.isMoreThanOneHardLink()) { + return tr("Warning: This world is hard linked elsewhere. Editing it will also change the original."); + } + } + return world.folderName(); + } + case ObjectRole: { + return QVariant::fromValue((void*)&world); + } + case FolderRole: { + return QDir::toNativeSeparators(dir().absoluteFilePath(world.folderName())); + } + case SeedRole: { + return QVariant::fromValue(world.seed()); + } + case NameRole: { return world.name(); - - case GameModeColumn: - return world.gameType().toTranslatedString(); - - case LastPlayedColumn: + } + case LastPlayedRole: { return world.lastPlayed(); - - case SizeColumn: - return locale.formattedDataSize(world.bytes()); - - case InfoColumn: - if (world.isSymLinkUnder(instDirPath())) { - return tr("This world is symbolically linked from elsewhere."); - } - if (world.isMoreThanOneHardLink()) { - return tr("\nThis world is hard linked elsewhere."); - } - return ""; + } + case SizeRole: { + return QVariant::fromValue(world.bytes()); + } + case IconFileRole: { + return world.iconFile(); + } default: return QVariant(); - } - - case Qt::UserRole: - switch (column) - { - case SizeColumn: - return QVariant::fromValue(world.bytes()); - - default: - return data(index, Qt::DisplayRole); - } - - case Qt::ToolTipRole: - { - if (column == InfoColumn) { - if (world.isSymLinkUnder(instDirPath())) { - return tr("Warning: This world is symbolically linked from elsewhere. Editing it will also change the original." - "\nCanonical Path: %1").arg(world.canonicalFilePath()); - } - if (world.isMoreThanOneHardLink()) { - return tr("Warning: This world is hard linked elsewhere. Editing it will also change the original."); - } - } - return world.folderName(); - } - case ObjectRole: - { - return QVariant::fromValue((void *)&world); - } - case FolderRole: - { - return QDir::toNativeSeparators(dir().absoluteFilePath(world.folderName())); - } - case SeedRole: - { - return QVariant::fromValue(world.seed()); - } - case NameRole: - { - return world.name(); - } - case LastPlayedRole: - { - return world.lastPlayed(); - } - case SizeRole: - { - return QVariant::fromValue(world.bytes()); - } - case IconFileRole: - { - return world.iconFile(); - } - default: - return QVariant(); } } QVariant WorldList::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { - switch (role) - { - case Qt::DisplayRole: - switch (section) - { - case NameColumn: - return tr("Name"); - case GameModeColumn: - return tr("Game Mode"); - case LastPlayedColumn: - return tr("Last Played"); - case SizeColumn: - //: World size on disk - return tr("Size"); - case InfoColumn: - //: special warnings? - return tr("Info"); - default: - return QVariant(); - } + switch (role) { + case Qt::DisplayRole: + switch (section) { + case NameColumn: + return tr("Name"); + case GameModeColumn: + return tr("Game Mode"); + case LastPlayedColumn: + return tr("Last Played"); + case SizeColumn: + //: World size on disk + return tr("Size"); + case InfoColumn: + //: special warnings? + return tr("Info"); + default: + return QVariant(); + } - case Qt::ToolTipRole: - switch (section) - { - case NameColumn: - return tr("The name of the world."); - case GameModeColumn: - return tr("Game mode of the world."); - case LastPlayedColumn: - return tr("Date and time the world was last played."); - case SizeColumn: - return tr("Size of the world on disk."); - case InfoColumn: - return tr("Information and warnings about the world."); + case Qt::ToolTipRole: + switch (section) { + case NameColumn: + return tr("The name of the world."); + case GameModeColumn: + return tr("Game mode of the world."); + case LastPlayedColumn: + return tr("Date and time the world was last played."); + case SizeColumn: + return tr("Size of the world on disk."); + case InfoColumn: + return tr("Information and warnings about the world."); + default: + return QVariant(); + } default: return QVariant(); - } - default: - return QVariant(); } } @@ -329,32 +303,23 @@ QStringList WorldList::mimeTypes() const return types; } -class WorldMimeData : public QMimeData -{ -Q_OBJECT +class WorldMimeData : public QMimeData { + Q_OBJECT -public: - WorldMimeData(QList worlds) - { - m_worlds = worlds; + public: + WorldMimeData(QList worlds) { m_worlds = worlds; } + QStringList formats() const { return QMimeData::formats() << "text/uri-list"; } - } - QStringList formats() const - { - return QMimeData::formats() << "text/uri-list"; - } - -protected: + protected: #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QVariant retrieveData(const QString &mimetype, QMetaType type) const + QVariant retrieveData(const QString& mimetype, QMetaType type) const #else - QVariant retrieveData(const QString &mimetype, QVariant::Type type) const + QVariant retrieveData(const QString& mimetype, QVariant::Type type) const #endif { QList urls; - for(auto &world: m_worlds) - { - if(!world.isValid() || !world.isOnFS()) + for (auto& world : m_worlds) { + if (!world.isValid() || !world.isOnFS()) continue; QString worldPath = world.container().absoluteFilePath(); qDebug() << worldPath; @@ -363,38 +328,36 @@ protected: const_cast(this)->setUrls(urls); return QMimeData::retrieveData(mimetype, type); } -private: + + private: QList m_worlds; }; -QMimeData *WorldList::mimeData(const QModelIndexList &indexes) const +QMimeData* WorldList::mimeData(const QModelIndexList& indexes) const { if (indexes.size() == 0) return new QMimeData(); QList worlds_; - for(auto idx : indexes) - { - if(idx.column() != 0) + for (auto idx : indexes) { + if (idx.column() != 0) continue; int row = idx.row(); if (row < 0 || row >= this->worlds.size()) continue; worlds_.append(this->worlds[row]); } - if(!worlds_.size()) - { + if (!worlds_.size()) { return new QMimeData(); } return new WorldMimeData(worlds_); } -Qt::ItemFlags WorldList::flags(const QModelIndex &index) const +Qt::ItemFlags WorldList::flags(const QModelIndex& index) const { Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); if (index.isValid()) - return Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | - defaultFlags; + return Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; else return Qt::ItemIsDropEnabled | defaultFlags; } @@ -415,15 +378,17 @@ void WorldList::installWorld(QFileInfo filename) { qDebug() << "installing: " << filename.absoluteFilePath(); World w(filename); - if(!w.isValid()) - { + if (!w.isValid()) { return; } w.install(m_dir.absolutePath()); } -bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, - [[maybe_unused]] const QModelIndex &parent) +bool WorldList::dropMimeData(const QMimeData* data, + Qt::DropAction action, + [[maybe_unused]] int row, + [[maybe_unused]] int column, + [[maybe_unused]] const QModelIndex& parent) { if (action == Qt::IgnoreAction) return true; @@ -431,14 +396,12 @@ bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[may if (!data || !(action & supportedDropActions())) return false; // files dropped from outside? - if (data->hasUrls()) - { + if (data->hasUrls()) { bool was_watching = is_watching; if (was_watching) stopWatching(); auto urls = data->urls(); - for (auto url : urls) - { + for (auto url : urls) { // only local files may be dropped... if (!url.isLocalFile()) continue; @@ -446,8 +409,7 @@ bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[may QFileInfo worldInfo(filename); - if(!m_dir.entryInfoList().contains(worldInfo)) - { + if (!m_dir.entryInfoList().contains(worldInfo)) { installWorld(worldInfo); } } diff --git a/launcher/minecraft/WorldList.h b/launcher/minecraft/WorldList.h index 96b64193f..bea24bb9a 100644 --- a/launcher/minecraft/WorldList.h +++ b/launcher/minecraft/WorldList.h @@ -15,65 +15,34 @@ #pragma once -#include -#include -#include #include +#include +#include #include -#include "minecraft/World.h" +#include #include "BaseInstance.h" +#include "minecraft/World.h" class QFileSystemWatcher; -class WorldList : public QAbstractListModel -{ +class WorldList : public QAbstractListModel { Q_OBJECT -public: - enum Columns - { - NameColumn, - GameModeColumn, - LastPlayedColumn, - SizeColumn, - InfoColumn - }; + public: + enum Columns { NameColumn, GameModeColumn, LastPlayedColumn, SizeColumn, InfoColumn }; - enum Roles - { - ObjectRole = Qt::UserRole + 1, - FolderRole, - SeedRole, - NameRole, - GameModeRole, - LastPlayedRole, - SizeRole, - IconFileRole - }; + enum Roles { ObjectRole = Qt::UserRole + 1, FolderRole, SeedRole, NameRole, GameModeRole, LastPlayedRole, SizeRole, IconFileRole }; - WorldList(const QString &dir, BaseInstance* instance); + WorldList(const QString& dir, BaseInstance* instance); - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const - { - return parent.isValid() ? 0 : static_cast(size()); - }; - virtual QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - virtual int columnCount(const QModelIndex &parent) const; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const { return parent.isValid() ? 0 : static_cast(size()); }; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual int columnCount(const QModelIndex& parent) const; - size_t size() const - { - return worlds.size(); - }; - bool empty() const - { - return size() == 0; - } - World &operator[](size_t index) - { - return worlds[index]; - } + size_t size() const { return worlds.size(); }; + bool empty() const { return size() == 0; } + World& operator[](size_t index) { return worlds[index]; } /// Reloads the mod list and returns true if the list changed. virtual bool update(); @@ -91,13 +60,13 @@ public: virtual bool deleteWorlds(int first, int last); /// flags, mostly to support drag&drop - virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual Qt::ItemFlags flags(const QModelIndex& index) const; /// get data for drag action - virtual QMimeData *mimeData(const QModelIndexList &indexes) const; + virtual QMimeData* mimeData(const QModelIndexList& indexes) const; /// get the supported mime types virtual QStringList mimeTypes() const; /// process data from drop action - virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent); /// what drag actions do we support? virtual Qt::DropActions supportedDragActions() const; @@ -109,27 +78,21 @@ public: virtual bool isValid(); - QDir dir() const - { - return m_dir; - } + QDir dir() const { return m_dir; } QString instDirPath() const; - const QList &allWorlds() const - { - return worlds; - } + const QList& allWorlds() const { return worlds; } -private slots: + private slots: void directoryChanged(QString path); -signals: + signals: void changed(); -protected: + protected: BaseInstance* m_instance; - QFileSystemWatcher *m_watcher; + QFileSystemWatcher* m_watcher; bool is_watching; QDir m_dir; QList worlds; diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp index 707483ef9..fc870811f 100644 --- a/launcher/minecraft/auth/AccountData.cpp +++ b/launcher/minecraft/auth/AccountData.cpp @@ -34,87 +34,90 @@ */ #include "AccountData.h" +#include +#include #include #include -#include -#include -#include #include +#include namespace { -void tokenToJSONV3(QJsonObject &parent, Katabasis::Token t, const char * tokenName) { - if(!t.persistent) { +void tokenToJSONV3(QJsonObject& parent, Katabasis::Token t, const char* tokenName) +{ + if (!t.persistent) { return; } QJsonObject out; - if(t.issueInstant.isValid()) { + if (t.issueInstant.isValid()) { out["iat"] = QJsonValue(t.issueInstant.toMSecsSinceEpoch() / 1000); } - if(t.notAfter.isValid()) { + if (t.notAfter.isValid()) { out["exp"] = QJsonValue(t.notAfter.toMSecsSinceEpoch() / 1000); } bool save = false; - if(!t.token.isEmpty()) { + if (!t.token.isEmpty()) { out["token"] = QJsonValue(t.token); save = true; } - if(!t.refresh_token.isEmpty()) { + if (!t.refresh_token.isEmpty()) { out["refresh_token"] = QJsonValue(t.refresh_token); save = true; } - if(t.extra.size()) { + if (t.extra.size()) { out["extra"] = QJsonObject::fromVariantMap(t.extra); save = true; } - if(save) { + if (save) { parent[tokenName] = out; } } -Katabasis::Token tokenFromJSONV3(const QJsonObject &parent, const char * tokenName) { +Katabasis::Token tokenFromJSONV3(const QJsonObject& parent, const char* tokenName) +{ Katabasis::Token out; auto tokenObject = parent.value(tokenName).toObject(); - if(tokenObject.isEmpty()) { + if (tokenObject.isEmpty()) { return out; } auto issueInstant = tokenObject.value("iat"); - if(issueInstant.isDouble()) { - out.issueInstant = QDateTime::fromMSecsSinceEpoch(((int64_t) issueInstant.toDouble()) * 1000); + if (issueInstant.isDouble()) { + out.issueInstant = QDateTime::fromMSecsSinceEpoch(((int64_t)issueInstant.toDouble()) * 1000); } auto notAfter = tokenObject.value("exp"); - if(notAfter.isDouble()) { - out.notAfter = QDateTime::fromMSecsSinceEpoch(((int64_t) notAfter.toDouble()) * 1000); + if (notAfter.isDouble()) { + out.notAfter = QDateTime::fromMSecsSinceEpoch(((int64_t)notAfter.toDouble()) * 1000); } auto token = tokenObject.value("token"); - if(token.isString()) { + if (token.isString()) { out.token = token.toString(); out.validity = Katabasis::Validity::Assumed; } auto refresh_token = tokenObject.value("refresh_token"); - if(refresh_token.isString()) { + if (refresh_token.isString()) { out.refresh_token = refresh_token.toString(); } auto extra = tokenObject.value("extra"); - if(extra.isObject()) { + if (extra.isObject()) { out.extra = extra.toObject().toVariantMap(); } return out; } -void profileToJSONV3(QJsonObject &parent, MinecraftProfile p, const char * tokenName) { - if(p.id.isEmpty()) { +void profileToJSONV3(QJsonObject& parent, MinecraftProfile p, const char* tokenName) +{ + if (p.id.isEmpty()) { return; } QJsonObject out; out["id"] = QJsonValue(p.id); out["name"] = QJsonValue(p.name); - if(!p.currentCape.isEmpty()) { + if (!p.currentCape.isEmpty()) { out["cape"] = p.currentCape; } @@ -123,19 +126,19 @@ void profileToJSONV3(QJsonObject &parent, MinecraftProfile p, const char * token skinObj["id"] = p.skin.id; skinObj["url"] = p.skin.url; skinObj["variant"] = p.skin.variant; - if(p.skin.data.size()) { + if (p.skin.data.size()) { skinObj["data"] = QString::fromLatin1(p.skin.data.toBase64()); } out["skin"] = skinObj; } QJsonArray capesArray; - for(auto & cape: p.capes) { + for (auto& cape : p.capes) { QJsonObject capeObj; capeObj["id"] = cape.id; capeObj["url"] = cape.url; capeObj["alias"] = cape.alias; - if(cape.data.size()) { + if (cape.data.size()) { capeObj["data"] = QString::fromLatin1(cape.data.toBase64()); } capesArray.push_back(capeObj); @@ -144,16 +147,17 @@ void profileToJSONV3(QJsonObject &parent, MinecraftProfile p, const char * token parent[tokenName] = out; } -MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * tokenName) { +MinecraftProfile profileFromJSONV3(const QJsonObject& parent, const char* tokenName) +{ MinecraftProfile out; auto tokenObject = parent.value(tokenName).toObject(); - if(tokenObject.isEmpty()) { + if (tokenObject.isEmpty()) { return out; } { auto idV = tokenObject.value("id"); auto nameV = tokenObject.value("name"); - if(!idV.isString() || !nameV.isString()) { + if (!idV.isString() || !nameV.isString()) { qWarning() << "mandatory profile attributes are missing or of unexpected type"; return MinecraftProfile(); } @@ -163,7 +167,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token { auto skinV = tokenObject.value("skin"); - if(!skinV.isObject()) { + if (!skinV.isObject()) { qWarning() << "skin is missing"; return MinecraftProfile(); } @@ -171,7 +175,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token auto idV = skinObj.value("id"); auto urlV = skinObj.value("url"); auto variantV = skinObj.value("variant"); - if(!idV.isString() || !urlV.isString() || !variantV.isString()) { + if (!idV.isString() || !urlV.isString() || !variantV.isString()) { qWarning() << "mandatory skin attributes are missing or of unexpected type"; return MinecraftProfile(); } @@ -181,11 +185,10 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token // data for skin is optional auto dataV = skinObj.value("data"); - if(dataV.isString()) { + if (dataV.isString()) { // TODO: validate base64 out.skin.data = QByteArray::fromBase64(dataV.toString().toLatin1()); - } - else if (!dataV.isUndefined()) { + } else if (!dataV.isUndefined()) { qWarning() << "skin data is something unexpected"; return MinecraftProfile(); } @@ -193,13 +196,13 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token { auto capesV = tokenObject.value("capes"); - if(!capesV.isArray()) { + if (!capesV.isArray()) { qWarning() << "capes is not an array!"; return MinecraftProfile(); } auto capesArray = capesV.toArray(); - for(auto capeV: capesArray) { - if(!capeV.isObject()) { + for (auto capeV : capesArray) { + if (!capeV.isObject()) { qWarning() << "cape is not an object!"; return MinecraftProfile(); } @@ -207,7 +210,7 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token auto idV = capeObj.value("id"); auto urlV = capeObj.value("url"); auto aliasV = capeObj.value("alias"); - if(!idV.isString() || !urlV.isString() || !aliasV.isString()) { + if (!idV.isString() || !urlV.isString() || !aliasV.isString()) { qWarning() << "mandatory skin attributes are missing or of unexpected type"; return MinecraftProfile(); } @@ -218,11 +221,10 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token // data for cape is optional. auto dataV = capeObj.value("data"); - if(dataV.isString()) { + if (dataV.isString()) { // TODO: validate base64 cape.data = QByteArray::fromBase64(dataV.toString().toLatin1()); - } - else if (!dataV.isUndefined()) { + } else if (!dataV.isUndefined()) { qWarning() << "cape data is something unexpected"; return MinecraftProfile(); } @@ -232,9 +234,9 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token // current cape { auto capeV = tokenObject.value("cape"); - if(capeV.isString()) { + if (capeV.isString()) { auto currentCape = capeV.toString(); - if(out.capes.contains(currentCape)) { + if (out.capes.contains(currentCape)) { out.currentCape = currentCape; } } @@ -243,8 +245,9 @@ MinecraftProfile profileFromJSONV3(const QJsonObject &parent, const char * token return out; } -void entitlementToJSONV3(QJsonObject &parent, MinecraftEntitlement p) { - if(p.validity == Katabasis::Validity::None) { +void entitlementToJSONV3(QJsonObject& parent, MinecraftEntitlement p) +{ + if (p.validity == Katabasis::Validity::None) { return; } QJsonObject out; @@ -253,15 +256,16 @@ void entitlementToJSONV3(QJsonObject &parent, MinecraftEntitlement p) { parent["entitlement"] = out; } -bool entitlementFromJSONV3(const QJsonObject &parent, MinecraftEntitlement & out) { +bool entitlementFromJSONV3(const QJsonObject& parent, MinecraftEntitlement& out) +{ auto entitlementObject = parent.value("entitlement").toObject(); - if(entitlementObject.isEmpty()) { + if (entitlementObject.isEmpty()) { return false; } { auto ownsMinecraftV = entitlementObject.value("ownsMinecraft"); auto canPlayMinecraftV = entitlementObject.value("canPlayMinecraft"); - if(!ownsMinecraftV.isBool() || !canPlayMinecraftV.isBool()) { + if (!ownsMinecraftV.isBool() || !canPlayMinecraftV.isBool()) { qWarning() << "mandatory attributes are missing or of unexpected type"; return false; } @@ -272,12 +276,12 @@ bool entitlementFromJSONV3(const QJsonObject &parent, MinecraftEntitlement & out return true; } -} +} // namespace -bool AccountData::resumeStateFromV2(QJsonObject data) { +bool AccountData::resumeStateFromV2(QJsonObject data) +{ // The JSON object must at least have a username for it to be valid. - if (!data.value("username").isString()) - { + if (!data.value("username").isString()) { qCritical() << "Can't load Mojang account info from JSON object. Username field is missing or of the wrong type."; return false; } @@ -287,14 +291,12 @@ bool AccountData::resumeStateFromV2(QJsonObject data) { QString accessToken = data.value("accessToken").toString(""); QJsonArray profileArray = data.value("profiles").toArray(); - if (profileArray.size() < 1) - { + if (profileArray.size() < 1) { qCritical() << "Can't load Mojang account with username \"" << userName << "\". No profiles found."; return false; } - struct AccountProfile - { + struct AccountProfile { QString id; QString name; bool legacy; @@ -304,24 +306,22 @@ bool AccountData::resumeStateFromV2(QJsonObject data) { int currentProfileIndex = 0; int index = -1; QString currentProfile = data.value("activeProfile").toString(""); - for (QJsonValue profileVal : profileArray) - { + for (QJsonValue profileVal : profileArray) { index++; QJsonObject profileObject = profileVal.toObject(); QString id = profileObject.value("id").toString(""); QString name = profileObject.value("name").toString(""); bool legacy_ = profileObject.value("legacy").toBool(false); - if (id.isEmpty() || name.isEmpty()) - { + if (id.isEmpty() || name.isEmpty()) { qWarning() << "Unable to load a profile" << name << "because it was missing an ID or a name."; continue; } - if(id == currentProfile) { + if (id == currentProfile) { currentProfileIndex = index; } - profiles.append({id, name, legacy_}); + profiles.append({ id, name, legacy_ }); } - auto & profile = profiles[currentProfileIndex]; + auto& profile = profiles[currentProfileIndex]; type = AccountType::Mojang; legacy = profile.legacy; @@ -339,14 +339,15 @@ bool AccountData::resumeStateFromV2(QJsonObject data) { return true; } -bool AccountData::resumeStateFromV3(QJsonObject data) { +bool AccountData::resumeStateFromV3(QJsonObject data) +{ auto typeV = data.value("type"); - if(!typeV.isString()) { + if (!typeV.isString()) { qWarning() << "Failed to parse account data: type is missing."; return false; } auto typeS = typeV.toString(); - if(typeS == "MSA") { + if (typeS == "MSA") { type = AccountType::MSA; } else if (typeS == "Mojang") { type = AccountType::Mojang; @@ -357,16 +358,16 @@ bool AccountData::resumeStateFromV3(QJsonObject data) { return false; } - if(type == AccountType::Mojang) { + if (type == AccountType::Mojang) { legacy = data.value("legacy").toBool(false); canMigrateToMSA = data.value("canMigrateToMSA").toBool(false); } - if(type == AccountType::MSA) { + if (type == AccountType::MSA) { auto clientIDV = data.value("msa-client-id"); if (clientIDV.isString()) { msaClientID = clientIDV.toString(); - } // leave msaClientID empty if it doesn't exist or isn't a string + } // leave msaClientID empty if it doesn't exist or isn't a string msaToken = tokenFromJSONV3(data, "msa"); userToken = tokenFromJSONV3(data, "utoken"); xboxApiToken = tokenFromJSONV3(data, "xrp-main"); @@ -379,8 +380,8 @@ bool AccountData::resumeStateFromV3(QJsonObject data) { yggdrasilToken.token = "0"; minecraftProfile = profileFromJSONV3(data, "profile"); - if(!entitlementFromJSONV3(data, minecraftEntitlement)) { - if(minecraftProfile.validity != Katabasis::Validity::None) { + if (!entitlementFromJSONV3(data, minecraftEntitlement)) { + if (minecraftProfile.validity != Katabasis::Validity::None) { minecraftEntitlement.canPlayMinecraft = true; minecraftEntitlement.ownsMinecraft = true; minecraftEntitlement.validity = Katabasis::Validity::Assumed; @@ -391,26 +392,25 @@ bool AccountData::resumeStateFromV3(QJsonObject data) { return true; } -QJsonObject AccountData::saveState() const { +QJsonObject AccountData::saveState() const +{ QJsonObject output; - if(type == AccountType::Mojang) { + if (type == AccountType::Mojang) { output["type"] = "Mojang"; - if(legacy) { + if (legacy) { output["legacy"] = true; } - if(canMigrateToMSA) { + if (canMigrateToMSA) { output["canMigrateToMSA"] = true; } - } - else if (type == AccountType::MSA) { + } else if (type == AccountType::MSA) { output["type"] = "MSA"; output["msa-client-id"] = msaClientID; tokenToJSONV3(output, msaToken, "msa"); tokenToJSONV3(output, userToken, "utoken"); tokenToJSONV3(output, xboxApiToken, "xrp-main"); tokenToJSONV3(output, mojangservicesToken, "xrp-mc"); - } - else if (type == AccountType::Offline) { + } else if (type == AccountType::Offline) { output["type"] = "Offline"; } @@ -420,60 +420,68 @@ QJsonObject AccountData::saveState() const { return output; } -QString AccountData::userName() const { - if(type == AccountType::MSA) { +QString AccountData::userName() const +{ + if (type == AccountType::MSA) { return QString(); } return yggdrasilToken.extra["userName"].toString(); } -QString AccountData::accessToken() const { +QString AccountData::accessToken() const +{ return yggdrasilToken.token; } -QString AccountData::clientToken() const { - if(type != AccountType::Mojang) { +QString AccountData::clientToken() const +{ + if (type != AccountType::Mojang) { return QString(); } return yggdrasilToken.extra["clientToken"].toString(); } -void AccountData::setClientToken(QString clientToken) { - if(type != AccountType::Mojang) { +void AccountData::setClientToken(QString clientToken) +{ + if (type != AccountType::Mojang) { return; } yggdrasilToken.extra["clientToken"] = clientToken; } -void AccountData::generateClientTokenIfMissing() { - if(yggdrasilToken.extra.contains("clientToken")) { +void AccountData::generateClientTokenIfMissing() +{ + if (yggdrasilToken.extra.contains("clientToken")) { return; } invalidateClientToken(); } -void AccountData::invalidateClientToken() { - if(type != AccountType::Mojang) { +void AccountData::invalidateClientToken() +{ + if (type != AccountType::Mojang) { return; } yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{-}]")); } -QString AccountData::profileId() const { +QString AccountData::profileId() const +{ return minecraftProfile.id; } -QString AccountData::profileName() const { - if(minecraftProfile.name.size() == 0) { +QString AccountData::profileName() const +{ + if (minecraftProfile.name.size() == 0) { return QObject::tr("No profile (%1)").arg(accountDisplayString()); - } - else { + } else { return minecraftProfile.name; } } -QString AccountData::accountDisplayString() const { - switch(type) { +QString AccountData::accountDisplayString() const +{ + switch (type) { case AccountType::Mojang: { return userName(); } @@ -481,7 +489,7 @@ QString AccountData::accountDisplayString() const { return QObject::tr(""); } case AccountType::MSA: { - if(xboxApiToken.extra.contains("gtg")) { + if (xboxApiToken.extra.contains("gtg")) { return xboxApiToken.extra["gtg"].toString(); } return "Xbox profile missing"; @@ -492,6 +500,7 @@ QString AccountData::accountDisplayString() const { } } -QString AccountData::lastError() const { +QString AccountData::lastError() const +{ return errorString; } diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h index 092e1691d..38e3c3c90 100644 --- a/launcher/minecraft/auth/AccountData.h +++ b/launcher/minecraft/auth/AccountData.h @@ -34,11 +34,11 @@ */ #pragma once -#include -#include -#include #include +#include #include +#include +#include struct Skin { QString id; @@ -71,22 +71,9 @@ struct MinecraftProfile { Katabasis::Validity validity = Katabasis::Validity::None; }; -enum class AccountType { - MSA, - Mojang, - Offline -}; +enum class AccountType { MSA, Mojang, Offline }; -enum class AccountState { - Unchecked, - Offline, - Working, - Online, - Disabled, - Errored, - Expired, - Gone -}; +enum class AccountState { Unchecked, Offline, Working, Online, Disabled, Errored, Expired, Gone }; struct AccountData { QJsonObject saveState() const; diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 14e3ca7ca..3ef6a7584 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -37,14 +37,14 @@ #include "AccountData.h" #include "AccountTask.h" -#include +#include #include -#include -#include +#include #include +#include #include #include -#include +#include #include #include @@ -54,12 +54,10 @@ #include -enum AccountListVersion { - MojangOnly = 2, - MojangMSA = 3 -}; +enum AccountListVersion { MojangOnly = 2, MojangMSA = 3 }; -AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) { +AccountList::AccountList(QObject* parent) : QAbstractListModel(parent) +{ m_refreshTimer = new QTimer(this); m_refreshTimer->setSingleShot(true); connect(m_refreshTimer, &QTimer::timeout, this, &AccountList::fillQueue); @@ -70,7 +68,8 @@ AccountList::AccountList(QObject *parent) : QAbstractListModel(parent) { AccountList::~AccountList() noexcept {} -int AccountList::findAccountByProfileId(const QString& profileId) const { +int AccountList::findAccountByProfileId(const QString& profileId) const +{ for (int i = 0; i < count(); i++) { MinecraftAccountPtr account = at(i); if (account->profileId() == profileId) { @@ -80,7 +79,8 @@ int AccountList::findAccountByProfileId(const QString& profileId) const { return -1; } -MinecraftAccountPtr AccountList::getAccountByProfileName(const QString& profileName) const { +MinecraftAccountPtr AccountList::getAccountByProfileName(const QString& profileName) const +{ for (int i = 0; i < count(); i++) { MinecraftAccountPtr account = at(i); if (account->profileName() == profileName) { @@ -95,11 +95,12 @@ const MinecraftAccountPtr AccountList::at(int i) const return MinecraftAccountPtr(m_accounts.at(i)); } -QStringList AccountList::profileNames() const { +QStringList AccountList::profileNames() const +{ QStringList out; - for(auto & account: m_accounts) { - auto profileName = account->profileName(); - if(profileName.isEmpty()) { + for (auto& account : m_accounts) { + auto profileName = account->profileName(); + if (profileName.isEmpty()) { continue; } out.append(profileName); @@ -122,14 +123,14 @@ void AccountList::addAccount(const MinecraftAccountPtr account) // override/replace existing account with the same profileId auto profileId = account->profileId(); - if(profileId.size()) { + if (profileId.size()) { auto existingAccount = findAccountByProfileId(profileId); - if(existingAccount != -1) { + if (existingAccount != -1) { qDebug() << "Replacing old account with a new one with the same profile ID!"; MinecraftAccountPtr existingAccountPtr = m_accounts[existingAccount]; m_accounts[existingAccount] = account; - if(m_defaultAccount == existingAccountPtr) { + if (m_defaultAccount == existingAccountPtr) { m_defaultAccount = account; } // disconnect notifications for changes in the account being replaced @@ -154,11 +155,9 @@ void AccountList::addAccount(const MinecraftAccountPtr account) void AccountList::removeAccount(QModelIndex index) { int row = index.row(); - if(index.isValid() && row >= 0 && row < m_accounts.size()) - { - auto & account = m_accounts[row]; - if(account == m_defaultAccount) - { + if (index.isValid() && row >= 0 && row < m_accounts.size()) { + auto& account = m_accounts[row]; + if (account == m_defaultAccount) { m_defaultAccount = nullptr; onDefaultAccountChanged(); } @@ -178,43 +177,34 @@ MinecraftAccountPtr AccountList::defaultAccount() const void AccountList::setDefaultAccount(MinecraftAccountPtr newAccount) { - if (!newAccount && m_defaultAccount) - { + if (!newAccount && m_defaultAccount) { int idx = 0; auto previousDefaultAccount = m_defaultAccount; m_defaultAccount = nullptr; - for (MinecraftAccountPtr account : m_accounts) - { - if (account == previousDefaultAccount) - { + for (MinecraftAccountPtr account : m_accounts) { + if (account == previousDefaultAccount) { emit dataChanged(index(idx), index(idx, columnCount(QModelIndex()) - 1)); } - idx ++; + idx++; } onDefaultAccountChanged(); - } - else - { + } else { auto currentDefaultAccount = m_defaultAccount; int currentDefaultAccountIdx = -1; auto newDefaultAccount = m_defaultAccount; int newDefaultAccountIdx = -1; int idx = 0; - for (MinecraftAccountPtr account : m_accounts) - { - if (account == newAccount) - { + for (MinecraftAccountPtr account : m_accounts) { + if (account == newAccount) { newDefaultAccount = account; newDefaultAccountIdx = idx; } - if(currentDefaultAccount == account) - { + if (currentDefaultAccount == account) { currentDefaultAccountIdx = idx; } idx++; } - if(currentDefaultAccount != newDefaultAccount) - { + if (currentDefaultAccount != newDefaultAccount) { emit dataChanged(index(currentDefaultAccountIdx), index(currentDefaultAccountIdx, columnCount(QModelIndex()) - 1)); emit dataChanged(index(newDefaultAccountIdx), index(newDefaultAccountIdx, columnCount(QModelIndex()) - 1)); m_defaultAccount = newDefaultAccount; @@ -231,27 +221,25 @@ void AccountList::accountChanged() void AccountList::accountActivityChanged(bool active) { - MinecraftAccount *account = qobject_cast(sender()); + MinecraftAccount* account = qobject_cast(sender()); bool found = false; for (int i = 0; i < count(); i++) { if (at(i).get() == account) { - emit dataChanged(index(i), index(i, columnCount(QModelIndex()) - 1)); + emit dataChanged(index(i), index(i, columnCount(QModelIndex()) - 1)); found = true; break; } } - if(found) { + if (found) { emit listActivityChanged(); - if(active) { + if (active) { beginActivity(); - } - else { + } else { endActivity(); } } } - void AccountList::onListChanged() { if (m_autosave) @@ -274,7 +262,7 @@ int AccountList::count() const return m_accounts.count(); } -QVariant AccountList::data(const QModelIndex &index, int role) const +QVariant AccountList::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); @@ -284,70 +272,67 @@ QVariant AccountList::data(const QModelIndex &index, int role) const MinecraftAccountPtr account = at(index.row()); - switch (role) - { + switch (role) { case Qt::DisplayRole: - switch (index.column()) - { - case ProfileNameColumn: { - return account->profileName(); - } + switch (index.column()) { + case ProfileNameColumn: { + return account->profileName(); + } - case NameColumn: - return account->accountDisplayString(); + case NameColumn: + return account->accountDisplayString(); - case TypeColumn: { - auto typeStr = account->typeString(); - typeStr[0] = typeStr[0].toUpper(); - return typeStr; - } + case TypeColumn: { + auto typeStr = account->typeString(); + typeStr[0] = typeStr[0].toUpper(); + return typeStr; + } - case StatusColumn: { - switch(account->accountState()) { - case AccountState::Unchecked: { - return tr("Unchecked", "Account status"); - } - case AccountState::Offline: { - return tr("Offline", "Account status"); - } - case AccountState::Online: { - return tr("Ready", "Account status"); - } - case AccountState::Working: { - return tr("Working", "Account status"); - } - case AccountState::Errored: { - return tr("Errored", "Account status"); - } - case AccountState::Expired: { - return tr("Expired", "Account status"); - } - case AccountState::Disabled: { - return tr("Disabled", "Account status"); - } - case AccountState::Gone: { - return tr("Gone", "Account status"); - } - default: { - return tr("Unknown", "Account status"); + case StatusColumn: { + switch (account->accountState()) { + case AccountState::Unchecked: { + return tr("Unchecked", "Account status"); + } + case AccountState::Offline: { + return tr("Offline", "Account status"); + } + case AccountState::Online: { + return tr("Ready", "Account status"); + } + case AccountState::Working: { + return tr("Working", "Account status"); + } + case AccountState::Errored: { + return tr("Errored", "Account status"); + } + case AccountState::Expired: { + return tr("Expired", "Account status"); + } + case AccountState::Disabled: { + return tr("Disabled", "Account status"); + } + case AccountState::Gone: { + return tr("Gone", "Account status"); + } + default: { + return tr("Unknown", "Account status"); + } } } - } - case MigrationColumn: { - if(account->isMSA() || account->isOffline()) { - return tr("N/A", "Can Migrate"); + case MigrationColumn: { + if (account->isMSA() || account->isOffline()) { + return tr("N/A", "Can Migrate"); + } + if (account->canMigrate()) { + return tr("Yes", "Can Migrate"); + } else { + return tr("No", "Can Migrate"); + } } - if (account->canMigrate()) { - return tr("Yes", "Can Migrate"); - } - else { - return tr("No", "Can Migrate"); - } - } - default: - return QVariant(); + default: + return QVariant(); } case Qt::ToolTipRole: @@ -362,7 +347,6 @@ QVariant AccountList::data(const QModelIndex &index, int role) const } else { return QVariant(); } - default: return QVariant(); @@ -371,79 +355,72 @@ QVariant AccountList::data(const QModelIndex &index, int role) const QVariant AccountList::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { - switch (role) - { - case Qt::DisplayRole: - switch (section) - { - case ProfileNameColumn: - return tr("Username"); - case NameColumn: - return tr("Account"); - case TypeColumn: - return tr("Type"); - case StatusColumn: - return tr("Status"); - case MigrationColumn: - return tr("Can Migrate?"); + switch (role) { + case Qt::DisplayRole: + switch (section) { + case ProfileNameColumn: + return tr("Username"); + case NameColumn: + return tr("Account"); + case TypeColumn: + return tr("Type"); + case StatusColumn: + return tr("Status"); + case MigrationColumn: + return tr("Can Migrate?"); + default: + return QVariant(); + } + + case Qt::ToolTipRole: + switch (section) { + case ProfileNameColumn: + return tr("Minecraft username associated with the account."); + case NameColumn: + return tr("User name of the account."); + case TypeColumn: + return tr("Type of the account - Mojang or MSA."); + case StatusColumn: + return tr("Current status of the account."); + case MigrationColumn: + return tr("Can this account migrate to a Microsoft account?"); + default: + return QVariant(); + } + default: return QVariant(); - } - - case Qt::ToolTipRole: - switch (section) - { - case ProfileNameColumn: - return tr("Minecraft username associated with the account."); - case NameColumn: - return tr("User name of the account."); - case TypeColumn: - return tr("Type of the account - Mojang or MSA."); - case StatusColumn: - return tr("Current status of the account."); - case MigrationColumn: - return tr("Can this account migrate to a Microsoft account?"); - default: - return QVariant(); - } - - default: - return QVariant(); } } -int AccountList::rowCount(const QModelIndex &parent) const +int AccountList::rowCount(const QModelIndex& parent) const { // Return count return parent.isValid() ? 0 : count(); } -int AccountList::columnCount(const QModelIndex &parent) const +int AccountList::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : NUM_COLUMNS; } -Qt::ItemFlags AccountList::flags(const QModelIndex &index) const +Qt::ItemFlags AccountList::flags(const QModelIndex& index) const { - if (index.row() < 0 || index.row() >= rowCount(index.parent()) || !index.isValid()) - { + if (index.row() < 0 || index.row() >= rowCount(index.parent()) || !index.isValid()) { return Qt::NoItemFlags; } return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; } -bool AccountList::setData(const QModelIndex &idx, const QVariant &value, int role) +bool AccountList::setData(const QModelIndex& idx, const QVariant& value, int role) { - if (idx.row() < 0 || idx.row() >= rowCount(idx) || !idx.isValid()) - { + if (idx.row() < 0 || idx.row() >= rowCount(idx) || !idx.isValid()) { return false; } - if(role == Qt::CheckStateRole) - { - if(value == Qt::Checked) - { + if (role == Qt::CheckStateRole) { + if (value == Qt::Checked) { MinecraftAccountPtr account = at(idx.row()); setDefaultAccount(account); } @@ -455,8 +432,7 @@ bool AccountList::setData(const QModelIndex &idx, const QVariant &value, int rol bool AccountList::loadList() { - if (m_listFilePath.isEmpty()) - { + if (m_listFilePath.isEmpty()) { qCritical() << "Can't load Mojang account list. No file path given and no default set."; return false; } @@ -465,8 +441,7 @@ bool AccountList::loadList() // Try to open the file and fail if we can't. // TODO: We should probably report this error to the user. - if (!file.open(QIODevice::ReadOnly)) - { + if (!file.open(QIODevice::ReadOnly)) { qCritical() << QString("Failed to read the account list file (%1).").arg(m_listFilePath).toUtf8(); return false; } @@ -479,17 +454,15 @@ bool AccountList::loadList() QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError); // Fail if the JSON is invalid. - if (parseError.error != QJsonParseError::NoError) - { + if (parseError.error != QJsonParseError::NoError) { qCritical() << QString("Failed to parse account list file: %1 at offset %2") - .arg(parseError.errorString(), QString::number(parseError.offset)) - .toUtf8(); + .arg(parseError.errorString(), QString::number(parseError.offset)) + .toUtf8(); return false; } // Make sure the root is an object. - if (!jsonDoc.isObject()) - { + if (!jsonDoc.isObject()) { qCritical() << "Invalid account list JSON: Root should be an array."; return false; } @@ -498,15 +471,13 @@ bool AccountList::loadList() // Make sure the format version matches. auto listVersion = root.value("formatVersion").toVariant().toInt(); - switch(listVersion) { + switch (listVersion) { case AccountListVersion::MojangOnly: { return loadV2(root); - } - break; + } break; case AccountListVersion::MojangMSA: { return loadV3(root); - } - break; + } break; default: { QString newName = "accounts-old.json"; qWarning() << "Unknown format version when loading account list. Existing one will be renamed to" << newName; @@ -517,21 +488,20 @@ bool AccountList::loadList() } } -bool AccountList::loadV2(QJsonObject& root) { +bool AccountList::loadV2(QJsonObject& root) +{ beginResetModel(); auto defaultUserName = root.value("activeAccount").toString(""); QJsonArray accounts = root.value("accounts").toArray(); - for (QJsonValue accountVal : accounts) - { + for (QJsonValue accountVal : accounts) { QJsonObject accountObj = accountVal.toObject(); MinecraftAccountPtr account = MinecraftAccount::loadFromJsonV2(accountObj); - if (account.get() != nullptr) - { + if (account.get() != nullptr) { auto profileId = account->profileId(); - if(!profileId.size()) { + if (!profileId.size()) { continue; } - if(findAccountByProfileId(profileId) != -1) { + if (findAccountByProfileId(profileId) != -1) { continue; } connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged); @@ -540,9 +510,7 @@ bool AccountList::loadV2(QJsonObject& root) { if (defaultUserName.size() && account->mojangUserName() == defaultUserName) { m_defaultAccount = account; } - } - else - { + } else { qWarning() << "Failed to load an account."; } } @@ -550,30 +518,27 @@ bool AccountList::loadV2(QJsonObject& root) { return true; } -bool AccountList::loadV3(QJsonObject& root) { +bool AccountList::loadV3(QJsonObject& root) +{ beginResetModel(); QJsonArray accounts = root.value("accounts").toArray(); - for (QJsonValue accountVal : accounts) - { + for (QJsonValue accountVal : accounts) { QJsonObject accountObj = accountVal.toObject(); MinecraftAccountPtr account = MinecraftAccount::loadFromJsonV3(accountObj); - if (account.get() != nullptr) - { + if (account.get() != nullptr) { auto profileId = account->profileId(); - if(profileId.size()) { - if(findAccountByProfileId(profileId) != -1) { + if (profileId.size()) { + if (findAccountByProfileId(profileId) != -1) { continue; } } connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged); connect(account.get(), &MinecraftAccount::activityChanged, this, &AccountList::accountActivityChanged); m_accounts.append(account); - if(accountObj.value("active").toBool(false)) { + if (accountObj.value("active").toBool(false)) { m_defaultAccount = account; } - } - else - { + } else { qWarning() << "Failed to load an account."; } } @@ -581,23 +546,20 @@ bool AccountList::loadV3(QJsonObject& root) { return true; } - bool AccountList::saveList() { - if (m_listFilePath.isEmpty()) - { + if (m_listFilePath.isEmpty()) { qCritical() << "Can't save Mojang account list. No file path given and no default set."; return false; } // make sure the parent folder exists - if(!FS::ensureFilePathExists(m_listFilePath)) + if (!FS::ensureFilePathExists(m_listFilePath)) return false; // make sure the file wasn't overwritten with a folder before (fixes a bug) QFileInfo finfo(m_listFilePath); - if(finfo.isDir()) - { + if (finfo.isDir()) { QDir badDir(m_listFilePath); badDir.removeRecursively(); } @@ -613,10 +575,9 @@ bool AccountList::saveList() // Build a list of accounts. qDebug() << "Building account array."; QJsonArray accounts; - for (MinecraftAccountPtr account : m_accounts) - { + for (MinecraftAccountPtr account : m_accounts) { QJsonObject accountObj = account->saveToJson(); - if(m_defaultAccount == account) { + if (m_defaultAccount == account) { accountObj["active"] = true; } accounts.append(accountObj); @@ -634,20 +595,18 @@ bool AccountList::saveList() // Try to open the file and fail if we can't. // TODO: We should probably report this error to the user. - if (!file.open(QIODevice::WriteOnly)) - { + if (!file.open(QIODevice::WriteOnly)) { qCritical() << QString("Failed to read the account list file (%1).").arg(m_listFilePath).toUtf8(); return false; } // Write the JSON to the file. file.write(doc.toJson()); - file.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser); - if(file.commit()) { + file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser); + if (file.commit()) { qDebug() << "Saved account list to" << m_listFilePath; return true; - } - else { + } else { qDebug() << "Failed to save accounts to" << m_listFilePath; return false; } @@ -661,30 +620,29 @@ void AccountList::setListFilePath(QString path, bool autosave) bool AccountList::anyAccountIsValid() { - for(auto account: m_accounts) - { - if(account->ownsMinecraft()) { + for (auto account : m_accounts) { + if (account->ownsMinecraft()) { return true; } } return false; } -void AccountList::fillQueue() { - - if(m_defaultAccount && m_defaultAccount->shouldRefresh()) { +void AccountList::fillQueue() +{ + if (m_defaultAccount && m_defaultAccount->shouldRefresh()) { auto idToRefresh = m_defaultAccount->internalId(); m_refreshQueue.push_back(idToRefresh); qDebug() << "AccountList: Queued default account with internal ID " << idToRefresh << " to refresh first"; } - for(int i = 0; i < count(); i++) { + for (int i = 0; i < count(); i++) { auto account = at(i); - if(account == m_defaultAccount) { + if (account == m_defaultAccount) { continue; } - if(account->shouldRefresh()) { + if (account->shouldRefresh()) { auto idToRefresh = account->internalId(); queueRefresh(idToRefresh); } @@ -692,40 +650,43 @@ void AccountList::fillQueue() { tryNext(); } -void AccountList::requestRefresh(QString accountId) { +void AccountList::requestRefresh(QString accountId) +{ auto index = m_refreshQueue.indexOf(accountId); - if(index != -1) { + if (index != -1) { m_refreshQueue.removeAt(index); } m_refreshQueue.push_front(accountId); qDebug() << "AccountList: Pushed account with internal ID " << accountId << " to the front of the queue"; - if(!isActive()) { + if (!isActive()) { tryNext(); } } -void AccountList::queueRefresh(QString accountId) { - if(m_refreshQueue.indexOf(accountId) != -1) { +void AccountList::queueRefresh(QString accountId) +{ + if (m_refreshQueue.indexOf(accountId) != -1) { return; } m_refreshQueue.push_back(accountId); qDebug() << "AccountList: Queued account with internal ID " << accountId << " to refresh"; } - -void AccountList::tryNext() { +void AccountList::tryNext() +{ while (m_refreshQueue.length()) { auto accountId = m_refreshQueue.front(); m_refreshQueue.pop_front(); - for(int i = 0; i < count(); i++) { + for (int i = 0; i < count(); i++) { auto account = at(i); - if(account->internalId() == accountId) { + if (account->internalId() == accountId) { m_currentTask = account->refresh(); - if(m_currentTask) { + if (m_currentTask) { connect(m_currentTask.get(), &AccountTask::succeeded, this, &AccountList::authSucceeded); connect(m_currentTask.get(), &AccountTask::failed, this, &AccountList::authFailed); m_currentTask->start(); - qDebug() << "RefreshSchedule: Processing account " << account->accountDisplayString() << " with internal ID " << accountId; + qDebug() << "RefreshSchedule: Processing account " << account->accountDisplayString() << " with internal ID " + << accountId; return; } } @@ -736,38 +697,43 @@ void AccountList::tryNext() { m_refreshTimer->start(1000 * 3600); } -void AccountList::authSucceeded() { +void AccountList::authSucceeded() +{ qDebug() << "RefreshSchedule: Background account refresh succeeded"; m_currentTask.reset(); m_nextTimer->start(1000 * 20); } -void AccountList::authFailed(QString reason) { +void AccountList::authFailed(QString reason) +{ qDebug() << "RefreshSchedule: Background account refresh failed: " << reason; m_currentTask.reset(); m_nextTimer->start(1000 * 20); } -bool AccountList::isActive() const { +bool AccountList::isActive() const +{ return m_activityCount != 0; } -void AccountList::beginActivity() { +void AccountList::beginActivity() +{ bool activating = m_activityCount == 0; m_activityCount++; - if(activating) { + if (activating) { emit activityChanged(true); } } -void AccountList::endActivity() { - if(m_activityCount == 0) { +void AccountList::endActivity() +{ + if (m_activityCount == 0) { qWarning() << m_name << " - Activity count would become below zero"; return; } bool deactivating = m_activityCount == 1; m_activityCount--; - if(deactivating) { + if (deactivating) { emit activityChanged(false); } } diff --git a/launcher/minecraft/auth/AccountList.h b/launcher/minecraft/auth/AccountList.h index a8c3529ac..30926d13f 100644 --- a/launcher/minecraft/auth/AccountList.h +++ b/launcher/minecraft/auth/AccountList.h @@ -37,26 +37,21 @@ #include "MinecraftAccount.h" -#include -#include #include +#include #include +#include /*! * List of available Mojang accounts. * This should be loaded in the background by Prism Launcher on startup. */ -class AccountList : public QAbstractListModel -{ +class AccountList : public QAbstractListModel { Q_OBJECT -public: - enum ModelRoles - { - PointerRole = 0x34B1CB48 - }; + public: + enum ModelRoles { PointerRole = 0x34B1CB48 }; - enum VListColumns - { + enum VListColumns { // TODO: Add icon column. ProfileNameColumn = 0, NameColumn, @@ -67,24 +62,24 @@ public: NUM_COLUMNS }; - explicit AccountList(QObject *parent = 0); + explicit AccountList(QObject* parent = 0); virtual ~AccountList() noexcept; const MinecraftAccountPtr at(int i) const; int count() const; //////// List Model Functions //////// - QVariant data(const QModelIndex &index, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - virtual int rowCount(const QModelIndex &parent) const override; - virtual int columnCount(const QModelIndex &parent) const override; - virtual Qt::ItemFlags flags(const QModelIndex &index) const override; - virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override; + virtual int rowCount(const QModelIndex& parent) const override; + virtual int columnCount(const QModelIndex& parent) const override; + virtual Qt::ItemFlags flags(const QModelIndex& index) const override; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role) override; void addAccount(const MinecraftAccountPtr account); void removeAccount(QModelIndex index); - int findAccountByProfileId(const QString &profileId) const; - MinecraftAccountPtr getAccountByProfileName(const QString &profileName) const; + int findAccountByProfileId(const QString& profileId) const; + MinecraftAccountPtr getAccountByProfileName(const QString& profileName) const; QStringList profileNames() const; // requesting a refresh pushes it to the front of the queue @@ -102,8 +97,8 @@ public: void setListFilePath(QString path, bool autosave = false); bool loadList(); - bool loadV2(QJsonObject &root); - bool loadV3(QJsonObject &root); + bool loadV2(QJsonObject& root); + bool loadV3(QJsonObject& root); bool saveList(); MinecraftAccountPtr defaultAccount() const; @@ -112,20 +107,20 @@ public: bool isActive() const; -protected: + protected: void beginActivity(); void endActivity(); -private: + private: const char* m_name; uint32_t m_activityCount = 0; -signals: + signals: void listChanged(); void listActivityChanged(); void defaultAccountChanged(); void activityChanged(bool active); -public slots: + public slots: /** * This is called when one of the accounts changes and the list needs to be updated */ @@ -141,16 +136,16 @@ public slots: */ void fillQueue(); -private slots: + private slots: void tryNext(); void authSucceeded(); void authFailed(QString reason); -protected: + protected: QList m_refreshQueue; - QTimer *m_refreshTimer; - QTimer *m_nextTimer; + QTimer* m_refreshTimer; + QTimer* m_nextTimer; shared_qobject_ptr m_currentTask; /*! @@ -178,4 +173,3 @@ protected: */ bool m_autosave = false; }; - diff --git a/launcher/minecraft/auth/AccountTask.cpp b/launcher/minecraft/auth/AccountTask.cpp index 4118c3c5d..896607197 100644 --- a/launcher/minecraft/auth/AccountTask.cpp +++ b/launcher/minecraft/auth/AccountTask.cpp @@ -36,43 +36,41 @@ #include "AccountTask.h" #include "MinecraftAccount.h" +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -AccountTask::AccountTask(AccountData *data, QObject *parent) - : Task(parent), m_data(data) +AccountTask::AccountTask(AccountData* data, QObject* parent) : Task(parent), m_data(data) { changeState(AccountTaskState::STATE_CREATED); } QString AccountTask::getStateMessage() const { - switch (m_taskState) - { - case AccountTaskState::STATE_CREATED: - return "Waiting..."; - case AccountTaskState::STATE_WORKING: - return tr("Sending request to auth servers..."); - case AccountTaskState::STATE_SUCCEEDED: - return tr("Authentication task succeeded."); - case AccountTaskState::STATE_OFFLINE: - return tr("Failed to contact the authentication server."); - case AccountTaskState::STATE_DISABLED: - return tr("Client ID has changed. New session needs to be created."); - case AccountTaskState::STATE_FAILED_SOFT: - return tr("Encountered an error during authentication."); - case AccountTaskState::STATE_FAILED_HARD: - return tr("Failed to authenticate. The session has expired."); - case AccountTaskState::STATE_FAILED_GONE: - return tr("Failed to authenticate. The account no longer exists."); - default: - return tr("..."); + switch (m_taskState) { + case AccountTaskState::STATE_CREATED: + return "Waiting..."; + case AccountTaskState::STATE_WORKING: + return tr("Sending request to auth servers..."); + case AccountTaskState::STATE_SUCCEEDED: + return tr("Authentication task succeeded."); + case AccountTaskState::STATE_OFFLINE: + return tr("Failed to contact the authentication server."); + case AccountTaskState::STATE_DISABLED: + return tr("Client ID has changed. New session needs to be created."); + case AccountTaskState::STATE_FAILED_SOFT: + return tr("Encountered an error during authentication."); + case AccountTaskState::STATE_FAILED_HARD: + return tr("Failed to authenticate. The session has expired."); + case AccountTaskState::STATE_FAILED_GONE: + return tr("Failed to authenticate. The account no longer exists."); + default: + return tr("..."); } } @@ -82,7 +80,7 @@ bool AccountTask::changeState(AccountTaskState newState, QString reason) // FIXME: virtual method invoked in constructor. // We want that behavior, but maybe make it less weird? setStatus(getStateMessage()); - switch(newState) { + switch (newState) { case AccountTaskState::STATE_CREATED: { m_data->errorString.clear(); return true; diff --git a/launcher/minecraft/auth/AccountTask.h b/launcher/minecraft/auth/AccountTask.h index 1bd6c59f3..68bbfe5fa 100644 --- a/launcher/minecraft/auth/AccountTask.h +++ b/launcher/minecraft/auth/AccountTask.h @@ -37,10 +37,10 @@ #include -#include -#include -#include #include +#include +#include +#include #include "MinecraftAccount.h" @@ -50,37 +50,32 @@ class QNetworkReply; * Enum for describing the state of the current task. * Used by the getStateMessage function to determine what the status message should be. */ -enum class AccountTaskState -{ +enum class AccountTaskState { STATE_CREATED, STATE_WORKING, STATE_SUCCEEDED, - STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn - STATE_FAILED_SOFT, //!< soft failure. authentication went through partially - STATE_FAILED_HARD, //!< hard failure. main tokens are invalid - STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists - STATE_OFFLINE //!< soft failure. authentication failed in the first step in a 'soft' way + STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn + STATE_FAILED_SOFT, //!< soft failure. authentication went through partially + STATE_FAILED_HARD, //!< hard failure. main tokens are invalid + STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists + STATE_OFFLINE //!< soft failure. authentication failed in the first step in a 'soft' way }; -class AccountTask : public Task -{ +class AccountTask : public Task { Q_OBJECT -public: - explicit AccountTask(AccountData * data, QObject *parent = 0); - virtual ~AccountTask() {}; + public: + explicit AccountTask(AccountData* data, QObject* parent = 0); + virtual ~AccountTask(){}; AccountTaskState m_taskState = AccountTaskState::STATE_CREATED; - AccountTaskState taskState() { - return m_taskState; - } + AccountTaskState taskState() { return m_taskState; } -signals: - void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn); + signals: + void showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn); void hideVerificationUriAndCode(); -protected: - + protected: /** * Returns the state message for the given state. * Used to set the status message for the task. @@ -88,10 +83,10 @@ protected: */ virtual QString getStateMessage() const; -protected slots: + protected slots: // NOTE: true -> non-terminal state, false -> terminal state bool changeState(AccountTaskState newState, QString reason = QString()); -protected: - AccountData *m_data = nullptr; + protected: + AccountData* m_data = nullptr; }; diff --git a/launcher/minecraft/auth/AuthRequest.cpp b/launcher/minecraft/auth/AuthRequest.cpp index a21634b7a..bd48a059d 100644 --- a/launcher/minecraft/auth/AuthRequest.cpp +++ b/launcher/minecraft/auth/AuthRequest.cpp @@ -35,44 +35,44 @@ #include +#include #include #include -#include #include #include "Application.h" #include "AuthRequest.h" #include "katabasis/Globals.h" -AuthRequest::AuthRequest(QObject *parent): QObject(parent) { -} +AuthRequest::AuthRequest(QObject* parent) : QObject(parent) {} -AuthRequest::~AuthRequest() { -} +AuthRequest::~AuthRequest() {} -void AuthRequest::get(const QNetworkRequest &req, int timeout/* = 60*1000*/) { +void AuthRequest::get(const QNetworkRequest& req, int timeout /* = 60*1000*/) +{ setup(req, QNetworkAccessManager::GetOperation); reply_ = APPLICATION->network()->get(request_); status_ = Requesting; timedReplies_.add(new Katabasis::Reply(reply_, timeout)); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(reply_, &QNetworkReply::errorOccurred, this, &AuthRequest::onRequestError); -#else // &QNetworkReply::error SIGNAL depricated +#else // &QNetworkReply::error SIGNAL depricated connect(reply_, QOverload::of(&QNetworkReply::error), this, &AuthRequest::onRequestError); #endif connect(reply_, &QNetworkReply::finished, this, &AuthRequest::onRequestFinished); connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors); } -void AuthRequest::post(const QNetworkRequest &req, const QByteArray &data, int timeout/* = 60*1000*/) { +void AuthRequest::post(const QNetworkRequest& req, const QByteArray& data, int timeout /* = 60*1000*/) +{ setup(req, QNetworkAccessManager::PostOperation); data_ = data; status_ = Requesting; reply_ = APPLICATION->network()->post(request_, data_); timedReplies_.add(new Katabasis::Reply(reply_, timeout)); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(reply_, &QNetworkReply::errorOccurred, this, &AuthRequest::onRequestError); -#else // &QNetworkReply::error SIGNAL depricated +#else // &QNetworkReply::error SIGNAL depricated connect(reply_, QOverload::of(&QNetworkReply::error), this, &AuthRequest::onRequestError); #endif connect(reply_, &QNetworkReply::finished, this, &AuthRequest::onRequestFinished); @@ -80,35 +80,39 @@ void AuthRequest::post(const QNetworkRequest &req, const QByteArray &data, int t connect(reply_, &QNetworkReply::uploadProgress, this, &AuthRequest::onUploadProgress); } -void AuthRequest::onRequestFinished() { +void AuthRequest::onRequestFinished() +{ if (status_ == Idle) { return; } - if (reply_ != qobject_cast(sender())) { + if (reply_ != qobject_cast(sender())) { return; } httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); finish(); } -void AuthRequest::onRequestError(QNetworkReply::NetworkError error) { +void AuthRequest::onRequestError(QNetworkReply::NetworkError error) +{ qWarning() << "AuthRequest::onRequestError: Error" << (int)error; if (status_ == Idle) { return; } - if (reply_ != qobject_cast(sender())) { + if (reply_ != qobject_cast(sender())) { return; } errorString_ = reply_->errorString(); httpStatus_ = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); error_ = error; qWarning() << "AuthRequest::onRequestError: Error string: " << errorString_; - qWarning() << "AuthRequest::onRequestError: HTTP status" << httpStatus_ << reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); + qWarning() << "AuthRequest::onRequestError: HTTP status" << httpStatus_ + << reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); // QTimer::singleShot(10, this, SLOT(finish())); } -void AuthRequest::onSslErrors(QList errors) { +void AuthRequest::onSslErrors(QList errors) +{ int i = 1; for (auto error : errors) { qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString(); @@ -118,23 +122,25 @@ void AuthRequest::onSslErrors(QList errors) { } } -void AuthRequest::onUploadProgress(qint64 uploaded, qint64 total) { +void AuthRequest::onUploadProgress(qint64 uploaded, qint64 total) +{ if (status_ == Idle) { qWarning() << "AuthRequest::onUploadProgress: No pending request"; return; } - if (reply_ != qobject_cast(sender())) { + if (reply_ != qobject_cast(sender())) { return; } // Restart timeout because request in progress - Katabasis::Reply *o2Reply = timedReplies_.find(reply_); - if(o2Reply) { + Katabasis::Reply* o2Reply = timedReplies_.find(reply_); + if (o2Reply) { o2Reply->start(); } emit uploadProgress(uploaded, total); } -void AuthRequest::setup(const QNetworkRequest &req, QNetworkAccessManager::Operation operation, const QByteArray &verb) { +void AuthRequest::setup(const QNetworkRequest& req, QNetworkAccessManager::Operation operation, const QByteArray& verb) +{ request_ = req; operation_ = operation; url_ = req.url(); @@ -152,7 +158,8 @@ void AuthRequest::setup(const QNetworkRequest &req, QNetworkAccessManager::Opera httpStatus_ = 0; } -void AuthRequest::finish() { +void AuthRequest::finish() +{ QByteArray data; if (status_ == Idle) { qWarning() << "AuthRequest::finish: No pending request"; diff --git a/launcher/minecraft/auth/AuthRequest.h b/launcher/minecraft/auth/AuthRequest.h index 89f7a123e..84d2a7d68 100644 --- a/launcher/minecraft/auth/AuthRequest.h +++ b/launcher/minecraft/auth/AuthRequest.h @@ -1,27 +1,26 @@ #pragma once -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include "katabasis/Reply.h" /// Makes authentication requests. -class AuthRequest: public QObject { +class AuthRequest : public QObject { Q_OBJECT -public: - explicit AuthRequest(QObject *parent = 0); + public: + explicit AuthRequest(QObject* parent = 0); ~AuthRequest(); -public slots: - void get(const QNetworkRequest &req, int timeout = 60*1000); - void post(const QNetworkRequest &req, const QByteArray &data, int timeout = 60*1000); + public slots: + void get(const QNetworkRequest& req, int timeout = 60 * 1000); + void post(const QNetworkRequest& req, const QByteArray& data, int timeout = 60 * 1000); - -signals: + signals: /// Emitted when a request has been completed or failed. void finished(QNetworkReply::NetworkError error, QByteArray data, QList headers); @@ -29,7 +28,7 @@ signals: /// Emitted when an upload has progressed. void uploadProgress(qint64 bytesSent, qint64 bytesTotal); -protected slots: + protected slots: /// Handle request finished. void onRequestFinished(); @@ -46,25 +45,23 @@ protected slots: /// Handle upload progress. void onUploadProgress(qint64 uploaded, qint64 total); -public: + public: QNetworkReply::NetworkError error_; int httpStatus_ = 0; QString errorString_; -protected: - void setup(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &verb = QByteArray()); + protected: + void setup(const QNetworkRequest& request, QNetworkAccessManager::Operation operation, const QByteArray& verb = QByteArray()); - enum Status { - Idle, Requesting, ReRequesting - }; + enum Status { Idle, Requesting, ReRequesting }; QNetworkRequest request_; QByteArray data_; - QNetworkReply *reply_; + QNetworkReply* reply_; Status status_; QNetworkAccessManager::Operation operation_; QUrl url_; Katabasis::ReplyList timedReplies_; - QTimer *timer_; + QTimer* timer_; }; diff --git a/launcher/minecraft/auth/AuthSession.cpp b/launcher/minecraft/auth/AuthSession.cpp index 2c06beaa2..37534f983 100644 --- a/launcher/minecraft/auth/AuthSession.cpp +++ b/launcher/minecraft/auth/AuthSession.cpp @@ -1,7 +1,7 @@ #include "AuthSession.h" -#include #include #include +#include #include QString AuthSession::serializeUserProperties() @@ -16,13 +16,11 @@ QString AuthSession::serializeUserProperties() */ QJsonDocument value(userAttrs); return value.toJson(QJsonDocument::Compact); - } bool AuthSession::MakeOffline(QString offline_playername) { - if (status != PlayableOffline && status != PlayableOnline) - { + if (status != PlayableOffline && status != PlayableOnline) { return false; } session = "-"; @@ -32,7 +30,8 @@ bool AuthSession::MakeOffline(QString offline_playername) return true; } -void AuthSession::MakeDemo() { +void AuthSession::MakeDemo() +{ player_name = "Player"; demo = true; } diff --git a/launcher/minecraft/auth/AuthSession.h b/launcher/minecraft/auth/AuthSession.h index a75df506b..40519476d 100644 --- a/launcher/minecraft/auth/AuthSession.h +++ b/launcher/minecraft/auth/AuthSession.h @@ -1,22 +1,20 @@ #pragma once -#include #include +#include #include #include "QObjectPtr.h" class MinecraftAccount; class QNetworkAccessManager; -struct AuthSession -{ +struct AuthSession { bool MakeOffline(QString offline_playername); void MakeDemo(); QString serializeUserProperties(); - enum Status - { + enum Status { Undetermined, RequiresOAuth, RequiresPassword, @@ -45,7 +43,7 @@ struct AuthSession // Did the user request online mode? bool wants_online = true; - //Is this a demo session? + // Is this a demo session? bool demo = false; }; diff --git a/launcher/minecraft/auth/AuthStep.cpp b/launcher/minecraft/auth/AuthStep.cpp index ffa2581b6..6240cc549 100644 --- a/launcher/minecraft/auth/AuthStep.cpp +++ b/launcher/minecraft/auth/AuthStep.cpp @@ -1,7 +1,5 @@ #include "AuthStep.h" -AuthStep::AuthStep(AccountData *data) : QObject(nullptr), m_data(data) { -} +AuthStep::AuthStep(AccountData* data) : QObject(nullptr), m_data(data) {} AuthStep::~AuthStep() noexcept = default; - diff --git a/launcher/minecraft/auth/AuthStep.h b/launcher/minecraft/auth/AuthStep.h index 2a8dc2cac..becd9b0c5 100644 --- a/launcher/minecraft/auth/AuthStep.h +++ b/launcher/minecraft/auth/AuthStep.h @@ -1,33 +1,33 @@ #pragma once -#include #include #include +#include +#include "AccountTask.h" #include "QObjectPtr.h" #include "minecraft/auth/AccountData.h" -#include "AccountTask.h" class AuthStep : public QObject { Q_OBJECT -public: + public: using Ptr = shared_qobject_ptr; -public: - explicit AuthStep(AccountData *data); + public: + explicit AuthStep(AccountData* data); virtual ~AuthStep() noexcept; virtual QString describe() = 0; -public slots: + public slots: virtual void perform() = 0; virtual void rehydrate() = 0; -signals: + signals: void finished(AccountTaskState resultingState, QString message); - void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn); + void showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn); void hideVerificationUriAndCode(); -protected: - AccountData *m_data; + protected: + AccountData* m_data; }; diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 5d279af1c..e8422a6f3 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -38,12 +38,12 @@ #include "MinecraftAccount.h" #include -#include -#include #include +#include +#include #include #include -#include +#include #include @@ -53,28 +53,30 @@ #include "flows/Mojang.h" #include "flows/Offline.h" -MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) { +MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) +{ data.internalId = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); } - -MinecraftAccountPtr MinecraftAccount::loadFromJsonV2(const QJsonObject& json) { +MinecraftAccountPtr MinecraftAccount::loadFromJsonV2(const QJsonObject& json) +{ MinecraftAccountPtr account(new MinecraftAccount()); - if(account->data.resumeStateFromV2(json)) { + if (account->data.resumeStateFromV2(json)) { return account; } return nullptr; } -MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json) { +MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json) +{ MinecraftAccountPtr account(new MinecraftAccount()); - if(account->data.resumeStateFromV3(json)) { + if (account->data.resumeStateFromV3(json)) { return account; } return nullptr; } -MinecraftAccountPtr MinecraftAccount::createFromUsername(const QString &username) +MinecraftAccountPtr MinecraftAccount::createFromUsername(const QString& username) { auto account = makeShared(); account->data.type = AccountType::Mojang; @@ -90,7 +92,7 @@ MinecraftAccountPtr MinecraftAccount::createBlankMSA() return account; } -MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username) +MinecraftAccountPtr MinecraftAccount::createOffline(const QString& username) { auto account = makeShared(); account->data.type = AccountType::Offline; @@ -107,19 +109,20 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username) return account; } - QJsonObject MinecraftAccount::saveToJson() const { return data.saveState(); } -AccountState MinecraftAccount::accountState() const { +AccountState MinecraftAccount::accountState() const +{ return data.accountState; } -QPixmap MinecraftAccount::getFace() const { +QPixmap MinecraftAccount::getFace() const +{ QPixmap skinTexture; - if(!skinTexture.loadFromData(data.minecraftProfile.skin.data, "PNG")) { + if (!skinTexture.loadFromData(data.minecraftProfile.skin.data, "PNG")) { return QPixmap(); } QPixmap skin = QPixmap(8, 8); @@ -129,67 +132,68 @@ QPixmap MinecraftAccount::getFace() const { return skin.scaled(64, 64, Qt::KeepAspectRatio); } - -shared_qobject_ptr MinecraftAccount::login(QString password) { +shared_qobject_ptr MinecraftAccount::login(QString password) +{ Q_ASSERT(m_currentTask.get() == nullptr); m_currentTask.reset(new MojangLogin(&data, password)); connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); - connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); + connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; } -shared_qobject_ptr MinecraftAccount::loginMSA() { +shared_qobject_ptr MinecraftAccount::loginMSA() +{ Q_ASSERT(m_currentTask.get() == nullptr); m_currentTask.reset(new MSAInteractive(&data)); connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); - connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); + connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; } -shared_qobject_ptr MinecraftAccount::loginOffline() { +shared_qobject_ptr MinecraftAccount::loginOffline() +{ Q_ASSERT(m_currentTask.get() == nullptr); m_currentTask.reset(new OfflineLogin(&data)); connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); - connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); + connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; } -shared_qobject_ptr MinecraftAccount::refresh() { - if(m_currentTask) { +shared_qobject_ptr MinecraftAccount::refresh() +{ + if (m_currentTask) { return m_currentTask; } - if(data.type == AccountType::MSA) { + if (data.type == AccountType::MSA) { m_currentTask.reset(new MSASilent(&data)); - } - else if(data.type == AccountType::Offline) { + } else if (data.type == AccountType::Offline) { m_currentTask.reset(new OfflineRefresh(&data)); - } - else { + } else { m_currentTask.reset(new MojangRefresh(&data)); } connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); - connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); + connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; } -shared_qobject_ptr MinecraftAccount::currentTask() { +shared_qobject_ptr MinecraftAccount::currentTask() +{ return m_currentTask; } - void MinecraftAccount::authSucceeded() { m_currentTask.reset(); @@ -206,28 +210,24 @@ void MinecraftAccount::authFailed(QString reason) } case AccountTaskState::STATE_FAILED_SOFT: { // NOTE: this doesn't do much. There was an error of some sort. - } - break; + } break; case AccountTaskState::STATE_FAILED_HARD: { - if(isMSA()) { + if (isMSA()) { data.msaToken.token = QString(); data.msaToken.refresh_token = QString(); data.msaToken.validity = Katabasis::Validity::None; data.validity_ = Katabasis::Validity::None; - } - else { + } else { data.yggdrasilToken.token = QString(); data.yggdrasilToken.validity = Katabasis::Validity::None; data.validity_ = Katabasis::Validity::None; } emit changed(); - } - break; + } break; case AccountTaskState::STATE_FAILED_GONE: { data.validity_ = Katabasis::Validity::None; emit changed(); - } - break; + } break; case AccountTaskState::STATE_CREATED: case AccountTaskState::STATE_WORKING: case AccountTaskState::STATE_SUCCEEDED: { @@ -238,21 +238,23 @@ void MinecraftAccount::authFailed(QString reason) emit activityChanged(false); } -bool MinecraftAccount::isActive() const { +bool MinecraftAccount::isActive() const +{ return !m_currentTask.isNull(); } -bool MinecraftAccount::shouldRefresh() const { +bool MinecraftAccount::shouldRefresh() const +{ /* * Never refresh accounts that are being used by the game, it breaks the game session. * Always refresh accounts that have not been refreshed yet during this session. * Don't refresh broken accounts. * Refresh accounts that would expire in the next 12 hours (fresh token validity is 24 hours). */ - if(isInUse()) { + if (isInUse()) { return false; } - switch(data.validity_) { + switch (data.validity_) { case Katabasis::Validity::Certain: { break; } @@ -267,7 +269,7 @@ bool MinecraftAccount::shouldRefresh() const { auto issuedTimestamp = data.yggdrasilToken.issueInstant; auto expiresTimestamp = data.yggdrasilToken.notAfter; - if(!expiresTimestamp.isValid()) { + if (!expiresTimestamp.isValid()) { expiresTimestamp = issuedTimestamp.addSecs(24 * 3600); } if (now.secsTo(expiresTimestamp) < (12 * 3600)) { @@ -278,14 +280,12 @@ bool MinecraftAccount::shouldRefresh() const { void MinecraftAccount::fillSession(AuthSessionPtr session) { - if(ownsMinecraft() && !hasProfile()) { + if (ownsMinecraft() && !hasProfile()) { session->status = AuthSession::RequiresProfileSetup; - } - else { - if(session->wants_online) { + } else { + if (session->wants_online) { session->status = AuthSession::PlayableOnline; - } - else { + } else { session->status = AuthSession::PlayableOffline; } } @@ -303,12 +303,9 @@ void MinecraftAccount::fillSession(AuthSessionPtr session) session->uuid = data.profileId(); // 'legacy' or 'mojang', depending on account type session->user_type = typeString(); - if (!session->access_token.isEmpty()) - { + if (!session->access_token.isEmpty()) { session->session = "token:" + data.accessToken() + ":" + data.profileId(); - } - else - { + } else { session->session = "-"; } } @@ -316,8 +313,7 @@ void MinecraftAccount::fillSession(AuthSessionPtr session) void MinecraftAccount::decrementUses() { Usable::decrementUses(); - if(!isInUse()) - { + if (!isInUse()) { emit changed(); // FIXME: we now need a better way to identify accounts... qWarning() << "Profile" << data.profileId() << "is no longer in use."; @@ -328,39 +324,31 @@ void MinecraftAccount::incrementUses() { bool wasInUse = isInUse(); Usable::incrementUses(); - if(!wasInUse) - { + if (!wasInUse) { emit changed(); // FIXME: we now need a better way to identify accounts... qWarning() << "Profile" << data.profileId() << "is now in use."; } } -QUuid MinecraftAccount::uuidFromUsername(QString username) { +QUuid MinecraftAccount::uuidFromUsername(QString username) +{ auto input = QString("OfflinePlayer:%1").arg(username).toUtf8(); // basically a reimplementation of Java's UUID#nameUUIDFromBytes QByteArray digest = QCryptographicHash::hash(input, QCryptographicHash::Md5); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - auto bOr = [](QByteArray& array, int index, char value) { - array[index] = array.at(index) | value; - }; - auto bAnd = [](QByteArray& array, int index, char value) { - array[index] = array.at(index) & value; - }; + auto bOr = [](QByteArray& array, int index, char value) { array[index] = array.at(index) | value; }; + auto bAnd = [](QByteArray& array, int index, char value) { array[index] = array.at(index) & value; }; #else - auto bOr = [](QByteArray& array, qsizetype index, char value) { - array[index] |= value; - }; - auto bAnd = [](QByteArray& array, qsizetype index, char value) { - array[index] &= value; - }; + auto bOr = [](QByteArray& array, qsizetype index, char value) { array[index] |= value; }; + auto bAnd = [](QByteArray& array, qsizetype index, char value) { array[index] &= value; }; #endif - bAnd(digest, 6, (char) 0x0f); // clear version - bOr(digest, 6, (char) 0x30); // set to version 3 - bAnd(digest, 8, (char) 0x3f); // clear variant - bOr(digest, 8, (char) 0x80); // set to IETF variant + bAnd(digest, 6, (char)0x0f); // clear version + bOr(digest, 6, (char)0x30); // set to version 3 + bAnd(digest, 8, (char)0x3f); // clear variant + bOr(digest, 8, (char)0x80); // set to IETF variant return QUuid::fromRfc4122(digest); } diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h index 67623a5ab..395ca5498 100644 --- a/launcher/minecraft/auth/MinecraftAccount.h +++ b/launcher/minecraft/auth/MinecraftAccount.h @@ -35,20 +35,20 @@ #pragma once -#include -#include -#include #include -#include +#include #include +#include +#include #include +#include #include -#include "AuthSession.h" -#include "Usable.h" #include "AccountData.h" +#include "AuthSession.h" #include "QObjectPtr.h" +#include "Usable.h" class Task; class AccountTask; @@ -64,8 +64,7 @@ Q_DECLARE_METATYPE(MinecraftAccountPtr) * but we might as well add some things for it in Prism Launcher right now so * we don't have to rip the code to pieces to add it later. */ -struct AccountProfile -{ +struct AccountProfile { QString id; QString name; bool legacy; @@ -77,34 +76,30 @@ struct AccountProfile * Said information may include things such as that account's username, client token, and access * token if the user chose to stay logged in. */ -class MinecraftAccount : - public QObject, - public Usable -{ +class MinecraftAccount : public QObject, public Usable { Q_OBJECT -public: /* construction */ + public: /* construction */ //! Do not copy accounts. ever. - explicit MinecraftAccount(const MinecraftAccount &other, QObject *parent) = delete; + explicit MinecraftAccount(const MinecraftAccount& other, QObject* parent) = delete; //! Default constructor - explicit MinecraftAccount(QObject *parent = 0); + explicit MinecraftAccount(QObject* parent = 0); - static MinecraftAccountPtr createFromUsername(const QString &username); + static MinecraftAccountPtr createFromUsername(const QString& username); static MinecraftAccountPtr createBlankMSA(); - static MinecraftAccountPtr createOffline(const QString &username); + static MinecraftAccountPtr createOffline(const QString& username); - static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json); - static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json); + static MinecraftAccountPtr loadFromJsonV2(const QJsonObject& json); + static MinecraftAccountPtr loadFromJsonV3(const QJsonObject& json); static QUuid uuidFromUsername(QString username); //! Saves a MinecraftAccount to a JSON object and returns it. QJsonObject saveToJson() const; -public: /* manipulation */ - + public: /* manipulation */ /** * Attempt to login. Empty password means we use the token. * If the attempt fails because we already are performing some task, it returns false. @@ -119,70 +114,46 @@ public: /* manipulation */ shared_qobject_ptr currentTask(); -public: /* queries */ - QString internalId() const { - return data.internalId; - } + public: /* queries */ + QString internalId() const { return data.internalId; } - QString accountDisplayString() const { - return data.accountDisplayString(); - } + QString accountDisplayString() const { return data.accountDisplayString(); } - QString mojangUserName() const { - return data.userName(); - } + QString mojangUserName() const { return data.userName(); } - QString accessToken() const { - return data.accessToken(); - } + QString accessToken() const { return data.accessToken(); } - QString profileId() const { - return data.profileId(); - } + QString profileId() const { return data.profileId(); } - QString profileName() const { - return data.profileName(); - } + QString profileName() const { return data.profileName(); } bool isActive() const; - bool canMigrate() const { - return data.canMigrateToMSA; - } + bool canMigrate() const { return data.canMigrateToMSA; } - bool isMSA() const { - return data.type == AccountType::MSA; - } + bool isMSA() const { return data.type == AccountType::MSA; } - bool isOffline() const { - return data.type == AccountType::Offline; - } + bool isOffline() const { return data.type == AccountType::Offline; } - bool ownsMinecraft() const { - return data.minecraftEntitlement.ownsMinecraft; - } + bool ownsMinecraft() const { return data.minecraftEntitlement.ownsMinecraft; } - bool hasProfile() const { - return data.profileId().size() != 0; - } + bool hasProfile() const { return data.profileId().size() != 0; } - QString typeString() const { - switch(data.type) { + QString typeString() const + { + switch (data.type) { case AccountType::Mojang: { - if(data.legacy) { + if (data.legacy) { return "legacy"; } return "mojang"; - } - break; + } break; case AccountType::MSA: { return "msa"; - } - break; + } break; case AccountType::Offline: { return "offline"; - } - break; + } break; default: { return "unknown"; } @@ -194,19 +165,15 @@ public: /* queries */ //! Returns the current state of the account AccountState accountState() const; - AccountData * accountData() { - return &data; - } + AccountData* accountData() { return &data; } bool shouldRefresh() const; void fillSession(AuthSessionPtr session); - QString lastError() const { - return data.lastError(); - } + QString lastError() const { return data.lastError(); } -signals: + signals: /** * This signal is emitted when the account changes */ @@ -216,20 +183,17 @@ signals: // TODO: better signalling for the various possible state changes - especially errors -protected: /* variables */ + protected: /* variables */ AccountData data; // current task we are executing here shared_qobject_ptr m_currentTask; -protected: /* methods */ - + protected: /* methods */ void incrementUses() override; void decrementUses() override; -private -slots: + private slots: void authSucceeded(); void authFailed(QString reason); }; - diff --git a/launcher/minecraft/auth/Parsers.cpp b/launcher/minecraft/auth/Parsers.cpp index 98326272a..f6179a93e 100644 --- a/launcher/minecraft/auth/Parsers.cpp +++ b/launcher/minecraft/auth/Parsers.cpp @@ -2,46 +2,51 @@ #include "Json.h" #include "Logging.h" -#include -#include #include +#include +#include namespace Parsers { -bool getDateTime(QJsonValue value, QDateTime & out) { - if(!value.isString()) { +bool getDateTime(QJsonValue value, QDateTime& out) +{ + if (!value.isString()) { return false; } out = QDateTime::fromString(value.toString(), Qt::ISODate); return out.isValid(); } -bool getString(QJsonValue value, QString & out) { - if(!value.isString()) { +bool getString(QJsonValue value, QString& out) +{ + if (!value.isString()) { return false; } out = value.toString(); return true; } -bool getNumber(QJsonValue value, double & out) { - if(!value.isDouble()) { +bool getNumber(QJsonValue value, double& out) +{ + if (!value.isDouble()) { return false; } out = value.toDouble(); return true; } -bool getNumber(QJsonValue value, int64_t & out) { - if(!value.isDouble()) { +bool getNumber(QJsonValue value, int64_t& out) +{ + if (!value.isDouble()) { return false; } - out = (int64_t) value.toDouble(); + out = (int64_t)value.toDouble(); return true; } -bool getBool(QJsonValue value, bool & out) { - if(!value.isBool()) { +bool getBool(QJsonValue value, bool& out) +{ + if (!value.isBool()) { return false; } out = value.toBool(); @@ -74,49 +79,50 @@ bool getBool(QJsonValue value, bool & out) { // 2148916238 = child account not linked to a family */ -bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) { - qDebug() << "Parsing" << name <<":"; +bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString name) +{ + qDebug() << "Parsing" << name << ":"; qCDebug(authCredentials()) << data; QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if(jsonError.error) { + if (jsonError.error) { qWarning() << "Failed to parse response from user.auth.xboxlive.com as JSON: " << jsonError.errorString(); return false; } auto obj = doc.object(); - if(!getDateTime(obj.value("IssueInstant"), output.issueInstant)) { + if (!getDateTime(obj.value("IssueInstant"), output.issueInstant)) { qWarning() << "User IssueInstant is not a timestamp"; return false; } - if(!getDateTime(obj.value("NotAfter"), output.notAfter)) { + if (!getDateTime(obj.value("NotAfter"), output.notAfter)) { qWarning() << "User NotAfter is not a timestamp"; return false; } - if(!getString(obj.value("Token"), output.token)) { + if (!getString(obj.value("Token"), output.token)) { qWarning() << "User Token is not a string"; return false; } auto arrayVal = obj.value("DisplayClaims").toObject().value("xui"); - if(!arrayVal.isArray()) { + if (!arrayVal.isArray()) { qWarning() << "Missing xui claims array"; return false; } bool foundUHS = false; - for(auto item: arrayVal.toArray()) { - if(!item.isObject()) { + for (auto item : arrayVal.toArray()) { + if (!item.isObject()) { continue; } auto obj_ = item.toObject(); - if(obj_.contains("uhs")) { + if (obj_.contains("uhs")) { foundUHS = true; } else { continue; } // consume all 'display claims' ... whatever that means - for(auto iter = obj_.begin(); iter != obj_.end(); iter++) { + for (auto iter = obj_.begin(); iter != obj_.end(); iter++) { QString claim; - if(!getString(obj_.value(iter.key()), claim)) { + if (!getString(obj_.value(iter.key()), claim)) { qWarning() << "display claim " << iter.key() << " is not a string..."; return false; } @@ -125,7 +131,7 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na break; } - if(!foundUHS) { + if (!foundUHS) { qWarning() << "Missing uhs"; return false; } @@ -134,46 +140,47 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na return true; } -bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) { +bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output) +{ qDebug() << "Parsing Minecraft profile..."; qCDebug(authCredentials()) << data; QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if(jsonError.error) { + if (jsonError.error) { qWarning() << "Failed to parse response from user.auth.xboxlive.com as JSON: " << jsonError.errorString(); return false; } auto obj = doc.object(); - if(!getString(obj.value("id"), output.id)) { + if (!getString(obj.value("id"), output.id)) { qWarning() << "Minecraft profile id is not a string"; return false; } - if(!getString(obj.value("name"), output.name)) { + if (!getString(obj.value("name"), output.name)) { qWarning() << "Minecraft profile name is not a string"; return false; } auto skinsArray = obj.value("skins").toArray(); - for(auto skin: skinsArray) { + for (auto skin : skinsArray) { auto skinObj = skin.toObject(); Skin skinOut; - if(!getString(skinObj.value("id"), skinOut.id)) { + if (!getString(skinObj.value("id"), skinOut.id)) { continue; } QString state; - if(!getString(skinObj.value("state"), state)) { + if (!getString(skinObj.value("state"), state)) { continue; } - if(state != "ACTIVE") { + if (state != "ACTIVE") { continue; } - if(!getString(skinObj.value("url"), skinOut.url)) { + if (!getString(skinObj.value("url"), skinOut.url)) { continue; } - if(!getString(skinObj.value("variant"), skinOut.variant)) { + if (!getString(skinObj.value("variant"), skinOut.variant)) { continue; } // we deal with only the active skin @@ -183,23 +190,23 @@ bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) { auto capesArray = obj.value("capes").toArray(); QString currentCape; - for(auto cape: capesArray) { + for (auto cape : capesArray) { auto capeObj = cape.toObject(); Cape capeOut; - if(!getString(capeObj.value("id"), capeOut.id)) { + if (!getString(capeObj.value("id"), capeOut.id)) { continue; } QString state; - if(!getString(capeObj.value("state"), state)) { + if (!getString(capeObj.value("state"), state)) { continue; } - if(state == "ACTIVE") { + if (state == "ACTIVE") { currentCape = capeOut.id; } - if(!getString(capeObj.value("url"), capeOut.url)) { + if (!getString(capeObj.value("url"), capeOut.url)) { continue; } - if(!getString(capeObj.value("alias"), capeOut.alias)) { + if (!getString(capeObj.value("alias"), capeOut.alias)) { continue; } @@ -211,30 +218,33 @@ bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) { } namespace { - // these skin URLs are for the MHF_Steve and MHF_Alex accounts (made by a Mojang employee) - // they are needed because the session server doesn't return skin urls for default skins - static const QString SKIN_URL_STEVE = "http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b"; - static const QString SKIN_URL_ALEX = "http://textures.minecraft.net/texture/83cee5ca6afcdb171285aa00e8049c297b2dbeba0efb8ff970a5677a1b644032"; +// these skin URLs are for the MHF_Steve and MHF_Alex accounts (made by a Mojang employee) +// they are needed because the session server doesn't return skin urls for default skins +static const QString SKIN_URL_STEVE = + "http://textures.minecraft.net/texture/1a4af718455d4aab528e7a61f86fa25e6a369d1768dcb13f7df319a713eb810b"; +static const QString SKIN_URL_ALEX = + "http://textures.minecraft.net/texture/83cee5ca6afcdb171285aa00e8049c297b2dbeba0efb8ff970a5677a1b644032"; - bool isDefaultModelSteve(QString uuid) { - // need to calculate *Java* hashCode of UUID - // if number is even, skin/model is steve, otherwise it is alex +bool isDefaultModelSteve(QString uuid) +{ + // need to calculate *Java* hashCode of UUID + // if number is even, skin/model is steve, otherwise it is alex - // just in case dashes are in the id - uuid.remove('-'); + // just in case dashes are in the id + uuid.remove('-'); - if (uuid.size() != 32) { - return true; - } - - // qulonglong is guaranteed to be 64 bits - // we need to use unsigned numbers to guarantee truncation below - qulonglong most = uuid.left(16).toULongLong(nullptr, 16); - qulonglong least = uuid.right(16).toULongLong(nullptr, 16); - qulonglong xored = most ^ least; - return ((static_cast(xored >> 32)) ^ static_cast(xored)) % 2 == 0; + if (uuid.size() != 32) { + return true; } + + // qulonglong is guaranteed to be 64 bits + // we need to use unsigned numbers to guarantee truncation below + qulonglong most = uuid.left(16).toULongLong(nullptr, 16); + qulonglong least = uuid.right(16).toULongLong(nullptr, 16); + qulonglong xored = most ^ least; + return ((static_cast(xored >> 32)) ^ static_cast(xored)) % 2 == 0; } +} // namespace /** Uses session server for skin/cape lookup instead of profile, @@ -270,31 +280,32 @@ decoded base64 "value": } */ -bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) { +bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output) +{ qDebug() << "Parsing Minecraft profile..."; qCDebug(authCredentials()) << data; QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if(jsonError.error) { + if (jsonError.error) { qWarning() << "Failed to parse response as JSON: " << jsonError.errorString(); return false; } auto obj = Json::requireObject(doc, "mojang minecraft profile"); - if(!getString(obj.value("id"), output.id)) { + if (!getString(obj.value("id"), output.id)) { qWarning() << "Minecraft profile id is not a string"; return false; } - if(!getString(obj.value("name"), output.name)) { + if (!getString(obj.value("name"), output.name)) { qWarning() << "Minecraft profile name is not a string"; return false; } auto propsArray = obj.value("properties").toArray(); QByteArray texturePayload; - for( auto p : propsArray) { + for (auto p : propsArray) { auto pObj = p.toObject(); auto name = pObj.value("name"); if (!name.isString() || name.toString() != "textures") { @@ -321,7 +332,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) { } doc = QJsonDocument::fromJson(texturePayload, &jsonError); - if(jsonError.error) { + if (jsonError.error) { qWarning() << "Failed to parse response as JSON: " << jsonError.errorString(); return false; } @@ -357,8 +368,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) { // might not be present getString(meta.value("model"), skinOut.variant); } - } - else if (idx.key() == "CAPE") { + } else if (idx.key() == "CAPE") { auto cape = idx->toObject(); if (!getString(cape.value("url"), capeOut.url)) { qWarning() << "Cape url is not a string"; @@ -374,7 +384,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) { output.skin = skinOut; if (capeOut.alias == "cape") { - output.capes = QMap({{capeOut.alias, capeOut}}); + output.capes = QMap({ { capeOut.alias, capeOut } }); output.currentCape = capeOut.alias; } @@ -382,13 +392,14 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) { return true; } -bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) { +bool parseMinecraftEntitlements(QByteArray& data, MinecraftEntitlement& output) +{ qDebug() << "Parsing Minecraft entitlements..."; qCDebug(authCredentials()) << data; QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if(jsonError.error) { + if (jsonError.error) { qWarning() << "Failed to parse response from user.auth.xboxlive.com as JSON: " << jsonError.errorString(); return false; } @@ -398,16 +409,16 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) output.ownsMinecraft = false; auto itemsArray = obj.value("items").toArray(); - for(auto item: itemsArray) { + for (auto item : itemsArray) { auto itemObj = item.toObject(); QString name; - if(!getString(itemObj.value("name"), name)) { + if (!getString(itemObj.value("name"), name)) { continue; } - if(name == "game_minecraft") { + if (name == "game_minecraft") { output.canPlayMinecraft = true; } - if(name == "product_minecraft") { + if (name == "product_minecraft") { output.ownsMinecraft = true; } } @@ -415,47 +426,50 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) return true; } -bool parseRolloutResponse(QByteArray & data, bool& result) { +bool parseRolloutResponse(QByteArray& data, bool& result) +{ qDebug() << "Parsing Rollout response..."; qCDebug(authCredentials()) << data; QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if(jsonError.error) { - qWarning() << "Failed to parse response from https://api.minecraftservices.com/rollout/v1/msamigration as JSON: " << jsonError.errorString(); + if (jsonError.error) { + qWarning() << "Failed to parse response from https://api.minecraftservices.com/rollout/v1/msamigration as JSON: " + << jsonError.errorString(); return false; } auto obj = doc.object(); QString feature; - if(!getString(obj.value("feature"), feature)) { + if (!getString(obj.value("feature"), feature)) { qWarning() << "Rollout feature is not a string"; return false; } - if(feature != "msamigration") { + if (feature != "msamigration") { qWarning() << "Rollout feature is not what we expected (msamigration), but is instead \"" << feature << "\""; return false; } - if(!getBool(obj.value("rollout"), result)) { + if (!getBool(obj.value("rollout"), result)) { qWarning() << "Rollout feature is not a string"; return false; } return true; } -bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) { +bool parseMojangResponse(QByteArray& data, Katabasis::Token& output) +{ QJsonParseError jsonError; qDebug() << "Parsing Mojang response..."; qCDebug(authCredentials()) << data; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if(jsonError.error) { + if (jsonError.error) { qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString(); return false; } auto obj = doc.object(); double expires_in = 0; - if(!getNumber(obj.value("expires_in"), expires_in)) { + if (!getNumber(obj.value("expires_in"), expires_in)) { qWarning() << "expires_in is not a valid number"; return false; } @@ -464,13 +478,13 @@ bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) { output.notAfter = currentTime.addSecs(expires_in); QString username; - if(!getString(obj.value("username"), username)) { + if (!getString(obj.value("username"), username)) { qWarning() << "username is not valid"; return false; } // TODO: it's a JWT... validate it? - if(!getString(obj.value("access_token"), output.token)) { + if (!getString(obj.value("access_token"), output.token)) { qWarning() << "access_token is not valid"; return false; } @@ -479,4 +493,4 @@ bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) { return true; } -} +} // namespace Parsers diff --git a/launcher/minecraft/auth/Parsers.h b/launcher/minecraft/auth/Parsers.h index 2666d890c..d073f9994 100644 --- a/launcher/minecraft/auth/Parsers.h +++ b/launcher/minecraft/auth/Parsers.h @@ -2,19 +2,18 @@ #include "AccountData.h" -namespace Parsers -{ - bool getDateTime(QJsonValue value, QDateTime & out); - bool getString(QJsonValue value, QString & out); - bool getNumber(QJsonValue value, double & out); - bool getNumber(QJsonValue value, int64_t & out); - bool getBool(QJsonValue value, bool & out); +namespace Parsers { +bool getDateTime(QJsonValue value, QDateTime& out); +bool getString(QJsonValue value, QString& out); +bool getNumber(QJsonValue value, double& out); +bool getNumber(QJsonValue value, int64_t& out); +bool getBool(QJsonValue value, bool& out); - bool parseXTokenResponse(QByteArray &data, Katabasis::Token &output, QString name); - bool parseMojangResponse(QByteArray &data, Katabasis::Token &output); +bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString name); +bool parseMojangResponse(QByteArray& data, Katabasis::Token& output); - bool parseMinecraftProfile(QByteArray &data, MinecraftProfile &output); - bool parseMinecraftProfileMojang(QByteArray &data, MinecraftProfile &output); - bool parseMinecraftEntitlements(QByteArray &data, MinecraftEntitlement &output); - bool parseRolloutResponse(QByteArray &data, bool& result); -} +bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output); +bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output); +bool parseMinecraftEntitlements(QByteArray& data, MinecraftEntitlement& output); +bool parseRolloutResponse(QByteArray& data, bool& result); +} // namespace Parsers diff --git a/launcher/minecraft/auth/Yggdrasil.cpp b/launcher/minecraft/auth/Yggdrasil.cpp index d3e7ccddb..97f2a78d4 100644 --- a/launcher/minecraft/auth/Yggdrasil.cpp +++ b/launcher/minecraft/auth/Yggdrasil.cpp @@ -16,24 +16,24 @@ #include "Yggdrasil.h" #include "AccountData.h" +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include #include "Application.h" -Yggdrasil::Yggdrasil(AccountData *data, QObject *parent) - : AccountTask(data, parent) +Yggdrasil::Yggdrasil(AccountData* data, QObject* parent) : AccountTask(data, parent) { changeState(AccountTaskState::STATE_CREATED); } -void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) { +void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) +{ changeState(AccountTaskState::STATE_WORKING); QNetworkRequest netRequest(endpoint); @@ -52,10 +52,10 @@ void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) { connect(&counter, &QTimer::timeout, this, &Yggdrasil::heartbeat); } -void Yggdrasil::executeTask() { -} +void Yggdrasil::executeTask() {} -void Yggdrasil::refresh() { +void Yggdrasil::refresh() +{ start(); /* * { @@ -90,7 +90,8 @@ void Yggdrasil::refresh() { sendRequest(reqUrl, requestData); } -void Yggdrasil::login(QString password) { +void Yggdrasil::login(QString password) +{ start(); /* * { @@ -136,20 +137,21 @@ void Yggdrasil::login(QString password) { sendRequest(reqUrl, requestData); } - - -void Yggdrasil::refreshTimers(qint64, qint64) { +void Yggdrasil::refreshTimers(qint64, qint64) +{ timeout_keeper.stop(); timeout_keeper.start(timeout_max); progress(count = 0, timeout_max); } -void Yggdrasil::heartbeat() { +void Yggdrasil::heartbeat() +{ count += time_step; progress(count, timeout_max); } -bool Yggdrasil::abort() { +bool Yggdrasil::abort() +{ progress(timeout_max, timeout_max); // TODO: actually use this in a meaningful way m_aborted = Yggdrasil::BY_USER; @@ -157,14 +159,16 @@ bool Yggdrasil::abort() { return true; } -void Yggdrasil::abortByTimeout() { +void Yggdrasil::abortByTimeout() +{ progress(timeout_max, timeout_max); // TODO: actually use this in a meaningful way m_aborted = Yggdrasil::BY_TIMEOUT; m_netReply->abort(); } -void Yggdrasil::sslErrors(QList errors) { +void Yggdrasil::sslErrors(QList errors) +{ int i = 1; for (auto error : errors) { qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString(); @@ -174,7 +178,8 @@ void Yggdrasil::sslErrors(QList errors) { } } -void Yggdrasil::processResponse(QJsonObject responseData) { +void Yggdrasil::processResponse(QJsonObject responseData) +{ // Read the response data. We need to get the client token, access token, and the selected // profile. qDebug() << "Processing authentication response."; @@ -188,11 +193,11 @@ void Yggdrasil::processResponse(QJsonObject responseData) { changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a client token.")); return; } - if(m_data->clientToken().isEmpty()) { + if (m_data->clientToken().isEmpty()) { m_data->setClientToken(clientToken); - } - else if(clientToken != m_data->clientToken()) { - changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server attempted to change the client token. This isn't supported.")); + } else if (clientToken != m_data->clientToken()) { + changeState(AccountTaskState::STATE_FAILED_HARD, + tr("Authentication server attempted to change the client token. This isn't supported.")); return; } @@ -220,8 +225,7 @@ void Yggdrasil::processResponse(QJsonObject responseData) { for (auto i = profileObj.constBegin(); i != profileObj.constEnd(); ++i) { if (i.key() == "name" && i.value().isString()) { m_data->minecraftProfile.name = i->toString(); - } - else if (i.key() == "id" && i.value().isString()) { + } else if (i.key() == "id" && i.value().isString()) { m_data->minecraftProfile.id = i->toString(); } } @@ -237,50 +241,43 @@ void Yggdrasil::processResponse(QJsonObject responseData) { changeState(AccountTaskState::STATE_SUCCEEDED); } -void Yggdrasil::processReply() { +void Yggdrasil::processReply() +{ changeState(AccountTaskState::STATE_WORKING); - switch (m_netReply->error()) - { - case QNetworkReply::NoError: - break; - case QNetworkReply::TimeoutError: - changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation timed out.")); - return; - case QNetworkReply::OperationCanceledError: - changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation cancelled.")); - return; - case QNetworkReply::SslHandshakeFailedError: - changeState( - AccountTaskState::STATE_FAILED_SOFT, - tr( - "SSL Handshake failed.
There might be a few causes for it:
" - "
    " - "
  • You use Windows and need to update your root certificates, please install any outstanding updates.
  • " - "
  • Some device on your network is interfering with SSL traffic. In that case, " - "you have bigger worries than Minecraft not starting.
  • " - "
  • Possibly something else. Check the log file for details
  • " - "
" - ) - ); - return; - // used for invalid credentials and similar errors. Fall through. - case QNetworkReply::ContentAccessDenied: - case QNetworkReply::ContentOperationNotPermittedError: - break; - case QNetworkReply::ContentGoneError: { - changeState( - AccountTaskState::STATE_FAILED_GONE, - tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account.") - ); - return; - } - default: - changeState( - AccountTaskState::STATE_FAILED_SOFT, - tr("Authentication operation failed due to a network error: %1 (%2)").arg(m_netReply->errorString()).arg(m_netReply->error()) - ); - return; + switch (m_netReply->error()) { + case QNetworkReply::NoError: + break; + case QNetworkReply::TimeoutError: + changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation timed out.")); + return; + case QNetworkReply::OperationCanceledError: + changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation cancelled.")); + return; + case QNetworkReply::SslHandshakeFailedError: + changeState(AccountTaskState::STATE_FAILED_SOFT, + tr("SSL Handshake failed.
There might be a few causes for it:
" + "
    " + "
  • You use Windows and need to update your root certificates, please install any outstanding updates.
  • " + "
  • Some device on your network is interfering with SSL traffic. In that case, " + "you have bigger worries than Minecraft not starting.
  • " + "
  • Possibly something else. Check the log file for details
  • " + "
")); + return; + // used for invalid credentials and similar errors. Fall through. + case QNetworkReply::ContentAccessDenied: + case QNetworkReply::ContentOperationNotPermittedError: + break; + case QNetworkReply::ContentGoneError: { + changeState(AccountTaskState::STATE_FAILED_GONE, + tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account.")); + return; + } + default: + changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation failed due to a network error: %1 (%2)") + .arg(m_netReply->errorString()) + .arg(m_netReply->error())); + return; } // Try to parse the response regardless of the response code. @@ -299,12 +296,11 @@ void Yggdrasil::processReply() { if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) { processResponse(replyData.size() > 0 ? doc.object() : QJsonObject()); return; - } - else { - changeState( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to parse authentication server response JSON response: %1 at offset %2.").arg(jsonError.errorString()).arg(jsonError.offset) - ); + } else { + changeState(AccountTaskState::STATE_FAILED_SOFT, + tr("Failed to parse authentication server response JSON response: %1 at offset %2.") + .arg(jsonError.errorString()) + .arg(jsonError.offset)); qCritical() << replyData; } return; @@ -320,34 +316,26 @@ void Yggdrasil::processReply() { // stuff there. qDebug() << "The request failed, but the server gave us an error message. Processing error."; processError(doc.object()); - } - else { + } else { // The server didn't say anything regarding the error. Give the user an unknown // error. qDebug() << "The request failed and the server gave no error message. Unknown error."; changeState( AccountTaskState::STATE_FAILED_SOFT, - tr("An unknown error occurred when trying to communicate with the authentication server: %1").arg(m_netReply->errorString()) - ); + tr("An unknown error occurred when trying to communicate with the authentication server: %1").arg(m_netReply->errorString())); } } -void Yggdrasil::processError(QJsonObject responseData) { +void Yggdrasil::processError(QJsonObject responseData) +{ QJsonValue errorVal = responseData.value("error"); QJsonValue errorMessageValue = responseData.value("errorMessage"); QJsonValue causeVal = responseData.value("cause"); if (errorVal.isString() && errorMessageValue.isString()) { - m_error = std::shared_ptr( - new Error { - errorVal.toString(""), - errorMessageValue.toString(""), - causeVal.toString("") - } - ); + m_error = std::shared_ptr(new Error{ errorVal.toString(""), errorMessageValue.toString(""), causeVal.toString("") }); changeState(AccountTaskState::STATE_FAILED_HARD, m_error->m_errorMessageVerbose); - } - else { + } else { // Error is not in standard format. Don't set m_error and return unknown error. changeState(AccountTaskState::STATE_FAILED_HARD, tr("An unknown Yggdrasil error occurred.")); } diff --git a/launcher/minecraft/auth/Yggdrasil.h b/launcher/minecraft/auth/Yggdrasil.h index 4f52a04c2..560d7fb81 100644 --- a/launcher/minecraft/auth/Yggdrasil.h +++ b/launcher/minecraft/auth/Yggdrasil.h @@ -17,10 +17,10 @@ #include "AccountTask.h" -#include -#include -#include #include +#include +#include +#include #include "MinecraftAccount.h" @@ -30,35 +30,25 @@ class QNetworkReply; /** * A Yggdrasil task is a task that performs an operation on a given mojang account. */ -class Yggdrasil : public AccountTask -{ +class Yggdrasil : public AccountTask { Q_OBJECT -public: - explicit Yggdrasil( - AccountData *data, - QObject *parent = 0 - ); + public: + explicit Yggdrasil(AccountData* data, QObject* parent = 0); virtual ~Yggdrasil() = default; void refresh(); void login(QString password); - struct Error - { + struct Error { QString m_errorMessageShort; QString m_errorMessageVerbose; QString m_cause; }; std::shared_ptr m_error; - enum AbortedBy - { - BY_NOTHING, - BY_USER, - BY_TIMEOUT - } m_aborted = BY_NOTHING; + enum AbortedBy { BY_NOTHING, BY_USER, BY_TIMEOUT } m_aborted = BY_NOTHING; -protected: + protected: void executeTask() override; /** @@ -78,24 +68,24 @@ protected: */ virtual void processError(QJsonObject responseData); -protected slots: + protected slots: void processReply(); void refreshTimers(qint64, qint64); void heartbeat(); void sslErrors(QList); void abortByTimeout(); -public slots: + public slots: virtual bool abort() override; -private: + private: void sendRequest(QUrl endpoint, QByteArray content); -protected: - QNetworkReply *m_netReply = nullptr; + protected: + QNetworkReply* m_netReply = nullptr; QTimer timeout_keeper; QTimer counter; - int count = 0; // num msec since time reset + int count = 0; // num msec since time reset const int timeout_max = 30000; const int time_step = 50; diff --git a/launcher/minecraft/auth/flows/AuthFlow.cpp b/launcher/minecraft/auth/flows/AuthFlow.cpp index 4f78e8c31..c51839a8c 100644 --- a/launcher/minecraft/auth/flows/AuthFlow.cpp +++ b/launcher/minecraft/auth/flows/AuthFlow.cpp @@ -1,36 +1,33 @@ -#include -#include -#include #include +#include +#include +#include #include "AuthFlow.h" #include "katabasis/Globals.h" #include -AuthFlow::AuthFlow(AccountData * data, QObject *parent) : - AccountTask(data, parent) +AuthFlow::AuthFlow(AccountData* data, QObject* parent) : AccountTask(data, parent) {} + +void AuthFlow::succeed() { -} - -void AuthFlow::succeed() { m_data->validity_ = Katabasis::Validity::Certain; - changeState( - AccountTaskState::STATE_SUCCEEDED, - tr("Finished all authentication steps") - ); + changeState(AccountTaskState::STATE_SUCCEEDED, tr("Finished all authentication steps")); } -void AuthFlow::executeTask() { - if(m_currentStep) { +void AuthFlow::executeTask() +{ + if (m_currentStep) { return; } changeState(AccountTaskState::STATE_WORKING, tr("Initializing")); nextStep(); } -void AuthFlow::nextStep() { - if(m_steps.size() == 0) { +void AuthFlow::nextStep() +{ + if (m_steps.size() == 0) { // we got to the end without an incident... assume this is all. m_currentStep.reset(); succeed(); @@ -46,15 +43,13 @@ void AuthFlow::nextStep() { m_currentStep->perform(); } - -QString AuthFlow::getStateMessage() const { - switch (m_taskState) - { +QString AuthFlow::getStateMessage() const +{ + switch (m_taskState) { case AccountTaskState::STATE_WORKING: { - if(m_currentStep) { + if (m_currentStep) { return m_currentStep->describe(); - } - else { + } else { return tr("Working..."); } } @@ -64,8 +59,9 @@ QString AuthFlow::getStateMessage() const { } } -void AuthFlow::stepFinished(AccountTaskState resultingState, QString message) { - if(changeState(resultingState, message)) { +void AuthFlow::stepFinished(AccountTaskState resultingState, QString message) +{ + if (changeState(resultingState, message)) { nextStep(); } } diff --git a/launcher/minecraft/auth/flows/AuthFlow.h b/launcher/minecraft/auth/flows/AuthFlow.h index e067cc99f..c2c412abc 100644 --- a/launcher/minecraft/auth/flows/AuthFlow.h +++ b/launcher/minecraft/auth/flows/AuthFlow.h @@ -1,45 +1,42 @@ #pragma once -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include -#include "minecraft/auth/Yggdrasil.h" #include "minecraft/auth/AccountData.h" #include "minecraft/auth/AccountTask.h" #include "minecraft/auth/AuthStep.h" +#include "minecraft/auth/Yggdrasil.h" -class AuthFlow : public AccountTask -{ +class AuthFlow : public AccountTask { Q_OBJECT -public: - explicit AuthFlow(AccountData * data, QObject *parent = 0); + public: + explicit AuthFlow(AccountData* data, QObject* parent = 0); - Katabasis::Validity validity() { - return m_data->validity_; - }; + Katabasis::Validity validity() { return m_data->validity_; }; QString getStateMessage() const override; void executeTask() override; -signals: + signals: void activityChanged(Katabasis::Activity activity); -private slots: + private slots: void stepFinished(AccountTaskState resultingState, QString message); -protected: + protected: void succeed(); void nextStep(); -protected: + protected: QList m_steps; AuthStep::Ptr m_currentStep; }; diff --git a/launcher/minecraft/auth/flows/MSA.cpp b/launcher/minecraft/auth/flows/MSA.cpp index f1987e0c1..f0399342e 100644 --- a/launcher/minecraft/auth/flows/MSA.cpp +++ b/launcher/minecraft/auth/flows/MSA.cpp @@ -1,15 +1,16 @@ #include "MSA.h" -#include "minecraft/auth/steps/MSAStep.h" -#include "minecraft/auth/steps/XboxUserStep.h" -#include "minecraft/auth/steps/XboxAuthorizationStep.h" -#include "minecraft/auth/steps/LauncherLoginStep.h" -#include "minecraft/auth/steps/XboxProfileStep.h" #include "minecraft/auth/steps/EntitlementsStep.h" -#include "minecraft/auth/steps/MinecraftProfileStep.h" #include "minecraft/auth/steps/GetSkinStep.h" +#include "minecraft/auth/steps/LauncherLoginStep.h" +#include "minecraft/auth/steps/MSAStep.h" +#include "minecraft/auth/steps/MinecraftProfileStep.h" +#include "minecraft/auth/steps/XboxAuthorizationStep.h" +#include "minecraft/auth/steps/XboxProfileStep.h" +#include "minecraft/auth/steps/XboxUserStep.h" -MSASilent::MSASilent(AccountData* data, QObject* parent) : AuthFlow(data, parent) { +MSASilent::MSASilent(AccountData* data, QObject* parent) : AuthFlow(data, parent) +{ m_steps.append(makeShared(m_data, MSAStep::Action::Refresh)); m_steps.append(makeShared(m_data)); m_steps.append(makeShared(m_data, &m_data->xboxApiToken, "http://xboxlive.com", "Xbox")); @@ -21,10 +22,8 @@ MSASilent::MSASilent(AccountData* data, QObject* parent) : AuthFlow(data, parent m_steps.append(makeShared(m_data)); } -MSAInteractive::MSAInteractive( - AccountData* data, - QObject* parent -) : AuthFlow(data, parent) { +MSAInteractive::MSAInteractive(AccountData* data, QObject* parent) : AuthFlow(data, parent) +{ m_steps.append(makeShared(m_data, MSAStep::Action::Login)); m_steps.append(makeShared(m_data)); m_steps.append(makeShared(m_data, &m_data->xboxApiToken, "http://xboxlive.com", "Xbox")); diff --git a/launcher/minecraft/auth/flows/MSA.h b/launcher/minecraft/auth/flows/MSA.h index 14a4ff430..e403d530f 100644 --- a/launcher/minecraft/auth/flows/MSA.h +++ b/launcher/minecraft/auth/flows/MSA.h @@ -1,22 +1,14 @@ #pragma once #include "AuthFlow.h" -class MSAInteractive : public AuthFlow -{ +class MSAInteractive : public AuthFlow { Q_OBJECT -public: - explicit MSAInteractive( - AccountData *data, - QObject *parent = 0 - ); + public: + explicit MSAInteractive(AccountData* data, QObject* parent = 0); }; -class MSASilent : public AuthFlow -{ +class MSASilent : public AuthFlow { Q_OBJECT -public: - explicit MSASilent( - AccountData * data, - QObject *parent = 0 - ); + public: + explicit MSASilent(AccountData* data, QObject* parent = 0); }; diff --git a/launcher/minecraft/auth/flows/Mojang.cpp b/launcher/minecraft/auth/flows/Mojang.cpp index 5900ea988..7e2db16fa 100644 --- a/launcher/minecraft/auth/flows/Mojang.cpp +++ b/launcher/minecraft/auth/flows/Mojang.cpp @@ -1,25 +1,20 @@ #include "Mojang.h" -#include "minecraft/auth/steps/YggdrasilStep.h" -#include "minecraft/auth/steps/MinecraftProfileStepMojang.h" -#include "minecraft/auth/steps/MigrationEligibilityStep.h" #include "minecraft/auth/steps/GetSkinStep.h" +#include "minecraft/auth/steps/MigrationEligibilityStep.h" +#include "minecraft/auth/steps/MinecraftProfileStepMojang.h" +#include "minecraft/auth/steps/YggdrasilStep.h" -MojangRefresh::MojangRefresh( - AccountData *data, - QObject *parent -) : AuthFlow(data, parent) { +MojangRefresh::MojangRefresh(AccountData* data, QObject* parent) : AuthFlow(data, parent) +{ m_steps.append(makeShared(m_data, QString())); m_steps.append(makeShared(m_data)); m_steps.append(makeShared(m_data)); m_steps.append(makeShared(m_data)); } -MojangLogin::MojangLogin( - AccountData *data, - QString password, - QObject *parent -): AuthFlow(data, parent), m_password(password) { +MojangLogin::MojangLogin(AccountData* data, QString password, QObject* parent) : AuthFlow(data, parent), m_password(password) +{ m_steps.append(makeShared(m_data, m_password)); m_steps.append(makeShared(m_data)); m_steps.append(makeShared(m_data)); diff --git a/launcher/minecraft/auth/flows/Mojang.h b/launcher/minecraft/auth/flows/Mojang.h index c09c81a80..779ca7e34 100644 --- a/launcher/minecraft/auth/flows/Mojang.h +++ b/launcher/minecraft/auth/flows/Mojang.h @@ -1,26 +1,17 @@ #pragma once #include "AuthFlow.h" -class MojangRefresh : public AuthFlow -{ +class MojangRefresh : public AuthFlow { Q_OBJECT -public: - explicit MojangRefresh( - AccountData *data, - QObject *parent = 0 - ); + public: + explicit MojangRefresh(AccountData* data, QObject* parent = 0); }; -class MojangLogin : public AuthFlow -{ +class MojangLogin : public AuthFlow { Q_OBJECT -public: - explicit MojangLogin( - AccountData *data, - QString password, - QObject *parent = 0 - ); + public: + explicit MojangLogin(AccountData* data, QString password, QObject* parent = 0); -private: + private: QString m_password; }; diff --git a/launcher/minecraft/auth/flows/Offline.cpp b/launcher/minecraft/auth/flows/Offline.cpp index d5c632715..3770b869a 100644 --- a/launcher/minecraft/auth/flows/Offline.cpp +++ b/launcher/minecraft/auth/flows/Offline.cpp @@ -2,16 +2,12 @@ #include "minecraft/auth/steps/OfflineStep.h" -OfflineRefresh::OfflineRefresh( - AccountData *data, - QObject *parent -) : AuthFlow(data, parent) { +OfflineRefresh::OfflineRefresh(AccountData* data, QObject* parent) : AuthFlow(data, parent) +{ m_steps.append(makeShared(m_data)); } -OfflineLogin::OfflineLogin( - AccountData *data, - QObject *parent -) : AuthFlow(data, parent) { +OfflineLogin::OfflineLogin(AccountData* data, QObject* parent) : AuthFlow(data, parent) +{ m_steps.append(makeShared(m_data)); } diff --git a/launcher/minecraft/auth/flows/Offline.h b/launcher/minecraft/auth/flows/Offline.h index 5d1f83a46..2bc9c7612 100644 --- a/launcher/minecraft/auth/flows/Offline.h +++ b/launcher/minecraft/auth/flows/Offline.h @@ -1,22 +1,14 @@ #pragma once #include "AuthFlow.h" -class OfflineRefresh : public AuthFlow -{ +class OfflineRefresh : public AuthFlow { Q_OBJECT -public: - explicit OfflineRefresh( - AccountData *data, - QObject *parent = 0 - ); + public: + explicit OfflineRefresh(AccountData* data, QObject* parent = 0); }; -class OfflineLogin : public AuthFlow -{ +class OfflineLogin : public AuthFlow { Q_OBJECT -public: - explicit OfflineLogin( - AccountData *data, - QObject *parent = 0 - ); + public: + explicit OfflineLogin(AccountData* data, QObject* parent = 0); }; diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.cpp b/launcher/minecraft/auth/steps/EntitlementsStep.cpp index b56827082..0573dcb6e 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.cpp +++ b/launcher/minecraft/auth/steps/EntitlementsStep.cpp @@ -11,12 +11,13 @@ EntitlementsStep::EntitlementsStep(AccountData* data) : AuthStep(data) {} EntitlementsStep::~EntitlementsStep() noexcept = default; -QString EntitlementsStep::describe() { +QString EntitlementsStep::describe() +{ return tr("Determining game ownership."); } - -void EntitlementsStep::perform() { +void EntitlementsStep::perform() +{ auto uuid = QUuid::createUuid(); m_entitlementsRequestId = uuid.toString().remove('{').remove('}'); auto url = "https://api.minecraftservices.com/entitlements/license?requestId=" + m_entitlementsRequestId; @@ -24,22 +25,22 @@ void EntitlementsStep::perform() { request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json"); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8()); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &EntitlementsStep::onRequestDone); requestor->get(request); qDebug() << "Getting entitlements..."; } -void EntitlementsStep::rehydrate() { +void EntitlementsStep::rehydrate() +{ // NOOP, for now. We only save bools and there's nothing to check. } -void EntitlementsStep::onRequestDone( - [[maybe_unused]] QNetworkReply::NetworkError error, - QByteArray data, - [[maybe_unused]] QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void EntitlementsStep::onRequestDone([[maybe_unused]] QNetworkReply::NetworkError error, + QByteArray data, + [[maybe_unused]] QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); qCDebug(authCredentials()) << data; diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.h b/launcher/minecraft/auth/steps/EntitlementsStep.h index 9412ae79d..be16bda13 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.h +++ b/launcher/minecraft/auth/steps/EntitlementsStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class EntitlementsStep : public AuthStep { Q_OBJECT -public: - explicit EntitlementsStep(AccountData *data); + public: + explicit EntitlementsStep(AccountData* data); virtual ~EntitlementsStep() noexcept; void perform() override; @@ -17,9 +16,9 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); -private: + private: QString m_entitlementsRequestId; }; diff --git a/launcher/minecraft/auth/steps/GetSkinStep.cpp b/launcher/minecraft/auth/steps/GetSkinStep.cpp index 3521f8dc5..520877020 100644 --- a/launcher/minecraft/auth/steps/GetSkinStep.cpp +++ b/launcher/minecraft/auth/steps/GetSkinStep.cpp @@ -6,34 +6,32 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" -GetSkinStep::GetSkinStep(AccountData* data) : AuthStep(data) { - -} +GetSkinStep::GetSkinStep(AccountData* data) : AuthStep(data) {} GetSkinStep::~GetSkinStep() noexcept = default; -QString GetSkinStep::describe() { +QString GetSkinStep::describe() +{ return tr("Getting skin."); } -void GetSkinStep::perform() { +void GetSkinStep::perform() +{ auto url = QUrl(m_data->minecraftProfile.skin.url); QNetworkRequest request = QNetworkRequest(url); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &GetSkinStep::onRequestDone); requestor->get(request); } -void GetSkinStep::rehydrate() { +void GetSkinStep::rehydrate() +{ // NOOP, for now. } -void GetSkinStep::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void GetSkinStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); if (error == QNetworkReply::NoError) { diff --git a/launcher/minecraft/auth/steps/GetSkinStep.h b/launcher/minecraft/auth/steps/GetSkinStep.h index 6b97371e5..105e497d1 100644 --- a/launcher/minecraft/auth/steps/GetSkinStep.h +++ b/launcher/minecraft/auth/steps/GetSkinStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class GetSkinStep : public AuthStep { Q_OBJECT -public: - explicit GetSkinStep(AccountData *data); + public: + explicit GetSkinStep(AccountData* data); virtual ~GetSkinStep() noexcept; void perform() override; @@ -17,6 +16,6 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); }; diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp index 8a26cbe77..c57f51113 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp @@ -8,17 +8,17 @@ #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) { - -} +LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {} LauncherLoginStep::~LauncherLoginStep() noexcept = default; -QString LauncherLoginStep::describe() { +QString LauncherLoginStep::describe() +{ return tr("Accessing Mojang services."); } -void LauncherLoginStep::perform() { +void LauncherLoginStep::perform() +{ auto requestURL = "https://api.minecraftservices.com/launcher/login"; auto uhs = m_data->mojangservicesToken.extra["uhs"].toString(); auto xToken = m_data->mojangservicesToken.token; @@ -34,22 +34,20 @@ void LauncherLoginStep::perform() { QNetworkRequest request = QNetworkRequest(QUrl(requestURL)); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json"); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &LauncherLoginStep::onRequestDone); requestor->post(request, requestBody.toUtf8()); qDebug() << "Getting Minecraft access token..."; } -void LauncherLoginStep::rehydrate() { +void LauncherLoginStep::rehydrate() +{ // TODO: check the token validity } -void LauncherLoginStep::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void LauncherLoginStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); qCDebug(authCredentials()) << data; @@ -57,27 +55,17 @@ void LauncherLoginStep::onRequestDone( qWarning() << "Reply error:" << error; qCDebug(authCredentials()) << data; if (Net::isApplicationError(error)) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_) - ); - } - else { - emit finished( - AccountTaskState::STATE_OFFLINE, - tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_) - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_)); + } else { + emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to get Minecraft access token: %1").arg(requestor->errorString_)); } return; } - if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) { + if (!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) { qWarning() << "Could not parse login_with_xbox response..."; qCDebug(authCredentials()) << data; - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to parse the Minecraft access token response.") - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to parse the Minecraft access token response.")); return; } emit finished(AccountTaskState::STATE_WORKING, tr("")); diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.h b/launcher/minecraft/auth/steps/LauncherLoginStep.h index e06a306f9..30c18e675 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.h +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class LauncherLoginStep : public AuthStep { Q_OBJECT -public: - explicit LauncherLoginStep(AccountData *data); + public: + explicit LauncherLoginStep(AccountData* data); virtual ~LauncherLoginStep() noexcept; void perform() override; @@ -17,6 +16,6 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); }; diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp index 6fc8d468e..66a9a0e80 100644 --- a/launcher/minecraft/auth/steps/MSAStep.cpp +++ b/launcher/minecraft/auth/steps/MSAStep.cpp @@ -47,7 +47,8 @@ using OAuth2 = Katabasis::DeviceFlow; using Activity = Katabasis::Activity; -MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) { +MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) +{ m_clientId = APPLICATION->getMSAClientID(); OAuth2::Options opts; opts.scope = "XboxLive.signin offline_access"; @@ -64,13 +65,14 @@ MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(ac MSAStep::~MSAStep() noexcept = default; -QString MSAStep::describe() { +QString MSAStep::describe() +{ return tr("Logging in with Microsoft account."); } - -void MSAStep::rehydrate() { - switch(m_action) { +void MSAStep::rehydrate() +{ + switch (m_action) { case Refresh: { // TODO: check the tokens and see if they are old (older than a day) return; @@ -82,12 +84,14 @@ void MSAStep::rehydrate() { } } -void MSAStep::perform() { - switch(m_action) { +void MSAStep::perform() +{ + switch (m_action) { case Refresh: { if (m_data->msaClientID != m_clientId) { emit hideVerificationUriAndCode(); - emit finished(AccountTaskState::STATE_DISABLED, tr("Microsoft user authentication failed - client identification has changed.")); + emit finished(AccountTaskState::STATE_DISABLED, + tr("Microsoft user authentication failed - client identification has changed.")); } m_oauth2->refresh(); return; @@ -105,8 +109,9 @@ void MSAStep::perform() { } } -void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) { - switch(activity) { +void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) +{ + switch (activity) { case Katabasis::Activity::Idle: case Katabasis::Activity::LoggingIn: case Katabasis::Activity::Refreshing: diff --git a/launcher/minecraft/auth/steps/MSAStep.h b/launcher/minecraft/auth/steps/MSAStep.h index e9a1524e8..fc070ff6a 100644 --- a/launcher/minecraft/auth/steps/MSAStep.h +++ b/launcher/minecraft/auth/steps/MSAStep.h @@ -43,13 +43,11 @@ class MSAStep : public AuthStep { Q_OBJECT -public: - enum Action { - Refresh, - Login - }; -public: - explicit MSAStep(AccountData *data, Action action); + public: + enum Action { Refresh, Login }; + + public: + explicit MSAStep(AccountData* data, Action action); virtual ~MSAStep() noexcept; void perform() override; @@ -57,11 +55,11 @@ public: QString describe() override; -private slots: + private slots: void onOAuthActivityChanged(Katabasis::Activity activity); -private: - Katabasis::DeviceFlow *m_oauth2 = nullptr; + private: + Katabasis::DeviceFlow* m_oauth2 = nullptr; Action m_action; QString m_clientId; }; diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp b/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp index f5b5637a4..5ce953dfb 100644 --- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp +++ b/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp @@ -5,37 +5,37 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" -MigrationEligibilityStep::MigrationEligibilityStep(AccountData* data) : AuthStep(data) { - -} +MigrationEligibilityStep::MigrationEligibilityStep(AccountData* data) : AuthStep(data) {} MigrationEligibilityStep::~MigrationEligibilityStep() noexcept = default; -QString MigrationEligibilityStep::describe() { +QString MigrationEligibilityStep::describe() +{ return tr("Checking for migration eligibility."); } -void MigrationEligibilityStep::perform() { +void MigrationEligibilityStep::perform() +{ auto url = QUrl("https://api.minecraftservices.com/rollout/v1/msamigration"); QNetworkRequest request = QNetworkRequest(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8()); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &MigrationEligibilityStep::onRequestDone); requestor->get(request); } -void MigrationEligibilityStep::rehydrate() { +void MigrationEligibilityStep::rehydrate() +{ // NOOP, for now. We only save bools and there's nothing to check. } -void MigrationEligibilityStep::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void MigrationEligibilityStep::onRequestDone(QNetworkReply::NetworkError error, + QByteArray data, + QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); if (error == QNetworkReply::NoError) { diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h b/launcher/minecraft/auth/steps/MigrationEligibilityStep.h index b1bf9cbf4..8638975d8 100644 --- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h +++ b/launcher/minecraft/auth/steps/MigrationEligibilityStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class MigrationEligibilityStep : public AuthStep { Q_OBJECT -public: - explicit MigrationEligibilityStep(AccountData *data); + public: + explicit MigrationEligibilityStep(AccountData* data); virtual ~MigrationEligibilityStep() noexcept; void perform() override; @@ -17,6 +16,6 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); }; diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp index 6cfa7c1cf..7cdce23f0 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp @@ -7,52 +7,46 @@ #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -MinecraftProfileStep::MinecraftProfileStep(AccountData* data) : AuthStep(data) { - -} +MinecraftProfileStep::MinecraftProfileStep(AccountData* data) : AuthStep(data) {} MinecraftProfileStep::~MinecraftProfileStep() noexcept = default; -QString MinecraftProfileStep::describe() { +QString MinecraftProfileStep::describe() +{ return tr("Fetching the Minecraft profile."); } - -void MinecraftProfileStep::perform() { +void MinecraftProfileStep::perform() +{ auto url = QUrl("https://api.minecraftservices.com/minecraft/profile"); QNetworkRequest request = QNetworkRequest(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8()); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &MinecraftProfileStep::onRequestDone); requestor->get(request); } -void MinecraftProfileStep::rehydrate() { +void MinecraftProfileStep::rehydrate() +{ // NOOP, for now. We only save bools and there's nothing to check. } -void MinecraftProfileStep::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void MinecraftProfileStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); qCDebug(authCredentials()) << data; if (error == QNetworkReply::ContentNotFoundError) { // NOTE: Succeed even if we do not have a profile. This is a valid account state. - if(m_data->type == AccountType::Mojang) { + if (m_data->type == AccountType::Mojang) { m_data->minecraftEntitlement.canPlayMinecraft = false; m_data->minecraftEntitlement.ownsMinecraft = false; } m_data->minecraftProfile = MinecraftProfile(); - emit finished( - AccountTaskState::STATE_SUCCEEDED, - tr("Account has no Minecraft profile.") - ); + emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Account has no Minecraft profile.")); return; } if (error != QNetworkReply::NoError) { @@ -65,35 +59,24 @@ void MinecraftProfileStep::onRequestDone( qWarning() << QString::fromUtf8(data); if (Net::isApplicationError(error)) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) - ); - } - else { - emit finished( - AccountTaskState::STATE_OFFLINE, - tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)); + } else { + emit finished(AccountTaskState::STATE_OFFLINE, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)); } return; } - if(!Parsers::parseMinecraftProfile(data, m_data->minecraftProfile)) { + if (!Parsers::parseMinecraftProfile(data, m_data->minecraftProfile)) { m_data->minecraftProfile = MinecraftProfile(); - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile response could not be parsed") - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Minecraft Java profile response could not be parsed")); return; } - if(m_data->type == AccountType::Mojang) { + if (m_data->type == AccountType::Mojang) { auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain; m_data->minecraftEntitlement.canPlayMinecraft = validProfile; m_data->minecraftEntitlement.ownsMinecraft = validProfile; } - emit finished( - AccountTaskState::STATE_WORKING, - tr("Minecraft Java profile acquisition succeeded.") - ); + emit finished(AccountTaskState::STATE_WORKING, tr("Minecraft Java profile acquisition succeeded.")); } diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.h b/launcher/minecraft/auth/steps/MinecraftProfileStep.h index 8ef3395c6..cb30dab21 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.h +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class MinecraftProfileStep : public AuthStep { Q_OBJECT -public: - explicit MinecraftProfileStep(AccountData *data); + public: + explicit MinecraftProfileStep(AccountData* data); virtual ~MinecraftProfileStep() noexcept; void perform() override; @@ -17,6 +16,6 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); }; diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp index 8c3785882..d035e39a0 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp @@ -7,18 +7,17 @@ #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -MinecraftProfileStepMojang::MinecraftProfileStepMojang(AccountData* data) : AuthStep(data) { - -} +MinecraftProfileStepMojang::MinecraftProfileStepMojang(AccountData* data) : AuthStep(data) {} MinecraftProfileStepMojang::~MinecraftProfileStepMojang() noexcept = default; -QString MinecraftProfileStepMojang::describe() { +QString MinecraftProfileStepMojang::describe() +{ return tr("Fetching the Minecraft profile."); } - -void MinecraftProfileStepMojang::perform() { +void MinecraftProfileStepMojang::perform() +{ if (m_data->minecraftProfile.id.isEmpty()) { emit finished(AccountTaskState::STATE_FAILED_HARD, tr("A UUID is required to get the profile.")); return; @@ -27,35 +26,32 @@ void MinecraftProfileStepMojang::perform() { // use session server instead of profile due to profile endpoint being locked for locked Mojang accounts QUrl url = QUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + m_data->minecraftProfile.id); QNetworkRequest req = QNetworkRequest(url); - AuthRequest *request = new AuthRequest(this); + AuthRequest* request = new AuthRequest(this); connect(request, &AuthRequest::finished, this, &MinecraftProfileStepMojang::onRequestDone); request->get(req); } -void MinecraftProfileStepMojang::rehydrate() { +void MinecraftProfileStepMojang::rehydrate() +{ // NOOP, for now. We only save bools and there's nothing to check. } -void MinecraftProfileStepMojang::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void MinecraftProfileStepMojang::onRequestDone(QNetworkReply::NetworkError error, + QByteArray data, + QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); qCDebug(authCredentials()) << data; if (error == QNetworkReply::ContentNotFoundError) { // NOTE: Succeed even if we do not have a profile. This is a valid account state. - if(m_data->type == AccountType::Mojang) { + if (m_data->type == AccountType::Mojang) { m_data->minecraftEntitlement.canPlayMinecraft = false; m_data->minecraftEntitlement.ownsMinecraft = false; } m_data->minecraftProfile = MinecraftProfile(); - emit finished( - AccountTaskState::STATE_SUCCEEDED, - tr("Account has no Minecraft profile.") - ); + emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Account has no Minecraft profile.")); return; } if (error != QNetworkReply::NoError) { @@ -68,35 +64,24 @@ void MinecraftProfileStepMojang::onRequestDone( qWarning() << QString::fromUtf8(data); if (Net::isApplicationError(error)) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) - ); - } - else { - emit finished( - AccountTaskState::STATE_OFFLINE, - tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_) - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)); + } else { + emit finished(AccountTaskState::STATE_OFFLINE, + tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)); } return; } - if(!Parsers::parseMinecraftProfileMojang(data, m_data->minecraftProfile)) { + if (!Parsers::parseMinecraftProfileMojang(data, m_data->minecraftProfile)) { m_data->minecraftProfile = MinecraftProfile(); - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile response could not be parsed") - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Minecraft Java profile response could not be parsed")); return; } - if(m_data->type == AccountType::Mojang) { + if (m_data->type == AccountType::Mojang) { auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain; m_data->minecraftEntitlement.canPlayMinecraft = validProfile; m_data->minecraftEntitlement.ownsMinecraft = validProfile; } - emit finished( - AccountTaskState::STATE_WORKING, - tr("Minecraft Java profile acquisition succeeded.") - ); + emit finished(AccountTaskState::STATE_WORKING, tr("Minecraft Java profile acquisition succeeded.")); } diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h index e06b30ab0..730ec3f68 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h +++ b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class MinecraftProfileStepMojang : public AuthStep { Q_OBJECT -public: - explicit MinecraftProfileStepMojang(AccountData *data); + public: + explicit MinecraftProfileStepMojang(AccountData* data); virtual ~MinecraftProfileStepMojang() noexcept; void perform() override; @@ -17,6 +16,6 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); }; diff --git a/launcher/minecraft/auth/steps/OfflineStep.cpp b/launcher/minecraft/auth/steps/OfflineStep.cpp index dc092bfd4..bf111abe8 100644 --- a/launcher/minecraft/auth/steps/OfflineStep.cpp +++ b/launcher/minecraft/auth/steps/OfflineStep.cpp @@ -5,14 +5,17 @@ OfflineStep::OfflineStep(AccountData* data) : AuthStep(data) {} OfflineStep::~OfflineStep() noexcept = default; -QString OfflineStep::describe() { +QString OfflineStep::describe() +{ return tr("Creating offline account."); } -void OfflineStep::rehydrate() { +void OfflineStep::rehydrate() +{ // NOOP } -void OfflineStep::perform() { +void OfflineStep::perform() +{ emit finished(AccountTaskState::STATE_WORKING, tr("Created offline account.")); } diff --git a/launcher/minecraft/auth/steps/OfflineStep.h b/launcher/minecraft/auth/steps/OfflineStep.h index 436597cd8..3bf123d6a 100644 --- a/launcher/minecraft/auth/steps/OfflineStep.h +++ b/launcher/minecraft/auth/steps/OfflineStep.h @@ -8,8 +8,8 @@ class OfflineStep : public AuthStep { Q_OBJECT -public: - explicit OfflineStep(AccountData *data); + public: + explicit OfflineStep(AccountData* data); virtual ~OfflineStep() noexcept; void perform() override; diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp index b397b7349..c33d7e629 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp @@ -1,33 +1,32 @@ #include "XboxAuthorizationStep.h" -#include -#include #include +#include +#include #include "Logging.h" #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Katabasis::Token *token, QString relyingParty, QString authorizationKind): - AuthStep(data), - m_token(token), - m_relyingParty(relyingParty), - m_authorizationKind(authorizationKind) -{ -} +XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Katabasis::Token* token, QString relyingParty, QString authorizationKind) + : AuthStep(data), m_token(token), m_relyingParty(relyingParty), m_authorizationKind(authorizationKind) +{} XboxAuthorizationStep::~XboxAuthorizationStep() noexcept = default; -QString XboxAuthorizationStep::describe() { +QString XboxAuthorizationStep::describe() +{ return tr("Getting authorization to access %1 services.").arg(m_authorizationKind); } -void XboxAuthorizationStep::rehydrate() { +void XboxAuthorizationStep::rehydrate() +{ // FIXME: check if the tokens are good? } -void XboxAuthorizationStep::perform() { +void XboxAuthorizationStep::perform() +{ QString xbox_auth_template = R"XXX( { "Properties": { @@ -41,129 +40,98 @@ void XboxAuthorizationStep::perform() { } )XXX"; auto xbox_auth_data = xbox_auth_template.arg(m_data->userToken.token, m_relyingParty); -// http://xboxlive.com + // http://xboxlive.com QNetworkRequest request = QNetworkRequest(QUrl("https://xsts.auth.xboxlive.com/xsts/authorize")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json"); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &XboxAuthorizationStep::onRequestDone); requestor->post(request, xbox_auth_data.toUtf8()); qDebug() << "Getting authorization token for " << m_relyingParty; } -void XboxAuthorizationStep::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void XboxAuthorizationStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); qCDebug(authCredentials()) << data; if (error != QNetworkReply::NoError) { qWarning() << "Reply error:" << error; if (Net::isApplicationError(error)) { - if(!processSTSError(error, data, headers)) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, error) - ); + if (!processSTSError(error, data, headers)) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, error)); + } else { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, requestor->errorString_)); } - else { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Unknown STS error for %1 services: %2").arg(m_authorizationKind, requestor->errorString_) - ); - } - } - else { - emit finished( - AccountTaskState::STATE_OFFLINE, - tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, requestor->errorString_) - ); + } else { + emit finished(AccountTaskState::STATE_OFFLINE, + tr("Failed to get authorization for %1 services: %2").arg(m_authorizationKind, requestor->errorString_)); } return; } Katabasis::Token temp; - if(!Parsers::parseXTokenResponse(data, temp, m_authorizationKind)) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind) - ); + if (!Parsers::parseXTokenResponse(data, temp, m_authorizationKind)) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind)); return; } - if(temp.extra["uhs"] != m_data->userToken.extra["uhs"]) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Server has changed %1 authorization user hash in the reply. Something is wrong.").arg(m_authorizationKind) - ); + if (temp.extra["uhs"] != m_data->userToken.extra["uhs"]) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Server has changed %1 authorization user hash in the reply. Something is wrong.").arg(m_authorizationKind)); return; } - auto & token = *m_token; + auto& token = *m_token; token = temp; emit finished(AccountTaskState::STATE_WORKING, tr("Got authorization to access %1").arg(m_relyingParty)); } - -bool XboxAuthorizationStep::processSTSError( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - if(error == QNetworkReply::AuthenticationRequiredError) { +bool XboxAuthorizationStep::processSTSError(QNetworkReply::NetworkError error, QByteArray data, QList headers) +{ + if (error == QNetworkReply::AuthenticationRequiredError) { QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if(jsonError.error) { + if (jsonError.error) { qWarning() << "Cannot parse error XSTS response as JSON: " << jsonError.errorString(); - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Cannot parse %1 authorization error response as JSON: %2").arg(m_authorizationKind, jsonError.errorString()) - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("Cannot parse %1 authorization error response as JSON: %2").arg(m_authorizationKind, jsonError.errorString())); return true; } int64_t errorCode = -1; auto obj = doc.object(); - if(!Parsers::getNumber(obj.value("XErr"), errorCode)) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("XErr element is missing from %1 authorization error response.").arg(m_authorizationKind) - ); + if (!Parsers::getNumber(obj.value("XErr"), errorCode)) { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("XErr element is missing from %1 authorization error response.").arg(m_authorizationKind)); return true; } - switch(errorCode) { - case 2148916233:{ - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("This Microsoft account does not have an XBox Live profile. Buy the game on %1 first.") - .arg("minecraft.net") - ); + switch (errorCode) { + case 2148916233: { + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("This Microsoft account does not have an XBox Live profile. Buy the game on %1 first.") + .arg("minecraft.net")); return true; } case 2148916235: { // NOTE: this is the Grulovia error - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("XBox Live is not available in your country. You've been blocked.") - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox Live is not available in your country. You've been blocked.")); return true; } case 2148916238: { emit finished( AccountTaskState::STATE_FAILED_SOFT, tr("This Microsoft account is underaged and is not linked to a family.\n\nPlease set up your account according to %1.") - .arg("help.minecraft.net") - ); + .arg("help.minecraft.net")); return true; } default: { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("XSTS authentication ended with unrecognized error(s):\n\n%1").arg(errorCode) - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, + tr("XSTS authentication ended with unrecognized error(s):\n\n%1").arg(errorCode)); return true; } } diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h index 31e43bf05..dee24c954 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class XboxAuthorizationStep : public AuthStep { Q_OBJECT -public: - explicit XboxAuthorizationStep(AccountData *data, Katabasis::Token *token, QString relyingParty, QString authorizationKind); + public: + explicit XboxAuthorizationStep(AccountData* data, Katabasis::Token* token, QString relyingParty, QString authorizationKind); virtual ~XboxAuthorizationStep() noexcept; void perform() override; @@ -17,18 +16,14 @@ public: QString describe() override; -private: - bool processSTSError( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers - ); + private: + bool processSTSError(QNetworkReply::NetworkError error, QByteArray data, QList headers); -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); -private: - Katabasis::Token *m_token; + private: + Katabasis::Token* m_token; QString m_relyingParty; QString m_authorizationKind; }; diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.cpp b/launcher/minecraft/auth/steps/XboxProfileStep.cpp index 644c419b1..fd2b32cce 100644 --- a/launcher/minecraft/auth/steps/XboxProfileStep.cpp +++ b/launcher/minecraft/auth/steps/XboxProfileStep.cpp @@ -8,66 +8,56 @@ #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -XboxProfileStep::XboxProfileStep(AccountData* data) : AuthStep(data) { - -} +XboxProfileStep::XboxProfileStep(AccountData* data) : AuthStep(data) {} XboxProfileStep::~XboxProfileStep() noexcept = default; -QString XboxProfileStep::describe() { +QString XboxProfileStep::describe() +{ return tr("Fetching Xbox profile."); } -void XboxProfileStep::rehydrate() { +void XboxProfileStep::rehydrate() +{ // NOOP, for now. We only save bools and there's nothing to check. } -void XboxProfileStep::perform() { +void XboxProfileStep::perform() +{ auto url = QUrl("https://profile.xboxlive.com/users/me/profile/settings"); QUrlQuery q; - q.addQueryItem( - "settings", - "GameDisplayName,AppDisplayName,AppDisplayPicRaw,GameDisplayPicRaw," - "PublicGamerpic,ShowUserAsAvatar,Gamerscore,Gamertag,ModernGamertag,ModernGamertagSuffix," - "UniqueModernGamertag,AccountTier,TenureLevel,XboxOneRep," - "PreferredColor,Location,Bio,Watermarks," - "RealName,RealNameOverride,IsQuarantined" - ); + q.addQueryItem("settings", + "GameDisplayName,AppDisplayName,AppDisplayPicRaw,GameDisplayPicRaw," + "PublicGamerpic,ShowUserAsAvatar,Gamerscore,Gamertag,ModernGamertag,ModernGamertagSuffix," + "UniqueModernGamertag,AccountTier,TenureLevel,XboxOneRep," + "PreferredColor,Location,Bio,Watermarks," + "RealName,RealNameOverride,IsQuarantined"); url.setQuery(q); QNetworkRequest request = QNetworkRequest(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json"); request.setRawHeader("x-xbl-contract-version", "3"); - request.setRawHeader("Authorization", QString("XBL3.0 x=%1;%2").arg(m_data->userToken.extra["uhs"].toString(), m_data->xboxApiToken.token).toUtf8()); - AuthRequest *requestor = new AuthRequest(this); + request.setRawHeader("Authorization", + QString("XBL3.0 x=%1;%2").arg(m_data->userToken.extra["uhs"].toString(), m_data->xboxApiToken.token).toUtf8()); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &XboxProfileStep::onRequestDone); requestor->get(request); qDebug() << "Getting Xbox profile..."; } -void XboxProfileStep::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void XboxProfileStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); if (error != QNetworkReply::NoError) { qWarning() << "Reply error:" << error; qCDebug(authCredentials()) << data; if (Net::isApplicationError(error)) { - emit finished( - AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_) - ); - } - else { - emit finished( - AccountTaskState::STATE_OFFLINE, - tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_) - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_)); + } else { + emit finished(AccountTaskState::STATE_OFFLINE, tr("Failed to retrieve the Xbox profile: %1").arg(requestor->errorString_)); } return; } diff --git a/launcher/minecraft/auth/steps/XboxProfileStep.h b/launcher/minecraft/auth/steps/XboxProfileStep.h index 7a0c5873d..b8494b6e5 100644 --- a/launcher/minecraft/auth/steps/XboxProfileStep.h +++ b/launcher/minecraft/auth/steps/XboxProfileStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class XboxProfileStep : public AuthStep { Q_OBJECT -public: - explicit XboxProfileStep(AccountData *data); + public: + explicit XboxProfileStep(AccountData* data); virtual ~XboxProfileStep() noexcept; void perform() override; @@ -17,6 +16,6 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); }; diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index 842eb60ff..61c33a18d 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -6,22 +6,22 @@ #include "minecraft/auth/Parsers.h" #include "net/NetUtils.h" -XboxUserStep::XboxUserStep(AccountData* data) : AuthStep(data) { - -} +XboxUserStep::XboxUserStep(AccountData* data) : AuthStep(data) {} XboxUserStep::~XboxUserStep() noexcept = default; -QString XboxUserStep::describe() { +QString XboxUserStep::describe() +{ return tr("Logging in as an Xbox user."); } - -void XboxUserStep::rehydrate() { +void XboxUserStep::rehydrate() +{ // NOOP, for now. We only save bools and there's nothing to check. } -void XboxUserStep::perform() { +void XboxUserStep::perform() +{ QString xbox_auth_template = R"XXX( { "Properties": { @@ -40,40 +40,31 @@ void XboxUserStep::perform() { request.setRawHeader("Accept", "application/json"); // set contract-verison header (prevent err 400 bad-request?) // https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/reference/live/rest/additional/httpstandardheaders - request.setRawHeader("x-xbl-contract-version", "1"); + request.setRawHeader("x-xbl-contract-version", "1"); - auto *requestor = new AuthRequest(this); + auto* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &XboxUserStep::onRequestDone); requestor->post(request, xbox_auth_data.toUtf8()); qDebug() << "First layer of XBox auth ... commencing."; } -void XboxUserStep::onRequestDone( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void XboxUserStep::onRequestDone(QNetworkReply::NetworkError error, QByteArray data, QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); if (error != QNetworkReply::NoError) { qWarning() << "Reply error:" << error; if (Net::isApplicationError(error)) { - emit finished(AccountTaskState::STATE_FAILED_SOFT, - tr("XBox user authentication failed: %1").arg(requestor->errorString_) - ); - } - else { - emit finished( - AccountTaskState::STATE_OFFLINE, - tr("XBox user authentication failed: %1").arg(requestor->errorString_) - ); + emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication failed: %1").arg(requestor->errorString_)); + } else { + emit finished(AccountTaskState::STATE_OFFLINE, tr("XBox user authentication failed: %1").arg(requestor->errorString_)); } return; } Katabasis::Token temp; - if(!Parsers::parseXTokenResponse(data, temp, "UToken")) { + if (!Parsers::parseXTokenResponse(data, temp, "UToken")) { qWarning() << "Could not parse user authentication response..."; emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication response could not be understood.")); return; diff --git a/launcher/minecraft/auth/steps/XboxUserStep.h b/launcher/minecraft/auth/steps/XboxUserStep.h index 83e9405f4..e92727a4d 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.h +++ b/launcher/minecraft/auth/steps/XboxUserStep.h @@ -4,12 +4,11 @@ #include "QObjectPtr.h" #include "minecraft/auth/AuthStep.h" - class XboxUserStep : public AuthStep { Q_OBJECT -public: - explicit XboxUserStep(AccountData *data); + public: + explicit XboxUserStep(AccountData* data); virtual ~XboxUserStep() noexcept; void perform() override; @@ -17,6 +16,6 @@ public: QString describe() override; -private slots: + private slots: void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); }; diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.cpp b/launcher/minecraft/auth/steps/YggdrasilStep.cpp index e1d331726..fdcaa0d67 100644 --- a/launcher/minecraft/auth/steps/YggdrasilStep.cpp +++ b/launcher/minecraft/auth/steps/YggdrasilStep.cpp @@ -4,7 +4,8 @@ #include "minecraft/auth/Parsers.h" #include "minecraft/auth/Yggdrasil.h" -YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(data), m_password(password) { +YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(data), m_password(password) +{ m_yggdrasil = new Yggdrasil(m_data, this); connect(m_yggdrasil, &Task::failed, this, &YggdrasilStep::onAuthFailed); @@ -14,28 +15,32 @@ YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(dat YggdrasilStep::~YggdrasilStep() noexcept = default; -QString YggdrasilStep::describe() { +QString YggdrasilStep::describe() +{ return tr("Logging in with Mojang account."); } -void YggdrasilStep::rehydrate() { +void YggdrasilStep::rehydrate() +{ // NOOP, for now. } -void YggdrasilStep::perform() { - if(m_password.size()) { +void YggdrasilStep::perform() +{ + if (m_password.size()) { m_yggdrasil->login(m_password); - } - else { + } else { m_yggdrasil->refresh(); } } -void YggdrasilStep::onAuthSucceeded() { +void YggdrasilStep::onAuthSucceeded() +{ emit finished(AccountTaskState::STATE_WORKING, tr("Logged in with Mojang")); } -void YggdrasilStep::onAuthFailed() { +void YggdrasilStep::onAuthFailed() +{ // TODO: hook these in again, expand to MSA // m_error = m_yggdrasil->m_error; // m_aborted = m_yggdrasil->m_aborted; @@ -44,7 +49,7 @@ void YggdrasilStep::onAuthFailed() { QString errorMessage = tr("Mojang user authentication failed."); // NOTE: soft error in the first step means 'offline' - if(state == AccountTaskState::STATE_FAILED_SOFT) { + if (state == AccountTaskState::STATE_FAILED_SOFT) { state = AccountTaskState::STATE_OFFLINE; errorMessage = tr("Mojang user authentication ended with a network error."); } diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.h b/launcher/minecraft/auth/steps/YggdrasilStep.h index ebafb8e5b..ef31f34d5 100644 --- a/launcher/minecraft/auth/steps/YggdrasilStep.h +++ b/launcher/minecraft/auth/steps/YggdrasilStep.h @@ -9,8 +9,8 @@ class Yggdrasil; class YggdrasilStep : public AuthStep { Q_OBJECT -public: - explicit YggdrasilStep(AccountData *data, QString password); + public: + explicit YggdrasilStep(AccountData* data, QString password); virtual ~YggdrasilStep() noexcept; void perform() override; @@ -18,11 +18,11 @@ public: QString describe() override; -private slots: + private slots: void onAuthSucceeded(); void onAuthFailed(); -private: - Yggdrasil *m_yggdrasil = nullptr; + private: + Yggdrasil* m_yggdrasil = nullptr; QString m_password; }; diff --git a/launcher/minecraft/gameoptions/GameOptions.cpp b/launcher/minecraft/gameoptions/GameOptions.cpp index ce0988cc8..4f4fb99a7 100644 --- a/launcher/minecraft/gameoptions/GameOptions.cpp +++ b/launcher/minecraft/gameoptions/GameOptions.cpp @@ -1,59 +1,51 @@ #include "GameOptions.h" -#include "FileSystem.h" #include #include +#include "FileSystem.h" namespace { -bool load(const QString& path, std::vector &contents, int & version) +bool load(const QString& path, std::vector& contents, int& version) { contents.clear(); QFile file(path); - if (!file.open(QFile::ReadOnly)) - { + if (!file.open(QFile::ReadOnly)) { qWarning() << "Failed to read options file."; return false; } version = 0; - while(!file.atEnd()) - { + while (!file.atEnd()) { auto line = file.readLine(); - if(line.endsWith('\n')) - { + if (line.endsWith('\n')) { line.chop(1); } auto separatorIndex = line.indexOf(':'); - if(separatorIndex == -1) - { + if (separatorIndex == -1) { continue; } auto key = QString::fromUtf8(line.data(), separatorIndex); auto value = QString::fromUtf8(line.data() + separatorIndex + 1, line.size() - 1 - separatorIndex); qDebug() << "!!" << key << "!!"; - if(key == "version") - { + if (key == "version") { version = value.toInt(); continue; } - contents.emplace_back(GameOptionItem{key, value}); + contents.emplace_back(GameOptionItem{ key, value }); } qDebug() << "Loaded" << path << "with version:" << version; return true; } -bool save(const QString& path, std::vector &mapping, int version) +bool save(const QString& path, std::vector& mapping, int version) { QSaveFile out(path); - if(!out.open(QIODevice::WriteOnly)) - { + if (!out.open(QIODevice::WriteOnly)) { return false; } - if(version != 0) - { + if (version != 0) { QString versionLine = QString("version:%1\n").arg(version); out.write(versionLine.toUtf8()); } auto iter = mapping.begin(); - while (iter != mapping.end()) - { + while (iter != mapping.end()) { out.write(iter->key.toUtf8()); out.write(":"); out.write(iter->value.toUtf8()); @@ -62,22 +54,19 @@ bool save(const QString& path, std::vector &mapping, int version } return out.commit(); } -} +} // namespace -GameOptions::GameOptions(const QString& path): - path(path) +GameOptions::GameOptions(const QString& path) : path(path) { reload(); } QVariant GameOptions::headerData(int section, Qt::Orientation orientation, int role) const { - if(role != Qt::DisplayRole) - { + if (role != Qt::DisplayRole) { return QAbstractListModel::headerData(section, orientation, role); } - switch(section) - { + switch (section) { case 0: return tr("Key"); case 1: @@ -98,19 +87,15 @@ QVariant GameOptions::data(const QModelIndex& index, int role) const if (row < 0 || row >= int(contents.size())) return QVariant(); - switch (role) - { - case Qt::DisplayRole: - if(column == 0) - { - return contents[row].key; - } - else - { - return contents[row].value; - } - default: - return QVariant(); + switch (role) { + case Qt::DisplayRole: + if (column == 0) { + return contents[row].key; + } else { + return contents[row].value; + } + default: + return QVariant(); } } diff --git a/launcher/minecraft/gameoptions/GameOptions.h b/launcher/minecraft/gameoptions/GameOptions.h index c6d254928..ae031efb2 100644 --- a/launcher/minecraft/gameoptions/GameOptions.h +++ b/launcher/minecraft/gameoptions/GameOptions.h @@ -1,32 +1,30 @@ #pragma once -#include -#include #include +#include +#include -struct GameOptionItem -{ +struct GameOptionItem { QString key; QString value; }; -class GameOptions : public QAbstractListModel -{ +class GameOptions : public QAbstractListModel { Q_OBJECT -public: + public: explicit GameOptions(const QString& path); virtual ~GameOptions() = default; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex & parent) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; bool isLoaded() const; bool reload(); bool save(); -private: + private: std::vector contents; bool loaded = false; QString path; diff --git a/launcher/minecraft/launch/ClaimAccount.cpp b/launcher/minecraft/launch/ClaimAccount.cpp index 1cd7c0da7..a3de1516a 100644 --- a/launcher/minecraft/launch/ClaimAccount.cpp +++ b/launcher/minecraft/launch/ClaimAccount.cpp @@ -4,10 +4,9 @@ #include "Application.h" #include "minecraft/auth/AccountList.h" -ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session): LaunchStep(parent) +ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session) : LaunchStep(parent) { - if(session->status == AuthSession::Status::PlayableOnline && !session->demo) - { + if (session->status == AuthSession::Status::PlayableOnline && !session->demo) { auto accounts = APPLICATION->accounts(); m_account = accounts->getAccountByProfileName(session->player_name); } @@ -15,8 +14,7 @@ ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session): LaunchSt void ClaimAccount::executeTask() { - if(m_account) - { + if (m_account) { lock.reset(new UseLock(m_account)); emitSucceeded(); } diff --git a/launcher/minecraft/launch/ClaimAccount.h b/launcher/minecraft/launch/ClaimAccount.h index cb4de23f5..3d47539ac 100644 --- a/launcher/minecraft/launch/ClaimAccount.h +++ b/launcher/minecraft/launch/ClaimAccount.h @@ -18,20 +18,17 @@ #include #include -class ClaimAccount: public LaunchStep -{ +class ClaimAccount : public LaunchStep { Q_OBJECT -public: - explicit ClaimAccount(LaunchTask *parent, AuthSessionPtr session); - virtual ~ClaimAccount() {}; + public: + explicit ClaimAccount(LaunchTask* parent, AuthSessionPtr session); + virtual ~ClaimAccount(){}; void executeTask() override; void finalize() override; - bool canAbort() const override - { - return false; - } -private: + bool canAbort() const override { return false; } + + private: std::unique_ptr lock; MinecraftAccountPtr m_account; }; diff --git a/launcher/minecraft/launch/CreateGameFolders.cpp b/launcher/minecraft/launch/CreateGameFolders.cpp index 4081e72ed..36f5e6407 100644 --- a/launcher/minecraft/launch/CreateGameFolders.cpp +++ b/launcher/minecraft/launch/CreateGameFolders.cpp @@ -1,27 +1,23 @@ #include "CreateGameFolders.h" -#include "minecraft/MinecraftInstance.h" -#include "launch/LaunchTask.h" #include "FileSystem.h" +#include "launch/LaunchTask.h" +#include "minecraft/MinecraftInstance.h" -CreateGameFolders::CreateGameFolders(LaunchTask* parent): LaunchStep(parent) -{ -} +CreateGameFolders::CreateGameFolders(LaunchTask* parent) : LaunchStep(parent) {} void CreateGameFolders::executeTask() { auto instance = m_parent->instance(); std::shared_ptr minecraftInstance = std::dynamic_pointer_cast(instance); - if(!FS::ensureFolderPathExists(minecraftInstance->gameRoot())) - { + if (!FS::ensureFolderPathExists(minecraftInstance->gameRoot())) { emit logLine("Couldn't create the main game folder", MessageLevel::Error); emitFailed(tr("Couldn't create the main game folder")); return; } // HACK: this is a workaround for MCL-3732 - 'server-resource-packs' folder is created. - if(!FS::ensureFolderPathExists(FS::PathCombine(minecraftInstance->gameRoot(), "server-resource-packs"))) - { + if (!FS::ensureFolderPathExists(FS::PathCombine(minecraftInstance->gameRoot(), "server-resource-packs"))) { emit logLine("Couldn't create the 'server-resource-packs' folder", MessageLevel::Error); } emitSucceeded(); diff --git a/launcher/minecraft/launch/CreateGameFolders.h b/launcher/minecraft/launch/CreateGameFolders.h index 9c7d3c940..44524ded5 100644 --- a/launcher/minecraft/launch/CreateGameFolders.h +++ b/launcher/minecraft/launch/CreateGameFolders.h @@ -15,23 +15,17 @@ #pragma once -#include #include +#include #include // Create the main .minecraft for the instance and any other necessary folders -class CreateGameFolders: public LaunchStep -{ +class CreateGameFolders : public LaunchStep { Q_OBJECT -public: - explicit CreateGameFolders(LaunchTask *parent); - virtual ~CreateGameFolders() {}; + public: + explicit CreateGameFolders(LaunchTask* parent); + virtual ~CreateGameFolders(){}; virtual void executeTask(); - virtual bool canAbort() const - { - return false; - } + virtual bool canAbort() const { return false; } }; - - diff --git a/launcher/minecraft/launch/ExtractNatives.cpp b/launcher/minecraft/launch/ExtractNatives.cpp index 7d5f41791..cebeaedd4 100644 --- a/launcher/minecraft/launch/ExtractNatives.cpp +++ b/launcher/minecraft/launch/ExtractNatives.cpp @@ -14,26 +14,25 @@ */ #include "ExtractNatives.h" -#include #include +#include #include #include -#include "MMCZip.h" -#include "FileSystem.h" #include +#include "FileSystem.h" +#include "MMCZip.h" #ifdef major - #undef major +#undef major #endif #ifdef minor - #undef minor +#undef minor #endif -static QString replaceSuffix (QString target, const QString &suffix, const QString &replacement) +static QString replaceSuffix(QString target, const QString& suffix, const QString& replacement) { - if (!target.endsWith(suffix)) - { + if (!target.endsWith(suffix)) { return target; } target.resize(target.length() - suffix.length()); @@ -43,17 +42,14 @@ static QString replaceSuffix (QString target, const QString &suffix, const QStri static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack, bool nativeOpenAL, bool nativeGLFW) { QuaZip zip(source); - if(!zip.open(QuaZip::mdUnzip)) - { + if (!zip.open(QuaZip::mdUnzip)) { return false; } QDir directory(targetFolder); - if (!zip.goToFirstFile()) - { + if (!zip.goToFirstFile()) { return false; } - do - { + do { QString name = zip.getCurrentFileName(); auto lowercase = name.toLower(); if (nativeGLFW && name.contains("glfw")) { @@ -62,19 +58,16 @@ static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibH if (nativeOpenAL && name.contains("openal")) { continue; } - if(applyJnilibHack) - { + if (applyJnilibHack) { name = replaceSuffix(name, ".jnilib", ".dylib"); } QString absFilePath = directory.absoluteFilePath(name); - if (!JlCompress::extractFile(&zip, "", absFilePath)) - { + if (!JlCompress::extractFile(&zip, "", absFilePath)) { return false; } } while (zip.goToNextFile()); zip.close(); - if(zip.getZipError()!=0) - { + if (zip.getZipError() != 0) { return false; } return true; @@ -85,8 +78,7 @@ void ExtractNatives::executeTask() auto instance = m_parent->instance(); std::shared_ptr minecraftInstance = std::dynamic_pointer_cast(instance); auto toExtract = minecraftInstance->getNativeJars(); - if(toExtract.isEmpty()) - { + if (toExtract.isEmpty()) { emitSucceeded(); return; } @@ -94,14 +86,12 @@ void ExtractNatives::executeTask() bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool(); bool nativeGLFW = settings->get("UseNativeGLFW").toBool(); - auto outputPath = minecraftInstance->getNativePath(); + auto outputPath = minecraftInstance->getNativePath(); auto javaVersion = minecraftInstance->getJavaVersion(); bool jniHackEnabled = javaVersion.major() >= 8; - for(const auto &source: toExtract) - { - if(!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL, nativeGLFW)) - { - const char *reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'"); + for (const auto& source : toExtract) { + if (!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL, nativeGLFW)) { + const char* reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'"); emit logLine(QString(reason).arg(source, outputPath), MessageLevel::Fatal); emitFailed(tr(reason).arg(source, outputPath)); } diff --git a/launcher/minecraft/launch/ExtractNatives.h b/launcher/minecraft/launch/ExtractNatives.h index 094fcd6bb..2ab8816bd 100644 --- a/launcher/minecraft/launch/ExtractNatives.h +++ b/launcher/minecraft/launch/ExtractNatives.h @@ -20,19 +20,13 @@ #include "minecraft/auth/AuthSession.h" // FIXME: temporary wrapper for existing task. -class ExtractNatives: public LaunchStep -{ +class ExtractNatives : public LaunchStep { Q_OBJECT -public: - explicit ExtractNatives(LaunchTask *parent) : LaunchStep(parent){}; + public: + explicit ExtractNatives(LaunchTask* parent) : LaunchStep(parent){}; virtual ~ExtractNatives(){}; void executeTask() override; - bool canAbort() const override - { - return false; - } + bool canAbort() const override { return false; } void finalize() override; }; - - diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index 01df85439..2980b0bd1 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -35,29 +35,27 @@ #include "LauncherPartLaunch.h" -#include #include +#include +#include "Application.h" +#include "Commandline.h" +#include "FileSystem.h" #include "launch/LaunchTask.h" #include "minecraft/MinecraftInstance.h" -#include "FileSystem.h" -#include "Commandline.h" -#include "Application.h" #ifdef Q_OS_LINUX #include "gamemode_client.h" #endif -LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent) +LauncherPartLaunch::LauncherPartLaunch(LaunchTask* parent) : LaunchStep(parent) { auto instance = parent->instance(); - if (instance->settings()->get("CloseAfterLaunch").toBool()) - { - std::shared_ptr connection{new QMetaObject::Connection}; + if (instance->settings()->get("CloseAfterLaunch").toBool()) { + std::shared_ptr connection{ new QMetaObject::Connection }; *connection = connect(&m_process, &LoggedProcess::log, this, [=](QStringList lines, [[maybe_unused]] MessageLevel::Enum level) { qDebug() << lines; - if (lines.filter(QRegularExpression(".*Setting user.+", QRegularExpression::CaseInsensitiveOption)).length() != 0) - { + if (lines.filter(QRegularExpression(".*Setting user.+", QRegularExpression::CaseInsensitiveOption)).length() != 0) { APPLICATION->closeAllWindows(); disconnect(*connection); } @@ -71,7 +69,7 @@ LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent) #ifdef Q_OS_WIN // returns 8.3 file format from long path #include -QString shortPathName(const QString & file) +QString shortPathName(const QString& file) { auto input = file.toStdWString(); std::wstring output; @@ -81,15 +79,15 @@ QString shortPathName(const QString & file) // when it succeeds, it returns length excluding null character // See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989(v=vs.85).aspx output.resize(length); - GetShortPathNameW(input.c_str(),(LPWSTR)output.c_str(),length); - output.resize(length-1); + GetShortPathNameW(input.c_str(), (LPWSTR)output.c_str(), length); + output.resize(length - 1); QString ret = QString::fromStdWString(output); return ret; } #endif // if the string survives roundtrip through local 8bit encoding... -bool fitsInLocal8bit(const QString & string) +bool fitsInLocal8bit(const QString& string) { return string == QString::fromLocal8Bit(string.toLocal8Bit()); } @@ -97,9 +95,8 @@ bool fitsInLocal8bit(const QString & string) void LauncherPartLaunch::executeTask() { QString jarPath = APPLICATION->getJarPath("NewLaunch.jar"); - if (jarPath.isEmpty()) - { - const char *reason = QT_TR_NOOP("Launcher library could not be found. Please check your installation."); + if (jarPath.isEmpty()) { + const char* reason = QT_TR_NOOP("Launcher library could not be found. Please check your installation."); emit logLine(tr(reason), MessageLevel::Fatal); emitFailed(tr(reason)); return; @@ -125,12 +122,9 @@ void LauncherPartLaunch::executeTask() auto natPath = minecraftInstance->getNativePath(); #ifdef Q_OS_WIN - if (!fitsInLocal8bit(natPath)) - { + if (!fitsInLocal8bit(natPath)) { args << "-Djava.library.path=" + shortPathName(natPath); - } - else - { + } else { args << "-Djava.library.path=" + natPath; } #else @@ -140,14 +134,10 @@ void LauncherPartLaunch::executeTask() args << "-cp"; #ifdef Q_OS_WIN QStringList processed; - for(auto & item: classPath) - { - if (!fitsInLocal8bit(item)) - { + for (auto& item : classPath) { + if (!fitsInLocal8bit(item)) { processed << shortPathName(item); - } - else - { + } else { processed << item; } } @@ -160,14 +150,12 @@ void LauncherPartLaunch::executeTask() qDebug() << args.join(' '); QString wrapperCommandStr = instance->getWrapperCommand().trimmed(); - if(!wrapperCommandStr.isEmpty()) - { + if (!wrapperCommandStr.isEmpty()) { auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr); auto wrapperCommand = wrapperArgs.takeFirst(); auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand); - if (realWrapperCommand.isEmpty()) - { - const char *reason = QT_TR_NOOP("The wrapper command \"%1\" couldn't be found."); + if (realWrapperCommand.isEmpty()) { + const char* reason = QT_TR_NOOP("The wrapper command \"%1\" couldn't be found."); emit logLine(QString(reason).arg(wrapperCommand), MessageLevel::Fatal); emitFailed(tr(reason).arg(wrapperCommand)); return; @@ -175,18 +163,14 @@ void LauncherPartLaunch::executeTask() emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::Launcher); args.prepend(javaPath); m_process.start(wrapperCommand, wrapperArgs + args); - } - else - { + } else { m_process.start(javaPath, args); } #ifdef Q_OS_LINUX - if (instance->settings()->get("EnableFeralGamemode").toBool() && APPLICATION->capabilities() & Application::SupportsGameMode) - { + if (instance->settings()->get("EnableFeralGamemode").toBool() && APPLICATION->capabilities() & Application::SupportsGameMode) { auto pid = m_process.processId(); - if (pid) - { + if (pid) { gamemode_request_start_for(pid); } } @@ -195,25 +179,21 @@ void LauncherPartLaunch::executeTask() void LauncherPartLaunch::on_state(LoggedProcess::State state) { - switch(state) - { - case LoggedProcess::FailedToStart: - { + switch (state) { + case LoggedProcess::FailedToStart: { //: Error message displayed if instace can't start - const char *reason = QT_TR_NOOP("Could not launch Minecraft!"); + const char* reason = QT_TR_NOOP("Could not launch Minecraft!"); emit logLine(reason, MessageLevel::Fatal); emitFailed(tr(reason)); return; } case LoggedProcess::Aborted: - case LoggedProcess::Crashed: - { + case LoggedProcess::Crashed: { m_parent->setPid(-1); emitFailed(tr("Game crashed.")); return; } - case LoggedProcess::Finished: - { + case LoggedProcess::Finished: { auto instance = m_parent->instance(); if (instance->settings()->get("CloseAfterLaunch").toBool()) APPLICATION->showMainWindow(); @@ -221,14 +201,13 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state) m_parent->setPid(-1); // if the exit code wasn't 0, report this as a crash auto exitCode = m_process.exitCode(); - if(exitCode != 0) - { + if (exitCode != 0) { emitFailed(tr("Game crashed.")); return; } - //FIXME: make this work again - // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode)); - // run post-exit + // FIXME: make this work again + // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode)); + // run post-exit emitSucceeded(); break; } @@ -247,15 +226,14 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state) } } -void LauncherPartLaunch::setWorkingDirectory(const QString &wd) +void LauncherPartLaunch::setWorkingDirectory(const QString& wd) { m_process.setWorkingDirectory(wd); } void LauncherPartLaunch::proceed() { - if(mayProceed) - { + if (mayProceed) { QString launchString("launch\n"); m_process.write(launchString.toUtf8()); mayProceed = false; @@ -264,17 +242,13 @@ void LauncherPartLaunch::proceed() bool LauncherPartLaunch::abort() { - if(mayProceed) - { + if (mayProceed) { mayProceed = false; QString launchString("abort\n"); m_process.write(launchString.toUtf8()); - } - else - { + } else { auto state = m_process.state(); - if (state == LoggedProcess::Running || state == LoggedProcess::Starting) - { + if (state == LoggedProcess::Running || state == LoggedProcess::Starting) { m_process.kill(); } } diff --git a/launcher/minecraft/launch/LauncherPartLaunch.h b/launcher/minecraft/launch/LauncherPartLaunch.h index 6a7ee0e5f..9f6ca1e7b 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.h +++ b/launcher/minecraft/launch/LauncherPartLaunch.h @@ -15,41 +15,31 @@ #pragma once -#include #include +#include #include #include "MinecraftServerTarget.h" -class LauncherPartLaunch: public LaunchStep -{ +class LauncherPartLaunch : public LaunchStep { Q_OBJECT -public: - explicit LauncherPartLaunch(LaunchTask *parent); - virtual ~LauncherPartLaunch() {}; + public: + explicit LauncherPartLaunch(LaunchTask* parent); + virtual ~LauncherPartLaunch(){}; virtual void executeTask(); virtual bool abort(); virtual void proceed(); - virtual bool canAbort() const - { - return true; - } - void setWorkingDirectory(const QString &wd); - void setAuthSession(AuthSessionPtr session) - { - m_session = session; - } + virtual bool canAbort() const { return true; } + void setWorkingDirectory(const QString& wd); + void setAuthSession(AuthSessionPtr session) { m_session = session; } - void setServerToJoin(MinecraftServerTargetPtr serverToJoin) - { - m_serverToJoin = std::move(serverToJoin); - } + void setServerToJoin(MinecraftServerTargetPtr serverToJoin) { m_serverToJoin = std::move(serverToJoin); } -private slots: + private slots: void on_state(LoggedProcess::State state); -private: + private: LoggedProcess m_process; QString m_command; AuthSessionPtr m_session; diff --git a/launcher/minecraft/launch/MinecraftServerTarget.cpp b/launcher/minecraft/launch/MinecraftServerTarget.cpp index a3383ec08..e201efab1 100644 --- a/launcher/minecraft/launch/MinecraftServerTarget.cpp +++ b/launcher/minecraft/launch/MinecraftServerTarget.cpp @@ -18,50 +18,43 @@ #include // FIXME: the way this is written, it can't ever do any sort of validation and can accept total junk -MinecraftServerTarget MinecraftServerTarget::parse(const QString &fullAddress) { +MinecraftServerTarget MinecraftServerTarget::parse(const QString& fullAddress) +{ QStringList split = fullAddress.split(":"); // The logic below replicates the exact logic minecraft uses for parsing server addresses. // While the conversion is not lossless and eats errors, it ensures the same behavior // within Minecraft and Prism Launcher when entering server addresses. - if (fullAddress.startsWith("[")) - { + if (fullAddress.startsWith("[")) { int bracket = fullAddress.indexOf("]"); - if (bracket > 0) - { + if (bracket > 0) { QString ipv6 = fullAddress.mid(1, bracket - 1); QString port = fullAddress.mid(bracket + 1).trimmed(); - if (port.startsWith(":") && !ipv6.isEmpty()) - { + if (port.startsWith(":") && !ipv6.isEmpty()) { port = port.mid(1); split = QStringList({ ipv6, port }); - } - else - { - split = QStringList({ipv6}); + } else { + split = QStringList({ ipv6 }); } } } - if (split.size() > 2) - { - split = QStringList({fullAddress}); + if (split.size() > 2) { + split = QStringList({ fullAddress }); } QString realAddress = split[0]; quint16 realPort = 25565; - if (split.size() > 1) - { + if (split.size() > 1) { bool ok; realPort = split[1].toUInt(&ok); - if (!ok) - { + if (!ok) { realPort = 25565; } } - return MinecraftServerTarget { realAddress, realPort }; + return MinecraftServerTarget{ realAddress, realPort }; } diff --git a/launcher/minecraft/launch/MinecraftServerTarget.h b/launcher/minecraft/launch/MinecraftServerTarget.h index a402421af..af8d6550b 100644 --- a/launcher/minecraft/launch/MinecraftServerTarget.h +++ b/launcher/minecraft/launch/MinecraftServerTarget.h @@ -23,7 +23,7 @@ struct MinecraftServerTarget { QString address; quint16 port; - static MinecraftServerTarget parse(const QString &fullAddress); + static MinecraftServerTarget parse(const QString& fullAddress); }; typedef std::shared_ptr MinecraftServerTargetPtr; diff --git a/launcher/minecraft/launch/ModMinecraftJar.cpp b/launcher/minecraft/launch/ModMinecraftJar.cpp index 1d6eecf2d..f858dd740 100644 --- a/launcher/minecraft/launch/ModMinecraftJar.cpp +++ b/launcher/minecraft/launch/ModMinecraftJar.cpp @@ -34,9 +34,9 @@ */ #include "ModMinecraftJar.h" -#include "launch/LaunchTask.h" -#include "MMCZip.h" #include "FileSystem.h" +#include "MMCZip.h" +#include "launch/LaunchTask.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" @@ -44,20 +44,17 @@ void ModMinecraftJar::executeTask() { auto m_inst = std::dynamic_pointer_cast(m_parent->instance()); - if(!m_inst->getJarMods().size()) - { + if (!m_inst->getJarMods().size()) { emitSucceeded(); return; } // nuke obsolete stripped jar(s) if needed - if(!FS::ensureFolderPathExists(m_inst->binRoot())) - { + if (!FS::ensureFolderPathExists(m_inst->binRoot())) { emitFailed(tr("Couldn't create the bin folder for Minecraft.jar")); } auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); - if(!removeJar()) - { + if (!removeJar()) { emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath)); } @@ -65,14 +62,12 @@ void ModMinecraftJar::executeTask() auto components = m_inst->getPackProfile(); auto profile = components->getProfile(); auto jarMods = m_inst->getJarMods(); - if(jarMods.size()) - { + if (jarMods.size()) { auto mainJar = profile->getMainJar(); QStringList jars, temp1, temp2, temp3, temp4; mainJar->getApplicableFiles(m_inst->runtimeContext(), jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath()); auto sourceJarPath = jars[0]; - if(!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods)) - { + if (!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods)) { emitFailed(tr("Failed to create the custom Minecraft jar file.")); return; } @@ -90,10 +85,8 @@ bool ModMinecraftJar::removeJar() auto m_inst = std::dynamic_pointer_cast(m_parent->instance()); auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); QFile finalJar(finalJarPath); - if(finalJar.exists()) - { - if(!finalJar.remove()) - { + if (finalJar.exists()) { + if (!finalJar.remove()) { return false; } } diff --git a/launcher/minecraft/launch/ModMinecraftJar.h b/launcher/minecraft/launch/ModMinecraftJar.h index 081c6a914..12e73b5f8 100644 --- a/launcher/minecraft/launch/ModMinecraftJar.h +++ b/launcher/minecraft/launch/ModMinecraftJar.h @@ -18,19 +18,16 @@ #include #include -class ModMinecraftJar: public LaunchStep -{ +class ModMinecraftJar : public LaunchStep { Q_OBJECT -public: - explicit ModMinecraftJar(LaunchTask *parent) : LaunchStep(parent) {}; + public: + explicit ModMinecraftJar(LaunchTask* parent) : LaunchStep(parent){}; virtual ~ModMinecraftJar(){}; virtual void executeTask() override; - virtual bool canAbort() const override - { - return false; - } + virtual bool canAbort() const override { return false; } void finalize() override; -private: + + private: bool removeJar(); }; diff --git a/launcher/minecraft/launch/PrintInstanceInfo.cpp b/launcher/minecraft/launch/PrintInstanceInfo.cpp index e8fbcb9b7..e3a45b030 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.cpp +++ b/launcher/minecraft/launch/PrintInstanceInfo.cpp @@ -16,50 +16,44 @@ #include #include -#include "PrintInstanceInfo.h" #include +#include "PrintInstanceInfo.h" #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) namespace { #if defined(Q_OS_LINUX) -void probeProcCpuinfo(QStringList &log) +void probeProcCpuinfo(QStringList& log) { std::ifstream cpuin("/proc/cpuinfo"); - for (std::string line; std::getline(cpuin, line);) - { - if (strncmp(line.c_str(), "model name", 10) == 0) - { + for (std::string line; std::getline(cpuin, line);) { + if (strncmp(line.c_str(), "model name", 10) == 0) { log << QString::fromStdString(line.substr(13, std::string::npos)); break; } } } -void runLspci(QStringList &log) +void runLspci(QStringList& log) { // FIXME: fixed size buffers... char buff[512]; int gpuline = -1; int cline = 0; - FILE * lspci = popen("lspci -k", "r"); + FILE* lspci = popen("lspci -k", "r"); if (!lspci) return; - while (fgets(buff, 512, lspci) != NULL) - { + while (fgets(buff, 512, lspci) != NULL) { std::string str(buff); if (str.length() < 9) continue; - if (str.substr(8, 3) == "VGA") - { + if (str.substr(8, 3) == "VGA") { gpuline = cline; log << QString::fromStdString(str.substr(35, std::string::npos)); } - if (gpuline > -1 && gpuline != cline) - { - if (cline - gpuline < 3) - { + if (gpuline > -1 && gpuline != cline) { + if (cline - gpuline < 3) { log << QString::fromStdString(str.substr(1, std::string::npos)); } } @@ -68,54 +62,47 @@ void runLspci(QStringList &log) pclose(lspci); } #elif defined(Q_OS_FREEBSD) -void runSysctlHwModel(QStringList &log) +void runSysctlHwModel(QStringList& log) { char buff[512]; - FILE *hwmodel = popen("sysctl hw.model", "r"); - while (fgets(buff, 512, hwmodel) != NULL) - { - log << QString::fromUtf8(buff); - break; + FILE* hwmodel = popen("sysctl hw.model", "r"); + while (fgets(buff, 512, hwmodel) != NULL) { + log << QString::fromUtf8(buff); + break; } pclose(hwmodel); } -void runPciconf(QStringList &log) +void runPciconf(QStringList& log) { char buff[512]; std::string strcard; - FILE *pciconf = popen("pciconf -lv -a vgapci0", "r"); - while (fgets(buff, 512, pciconf) != NULL) - { - if (strncmp(buff, " vendor", 10) == 0) - { - std::string str(buff); - strcard.append(str.substr(str.find_first_of("'") + 1, str.find_last_not_of("'") - (str.find_first_of("'") + 2))); - strcard.append(" "); - } - else if (strncmp(buff, " device", 10) == 0) - { - std::string str2(buff); - strcard.append(str2.substr(str2.find_first_of("'") + 1, str2.find_last_not_of("'") - (str2.find_first_of("'") + 2))); - } - log << QString::fromStdString(strcard); - break; + FILE* pciconf = popen("pciconf -lv -a vgapci0", "r"); + while (fgets(buff, 512, pciconf) != NULL) { + if (strncmp(buff, " vendor", 10) == 0) { + std::string str(buff); + strcard.append(str.substr(str.find_first_of("'") + 1, str.find_last_not_of("'") - (str.find_first_of("'") + 2))); + strcard.append(" "); + } else if (strncmp(buff, " device", 10) == 0) { + std::string str2(buff); + strcard.append(str2.substr(str2.find_first_of("'") + 1, str2.find_last_not_of("'") - (str2.find_first_of("'") + 2))); + } + log << QString::fromStdString(strcard); + break; } pclose(pciconf); } #endif -void runGlxinfo(QStringList & log) +void runGlxinfo(QStringList& log) { // FIXME: fixed size buffers... char buff[512]; - FILE *glxinfo = popen("glxinfo", "r"); + FILE* glxinfo = popen("glxinfo", "r"); if (!glxinfo) return; - while (fgets(buff, 512, glxinfo) != NULL) - { - if (strncmp(buff, "OpenGL version string:", 22) == 0) - { + while (fgets(buff, 512, glxinfo) != NULL) { + if (strncmp(buff, "OpenGL version string:", 22) == 0) { log << QString::fromUtf8(buff); break; } @@ -123,7 +110,7 @@ void runGlxinfo(QStringList & log) pclose(glxinfo); } -} +} // namespace #endif void PrintInstanceInfo::executeTask() diff --git a/launcher/minecraft/launch/PrintInstanceInfo.h b/launcher/minecraft/launch/PrintInstanceInfo.h index fdc30f316..8e1c41b62 100644 --- a/launcher/minecraft/launch/PrintInstanceInfo.h +++ b/launcher/minecraft/launch/PrintInstanceInfo.h @@ -21,21 +21,17 @@ #include "minecraft/launch/MinecraftServerTarget.h" // FIXME: temporary wrapper for existing task. -class PrintInstanceInfo: public LaunchStep -{ +class PrintInstanceInfo : public LaunchStep { Q_OBJECT -public: - explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) : - LaunchStep(parent), m_session(session), m_serverToJoin(serverToJoin) {}; + public: + explicit PrintInstanceInfo(LaunchTask* parent, AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) + : LaunchStep(parent), m_session(session), m_serverToJoin(serverToJoin){}; virtual ~PrintInstanceInfo(){}; virtual void executeTask(); - virtual bool canAbort() const - { - return false; - } -private: + virtual bool canAbort() const { return false; } + + private: AuthSessionPtr m_session; MinecraftServerTargetPtr m_serverToJoin; }; - diff --git a/launcher/minecraft/launch/ReconstructAssets.cpp b/launcher/minecraft/launch/ReconstructAssets.cpp index 4d206665f..843ccc554 100644 --- a/launcher/minecraft/launch/ReconstructAssets.cpp +++ b/launcher/minecraft/launch/ReconstructAssets.cpp @@ -14,10 +14,10 @@ */ #include "ReconstructAssets.h" +#include "launch/LaunchTask.h" +#include "minecraft/AssetsUtils.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -#include "minecraft/AssetsUtils.h" -#include "launch/LaunchTask.h" void ReconstructAssets::executeTask() { @@ -27,8 +27,7 @@ void ReconstructAssets::executeTask() auto profile = components->getProfile(); auto assets = profile->getMinecraftAssets(); - if(!AssetsUtils::reconstructAssets(assets->id, minecraftInstance->resourcesDir())) - { + if (!AssetsUtils::reconstructAssets(assets->id, minecraftInstance->resourcesDir())) { emit logLine("Failed to reconstruct Minecraft assets.", MessageLevel::Error); } diff --git a/launcher/minecraft/launch/ReconstructAssets.h b/launcher/minecraft/launch/ReconstructAssets.h index 58d7febd1..bd867c8d4 100644 --- a/launcher/minecraft/launch/ReconstructAssets.h +++ b/launcher/minecraft/launch/ReconstructAssets.h @@ -18,16 +18,12 @@ #include #include -class ReconstructAssets: public LaunchStep -{ +class ReconstructAssets : public LaunchStep { Q_OBJECT -public: - explicit ReconstructAssets(LaunchTask *parent) : LaunchStep(parent){}; + public: + explicit ReconstructAssets(LaunchTask* parent) : LaunchStep(parent){}; virtual ~ReconstructAssets(){}; void executeTask() override; - bool canAbort() const override - { - return false; - } + bool canAbort() const override { return false; } }; diff --git a/launcher/minecraft/launch/ScanModFolders.cpp b/launcher/minecraft/launch/ScanModFolders.cpp index 71e7638cd..04d820668 100644 --- a/launcher/minecraft/launch/ScanModFolders.cpp +++ b/launcher/minecraft/launch/ScanModFolders.cpp @@ -34,9 +34,9 @@ */ #include "ScanModFolders.h" -#include "launch/LaunchTask.h" -#include "MMCZip.h" #include "FileSystem.h" +#include "MMCZip.h" +#include "launch/LaunchTask.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/mod/ModFolderModel.h" @@ -46,19 +46,19 @@ void ScanModFolders::executeTask() auto loaders = m_inst->loaderModList(); connect(loaders.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone); - if(!loaders->update()) { + if (!loaders->update()) { m_modsDone = true; } auto cores = m_inst->coreModList(); connect(cores.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone); - if(!cores->update()) { + if (!cores->update()) { m_coreModsDone = true; } auto nils = m_inst->nilModList(); connect(nils.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone); - if(!nils->update()) { + if (!nils->update()) { m_nilModsDone = true; } checkDone(); @@ -84,7 +84,7 @@ void ScanModFolders::nilModsDone() void ScanModFolders::checkDone() { - if(m_modsDone && m_coreModsDone && m_nilModsDone) { + if (m_modsDone && m_coreModsDone && m_nilModsDone) { emitSucceeded(); } } diff --git a/launcher/minecraft/launch/ScanModFolders.h b/launcher/minecraft/launch/ScanModFolders.h index 111a5850b..a5b75825b 100644 --- a/launcher/minecraft/launch/ScanModFolders.h +++ b/launcher/minecraft/launch/ScanModFolders.h @@ -18,26 +18,23 @@ #include #include -class ScanModFolders: public LaunchStep -{ +class ScanModFolders : public LaunchStep { Q_OBJECT -public: - explicit ScanModFolders(LaunchTask *parent) : LaunchStep(parent) {}; + public: + explicit ScanModFolders(LaunchTask* parent) : LaunchStep(parent){}; virtual ~ScanModFolders(){}; virtual void executeTask() override; - virtual bool canAbort() const override - { - return false; - } -private slots: + virtual bool canAbort() const override { return false; } + private slots: void coreModsDone(); void modsDone(); void nilModsDone(); -private: + + private: void checkDone(); -private: // DATA + private: // DATA bool m_modsDone = false; bool m_nilModsDone = false; bool m_coreModsDone = false; diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index 6ae666b47..03831d175 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -36,10 +36,11 @@ #include "VerifyJavaInstall.h" #include "java/JavaVersion.h" -#include "minecraft/PackProfile.h" #include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" -void VerifyJavaInstall::executeTask() { +void VerifyJavaInstall::executeTask() +{ auto instance = std::dynamic_pointer_cast(m_parent->instance()); auto packProfile = instance->getPackProfile(); auto settings = instance->settings(); @@ -50,28 +51,27 @@ void VerifyJavaInstall::executeTask() { JavaVersion javaVersion(storedVersion); - if (compatibleMajors.isEmpty() || compatibleMajors.contains(javaVersion.major())) - { + if (compatibleMajors.isEmpty() || compatibleMajors.contains(javaVersion.major())) { emitSucceeded(); return; } - - if (ignoreCompatibility) - { + if (ignoreCompatibility) { emit logLine(tr("Java major version is incompatible. Things might break."), MessageLevel::Warning); emitSucceeded(); return; } emit logLine(tr("This instance is not compatible with Java version %1.\n" - "Please switch to one of the following Java versions for this instance:").arg(javaVersion.major()), + "Please switch to one of the following Java versions for this instance:") + .arg(javaVersion.major()), MessageLevel::Error); - for (auto major : compatibleMajors) - { + for (auto major : compatibleMajors) { emit logLine(tr("Java version %1").arg(major), MessageLevel::Error); } - emit logLine(tr("Go to instance Java settings to change your Java version or disable the Java compatibility check if you know what you're doing."), MessageLevel::Error); + emit logLine(tr("Go to instance Java settings to change your Java version or disable the Java compatibility check if you know what " + "you're doing."), + MessageLevel::Error); emitFailed(QString("Incompatible Java major version")); } diff --git a/launcher/minecraft/launch/VerifyJavaInstall.h b/launcher/minecraft/launch/VerifyJavaInstall.h index 9139c0faf..edf6015a3 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.h +++ b/launcher/minecraft/launch/VerifyJavaInstall.h @@ -41,13 +41,10 @@ class VerifyJavaInstall : public LaunchStep { Q_OBJECT -public: - explicit VerifyJavaInstall(LaunchTask *parent) : LaunchStep(parent) { - }; + public: + explicit VerifyJavaInstall(LaunchTask* parent) : LaunchStep(parent){}; ~VerifyJavaInstall() override = default; void executeTask() override; - bool canAbort() const override { - return false; - } + bool canAbort() const override { return false; } }; diff --git a/launcher/minecraft/mod/DataPack.cpp b/launcher/minecraft/mod/DataPack.cpp index c5754638a..7bf5a3112 100644 --- a/launcher/minecraft/mod/DataPack.cpp +++ b/launcher/minecraft/mod/DataPack.cpp @@ -30,10 +30,10 @@ // Values taken from: // https://minecraft.fandom.com/wiki/Tutorials/Creating_a_data_pack#%22pack_format%22 static const QMap> s_pack_format_versions = { - { 4, { Version("1.13"), Version("1.14.4") } }, { 5, { Version("1.15"), Version("1.16.1") } }, - { 6, { Version("1.16.2"), Version("1.16.5") } }, { 7, { Version("1.17"), Version("1.17.1") } }, - { 8, { Version("1.18"), Version("1.18.1") } }, { 9, { Version("1.18.2"), Version("1.18.2") } }, - { 10, { Version("1.19"), Version("1.19.3") } }, { 11, { Version("23w03a"), Version("23w05a") } }, + { 4, { Version("1.13"), Version("1.14.4") } }, { 5, { Version("1.15"), Version("1.16.1") } }, + { 6, { Version("1.16.2"), Version("1.16.5") } }, { 7, { Version("1.17"), Version("1.17.1") } }, + { 8, { Version("1.18"), Version("1.18.1") } }, { 9, { Version("1.18.2"), Version("1.18.2") } }, + { 10, { Version("1.19"), Version("1.19.3") } }, { 11, { Version("23w03a"), Version("23w05a") } }, { 12, { Version("1.19.4"), Version("1.19.4") } }, { 13, { Version("23w12a"), Version("23w14a") } }, { 14, { Version("23w16a"), Version("23w17a") } }, { 15, { Version("1.20"), Version("1.20") } }, }; diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index 39723b49c..ea9078e04 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #pragma once @@ -42,28 +42,13 @@ class Metadata { return Packwiz::V1::createModFormat(index_dir, internal_mod, mod_slug); } - static void update(QDir& index_dir, ModStruct& mod) - { - Packwiz::V1::updateModIndex(index_dir, mod); - } + static void update(QDir& index_dir, ModStruct& mod) { Packwiz::V1::updateModIndex(index_dir, mod); } - static void remove(QDir& index_dir, QString mod_slug) - { - Packwiz::V1::deleteModIndex(index_dir, mod_slug); - } + static void remove(QDir& index_dir, QString mod_slug) { Packwiz::V1::deleteModIndex(index_dir, mod_slug); } - static void remove(QDir& index_dir, QVariant& mod_id) - { - Packwiz::V1::deleteModIndex(index_dir, mod_id); - } + static void remove(QDir& index_dir, QVariant& mod_id) { Packwiz::V1::deleteModIndex(index_dir, mod_id); } - static auto get(QDir& index_dir, QString mod_slug) -> ModStruct - { - return Packwiz::V1::getIndexForMod(index_dir, mod_slug); - } + static auto get(QDir& index_dir, QString mod_slug) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_slug); } - static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct - { - return Packwiz::V1::getIndexForMod(index_dir, mod_id); - } + static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_id); } }; diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 880dacb15..46509cde6 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -1,45 +1,45 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 "Mod.h" #include #include -#include #include +#include #include "MTPixmapCache.h" #include "MetadataHandler.h" @@ -54,8 +54,7 @@ Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details() m_enabled = (file.suffix() != "disabled"); } -Mod::Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata) - : Mod(mods_dir.absoluteFilePath(metadata.filename)) +Mod::Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata) : Mod(mods_dir.absoluteFilePath(metadata.filename)) { m_name = metadata.name; m_local_details.metadata = std::make_shared(std::move(metadata)); @@ -73,7 +72,8 @@ void Mod::setMetadata(std::shared_ptr&& metadata) m_local_details.metadata = metadata; } -void Mod::setDetails(const ModDetails& details) { +void Mod::setDetails(const ModDetails& details) +{ m_local_details = details; } @@ -103,7 +103,8 @@ std::pair Mod::compare(const Resource& other, SortType type) const break; } case SortType::PROVIDER: { - auto compare_result = QString::compare(provider().value_or("Unknown"), cast_other->provider().value_or("Unknown"), Qt::CaseInsensitive); + auto compare_result = + QString::compare(provider().value_or("Unknown"), cast_other->provider().value_or("Unknown"), Qt::CaseInsensitive); if (compare_result != 0) return { compare_result, type == SortType::PROVIDER }; break; @@ -230,7 +231,7 @@ auto Mod::licenses() const -> const QList& return details().licenses; } - auto Mod::issueTracker() const -> QString +auto Mod::issueTracker() const -> QString { return details().issue_tracker; } @@ -245,7 +246,7 @@ void Mod::setIcon(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index ef1895e1b..543648115 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -1,76 +1,75 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 +#include #include #include #include #include -#include "Resource.h" #include "ModDetails.h" +#include "Resource.h" -class Mod : public Resource -{ +class Mod : public Resource { Q_OBJECT -public: + public: using Ptr = shared_qobject_ptr; using WeakPtr = QPointer; Mod() = default; - Mod(const QFileInfo &file); + Mod(const QFileInfo& file); Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); Mod(QString file_path) : Mod(QFileInfo(file_path)) {} - auto details() const -> const ModDetails&; - auto name() const -> QString override; - auto version() const -> QString; - auto homeurl() const -> QString; + auto details() const -> const ModDetails&; + auto name() const -> QString override; + auto version() const -> QString; + auto homeurl() const -> QString; auto description() const -> QString; - auto authors() const -> QStringList; - auto status() const -> ModStatus; - auto provider() const -> std::optional; - auto licenses() const -> const QList&; + auto authors() const -> QStringList; + auto status() const -> ModStatus; + auto provider() const -> std::optional; + auto licenses() const -> const QList&; auto issueTracker() const -> QString; - auto metaurl() const -> QString; + auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; } @@ -97,7 +96,7 @@ public: void finishResolvingWithDetails(ModDetails&& details); -protected: + protected: ModDetails m_local_details; mutable QMutex m_data_lock; @@ -107,5 +106,4 @@ protected: bool was_ever_used = false; bool was_read_attempt = false; } mutable m_pack_image_cache_key; - }; diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index ae36baa85..0235fe333 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -1,37 +1,37 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 @@ -44,10 +44,10 @@ #include "minecraft/mod/MetadataHandler.h" enum class ModStatus { - Installed, // Both JAR and Metadata are present - NotInstalled, // Only the Metadata is present - NoMetadata, // Only the JAR is present - Unknown, // Default status + Installed, // Both JAR and Metadata are present + NotInstalled, // Only the Metadata is present + NoMetadata, // Only the JAR is present + Unknown, // Default status }; struct ModLicense { @@ -58,11 +58,12 @@ struct ModLicense { ModLicense() {} - ModLicense(const QString license) { - // FIXME: come up with a better license parsing. + ModLicense(const QString license) + { + // FIXME: come up with a better license parsing. // handle SPDX identifiers? https://spdx.org/licenses/ auto parts = license.split(' '); - QStringList notNameParts = {}; + QStringList notNameParts = {}; for (auto part : parts) { auto _url = QUrl(part); if (part.startsWith("(") && part.endsWith(")")) @@ -78,7 +79,7 @@ struct ModLicense { for (auto part : notNameParts) { parts.removeOne(part); } - + auto licensePart = parts.join(' '); this->name = licensePart; this->description = licensePart; @@ -86,19 +87,13 @@ struct ModLicense { if (parts.size() == 1) { this->id = parts.first(); } - } ModLicense(const QString& name_, const QString& id_, const QString& url_, const QString& description_) : name(name_), id(id_), url(url_), description(description_) {} - ModLicense(const ModLicense& other) - : name(other.name) - , id(other.id) - , url(other.url) - , description(other.description) - {} + ModLicense(const ModLicense& other) : name(other.name), id(other.id), url(other.url), description(other.description) {} ModLicense& operator=(const ModLicense& other) { @@ -120,28 +115,25 @@ struct ModLicense { return *this; } - bool isEmpty() { - return this->name.isEmpty() && this->id.isEmpty() && this->url.isEmpty() && this->description.isEmpty(); - } + bool isEmpty() { return this->name.isEmpty() && this->id.isEmpty() && this->url.isEmpty() && this->description.isEmpty(); } }; -struct ModDetails -{ +struct ModDetails { /* Mod ID as defined in the ModLoader-specific metadata */ QString mod_id = {}; - + /* Human-readable name */ QString name = {}; - + /* Human-readable mod version */ QString version = {}; - + /* Human-readable minecraft version */ QString mcversion = {}; - + /* URL for mod's home page */ QString homeurl = {}; - + /* Human-readable description */ QString description = {}; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 7b6d936c6..a8451681c 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -1,38 +1,38 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 "ModFolderModel.h" @@ -59,12 +59,13 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool { m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") }); - m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER}; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; - m_columnsHideable = { false, true, false, true, true, true }; + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER }; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, + QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; + m_columnsHideable = { false, true, false, true, true, true }; } -QVariant ModFolderModel::data(const QModelIndex &index, int role) const +QVariant ModFolderModel::data(const QModelIndex& index, int role) const { if (!validateIndex(index)) return {}; @@ -72,115 +73,109 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const int row = index.row(); int column = index.column(); - switch (role) - { - case Qt::DisplayRole: - switch (column) - { - case NameColumn: - return m_resources[row]->name(); - case VersionColumn: { - switch(m_resources[row]->type()) { - case ResourceType::FOLDER: - return tr("Folder"); - case ResourceType::SINGLEFILE: - return tr("File"); + switch (role) { + case Qt::DisplayRole: + switch (column) { + case NameColumn: + return m_resources[row]->name(); + case VersionColumn: { + switch (m_resources[row]->type()) { + case ResourceType::FOLDER: + return tr("Folder"); + case ResourceType::SINGLEFILE: + return tr("File"); + default: + break; + } + return at(row)->version(); + } + case DateColumn: + return m_resources[row]->dateTimeChanged(); + case ProviderColumn: { + auto provider = at(row)->provider(); + if (!provider.has_value()) { + //: Unknown mod provider (i.e. not Modrinth, CurseForge, etc...) + return tr("Unknown"); + } + + return provider.value(); + } default: - break; - } - return at(row)->version(); - } - case DateColumn: - return m_resources[row]->dateTimeChanged(); - case ProviderColumn: { - auto provider = at(row)->provider(); - if (!provider.has_value()) { - //: Unknown mod provider (i.e. not Modrinth, CurseForge, etc...) - return tr("Unknown"); + return QVariant(); } - return provider.value(); + case Qt::ToolTipRole: + if (column == NAME_COLUMN) { + if (at(row)->isSymLinkUnder(instDirPath())) { + return m_resources[row]->internal_id() + + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." + "\nCanonical Path: %1") + .arg(at(row)->fileinfo().canonicalFilePath()); + } + if (at(row)->isMoreThanOneHardLink()) { + return m_resources[row]->internal_id() + + tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); + } + } + return m_resources[row]->internal_id(); + case Qt::DecorationRole: { + if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) + return APPLICATION->getThemedIcon("status-yellow"); + if (column == ImageColumn) { + return at(row)->icon({ 32, 32 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding); + } + return {}; } + case Qt::CheckStateRole: + switch (column) { + case ActiveColumn: + return at(row)->enabled() ? Qt::Checked : Qt::Unchecked; + default: + return QVariant(); + } default: return QVariant(); - } - - case Qt::ToolTipRole: - if (column == NAME_COLUMN) { - if (at(row)->isSymLinkUnder(instDirPath())) { - return m_resources[row]->internal_id() + - tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." - "\nCanonical Path: %1") - .arg(at(row)->fileinfo().canonicalFilePath()); - } - if (at(row)->isMoreThanOneHardLink()) { - return m_resources[row]->internal_id() + - tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); - } - } - return m_resources[row]->internal_id(); - case Qt::DecorationRole: { - if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) - return APPLICATION->getThemedIcon("status-yellow"); - if (column == ImageColumn) { - return at(row)->icon({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding); - } - return {}; - } - case Qt::CheckStateRole: - switch (column) - { - case ActiveColumn: - return at(row)->enabled() ? Qt::Checked : Qt::Unchecked; - default: - return QVariant(); - } - default: - return QVariant(); } } QVariant ModFolderModel::headerData(int section, [[maybe_unused]] Qt::Orientation orientation, int role) const { - switch (role) - { - case Qt::DisplayRole: - switch (section) - { - case ActiveColumn: - case NameColumn: - case VersionColumn: - case DateColumn: - case ProviderColumn: - case ImageColumn: - return columnNames().at(section); - default: - return QVariant(); - } + switch (role) { + case Qt::DisplayRole: + switch (section) { + case ActiveColumn: + case NameColumn: + case VersionColumn: + case DateColumn: + case ProviderColumn: + case ImageColumn: + return columnNames().at(section); + default: + return QVariant(); + } - case Qt::ToolTipRole: - switch (section) - { - case ActiveColumn: - return tr("Is the mod enabled?"); - case NameColumn: - return tr("The name of the mod."); - case VersionColumn: - return tr("The version of the mod."); - case DateColumn: - return tr("The date and time this mod was last changed (or added)."); - case ProviderColumn: - return tr("Where the mod was downloaded from."); + case Qt::ToolTipRole: + switch (section) { + case ActiveColumn: + return tr("Is the mod enabled?"); + case NameColumn: + return tr("The name of the mod."); + case VersionColumn: + return tr("The version of the mod."); + case DateColumn: + return tr("The date and time this mod was last changed (or added)."); + case ProviderColumn: + return tr("Where the mod was downloaded from."); + default: + return QVariant(); + } default: return QVariant(); - } - default: - return QVariant(); } return QVariant(); } -int ModFolderModel::columnCount(const QModelIndex &parent) const +int ModFolderModel::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : NUM_COLUMNS; } @@ -200,8 +195,8 @@ Task* ModFolderModel::createParseTask(Resource& resource) bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadata) { - for(auto mod : allMods()) { - if(mod->fileinfo().fileName() == filename) { + for (auto mod : allMods()) { + if (mod->fileinfo().fileName() == filename) { auto index_dir = indexDir(); mod->destroy(index_dir, preserve_metadata, false); @@ -254,7 +249,7 @@ auto ModFolderModel::selectedMods(QModelIndexList& indexes) -> QList { QList selected_resources; for (auto i : indexes) { - if(i.column() != 0) + if (i.column() != 0) continue; selected_resources.push_back(at(i.row())); diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 6ccaba235..f1f40a817 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -1,53 +1,53 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 #include #include -#include -#include #include "Mod.h" #include "ResourceFolderModel.h" -#include "minecraft/mod/tasks/ModFolderLoadTask.h" #include "minecraft/mod/tasks/LocalModParseTask.h" +#include "minecraft/mod/tasks/ModFolderLoadTask.h" class LegacyInstance; class BaseInstance; @@ -57,33 +57,19 @@ class QFileSystemWatcher; * A legacy mod list. * Backed by a folder. */ -class ModFolderModel : public ResourceFolderModel -{ +class ModFolderModel : public ResourceFolderModel { Q_OBJECT -public: - enum Columns - { - ActiveColumn = 0, - ImageColumn, - NameColumn, - VersionColumn, - DateColumn, - ProviderColumn, - NUM_COLUMNS - }; - enum ModStatusAction { - Disable, - Enable, - Toggle - }; - ModFolderModel(const QString &dir, BaseInstance* instance, bool is_indexed = false, bool create_dir = true); + public: + enum Columns { ActiveColumn = 0, ImageColumn, NameColumn, VersionColumn, DateColumn, ProviderColumn, NUM_COLUMNS }; + enum ModStatusAction { Disable, Enable, Toggle }; + ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed = false, bool create_dir = true); virtual QString id() const override { return "mods"; } - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - int columnCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Task* createUpdateTask() override; [[nodiscard]] Task* createParseTask(Resource&) override; @@ -92,7 +78,7 @@ public: bool uninstallMod(const QString& filename, bool preserve_metadata = false); /// Deletes all the selected mods - bool deleteMods(const QModelIndexList &indexes); + bool deleteMods(const QModelIndexList& indexes); bool isValid(); @@ -106,12 +92,11 @@ public: RESOURCE_HELPERS(Mod) -private -slots: + private slots: void onUpdateSucceeded() override; void onParseSucceeded(int ticket, QString resource_id) override; -protected: + protected: bool m_is_indexed; bool m_first_folder_load = true; }; diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index 098a617f8..da806f0f4 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -1,8 +1,7 @@ #include "Resource.h" - -#include #include +#include #include "FileSystem.h" @@ -105,7 +104,6 @@ bool Resource::enable(EnableAction action) if (m_type == ResourceType::UNKNOWN || m_type == ResourceType::FOLDER) return false; - QString path = m_file_info.absoluteFilePath(); QFile file(path); @@ -154,7 +152,7 @@ bool Resource::destroy(bool attemptTrash) return (attemptTrash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath()); } -bool Resource::isSymLinkUnder(const QString& instPath) const +bool Resource::isSymLinkUnder(const QString& instPath) const { if (isSymLink()) return true; @@ -167,7 +165,7 @@ bool Resource::isSymLinkUnder(const QString& instPath) const return relAbsPath != relCanonPath; } -bool Resource::isMoreThanOneHardLink() const +bool Resource::isMoreThanOneHardLink() const { return FS::hardLinkCount(m_file_info.absoluteFilePath()) > 1; } diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h index 94f3160c3..c1ed49461 100644 --- a/launcher/minecraft/mod/Resource.h +++ b/launcher/minecraft/mod/Resource.h @@ -15,20 +15,9 @@ enum class ResourceType { LITEMOD, //!< The resource is a litemod }; -enum class SortType { - NAME, - DATE, - VERSION, - ENABLED, - PACK_FORMAT, - PROVIDER -}; +enum class SortType { NAME, DATE, VERSION, ENABLED, PACK_FORMAT, PROVIDER }; -enum class EnableAction { - ENABLE, - DISABLE, - TOGGLE -}; +enum class EnableAction { ENABLE, DISABLE, TOGGLE }; /** General class for managed resources. It mirrors a file in disk, with some more info * for display and house-keeping purposes. @@ -98,10 +87,10 @@ class Resource : public QObject { /** * @brief Take a instance path, checks if the file pointed to by the resource is a symlink or under a symlink in that instance - * + * * @param instPath path to an instance directory - * @return true - * @return false + * @return true + * @return false */ [[nodiscard]] bool isSymLinkUnder(const QString& instPath) const; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index f48ddb642..d3237b34b 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -515,25 +515,25 @@ void ResourceFolderModel::setupHeaderAction(QAction* act, int column) void ResourceFolderModel::saveHiddenColumn(int column, bool hidden) { auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id()); - auto setting = (m_instance->settings()->contains(setting_name)) ? - m_instance->settings()->getSetting(setting_name) : m_instance->settings()->registerSetting(setting_name); + auto setting = (m_instance->settings()->contains(setting_name)) ? m_instance->settings()->getSetting(setting_name) + : m_instance->settings()->registerSetting(setting_name); auto hiddenColumns = setting->get().toStringList(); auto name = columnNames(false).at(column); auto index = hiddenColumns.indexOf(name); if (index >= 0 && !hidden) { hiddenColumns.removeAt(index); - } else if ( index < 0 && hidden) { + } else if (index < 0 && hidden) { hiddenColumns.append(name); } setting->set(hiddenColumns); } -void ResourceFolderModel::loadHiddenColumns(QTreeView *tree) +void ResourceFolderModel::loadHiddenColumns(QTreeView* tree) { auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id()); - auto setting = (m_instance->settings()->contains(setting_name)) ? - m_instance->settings()->getSetting(setting_name) : m_instance->settings()->registerSetting(setting_name); + auto setting = (m_instance->settings()->contains(setting_name)) ? m_instance->settings()->getSetting(setting_name) + : m_instance->settings()->registerSetting(setting_name); auto hiddenColumns = setting->get().toStringList(); auto col_names = columnNames(false); @@ -542,7 +542,6 @@ void ResourceFolderModel::loadHiddenColumns(QTreeView *tree) if (index >= 0) tree->setColumnHidden(index, true); } - } QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) @@ -553,16 +552,17 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) for (int col = 0; col < columnCount(); ++col) { // Skip creating actions for columns that should not be hidden - if (!m_columnsHideable.at(col)) continue; + if (!m_columnsHideable.at(col)) + continue; auto act = new QAction(menu); setupHeaderAction(act, col); act->setCheckable(true); act->setChecked(!tree->isColumnHidden(col)); - connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled){ + connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled) { tree->setColumnHidden(col, !toggled); - for(int c = 0; c < columnCount(); ++c) { + for (int c = 0; c < columnCount(); ++c) { if (m_column_resize_modes.at(c) == QHeaderView::ResizeToContents) tree->resizeColumnToContents(c); } @@ -570,7 +570,6 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) }); menu->addAction(act); - } return menu; @@ -588,7 +587,8 @@ SortType ResourceFolderModel::columnToSortKey(size_t column) const } /* Standard Proxy Model for createFilterProxyModel */ -[[nodiscard]] bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, [[maybe_unused]] const QModelIndex& source_parent) const +[[nodiscard]] bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, + [[maybe_unused]] const QModelIndex& source_parent) const { auto* model = qobject_cast(sourceModel()); if (!model) diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index e78848944..6277028b3 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -1,14 +1,14 @@ #pragma once -#include -#include -#include #include +#include #include #include +#include #include #include #include +#include #include "Resource.h" @@ -120,7 +120,7 @@ class ResourceFolderModel : public QAbstractListModel { void saveHiddenColumn(int column, bool hidden); void loadHiddenColumns(QTreeView* tree); QMenu* createHeaderContextMenu(QTreeView* tree); - + /** This creates a proxy model to filter / sort the model for a UI. * * The actual comparisons and filtering are done directly by the Resource, so to modify behavior go there instead! @@ -199,9 +199,10 @@ class ResourceFolderModel : public QAbstractListModel { // Represents the relationship between a column's index (represented by the list index), and it's sorting key. // As such, the order in with they appear is very important! QList m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE }; - QStringList m_column_names = {"Enable", "Name", "Last Modified"}; - QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")}; - QList m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents }; + QStringList m_column_names = { "Enable", "Name", "Last Modified" }; + QStringList m_column_names_translated = { tr("Enable"), tr("Name"), tr("Last Modified") }; + QList m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Stretch, + QHeaderView::ResizeToContents }; QList m_columnsHideable = { false, false, true }; QDir m_dir; @@ -224,15 +225,15 @@ class ResourceFolderModel : public QAbstractListModel { /* A macro to define useful functions to handle Resource* -> T* more easily on derived classes */ #define RESOURCE_HELPERS(T) \ - [[nodiscard]] T* operator[](int index) \ + [[nodiscard]] T* operator[](int index) \ { \ return static_cast(m_resources[index].get()); \ } \ - [[nodiscard]] T* at(int index) \ + [[nodiscard]] T* at(int index) \ { \ return static_cast(m_resources[index].get()); \ } \ - [[nodiscard]] const T* at(int index) const \ + [[nodiscard]] const T* at(int index) const \ { \ return static_cast(m_resources.at(index).get()); \ } \ diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 6d5978d4d..dab0f6d67 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -50,7 +50,7 @@ void ResourcePack::setImage(QImage new_image) const PixmapCache::instance().remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap); m_pack_image_cache_key.was_ever_used = true; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 0d316e365..7dfd09e62 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -47,14 +47,14 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalResourcePackParseTask.h" -ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance) - : ResourceFolderModel(QDir(dir), instance) +ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) { m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") }); - m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE}; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; - m_columnsHideable = { false, true, false, true, true }; + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE }; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, + QHeaderView::ResizeToContents }; + m_columnsHideable = { false, true, false, true, true }; } QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const @@ -93,7 +93,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) return APPLICATION->getThemedIcon("status-yellow"); if (column == ImageColumn) { - return at(row)->image({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding); + return at(row)->image({ 32, 32 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } return {}; } @@ -105,13 +105,14 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const if (column == NameColumn) { if (at(row)->isSymLinkUnder(instDirPath())) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." - "\nCanonical Path: %1") - .arg(at(row)->fileinfo().canonicalFilePath());; + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." + "\nCanonical Path: %1") + .arg(at(row)->fileinfo().canonicalFilePath()); + ; } if (at(row)->isMoreThanOneHardLink()) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); + tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); } } return m_resources[row]->internal_id(); @@ -159,7 +160,7 @@ QVariant ResourcePackFolderModel::headerData(int section, [[maybe_unused]] Qt::O } case Qt::SizeHintRole: if (section == ImageColumn) { - return QSize(64,0); + return QSize(64, 0); } return {}; default: diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index 531d81928..29c2c5995 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -4,28 +4,19 @@ #include "ResourcePack.h" -class ResourcePackFolderModel : public ResourceFolderModel -{ +class ResourcePackFolderModel : public ResourceFolderModel { Q_OBJECT -public: - enum Columns - { - ActiveColumn = 0, - ImageColumn, - NameColumn, - PackFormatColumn, - DateColumn, - NUM_COLUMNS - }; + public: + enum Columns { ActiveColumn = 0, ImageColumn, NameColumn, PackFormatColumn, DateColumn, NUM_COLUMNS }; - explicit ResourcePackFolderModel(const QString &dir, BaseInstance* instance); + explicit ResourcePackFolderModel(const QString& dir, BaseInstance* instance); virtual QString id() const override { return "resourcepacks"; } - [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + [[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - [[nodiscard]] int columnCount(const QModelIndex &parent) const override; + [[nodiscard]] int columnCount(const QModelIndex& parent) const override; [[nodiscard]] Task* createUpdateTask() override; [[nodiscard]] Task* createParseTask(Resource&) override; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index f8249962f..44ed37a47 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -6,9 +6,7 @@ class ShaderPackFolderModel : public ResourceFolderModel { Q_OBJECT public: - explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance) - : ResourceFolderModel(QDir(dir), instance) - {} - + explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) {} + virtual QString id() const override { return "shaderpacks"; } }; diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp index c7a50a97a..fbc716c42 100644 --- a/launcher/minecraft/mod/TexturePack.cpp +++ b/launcher/minecraft/mod/TexturePack.cpp @@ -44,7 +44,7 @@ void TexturePack::setImage(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 7dbedc3f2..a2cebb15f 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -42,15 +42,14 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalTexturePackParseTask.h" -TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance) - : ResourceFolderModel(QDir(dir), instance) +TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) { m_column_names = QStringList({ "Enable", "Image", "Name", "Last Modified" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE }; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents}; - m_columnsHideable = { false, true, false, true }; - + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, + QHeaderView::ResizeToContents }; + m_columnsHideable = { false, true, false, true }; } Task* TexturePackFolderModel::createUpdateTask() @@ -63,7 +62,6 @@ Task* TexturePackFolderModel::createParseTask(Resource& resource) return new LocalTexturePackParseTask(m_next_resolution_ticket, static_cast(resource)); } - QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const { if (!validateIndex(index)) @@ -86,28 +84,29 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const if (column == NameColumn) { if (at(row)->isSymLinkUnder(instDirPath())) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." - "\nCanonical Path: %1") - .arg(at(row)->fileinfo().canonicalFilePath());; + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." + "\nCanonical Path: %1") + .arg(at(row)->fileinfo().canonicalFilePath()); + ; } if (at(row)->isMoreThanOneHardLink()) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); + tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); } } - + return m_resources[row]->internal_id(); case Qt::DecorationRole: { if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) return APPLICATION->getThemedIcon("status-yellow"); if (column == ImageColumn) { - return at(row)->image({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding); + return at(row)->image({ 32, 32 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } return {}; } case Qt::CheckStateRole: if (column == ActiveColumn) { - return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked; + return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked; } return {}; default: @@ -154,4 +153,3 @@ int TexturePackFolderModel::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : NUM_COLUMNS; } - diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index 71a8bdd16..ccc634da7 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -40,31 +40,22 @@ #include "TexturePack.h" -class TexturePackFolderModel : public ResourceFolderModel -{ +class TexturePackFolderModel : public ResourceFolderModel { Q_OBJECT -public: + public: + enum Columns { ActiveColumn = 0, ImageColumn, NameColumn, DateColumn, NUM_COLUMNS }; - enum Columns - { - ActiveColumn = 0, - ImageColumn, - NameColumn, - DateColumn, - NUM_COLUMNS - }; - - explicit TexturePackFolderModel(const QString &dir, std::shared_ptr instance); + explicit TexturePackFolderModel(const QString& dir, std::shared_ptr instance); virtual QString id() const override { return "texturepacks"; } - [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + [[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - [[nodiscard]] int columnCount(const QModelIndex &parent) const override; + [[nodiscard]] int columnCount(const QModelIndex& parent) const override; - explicit TexturePackFolderModel(const QString &dir, BaseInstance* instance); + explicit TexturePackFolderModel(const QString& dir, BaseInstance* instance); [[nodiscard]] Task* createUpdateTask() override; [[nodiscard]] Task* createParseTask(Resource&) override; diff --git a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h index 3ee7e2e0f..23a2b649a 100644 --- a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h @@ -26,12 +26,14 @@ class BasicFolderLoadTask : public Task { public: BasicFolderLoadTask(QDir dir) : Task(nullptr, false), m_dir(dir), m_result(new Result), m_thread_to_spawn_into(thread()) { - m_create_func = [](QFileInfo const& entry) -> Resource::Ptr { - return makeShared(entry); - }; + m_create_func = [](QFileInfo const& entry) -> Resource::Ptr { return makeShared(entry); }; } BasicFolderLoadTask(QDir dir, std::function create_function) - : Task(nullptr, false), m_dir(dir), m_result(new Result), m_create_func(std::move(create_function)), m_thread_to_spawn_into(thread()) + : Task(nullptr, false) + , m_dir(dir) + , m_result(new Result) + , m_create_func(std::move(create_function)) + , m_thread_to_spawn_into(thread()) {} [[nodiscard]] bool canAbort() const override { return true; } @@ -59,7 +61,7 @@ class BasicFolderLoadTask : public Task { emitSucceeded(); } -private: + private: QDir m_dir; ResultPtr m_result; diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index 4c0188a89..7ec00c0c6 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -182,7 +182,7 @@ ModDetails ReadMCModTOML(QByteArray contents) QString license = ""; if (auto licenseDatum = tomlData["license"].as_string()) { license = QString::fromStdString(licenseDatum->get()); - } else if (auto licenseDatumMods =(*modsTable)["license"].as_string()) { + } else if (auto licenseDatumMods = (*modsTable)["license"].as_string()) { license = QString::fromStdString(licenseDatumMods->get()); } if (!license.isEmpty()) @@ -191,7 +191,7 @@ ModDetails ReadMCModTOML(QByteArray contents) QString logoFile = ""; if (auto logoFileDatum = tomlData["logoFile"].as_string()) { logoFile = QString::fromStdString(logoFileDatum->get()); - } else if (auto logoFileDatumMods =(*modsTable)["logoFile"].as_string()) { + } else if (auto logoFileDatumMods = (*modsTable)["logoFile"].as_string()) { logoFile = QString::fromStdString(logoFileDatumMods->get()); } details.icon_file = logoFile; @@ -272,7 +272,7 @@ ModDetails ReadFabricModInfo(QByteArray contents) if (largest > 0) { auto key = QString::number(largest) + "x" + QString::number(largest); details.icon_file = obj.value(key).toString(); - } else { // parsing the sizes failed + } else { // parsing the sizes failed // take the first for (auto i : obj) { details.icon_file = i.toString(); @@ -359,7 +359,7 @@ ModDetails ReadQuiltModInfo(QByteArray contents) if (largest > 0) { auto key = QString::number(largest) + "x" + QString::number(largest); details.icon_file = obj.value(key).toString(); - } else { // parsing the sizes failed + } else { // parsing the sizes failed // take the first for (auto i : obj) { details.icon_file = i.toString(); @@ -659,7 +659,8 @@ bool processIconPNG(const Mod& mod, QByteArray&& raw_data) return true; } -bool loadIconFile(const Mod& mod) { +bool loadIconFile(const Mod& mod) +{ if (mod.iconPath().isEmpty()) { qWarning() << "No Iconfile set, be sure to parse the mod first"; return false; @@ -671,15 +672,14 @@ bool loadIconFile(const Mod& mod) { }; switch (mod.type()) { - case ResourceType::FOLDER: - { + case ResourceType::FOLDER: { QFileInfo icon_info(FS::PathCombine(mod.fileinfo().filePath(), mod.iconPath())); if (icon_info.exists() && icon_info.isFile()) { QFile icon(icon_info.filePath()); if (!icon.open(QIODevice::ReadOnly)) return false; auto data = icon.readAll(); - + bool icon_result = ModUtils::processIconPNG(mod, std::move(data)); icon.close(); @@ -689,8 +689,7 @@ bool loadIconFile(const Mod& mod) { } } } - case ResourceType::ZIPFILE: - { + case ResourceType::ZIPFILE: { QuaZip zip(mod.fileinfo().filePath()); if (!zip.open(QuaZip::mdUnzip)) return false; @@ -716,9 +715,8 @@ bool loadIconFile(const Mod& mod) { return png_invalid(); // could not set icon as current file. } } - case ResourceType::LITEMOD: - { - return false; // can lightmods even have icons? + case ResourceType::LITEMOD: { + return false; // can lightmods even have icons? } default: qWarning() << "Invalid type for mod, can not load icon."; diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h index 1d2f06a6f..31f919b84 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #pragma once diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp index a67c56a8f..7440e6aa3 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp @@ -207,15 +207,14 @@ bool processPackPNG(const ResourcePack& pack, QByteArray&& raw_data) } bool processPackPNG(const ResourcePack& pack) -{ +{ auto png_invalid = [&pack]() { qWarning() << "Resource pack at" << pack.fileinfo().filePath() << "does not have a valid pack.png"; return false; }; switch (pack.type()) { - case ResourceType::FOLDER: - { + case ResourceType::FOLDER: { QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png")); if (image_file_info.exists() && image_file_info.isFile()) { QFile pack_png_file(image_file_info.filePath()); @@ -234,8 +233,7 @@ bool processPackPNG(const ResourcePack& pack) return png_invalid(); // pack.png does not exists or is not a valid file. } } - case ResourceType::ZIPFILE: - { + case ResourceType::ZIPFILE: { Q_ASSERT(pack.type() == ResourceType::ZIPFILE); QuaZip zip(pack.fileinfo().filePath()); diff --git a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp index 0894049cd..d5a090832 100644 --- a/launcher/minecraft/mod/tasks/LocalResourceParse.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourceParse.cpp @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -#include +#include #include "LocalResourceParse.h" @@ -30,19 +30,17 @@ #include "LocalTexturePackParseTask.h" #include "LocalWorldSaveParseTask.h" - -static const QMap s_packed_type_names = { - {PackedResourceType::ResourcePack, QObject::tr("resource pack")}, - {PackedResourceType::TexturePack, QObject::tr("texture pack")}, - {PackedResourceType::DataPack, QObject::tr("data pack")}, - {PackedResourceType::ShaderPack, QObject::tr("shader pack")}, - {PackedResourceType::WorldSave, QObject::tr("world save")}, - {PackedResourceType::Mod , QObject::tr("mod")}, - {PackedResourceType::UNKNOWN, QObject::tr("unknown")} -}; +static const QMap s_packed_type_names = { { PackedResourceType::ResourcePack, QObject::tr("resource pack") }, + { PackedResourceType::TexturePack, QObject::tr("texture pack") }, + { PackedResourceType::DataPack, QObject::tr("data pack") }, + { PackedResourceType::ShaderPack, QObject::tr("shader pack") }, + { PackedResourceType::WorldSave, QObject::tr("world save") }, + { PackedResourceType::Mod, QObject::tr("mod") }, + { PackedResourceType::UNKNOWN, QObject::tr("unknown") } }; namespace ResourceUtils { -PackedResourceType identify(QFileInfo file){ +PackedResourceType identify(QFileInfo file) +{ if (file.exists() && file.isFile()) { if (ModUtils::validate(file)) { // mods can contain resource and data packs so they must be tested first @@ -64,7 +62,7 @@ PackedResourceType identify(QFileInfo file){ qDebug() << file.fileName() << "is a shader pack"; return PackedResourceType::ShaderPack; } else { - qDebug() << "Can't Identify" << file.fileName() ; + qDebug() << "Can't Identify" << file.fileName(); } } else { qDebug() << "Can't find" << file.absolutePath(); @@ -72,8 +70,9 @@ PackedResourceType identify(QFileInfo file){ return PackedResourceType::UNKNOWN; } -QString getPackedTypeName(PackedResourceType type) { +QString getPackedTypeName(PackedResourceType type) +{ return s_packed_type_names.constFind(type).value(); } -} +} // namespace ResourceUtils diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp index a72e81150..817b0ea9c 100644 --- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp @@ -161,15 +161,14 @@ bool processPackPNG(const TexturePack& pack, QByteArray&& raw_data) } bool processPackPNG(const TexturePack& pack) -{ +{ auto png_invalid = [&pack]() { qWarning() << "Texture pack at" << pack.fileinfo().filePath() << "does not have a valid pack.png"; return false; }; switch (pack.type()) { - case ResourceType::FOLDER: - { + case ResourceType::FOLDER: { QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png")); if (image_file_info.exists() && image_file_info.isFile()) { QFile pack_png_file(image_file_info.filePath()); @@ -188,8 +187,7 @@ bool processPackPNG(const TexturePack& pack) return png_invalid(); // pack.png does not exists or is not a valid file. } } - case ResourceType::ZIPFILE: - { + case ResourceType::ZIPFILE: { Q_ASSERT(pack.type() == ResourceType::ZIPFILE); QuaZip zip(pack.fileinfo().filePath()); @@ -232,8 +230,7 @@ bool validate(QFileInfo file) } // namespace TexturePackUtils -LocalTexturePackParseTask::LocalTexturePackParseTask(int token, TexturePack& rp) - : Task(nullptr, false), m_token(token), m_texture_pack(rp) +LocalTexturePackParseTask::LocalTexturePackParseTask(int token, TexturePack& rp) : Task(nullptr, false), m_token(token), m_texture_pack(rp) {} bool LocalTexturePackParseTask::abort() diff --git a/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.cpp b/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.cpp index cbc8f8cee..9d564ddb3 100644 --- a/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.cpp @@ -50,8 +50,8 @@ bool process(WorldSave& pack, ProcessingLevel level) /// @param dir the path to check /// @param saves used in recursive call if a "saves" dir was found /// @return std::tuple of ( -/// bool , -/// QString , +/// bool , +/// QString , /// bool /// ) static std::tuple contains_level_dat(QDir dir, bool saves = false) @@ -101,8 +101,8 @@ bool processFolder(WorldSave& save, ProcessingLevel level) /// @brief checks a folder structure to see if it contains a level.dat /// @param zip the zip file to check /// @return std::tuple of ( -/// bool , -/// QString , +/// bool , +/// QString , /// bool /// ) static std::tuple contains_level_dat(QuaZip& zip) diff --git a/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h b/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h index 9dcdca2b9..12f677b02 100644 --- a/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalWorldSaveParseTask.h @@ -39,7 +39,7 @@ bool processFolder(WorldSave& pack, ProcessingLevel level = ProcessingLevel::Ful bool validate(QFileInfo file); -} // namespace WorldSaveUtils +} // namespace WorldSaveUtils class LocalWorldSaveParseTask : public Task { Q_OBJECT diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index ef353c701..4a19a8eb4 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -1,38 +1,38 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 "ModFolderLoadTask.h" @@ -70,13 +70,11 @@ void ModFolderLoadTask::executeTask() m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed); // Delete the object we just created, since a valid one is already in the mods list. delete mod; - } - else { + } else { m_result->mods[mod->internal_id()].reset(std::move(mod)); m_result->mods[mod->internal_id()]->setStatus(ModStatus::NoMetadata); } - } - else { + } else { QString chopped_id = mod->internal_id().chopped(9); if (m_result->mods.contains(chopped_id)) { m_result->mods[mod->internal_id()].reset(std::move(mod)); @@ -88,8 +86,7 @@ void ModFolderLoadTask::executeTask() m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed); m_result->mods.remove(chopped_id); } - } - else { + } else { m_result->mods[mod->internal_id()].reset(std::move(mod)); m_result->mods[mod->internal_id()]->setStatus(ModStatus::NoMetadata); } @@ -124,7 +121,7 @@ void ModFolderLoadTask::getFromMetadata() for (auto entry : m_index_dir.entryList(QDir::Files)) { auto metadata = Metadata::get(m_index_dir, entry); - if(!metadata.isValid()){ + if (!metadata.isValid()) { return; } diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h index af5f58a5e..7ce13cfaf 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h @@ -1,38 +1,38 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 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 @@ -44,19 +44,16 @@ #include "minecraft/mod/Mod.h" #include "tasks/Task.h" -class ModFolderLoadTask : public Task -{ +class ModFolderLoadTask : public Task { Q_OBJECT -public: + public: struct Result { QMap mods; }; using ResultPtr = std::shared_ptr; - ResultPtr result() const { - return m_result; - } + ResultPtr result() const { return m_result; } -public: + public: ModFolderLoadTask(QDir mods_dir, QDir index_dir, bool is_indexed, bool clean_orphan = false); [[nodiscard]] bool canAbort() const override { return true; } @@ -66,13 +63,12 @@ public: return true; } - void executeTask() override; -private: + private: void getFromMetadata(); -private: + private: QDir m_mods_dir, m_index_dir; bool m_is_indexed; bool m_clean_orphan; diff --git a/launcher/minecraft/services/CapeChange.cpp b/launcher/minecraft/services/CapeChange.cpp index 301550553..fe64e18b3 100644 --- a/launcher/minecraft/services/CapeChange.cpp +++ b/launcher/minecraft/services/CapeChange.cpp @@ -35,27 +35,25 @@ #include "CapeChange.h" -#include #include +#include #include "Application.h" -CapeChange::CapeChange(QObject *parent, QString token, QString cape) - : Task(parent), m_capeId(cape), m_token(token) -{ -} +CapeChange::CapeChange(QObject* parent, QString token, QString cape) : Task(parent), m_capeId(cape), m_token(token) {} -void CapeChange::setCape([[maybe_unused]] QString& cape) { +void CapeChange::setCape([[maybe_unused]] QString& cape) +{ QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/capes/active")); auto requestString = QString("{\"capeId\":\"%1\"}").arg(m_capeId); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit()); - QNetworkReply *rep = APPLICATION->network()->put(request, requestString.toUtf8()); + QNetworkReply* rep = APPLICATION->network()->put(request, requestString.toUtf8()); setStatus(tr("Equipping cape")); m_reply = shared_qobject_ptr(rep); connect(rep, &QNetworkReply::uploadProgress, this, &CapeChange::setProgress); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(rep, &QNetworkReply::errorOccurred, this, &CapeChange::downloadError); #else connect(rep, QOverload::of(&QNetworkReply::error), this, &CapeChange::downloadError); @@ -64,17 +62,18 @@ void CapeChange::setCape([[maybe_unused]] QString& cape) { connect(rep, &QNetworkReply::finished, this, &CapeChange::downloadFinished); } -void CapeChange::clearCape() { +void CapeChange::clearCape() +{ QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/capes/active")); auto requestString = QString("{\"capeId\":\"%1\"}").arg(m_capeId); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit()); - QNetworkReply *rep = APPLICATION->network()->deleteResource(request); + QNetworkReply* rep = APPLICATION->network()->deleteResource(request); setStatus(tr("Removing cape")); m_reply = shared_qobject_ptr(rep); connect(rep, &QNetworkReply::uploadProgress, this, &CapeChange::setProgress); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(rep, &QNetworkReply::errorOccurred, this, &CapeChange::downloadError); #else connect(rep, QOverload::of(&QNetworkReply::error), this, &CapeChange::downloadError); @@ -83,13 +82,11 @@ void CapeChange::clearCape() { connect(rep, &QNetworkReply::finished, this, &CapeChange::downloadFinished); } - void CapeChange::executeTask() { - if(m_capeId.isEmpty()) { + if (m_capeId.isEmpty()) { clearCape(); - } - else { + } else { setCape(m_capeId); } } @@ -115,8 +112,7 @@ void CapeChange::sslErrors(const QList& errors) void CapeChange::downloadFinished() { // if the download failed - if (m_reply->error() != QNetworkReply::NetworkError::NoError) - { + if (m_reply->error() != QNetworkReply::NetworkError::NoError) { emitFailed(QString("Network error: %1").arg(m_reply->errorString())); m_reply.reset(); return; diff --git a/launcher/minecraft/services/CapeChange.h b/launcher/minecraft/services/CapeChange.h index 38069f90a..d0c893c44 100644 --- a/launcher/minecraft/services/CapeChange.h +++ b/launcher/minecraft/services/CapeChange.h @@ -3,31 +3,29 @@ #include #include #include -#include "tasks/Task.h" #include "QObjectPtr.h" +#include "tasks/Task.h" -class CapeChange : public Task -{ +class CapeChange : public Task { Q_OBJECT -public: - CapeChange(QObject *parent, QString token, QString capeId); + public: + CapeChange(QObject* parent, QString token, QString capeId); virtual ~CapeChange() {} -private: - void setCape(QString & cape); + private: + void setCape(QString& cape); void clearCape(); -private: + private: QString m_capeId; QString m_token; shared_qobject_ptr m_reply; -protected: + protected: virtual void executeTask(); -public slots: + public slots: void downloadError(QNetworkReply::NetworkError); void sslErrors(const QList& errors); void downloadFinished(); }; - diff --git a/launcher/minecraft/services/SkinDelete.cpp b/launcher/minecraft/services/SkinDelete.cpp index fbaaeacb6..3737a5af8 100644 --- a/launcher/minecraft/services/SkinDelete.cpp +++ b/launcher/minecraft/services/SkinDelete.cpp @@ -35,26 +35,23 @@ #include "SkinDelete.h" -#include #include +#include #include "Application.h" -SkinDelete::SkinDelete(QObject *parent, QString token) - : Task(parent), m_token(token) -{ -} +SkinDelete::SkinDelete(QObject* parent, QString token) : Task(parent), m_token(token) {} void SkinDelete::executeTask() { QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/skins/active")); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit()); - QNetworkReply *rep = APPLICATION->network()->deleteResource(request); + QNetworkReply* rep = APPLICATION->network()->deleteResource(request); m_reply = shared_qobject_ptr(rep); setStatus(tr("Deleting skin")); connect(rep, &QNetworkReply::uploadProgress, this, &SkinDelete::setProgress); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(rep, &QNetworkReply::errorOccurred, this, &SkinDelete::downloadError); #else connect(rep, QOverload::of(&QNetworkReply::error), this, &SkinDelete::downloadError); @@ -84,12 +81,10 @@ void SkinDelete::sslErrors(const QList& errors) void SkinDelete::downloadFinished() { // if the download failed - if (m_reply->error() != QNetworkReply::NetworkError::NoError) - { + if (m_reply->error() != QNetworkReply::NetworkError::NoError) { emitFailed(QString("Network error: %1").arg(m_reply->errorString())); m_reply.reset(); return; } emitSucceeded(); } - diff --git a/launcher/minecraft/services/SkinDelete.h b/launcher/minecraft/services/SkinDelete.h index b9a1c9d3f..d5b2e63db 100644 --- a/launcher/minecraft/services/SkinDelete.h +++ b/launcher/minecraft/services/SkinDelete.h @@ -6,21 +6,20 @@ typedef shared_qobject_ptr SkinDeletePtr; -class SkinDelete : public Task -{ +class SkinDelete : public Task { Q_OBJECT -public: - SkinDelete(QObject *parent, QString token); + public: + SkinDelete(QObject* parent, QString token); virtual ~SkinDelete() = default; -private: + private: QString m_token; shared_qobject_ptr m_reply; -protected: + protected: virtual void executeTask(); -public slots: + public slots: void downloadError(QNetworkReply::NetworkError); void sslErrors(const QList& errors); void downloadFinished(); diff --git a/launcher/minecraft/services/SkinUpload.cpp b/launcher/minecraft/services/SkinUpload.cpp index 711f87392..299608815 100644 --- a/launcher/minecraft/services/SkinUpload.cpp +++ b/launcher/minecraft/services/SkinUpload.cpp @@ -35,12 +35,13 @@ #include "SkinUpload.h" -#include #include +#include #include "Application.h" -QByteArray getVariant(SkinUpload::Model model) { +QByteArray getVariant(SkinUpload::Model model) +{ switch (model) { default: qDebug() << "Unknown skin type!"; @@ -51,16 +52,15 @@ QByteArray getVariant(SkinUpload::Model model) { } } -SkinUpload::SkinUpload(QObject *parent, QString token, QByteArray skin, SkinUpload::Model model) +SkinUpload::SkinUpload(QObject* parent, QString token, QByteArray skin, SkinUpload::Model model) : Task(parent), m_model(model), m_skin(skin), m_token(token) -{ -} +{} void SkinUpload::executeTask() { QNetworkRequest request(QUrl("https://api.minecraftservices.com/minecraft/profile/skins")); request.setRawHeader("Authorization", QString("Bearer %1").arg(m_token).toLocal8Bit()); - QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart skin; skin.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png")); @@ -74,12 +74,12 @@ void SkinUpload::executeTask() multiPart->append(skin); multiPart->append(model); - QNetworkReply *rep = APPLICATION->network()->post(request, multiPart); + QNetworkReply* rep = APPLICATION->network()->post(request, multiPart); m_reply = shared_qobject_ptr(rep); setStatus(tr("Uploading skin")); connect(rep, &QNetworkReply::uploadProgress, this, &SkinUpload::setProgress); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(rep, &QNetworkReply::errorOccurred, this, &SkinUpload::downloadError); #else connect(rep, QOverload::of(&QNetworkReply::error), this, &SkinUpload::downloadError); @@ -109,8 +109,7 @@ void SkinUpload::sslErrors(const QList& errors) void SkinUpload::downloadFinished() { // if the download failed - if (m_reply->error() != QNetworkReply::NetworkError::NoError) - { + if (m_reply->error() != QNetworkReply::NetworkError::NoError) { emitFailed(QString("Network error: %1").arg(m_reply->errorString())); m_reply.reset(); return; diff --git a/launcher/minecraft/services/SkinUpload.h b/launcher/minecraft/services/SkinUpload.h index ac8c5b361..5716aa996 100644 --- a/launcher/minecraft/services/SkinUpload.h +++ b/launcher/minecraft/services/SkinUpload.h @@ -7,29 +7,25 @@ typedef shared_qobject_ptr SkinUploadPtr; -class SkinUpload : public Task -{ +class SkinUpload : public Task { Q_OBJECT -public: - enum Model - { - STEVE, - ALEX - }; + public: + enum Model { STEVE, ALEX }; // Note this class takes ownership of the file. - SkinUpload(QObject *parent, QString token, QByteArray skin, Model model = STEVE); + SkinUpload(QObject* parent, QString token, QByteArray skin, Model model = STEVE); virtual ~SkinUpload() {} -private: + private: Model m_model; QByteArray m_skin; QString m_token; shared_qobject_ptr m_reply; -protected: + + protected: virtual void executeTask(); -public slots: + public slots: void downloadError(QNetworkReply::NetworkError); void sslErrors(const QList& errors); diff --git a/launcher/minecraft/update/AssetUpdateTask.cpp b/launcher/minecraft/update/AssetUpdateTask.cpp index ec0c90b7f..8af014996 100644 --- a/launcher/minecraft/update/AssetUpdateTask.cpp +++ b/launcher/minecraft/update/AssetUpdateTask.cpp @@ -1,22 +1,20 @@ #include "AssetUpdateTask.h" +#include "minecraft/AssetsUtils.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" #include "net/ChecksumValidator.h" -#include "minecraft/AssetsUtils.h" #include "Application.h" #include "net/ApiDownload.h" -AssetUpdateTask::AssetUpdateTask(MinecraftInstance * inst) +AssetUpdateTask::AssetUpdateTask(MinecraftInstance* inst) { m_inst = inst; } -AssetUpdateTask::~AssetUpdateTask() -{ -} +AssetUpdateTask::~AssetUpdateTask() {} void AssetUpdateTask::executeTask() { @@ -26,10 +24,7 @@ void AssetUpdateTask::executeTask() auto assets = profile->getMinecraftAssets(); QUrl indexUrl = assets->url; QString localPath = assets->id + ".json"; - auto job = makeShared( - tr("Asset index for %1").arg(m_inst->name()), - APPLICATION->network() - ); + auto job = makeShared(tr("Asset index for %1").arg(m_inst->name()), APPLICATION->network()); auto metacache = APPLICATION->metacache(); auto entry = metacache->resolveEntry("asset_indexes", localPath); @@ -45,7 +40,7 @@ void AssetUpdateTask::executeTask() connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::assetIndexFinished); connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetIndexFailed); - connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); + connect(downloadJob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); @@ -69,8 +64,7 @@ void AssetUpdateTask::assetIndexFinished() QString asset_fname = "assets/indexes/" + assets->id + ".json"; // FIXME: this looks like a job for a generic validator based on json schema? - if (!AssetsUtils::loadAssetsIndexJson(assets->id, asset_fname, index)) - { + if (!AssetsUtils::loadAssetsIndexJson(assets->id, asset_fname, index)) { auto metacache = APPLICATION->metacache(); auto entry = metacache->resolveEntry("asset_indexes", assets->id + ".json"); metacache->evictEntry(entry); @@ -78,13 +72,12 @@ void AssetUpdateTask::assetIndexFinished() } auto job = index.getDownloadJob(); - if(job) - { + if (job) { setStatus(tr("Getting the assets files from Mojang...")); downloadJob = job; connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::emitSucceeded); connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed); - connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); + connect(downloadJob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress); connect(downloadJob.get(), &NetJob::stepProgress, this, &AssetUpdateTask::propagateStepProgress); downloadJob->start(); @@ -106,12 +99,9 @@ void AssetUpdateTask::assetsFailed(QString reason) bool AssetUpdateTask::abort() { - if(downloadJob) - { + if (downloadJob) { return downloadJob->abort(); - } - else - { + } else { qWarning() << "Prematurely aborted AssetUpdateTask"; } return true; diff --git a/launcher/minecraft/update/AssetUpdateTask.h b/launcher/minecraft/update/AssetUpdateTask.h index 6d7356f38..6f053a54a 100644 --- a/launcher/minecraft/update/AssetUpdateTask.h +++ b/launcher/minecraft/update/AssetUpdateTask.h @@ -1,28 +1,27 @@ #pragma once -#include "tasks/Task.h" #include "net/NetJob.h" +#include "tasks/Task.h" class MinecraftInstance; -class AssetUpdateTask : public Task -{ +class AssetUpdateTask : public Task { Q_OBJECT -public: - AssetUpdateTask(MinecraftInstance * inst); + public: + AssetUpdateTask(MinecraftInstance* inst); virtual ~AssetUpdateTask(); void executeTask() override; bool canAbort() const override; -private slots: + private slots: void assetIndexFinished(); void assetIndexFailed(QString reason); void assetsFailed(QString reason); -public slots: + public slots: bool abort() override; -private: - MinecraftInstance *m_inst; + private: + MinecraftInstance* m_inst; NetJob::Ptr downloadJob; }; diff --git a/launcher/minecraft/update/FMLLibrariesTask.cpp b/launcher/minecraft/update/FMLLibrariesTask.cpp index 51b6d74c7..ce0c9a723 100644 --- a/launcher/minecraft/update/FMLLibrariesTask.cpp +++ b/launcher/minecraft/update/FMLLibrariesTask.cpp @@ -1,53 +1,49 @@ #include "FMLLibrariesTask.h" #include "FileSystem.h" -#include "minecraft/VersionFilterData.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "minecraft/VersionFilterData.h" -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" #include "net/ApiDownload.h" -FMLLibrariesTask::FMLLibrariesTask(MinecraftInstance * inst) +FMLLibrariesTask::FMLLibrariesTask(MinecraftInstance* inst) { m_inst = inst; } void FMLLibrariesTask::executeTask() { // Get the mod list - MinecraftInstance *inst = (MinecraftInstance *)m_inst; + MinecraftInstance* inst = (MinecraftInstance*)m_inst; auto components = inst->getPackProfile(); auto profile = components->getProfile(); - if (!profile->hasTrait("legacyFML")) - { + if (!profile->hasTrait("legacyFML")) { emitSucceeded(); return; } QString version = components->getComponentVersion("net.minecraft"); - auto &fmlLibsMapping = g_VersionFilterData.fmlLibsMapping; - if (!fmlLibsMapping.contains(version)) - { + auto& fmlLibsMapping = g_VersionFilterData.fmlLibsMapping; + if (!fmlLibsMapping.contains(version)) { emitSucceeded(); return; } - auto &libList = fmlLibsMapping[version]; + auto& libList = fmlLibsMapping[version]; // determine if we need some libs for FML or forge setStatus(tr("Checking for FML libraries...")); - if(!components->getComponent("net.minecraftforge")) - { + if (!components->getComponent("net.minecraftforge")) { emitSucceeded(); return; } // now check the lib folder inside the instance for files. - for (auto &lib : libList) - { + for (auto& lib : libList) { QFileInfo libInfo(FS::PathCombine(inst->libDir(), lib.filename)); if (libInfo.exists()) continue; @@ -55,8 +51,7 @@ void FMLLibrariesTask::executeTask() } // if everything is in place, there's nothing to do here... - if (fmlLibsToProcess.isEmpty()) - { + if (fmlLibsToProcess.isEmpty()) { emitSucceeded(); return; } @@ -66,8 +61,7 @@ void FMLLibrariesTask::executeTask() NetJob::Ptr dljob{ new NetJob("FML libraries", APPLICATION->network()) }; auto metacache = APPLICATION->metacache(); Net::Download::Options options = Net::Download::Option::MakeEternal; - for (auto &lib : fmlLibsToProcess) - { + for (auto& lib : fmlLibsToProcess) { auto entry = metacache->resolveEntry("fmllibs", lib.filename); QString urlString = BuildConfig.FMLLIBS_BASE_URL + lib.filename; dljob->addNetAction(Net::ApiDownload::makeCached(QUrl(urlString), entry, options)); @@ -75,7 +69,7 @@ void FMLLibrariesTask::executeTask() connect(dljob.get(), &NetJob::succeeded, this, &FMLLibrariesTask::fmllibsFinished); connect(dljob.get(), &NetJob::failed, this, &FMLLibrariesTask::fmllibsFailed); - connect(dljob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); + connect(dljob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); connect(dljob.get(), &NetJob::progress, this, &FMLLibrariesTask::progress); connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propagateStepProgress); downloadJob.reset(dljob); @@ -90,24 +84,20 @@ bool FMLLibrariesTask::canAbort() const void FMLLibrariesTask::fmllibsFinished() { downloadJob.reset(); - if (!fmlLibsToProcess.isEmpty()) - { + if (!fmlLibsToProcess.isEmpty()) { setStatus(tr("Copying FML libraries into the instance...")); - MinecraftInstance *inst = (MinecraftInstance *)m_inst; + MinecraftInstance* inst = (MinecraftInstance*)m_inst; auto metacache = APPLICATION->metacache(); int index = 0; - for (auto &lib : fmlLibsToProcess) - { + for (auto& lib : fmlLibsToProcess) { progress(index, fmlLibsToProcess.size()); auto entry = metacache->resolveEntry("fmllibs", lib.filename); auto path = FS::PathCombine(inst->libDir(), lib.filename); - if (!FS::ensureFilePathExists(path)) - { + if (!FS::ensureFilePathExists(path)) { emitFailed(tr("Failed creating FML library folder inside the instance.")); return; } - if (!QFile::copy(entry->getFullPath(), FS::PathCombine(inst->libDir(), lib.filename))) - { + if (!QFile::copy(entry->getFullPath(), FS::PathCombine(inst->libDir(), lib.filename))) { emitFailed(tr("Failed copying Forge/FML library: %1.").arg(lib.filename)); return; } @@ -126,12 +116,9 @@ void FMLLibrariesTask::fmllibsFailed(QString reason) bool FMLLibrariesTask::abort() { - if(downloadJob) - { + if (downloadJob) { return downloadJob->abort(); - } - else - { + } else { qWarning() << "Prematurely aborted FMLLibrariesTask"; } return true; diff --git a/launcher/minecraft/update/FMLLibrariesTask.h b/launcher/minecraft/update/FMLLibrariesTask.h index 2e5ad83a2..9d0102be7 100644 --- a/launcher/minecraft/update/FMLLibrariesTask.h +++ b/launcher/minecraft/update/FMLLibrariesTask.h @@ -1,31 +1,29 @@ #pragma once -#include "tasks/Task.h" -#include "net/NetJob.h" #include "minecraft/VersionFilterData.h" +#include "net/NetJob.h" +#include "tasks/Task.h" class MinecraftInstance; -class FMLLibrariesTask : public Task -{ +class FMLLibrariesTask : public Task { Q_OBJECT -public: - FMLLibrariesTask(MinecraftInstance * inst); - virtual ~FMLLibrariesTask() {}; + public: + FMLLibrariesTask(MinecraftInstance* inst); + virtual ~FMLLibrariesTask(){}; void executeTask() override; bool canAbort() const override; -private slots: + private slots: void fmllibsFinished(); void fmllibsFailed(QString reason); -public slots: + public slots: bool abort() override; -private: - MinecraftInstance *m_inst; + private: + MinecraftInstance* m_inst; NetJob::Ptr downloadJob; QList fmlLibsToProcess; }; - diff --git a/launcher/minecraft/update/FoldersTask.cpp b/launcher/minecraft/update/FoldersTask.cpp index b9ee9d980..3cbc309d0 100644 --- a/launcher/minecraft/update/FoldersTask.cpp +++ b/launcher/minecraft/update/FoldersTask.cpp @@ -34,11 +34,10 @@ */ #include "FoldersTask.h" -#include "minecraft/MinecraftInstance.h" #include +#include "minecraft/MinecraftInstance.h" -FoldersTask::FoldersTask(MinecraftInstance * inst) - :Task() +FoldersTask::FoldersTask(MinecraftInstance* inst) : Task() { m_inst = inst; } @@ -47,8 +46,7 @@ void FoldersTask::executeTask() { // Make directories QDir mcDir(m_inst->gameRoot()); - if (!mcDir.exists() && !mcDir.mkpath(".")) - { + if (!mcDir.exists() && !mcDir.mkpath(".")) { emitFailed(tr("Failed to create folder for Minecraft binaries.")); return; } diff --git a/launcher/minecraft/update/FoldersTask.h b/launcher/minecraft/update/FoldersTask.h index f6ed5e6db..2d2954b2a 100644 --- a/launcher/minecraft/update/FoldersTask.h +++ b/launcher/minecraft/update/FoldersTask.h @@ -3,15 +3,14 @@ #include "tasks/Task.h" class MinecraftInstance; -class FoldersTask : public Task -{ +class FoldersTask : public Task { Q_OBJECT -public: - FoldersTask(MinecraftInstance * inst); - virtual ~FoldersTask() {}; + public: + FoldersTask(MinecraftInstance* inst); + virtual ~FoldersTask(){}; void executeTask() override; -private: - MinecraftInstance *m_inst; -}; + private: + MinecraftInstance* m_inst; +}; diff --git a/launcher/minecraft/update/LibrariesTask.cpp b/launcher/minecraft/update/LibrariesTask.cpp index 9d1c02957..1581b32ee 100644 --- a/launcher/minecraft/update/LibrariesTask.cpp +++ b/launcher/minecraft/update/LibrariesTask.cpp @@ -5,7 +5,7 @@ #include "Application.h" -LibrariesTask::LibrariesTask(MinecraftInstance * inst) +LibrariesTask::LibrariesTask(MinecraftInstance* inst) { m_inst = inst; } @@ -14,7 +14,7 @@ void LibrariesTask::executeTask() { setStatus(tr("Downloading required library files...")); qDebug() << m_inst->name() << ": downloading libraries"; - MinecraftInstance *inst = (MinecraftInstance *)m_inst; + MinecraftInstance* inst = (MinecraftInstance*)m_inst; // Build a list of URLs that will need to be downloaded. auto components = inst->getPackProfile(); @@ -25,18 +25,14 @@ void LibrariesTask::executeTask() auto metacache = APPLICATION->metacache(); - auto processArtifactPool = [&](const QList & pool, QStringList & errors, const QString & localPath) - { - for (auto lib : pool) - { - if(!lib) - { + auto processArtifactPool = [&](const QList& pool, QStringList& errors, const QString& localPath) { + for (auto lib : pool) { + if (!lib) { emitFailed(tr("Null jar is specified in the metadata, aborting.")); return false; } auto dls = lib->getDownloads(inst->runtimeContext(), metacache.get(), errors, localPath); - for(auto dl : dls) - { + for (auto dl : dls) { downloadJob->addNetAction(dl); } } @@ -48,8 +44,7 @@ void LibrariesTask::executeTask() libArtifactPool.append(profile->getLibraries()); libArtifactPool.append(profile->getNativeLibraries()); libArtifactPool.append(profile->getMavenFiles()); - for (auto agent : profile->getAgents()) - { + for (auto agent : profile->getAgents()) { libArtifactPool.append(agent->library()); } libArtifactPool.append(profile->getMainJar()); @@ -58,17 +53,18 @@ void LibrariesTask::executeTask() QStringList failedLocalJarMods; processArtifactPool(profile->getJarMods(), failedLocalJarMods, inst->jarModsDir()); - if (!failedLocalJarMods.empty() || !failedLocalLibraries.empty()) - { + if (!failedLocalJarMods.empty() || !failedLocalLibraries.empty()) { downloadJob.reset(); QString failed_all = (failedLocalLibraries + failedLocalJarMods).join("\n"); - emitFailed(tr("Some artifacts marked as 'local' are missing their files:\n%1\n\nYou need to either add the files, or removed the packages that require them.\nYou'll have to correct this problem manually.").arg(failed_all)); + emitFailed(tr("Some artifacts marked as 'local' are missing their files:\n%1\n\nYou need to either add the files, or removed the " + "packages that require them.\nYou'll have to correct this problem manually.") + .arg(failed_all)); return; } connect(downloadJob.get(), &NetJob::succeeded, this, &LibrariesTask::emitSucceeded); connect(downloadJob.get(), &NetJob::failed, this, &LibrariesTask::jarlibFailed); - connect(downloadJob.get(), &NetJob::aborted, this, [this]{ emitFailed(tr("Aborted")); }); + connect(downloadJob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); }); connect(downloadJob.get(), &NetJob::progress, this, &LibrariesTask::progress); connect(downloadJob.get(), &NetJob::stepProgress, this, &LibrariesTask::propagateStepProgress); @@ -87,12 +83,9 @@ void LibrariesTask::jarlibFailed(QString reason) bool LibrariesTask::abort() { - if(downloadJob) - { + if (downloadJob) { return downloadJob->abort(); - } - else - { + } else { qWarning() << "Prematurely aborted LibrariesTask"; } return true; diff --git a/launcher/minecraft/update/LibrariesTask.h b/launcher/minecraft/update/LibrariesTask.h index b966ad6cb..c969e74df 100644 --- a/launcher/minecraft/update/LibrariesTask.h +++ b/launcher/minecraft/update/LibrariesTask.h @@ -1,26 +1,25 @@ #pragma once -#include "tasks/Task.h" #include "net/NetJob.h" +#include "tasks/Task.h" class MinecraftInstance; -class LibrariesTask : public Task -{ +class LibrariesTask : public Task { Q_OBJECT -public: - LibrariesTask(MinecraftInstance * inst); - virtual ~LibrariesTask() {}; + public: + LibrariesTask(MinecraftInstance* inst); + virtual ~LibrariesTask(){}; void executeTask() override; bool canAbort() const override; -private slots: + private slots: void jarlibFailed(QString reason); -public slots: + public slots: bool abort() override; -private: - MinecraftInstance *m_inst; + private: + MinecraftInstance* m_inst; NetJob::Ptr downloadJob; }; diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index f7582b8f1..6d968ea48 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -1,8 +1,8 @@ #pragma once #include "minecraft/mod/Mod.h" -#include "modplatform/ResourceAPI.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "tasks/Task.h" class ResourceDownloadTask; @@ -12,8 +12,11 @@ class CheckUpdateTask : public Task { Q_OBJECT public: - CheckUpdateTask(QList& mods, std::list& mcVersions, std::optional loaders, std::shared_ptr mods_folder) - : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder) {}; + CheckUpdateTask(QList& mods, + std::list& mcVersions, + std::optional loaders, + std::shared_ptr mods_folder) + : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){}; struct UpdatableMod { QString name; @@ -25,7 +28,13 @@ class CheckUpdateTask : public Task { shared_qobject_ptr download; public: - UpdatableMod(QString name, QString old_h, QString old_v, QString new_v, QString changelog, ModPlatform::ResourceProvider p, shared_qobject_ptr t) + UpdatableMod(QString name, + QString old_h, + QString old_v, + QString new_v, + QString changelog, + ModPlatform::ResourceProvider p, + shared_qobject_ptr t) : name(name), old_hash(old_h), old_version(old_v), new_version(new_v), changelog(changelog), provider(p), download(t) {} }; diff --git a/launcher/modplatform/EnsureMetadataTask.h b/launcher/modplatform/EnsureMetadataTask.h index 03cae4e4a..2f276e5a0 100644 --- a/launcher/modplatform/EnsureMetadataTask.h +++ b/launcher/modplatform/EnsureMetadataTask.h @@ -35,10 +35,7 @@ class EnsureMetadataTask : public Task { auto flameProjectsTask() -> Task::Ptr; // Helpers - enum class RemoveFromList { - Yes, - No - }; + enum class RemoveFromList { Yes, No }; void emitReady(Mod*, QString key = {}, RemoveFromList = RemoveFromList::Yes); void emitFail(Mod*, QString key = {}, RemoveFromList = RemoveFromList::Yes); diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index a1c4d8917..ecea0d8ce 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "modplatform/ModIndex.h" diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index e8d544fc1..cad217034 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -144,12 +144,10 @@ inline auto getOverrideDeps() -> QList { "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH }, { "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } }; - } QString getMetaURL(ResourceProvider provider, QVariant projectID); - } // namespace ModPlatform Q_DECLARE_METATYPE(ModPlatform::IndexedPack) diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index baba550f8..63d0d2f2d 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -131,12 +131,14 @@ class ResourceAPI { qWarning() << "TODO: ResourceAPI::searchProjects"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProject([[maybe_unused]] QString addonId, [[maybe_unused]] std::shared_ptr response) const + [[nodiscard]] virtual Task::Ptr getProject([[maybe_unused]] QString addonId, + [[maybe_unused]] std::shared_ptr response) const { qWarning() << "TODO: ResourceAPI::getProject"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds, [[maybe_unused]] std::shared_ptr response) const + [[nodiscard]] virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds, + [[maybe_unused]] std::shared_ptr response) const { qWarning() << "TODO: ResourceAPI::getProjects"; return nullptr; diff --git a/launcher/modplatform/atlauncher/ATLPackIndex.cpp b/launcher/modplatform/atlauncher/ATLPackIndex.cpp index e649c43a6..3be169739 100644 --- a/launcher/modplatform/atlauncher/ATLPackIndex.cpp +++ b/launcher/modplatform/atlauncher/ATLPackIndex.cpp @@ -21,23 +21,20 @@ #include "Json.h" -static void loadIndexedVersion(ATLauncher::IndexedVersion & v, QJsonObject & obj) +static void loadIndexedVersion(ATLauncher::IndexedVersion& v, QJsonObject& obj) { v.version = Json::requireString(obj, "version"); v.minecraft = Json::requireString(obj, "minecraft"); } -void ATLauncher::loadIndexedPack(ATLauncher::IndexedPack & m, QJsonObject & obj) +void ATLauncher::loadIndexedPack(ATLauncher::IndexedPack& m, QJsonObject& obj) { m.id = Json::requireInteger(obj, "id"); m.position = Json::requireInteger(obj, "position"); m.name = Json::requireString(obj, "name"); - m.type = Json::requireString(obj, "type") == "private" ? - ATLauncher::PackType::Private : - ATLauncher::PackType::Public; + m.type = Json::requireString(obj, "type") == "private" ? ATLauncher::PackType::Private : ATLauncher::PackType::Public; auto versionsArr = Json::requireArray(obj, "versions"); - for (const auto versionRaw : versionsArr) - { + for (const auto versionRaw : versionsArr) { auto versionObj = Json::requireObject(versionRaw); ATLauncher::IndexedVersion version; loadIndexedVersion(version, versionObj); diff --git a/launcher/modplatform/atlauncher/ATLPackIndex.h b/launcher/modplatform/atlauncher/ATLPackIndex.h index 337b80b88..8d18c671d 100644 --- a/launcher/modplatform/atlauncher/ATLPackIndex.h +++ b/launcher/modplatform/atlauncher/ATLPackIndex.h @@ -18,21 +18,18 @@ #include "ATLPackManifest.h" +#include #include #include -#include -namespace ATLauncher -{ +namespace ATLauncher { -struct IndexedVersion -{ +struct IndexedVersion { QString version; QString minecraft; }; -struct IndexedPack -{ +struct IndexedPack { int id; int position; QString name; @@ -44,7 +41,7 @@ struct IndexedPack QString safeName; }; -void loadIndexedPack(IndexedPack & m, QJsonObject & obj); -} +void loadIndexedPack(IndexedPack& m, QJsonObject& obj); +} // namespace ATLauncher Q_DECLARE_METATYPE(ATLauncher::IndexedPack) diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 8260a25c5..1332583e5 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -40,29 +40,29 @@ #include -#include "MMCZip.h" -#include "minecraft/OneSixVersionFormat.h" -#include "Version.h" -#include "net/ChecksumValidator.h" #include "FileSystem.h" #include "Json.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" -#include "settings/INISettingsObject.h" +#include "MMCZip.h" +#include "Version.h" #include "meta/Index.h" #include "meta/Version.h" #include "meta/VersionList.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/OneSixVersionFormat.h" +#include "minecraft/PackProfile.h" +#include "net/ChecksumValidator.h" +#include "settings/INISettingsObject.h" #include "net/ApiDownload.h" -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" namespace ATLauncher { static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version); -PackInstallTask::PackInstallTask(UserInteractionSupport *support, QString packName, QString version, InstallMode installMode) +PackInstallTask::PackInstallTask(UserInteractionSupport* support, QString packName, QString version, InstallMode installMode) { m_support = support; m_pack_name = packName; @@ -73,8 +73,7 @@ PackInstallTask::PackInstallTask(UserInteractionSupport *support, QString packNa bool PackInstallTask::abort() { - if(abortable) - { + if (abortable) { return jobPtr->abort(); } return false; @@ -84,7 +83,7 @@ void PackInstallTask::executeTask() { qDebug() << "PackInstallTask::executeTask: " << QThread::currentThreadId(); NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) }; - auto searchUrl = + auto searchUrl = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json").arg(m_pack_safe_name).arg(m_version_name); netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response)); @@ -112,12 +111,9 @@ void PackInstallTask::onDownloadSucceeded() auto obj = doc.object(); ATLauncher::PackVersion version; - try - { + try { ATLauncher::loadVersion(version, obj); - } - catch (const JSONValidationError &e) - { + } catch (const JSONValidationError& e) { emitFailed(tr("Could not understand pack manifest:\n") + e.cause()); return; } @@ -128,20 +124,20 @@ void PackInstallTask::onDownloadSucceeded() bool resetDirectory; switch (m_install_mode) { - case InstallMode::Reinstall: - case InstallMode::Update: - message = m_version.messages.update; - resetDirectory = true; - break; + case InstallMode::Reinstall: + case InstallMode::Update: + message = m_version.messages.update; + resetDirectory = true; + break; - case InstallMode::Install: - message = m_version.messages.install; - resetDirectory = false; - break; + case InstallMode::Install: + message = m_version.messages.install; + resetDirectory = false; + break; - default: - emitFailed(tr("Unsupported installation mode")); - return; + default: + emitFailed(tr("Unsupported installation mode")); + return; } // Display message if one exists @@ -159,10 +155,9 @@ void PackInstallTask::onDownloadSucceeded() deleteExistingFiles(); } - if(m_version.noConfigs) { + if (m_version.noConfigs) { downloadMods(); - } - else { + } else { installConfigs(); } } @@ -214,11 +209,9 @@ void PackInstallTask::deleteExistingFiles() if (base == "root") { return minecraftPath; - } - else if (base == "config") { + } else if (base == "config") { return FS::PathCombine(minecraftPath, "config"); - } - else { + } else { qWarning() << "Unrecognised base path" << base; return minecraftPath; } @@ -340,19 +333,18 @@ QString PackInstallTask::getDirForModType(ModType type, QString raw) QString PackInstallTask::getVersionForLoader(QString uid) { - if(m_version.loader.recommended || m_version.loader.latest || m_version.loader.choose) { + if (m_version.loader.recommended || m_version.loader.latest || m_version.loader.choose) { auto vlist = APPLICATION->metadataIndex()->get(uid); - if(!vlist) - { + if (!vlist) { emitFailed(tr("Failed to get local metadata index for %1").arg(uid)); return Q_NULLPTR; } - if(!vlist->isLoaded()) { + if (!vlist->isLoaded()) { vlist->load(Net::Mode::Online); } - if(m_version.loader.recommended || m_version.loader.latest) { + if (m_version.loader.recommended || m_version.loader.latest) { for (int i = 0; i < vlist->versions().size(); i++) { auto version = vlist->versions().at(i); auto reqs = version->requiredSet(); @@ -361,16 +353,17 @@ QString PackInstallTask::getVersionForLoader(QString uid) // not all mod loaders depend on a given Minecraft version, so we won't do this // filtering for those loaders. if (m_version.loader.type != "fabric") { - auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Meta::Require &req) { - return req.uid == "net.minecraft"; - }); - if (iter == reqs.end()) continue; - if (iter->equalsVersion != m_version.minecraft) continue; + auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Meta::Require& req) { return req.uid == "net.minecraft"; }); + if (iter == reqs.end()) + continue; + if (iter->equalsVersion != m_version.minecraft) + continue; } if (m_version.loader.recommended) { // first recommended build we find, we use. - if (!version->isRecommended()) continue; + if (!version->isRecommended()) + continue; } return version->descriptor(); @@ -378,8 +371,7 @@ QString PackInstallTask::getVersionForLoader(QString uid) emitFailed(tr("Failed to find version for %1 loader").arg(m_version.loader.type)); return Q_NULLPTR; - } - else if(m_version.loader.choose) { + } else if (m_version.loader.choose) { // Fabric Loader doesn't depend on a given Minecraft version. if (m_version.loader.type == "fabric") { return m_support->chooseVersion(vlist, Q_NULLPTR); @@ -416,15 +408,14 @@ QString PackInstallTask::detectLibrary(VersionLibrary library) return group + ":" + artefact + ":" + version; } - if(library.file.contains("-")) { + if (library.file.contains("-")) { auto lastSlash = library.file.lastIndexOf("-"); auto name = library.file.mid(0, lastSlash); auto version = library.file.mid(lastSlash + 1).remove(".jar"); - if(name == QString("guava")) { + if (name == QString("guava")) { return "com.google.guava:guava:" + version; - } - else if(name == QString("commons-lang3")) { + } else if (name == QString("commons-lang3")) { return "org.apache.commons:commons-lang3:" + version; } } @@ -434,22 +425,22 @@ QString PackInstallTask::detectLibrary(VersionLibrary library) bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared_ptr profile) { - if(m_version.libraries.isEmpty()) { + if (m_version.libraries.isEmpty()) { return true; } QList exempt; - for(const auto & componentUid : componentsToInstall.keys()) { + for (const auto& componentUid : componentsToInstall.keys()) { auto componentVersion = componentsToInstall.value(componentUid); - for(const auto & library : componentVersion->data()->libraries) { + for (const auto& library : componentVersion->data()->libraries) { GradleSpecifier lib(library->rawName()); exempt.append(lib); } } { - for(const auto & library : minecraftVersion->data()->libraries) { + for (const auto& library : minecraftVersion->data()->libraries) { GradleSpecifier lib(library->rawName()); exempt.append(lib); } @@ -460,8 +451,7 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared auto target_id = "org.multimc.atlauncher." + id; auto patchDir = FS::PathCombine(instanceRoot, "patches"); - if(!FS::ensureFolderPathExists(patchDir)) - { + if (!FS::ensureFolderPathExists(patchDir)) { return false; } auto patchFileName = FS::PathCombine(patchDir, target_id + ".json"); @@ -470,38 +460,24 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared f->name = m_pack_name + " " + m_version_name + " (libraries)"; const static QMap liteLoaderMap = { - { "61179803bcd5fb7790789b790908663d", "1.12-SNAPSHOT" }, - { "1420785ecbfed5aff4a586c5c9dd97eb", "1.12.2-SNAPSHOT" }, - { "073f68e2fcb518b91fd0d99462441714", "1.6.2_03" }, - { "10a15b52fc59b1bfb9c05b56de1097d6", "1.6.2_02" }, - { "b52f90f08303edd3d4c374e268a5acf1", "1.6.2_04" }, - { "ea747e24e03e24b7cad5bc8a246e0319", "1.6.2_01" }, - { "55785ccc82c07ff0ba038fe24be63ea2", "1.7.10_01" }, - { "63ada46e033d0cb6782bada09ad5ca4e", "1.7.10_04" }, - { "7983e4b28217c9ae8569074388409c86", "1.7.10_03" }, - { "c09882458d74fe0697c7681b8993097e", "1.7.10_02" }, - { "db7235aefd407ac1fde09a7baba50839", "1.7.10_00" }, - { "6e9028816027f53957bd8fcdfabae064", "1.8" }, - { "5e732dc446f9fe2abe5f9decaec40cde", "1.10-SNAPSHOT" }, - { "3a98b5ed95810bf164e71c1a53be568d", "1.11.2-SNAPSHOT" }, - { "ba8e6285966d7d988a96496f48cbddaa", "1.8.9-SNAPSHOT" }, - { "8524af3ac3325a82444cc75ae6e9112f", "1.11-SNAPSHOT" }, - { "53639d52340479ccf206a04f5e16606f", "1.5.2_01" }, - { "1fcdcf66ce0a0806b7ad8686afdce3f7", "1.6.4_00" }, - { "531c116f71ae2b11033f9a11a0f8e668", "1.6.4_01" }, - { "4009eeb99c9068f608d3483a6439af88", "1.7.2_03" }, - { "66f343354b8417abce1a10d557d2c6e9", "1.7.2_04" }, - { "ab554c21f28fbc4ae9b098bcb5f4cceb", "1.7.2_05" }, - { "e1d76a05a3723920e2f80a5e66c45f16", "1.7.2_02" }, - { "00318cb0c787934d523f63cdfe8ddde4", "1.9-SNAPSHOT" }, - { "986fd1ee9525cb0dcab7609401cef754", "1.9.4-SNAPSHOT" }, - { "571ad5e6edd5ff40259570c9be588bb5", "1.9.4" }, - { "1cdd72f7232e45551f16cc8ffd27ccf3", "1.10.2-SNAPSHOT" }, - { "8a7c21f32d77ee08b393dd3921ced8eb", "1.10.2" }, - { "b9bef8abc8dc309069aeba6fbbe58980", "1.12.1-SNAPSHOT" } + { "61179803bcd5fb7790789b790908663d", "1.12-SNAPSHOT" }, { "1420785ecbfed5aff4a586c5c9dd97eb", "1.12.2-SNAPSHOT" }, + { "073f68e2fcb518b91fd0d99462441714", "1.6.2_03" }, { "10a15b52fc59b1bfb9c05b56de1097d6", "1.6.2_02" }, + { "b52f90f08303edd3d4c374e268a5acf1", "1.6.2_04" }, { "ea747e24e03e24b7cad5bc8a246e0319", "1.6.2_01" }, + { "55785ccc82c07ff0ba038fe24be63ea2", "1.7.10_01" }, { "63ada46e033d0cb6782bada09ad5ca4e", "1.7.10_04" }, + { "7983e4b28217c9ae8569074388409c86", "1.7.10_03" }, { "c09882458d74fe0697c7681b8993097e", "1.7.10_02" }, + { "db7235aefd407ac1fde09a7baba50839", "1.7.10_00" }, { "6e9028816027f53957bd8fcdfabae064", "1.8" }, + { "5e732dc446f9fe2abe5f9decaec40cde", "1.10-SNAPSHOT" }, { "3a98b5ed95810bf164e71c1a53be568d", "1.11.2-SNAPSHOT" }, + { "ba8e6285966d7d988a96496f48cbddaa", "1.8.9-SNAPSHOT" }, { "8524af3ac3325a82444cc75ae6e9112f", "1.11-SNAPSHOT" }, + { "53639d52340479ccf206a04f5e16606f", "1.5.2_01" }, { "1fcdcf66ce0a0806b7ad8686afdce3f7", "1.6.4_00" }, + { "531c116f71ae2b11033f9a11a0f8e668", "1.6.4_01" }, { "4009eeb99c9068f608d3483a6439af88", "1.7.2_03" }, + { "66f343354b8417abce1a10d557d2c6e9", "1.7.2_04" }, { "ab554c21f28fbc4ae9b098bcb5f4cceb", "1.7.2_05" }, + { "e1d76a05a3723920e2f80a5e66c45f16", "1.7.2_02" }, { "00318cb0c787934d523f63cdfe8ddde4", "1.9-SNAPSHOT" }, + { "986fd1ee9525cb0dcab7609401cef754", "1.9.4-SNAPSHOT" }, { "571ad5e6edd5ff40259570c9be588bb5", "1.9.4" }, + { "1cdd72f7232e45551f16cc8ffd27ccf3", "1.10.2-SNAPSHOT" }, { "8a7c21f32d77ee08b393dd3921ced8eb", "1.10.2" }, + { "b9bef8abc8dc309069aeba6fbbe58980", "1.12.1-SNAPSHOT" } }; - for(const auto & lib : m_version.libraries) { + for (const auto& lib : m_version.libraries) { // If the library is LiteLoader, we need to ignore it and handle it separately. if (liteLoaderMap.contains(lib.md5)) { auto ver = getComponentVersion("com.mumfrey.liteloader", liteLoaderMap.value(lib.md5)); @@ -515,18 +491,19 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared GradleSpecifier libSpecifier(libName); bool libExempt = false; - for(const auto & existingLib : exempt) { - if(libSpecifier.matchName(existingLib)) { + for (const auto& existingLib : exempt) { + if (libSpecifier.matchName(existingLib)) { // If the pack specifies a newer version of the lib, use that! libExempt = Version(libSpecifier.version()) >= Version(existingLib.version()); } } - if(libExempt) continue; + if (libExempt) + continue; auto library = std::make_shared(); library->setRawName(libName); - switch(lib.download) { + switch (lib.download) { case DownloadType::Server: library->setAbsoluteUrl(BuildConfig.ATL_DOWNLOAD_SERVER_URL + lib.url); break; @@ -542,15 +519,13 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared f->libraries.append(library); } - if(f->libraries.isEmpty()) { + if (f->libraries.isEmpty()) { return true; } QFile file(patchFileName); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); + if (!file.open(QFile::WriteOnly)) { + qCritical() << "Error opening" << file.fileName() << "for reading:" << file.errorString(); return false; } file.write(OneSixVersionFormat::versionFileToJson(f).toJson()); @@ -595,18 +570,17 @@ bool PackInstallTask::createPackComponent(QString instanceRoot, std::shared_ptr< auto target_id = "org.multimc.atlauncher." + id; auto patchDir = FS::PathCombine(instanceRoot, "patches"); - if(!FS::ensureFolderPathExists(patchDir)) - { + if (!FS::ensureFolderPathExists(patchDir)) { return false; } auto patchFileName = FS::PathCombine(patchDir, target_id + ".json"); QStringList mainClasses; QStringList tweakers; - for(const auto & componentUid : componentsToInstall.keys()) { + for (const auto& componentUid : componentsToInstall.keys()) { auto componentVersion = componentsToInstall.value(componentUid); - if(componentVersion->data()->mainClass != QString("")) { + if (componentVersion->data()->mainClass != QString("")) { mainClasses.append(componentVersion->data()->mainClass); } tweakers.append(componentVersion->data()->addTweakers); @@ -621,25 +595,24 @@ bool PackInstallTask::createPackComponent(QString instanceRoot, std::shared_ptr< // Parse out tweakers auto args = extraArguments.split(" "); QString previous; - for(auto arg : args) { - if(arg.startsWith("--tweakClass=") || previous == "--tweakClass") { + for (auto arg : args) { + if (arg.startsWith("--tweakClass=") || previous == "--tweakClass") { auto tweakClass = arg.remove("--tweakClass="); - if(tweakers.contains(tweakClass)) continue; + if (tweakers.contains(tweakClass)) + continue; f->addTweakers.append(tweakClass); } previous = arg; } - if(f->mainClass == QString() && f->addTweakers.isEmpty()) { + if (f->mainClass == QString() && f->addTweakers.isEmpty()) { return true; } QFile file(patchFileName); - if (!file.open(QFile::WriteOnly)) - { - qCritical() << "Error opening" << file.fileName() - << "for reading:" << file.errorString(); + if (!file.open(QFile::WriteOnly)) { + qCritical() << "Error opening" << file.fileName() << "for reading:" << file.errorString(); return false; } file.write(OneSixVersionFormat::versionFileToJson(f).toJson()); @@ -656,8 +629,7 @@ void PackInstallTask::installConfigs() jobPtr.reset(new NetJob(tr("Config download"), APPLICATION->network())); auto path = QString("Configs/%1/%2.zip").arg(m_pack_safe_name).arg(m_version_name); - auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.zip") - .arg(m_pack_safe_name).arg(m_version_name); + auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.zip").arg(m_pack_safe_name).arg(m_version_name); auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", path); entry->setStale(true); @@ -669,25 +641,22 @@ void PackInstallTask::installConfigs() jobPtr->addNetAction(dl); archivePath = entry->getFullPath(); - connect(jobPtr.get(), &NetJob::succeeded, this, [&]() - { + connect(jobPtr.get(), &NetJob::succeeded, this, [&]() { abortable = false; jobPtr.reset(); extractConfigs(); }); - connect(jobPtr.get(), &NetJob::failed, [&](QString reason) - { + connect(jobPtr.get(), &NetJob::failed, [&](QString reason) { abortable = false; jobPtr.reset(); emitFailed(reason); }); - connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) - { + connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) { abortable = true; setProgress(current, total); }); connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); - connect(jobPtr.get(), &NetJob::aborted, [&]{ + connect(jobPtr.get(), &NetJob::aborted, [&] { abortable = false; jobPtr.reset(); emitAborted(); @@ -704,25 +673,20 @@ void PackInstallTask::extractConfigs() QDir extractDir(m_stagingPath); QuaZip packZip(archivePath); - if(!packZip.open(QuaZip::mdUnzip)) - { + if (!packZip.open(QuaZip::mdUnzip)) { emitFailed(tr("Failed to open pack configs %1!").arg(archivePath)); return; } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), QOverload::of(MMCZip::extractDir), archivePath, extractDir.absolutePath() + "/minecraft"); + m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), QOverload::of(MMCZip::extractDir), archivePath, + extractDir.absolutePath() + "/minecraft"); #else - m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/minecraft"); + m_extractFuture = + QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/minecraft"); #endif - connect(&m_extractFutureWatcher, &QFutureWatcher::finished, this, [&]() - { - downloadMods(); - }); - connect(&m_extractFutureWatcher, &QFutureWatcher::canceled, this, [&]() - { - emitAborted(); - }); + connect(&m_extractFutureWatcher, &QFutureWatcher::finished, this, [&]() { downloadMods(); }); + connect(&m_extractFutureWatcher, &QFutureWatcher::canceled, this, [&]() { emitAborted(); }); m_extractFutureWatcher.setFuture(m_extractFuture); } @@ -753,15 +717,17 @@ void PackInstallTask::downloadMods() jarmods.clear(); jobPtr.reset(new NetJob(tr("Mod download"), APPLICATION->network())); - for(const auto& mod : m_version.mods) { + for (const auto& mod : m_version.mods) { // skip non-client mods - if(!mod.client) continue; + if (!mod.client) + continue; // skip optional mods that were not selected - if(mod.optional && !selectedMods.contains(mod.name)) continue; + if (mod.optional && !selectedMods.contains(mod.name)) + continue; QString url; - switch(mod.download) { + switch (mod.download) { case DownloadType::Server: url = BuildConfig.ATL_DOWNLOAD_SERVER_URL + mod.url; break; @@ -790,8 +756,7 @@ void PackInstallTask::downloadMods() dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); } jobPtr->addNetAction(dl); - } - else if(mod.type == ModType::Decomp) { + } else if (mod.type == ModType::Decomp) { auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", cacheName); entry->setStale(true); modsToDecomp.insert(entry->getFullPath(), mod); @@ -802,10 +767,10 @@ void PackInstallTask::downloadMods() dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5)); } jobPtr->addNetAction(dl); - } - else { + } else { auto relpath = getDirForModType(mod.type, mod.type_raw); - if(relpath == Q_NULLPTR) continue; + if (relpath == Q_NULLPTR) + continue; auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", cacheName); entry->setStale(true); @@ -819,7 +784,7 @@ void PackInstallTask::downloadMods() auto path = FS::PathCombine(m_stagingPath, "minecraft", relpath, mod.file); - if(mod.type == ModType::Forge) { + if (mod.type == ModType::Forge) { auto ver = getComponentVersion("net.minecraftforge", mod.version); if (ver) { componentsToInstall.insert("net.minecraftforge", ver); @@ -830,7 +795,7 @@ void PackInstallTask::downloadMods() jarmods.push_back(path); } - if(mod.type == ModType::Jar) { + if (mod.type == ModType::Jar) { qDebug() << "Jarmod: " + path; jarmods.push_back(path); } @@ -842,21 +807,18 @@ void PackInstallTask::downloadMods() } connect(jobPtr.get(), &NetJob::succeeded, this, &PackInstallTask::onModsDownloaded); - connect(jobPtr.get(), &NetJob::failed, [&](QString reason) - { + connect(jobPtr.get(), &NetJob::failed, [&](QString reason) { abortable = false; jobPtr.reset(); emitFailed(reason); }); - connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) - { + connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); abortable = true; setProgress(current, total); }); connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); - connect(jobPtr.get(), &NetJob::aborted, [&] - { + connect(jobPtr.get(), &NetJob::aborted, [&] { abortable = false; jobPtr.reset(); emitAborted(); @@ -865,60 +827,56 @@ void PackInstallTask::downloadMods() jobPtr->start(); } -void PackInstallTask::onModsDownloaded() { +void PackInstallTask::onModsDownloaded() +{ abortable = false; qDebug() << "PackInstallTask::onModsDownloaded: " << QThread::currentThreadId(); jobPtr.reset(); - if(!modsToExtract.empty() || !modsToDecomp.empty() || !modsToCopy.empty()) { + if (!modsToExtract.empty() || !modsToDecomp.empty() || !modsToCopy.empty()) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - m_modExtractFuture = QtConcurrent::run(QThreadPool::globalInstance(), &PackInstallTask::extractMods, this, modsToExtract, modsToDecomp, modsToCopy); + m_modExtractFuture = + QtConcurrent::run(QThreadPool::globalInstance(), &PackInstallTask::extractMods, this, modsToExtract, modsToDecomp, modsToCopy); #else - m_modExtractFuture = QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy); + m_modExtractFuture = + QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy); #endif connect(&m_modExtractFutureWatcher, &QFutureWatcher::finished, this, &PackInstallTask::onModsExtracted); - connect(&m_modExtractFutureWatcher, &QFutureWatcher::canceled, this, [&]() - { - emitAborted(); - }); + connect(&m_modExtractFutureWatcher, &QFutureWatcher::canceled, this, [&]() { emitAborted(); }); m_modExtractFutureWatcher.setFuture(m_modExtractFuture); - } - else { + } else { install(); } } -void PackInstallTask::onModsExtracted() { +void PackInstallTask::onModsExtracted() +{ qDebug() << "PackInstallTask::onModsExtracted: " << QThread::currentThreadId(); - if(m_modExtractFuture.result()) { + if (m_modExtractFuture.result()) { install(); - } - else { + } else { emitFailed(tr("Failed to extract mods...")); } } -bool PackInstallTask::extractMods( - const QMap &toExtract, - const QMap &toDecomp, - const QMap &toCopy -) { +bool PackInstallTask::extractMods(const QMap& toExtract, + const QMap& toDecomp, + const QMap& toCopy) +{ qDebug() << "PackInstallTask::extractMods: " << QThread::currentThreadId(); setStatus(tr("Extracting mods...")); for (auto iter = toExtract.begin(); iter != toExtract.end(); iter++) { - auto &modPath = iter.key(); - auto &mod = iter.value(); + auto& modPath = iter.key(); + auto& mod = iter.value(); QString extractToDir; - if(mod.type == ModType::Extract) { + if (mod.type == ModType::Extract) { extractToDir = getDirForModType(mod.extractTo, mod.extractTo_raw); - } - else if(mod.type == ModType::TexturePackExtract) { + } else if (mod.type == ModType::TexturePackExtract) { extractToDir = FS::PathCombine("texturepacks", "extracted"); - } - else if(mod.type == ModType::ResourcePackExtract) { + } else if (mod.type == ModType::ResourcePackExtract) { extractToDir = FS::PathCombine("resourcepacks", "extracted"); } @@ -926,36 +884,36 @@ bool PackInstallTask::extractMods( auto extractToPath = FS::PathCombine(extractDir.absolutePath(), "minecraft", extractToDir); QString folderToExtract = ""; - if(mod.type == ModType::Extract) { + if (mod.type == ModType::Extract) { folderToExtract = mod.extractFolder; folderToExtract.remove(QRegularExpression("^/")); } qDebug() << "Extracting " + mod.file + " to " + extractToDir; - if(!MMCZip::extractDir(modPath, folderToExtract, extractToPath)) { + if (!MMCZip::extractDir(modPath, folderToExtract, extractToPath)) { // assume error return false; } } for (auto iter = toDecomp.begin(); iter != toDecomp.end(); iter++) { - auto &modPath = iter.key(); - auto &mod = iter.value(); + auto& modPath = iter.key(); + auto& mod = iter.value(); auto extractToDir = getDirForModType(mod.decompType, mod.decompType_raw); QDir extractDir(m_stagingPath); auto extractToPath = FS::PathCombine(extractDir.absolutePath(), "minecraft", extractToDir, mod.decompFile); qDebug() << "Extracting " + mod.decompFile + " to " + extractToDir; - if(!MMCZip::extractFile(modPath, mod.decompFile, extractToPath)) { + if (!MMCZip::extractFile(modPath, mod.decompFile, extractToPath)) { qWarning() << "Failed to extract" << mod.decompFile; return false; } } for (auto iter = toCopy.begin(); iter != toCopy.end(); iter++) { - auto &from = iter.key(); - auto &to = iter.value(); + auto& from = iter.key(); + auto& to = iter.value(); // If the file already exists, assume the mod is the correct copy - and remove // the copy from the Configs.zip @@ -968,7 +926,7 @@ bool PackInstallTask::extractMods( } FS::copy fileCopyOperation(from, to); - if(!fileCopyOperation()) { + if (!fileCopyOperation()) { qWarning() << "Failed to copy" << from << "to" << to; return false; } @@ -990,7 +948,7 @@ void PackInstallTask::install() components->buildingFromScratch(); // Use a component to add libraries BEFORE Minecraft - if(!createLibrariesComponent(instance.instanceRoot(), components)) { + if (!createLibrariesComponent(instance.instanceRoot(), components)) { emitFailed(tr("Failed to create libraries component")); return; } @@ -999,27 +957,24 @@ void PackInstallTask::install() components->setComponentVersion("net.minecraft", m_version.minecraft, true); // Loader - if(m_version.loader.type == QString("forge")) - { + if (m_version.loader.type == QString("forge")) { auto version = getVersionForLoader("net.minecraftforge"); - if(version == Q_NULLPTR) return; + if (version == Q_NULLPTR) + return; components->setComponentVersion("net.minecraftforge", version); - } - else if(m_version.loader.type == QString("fabric")) - { + } else if (m_version.loader.type == QString("fabric")) { auto version = getVersionForLoader("net.fabricmc.fabric-loader"); - if(version == Q_NULLPTR) return; + if (version == Q_NULLPTR) + return; components->setComponentVersion("net.fabricmc.fabric-loader", version); - } - else if(m_version.loader.type != QString()) - { + } else if (m_version.loader.type != QString()) { emitFailed(tr("Unknown loader type: ") + m_version.loader.type); return; } - for(const auto & componentUid : componentsToInstall.keys()) { + for (const auto& componentUid : componentsToInstall.keys()) { auto version = componentsToInstall.value(componentUid); components->setComponentVersion(componentUid, version->version()); } @@ -1028,7 +983,7 @@ void PackInstallTask::install() // Use a component to fill in the rest of the data // todo: use more detection - if(!createPackComponent(instance.instanceRoot(), components)) { + if (!createPackComponent(instance.instanceRoot(), components)) { emitFailed(tr("Failed to create pack component")); return; } @@ -1063,4 +1018,4 @@ static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& return ver; } -} +} // namespace ATLauncher diff --git a/launcher/modplatform/atlauncher/ATLPackManifest.cpp b/launcher/modplatform/atlauncher/ATLPackManifest.cpp index 5a458f4e2..88d728c22 100644 --- a/launcher/modplatform/atlauncher/ATLPackManifest.cpp +++ b/launcher/modplatform/atlauncher/ATLPackManifest.cpp @@ -38,84 +38,67 @@ #include "Json.h" -static ATLauncher::DownloadType parseDownloadType(QString rawType) { - if(rawType == QString("server")) { +static ATLauncher::DownloadType parseDownloadType(QString rawType) +{ + if (rawType == QString("server")) { return ATLauncher::DownloadType::Server; - } - else if(rawType == QString("browser")) { + } else if (rawType == QString("browser")) { return ATLauncher::DownloadType::Browser; - } - else if(rawType == QString("direct")) { + } else if (rawType == QString("direct")) { return ATLauncher::DownloadType::Direct; } return ATLauncher::DownloadType::Unknown; } -static ATLauncher::ModType parseModType(QString rawType) { +static ATLauncher::ModType parseModType(QString rawType) +{ // See https://wiki.atlauncher.com/mod_types - if(rawType == QString("root")) { + if (rawType == QString("root")) { return ATLauncher::ModType::Root; - } - else if(rawType == QString("forge")) { + } else if (rawType == QString("forge")) { return ATLauncher::ModType::Forge; - } - else if(rawType == QString("jar")) { + } else if (rawType == QString("jar")) { return ATLauncher::ModType::Jar; - } - else if(rawType == QString("mods")) { + } else if (rawType == QString("mods")) { return ATLauncher::ModType::Mods; - } - else if(rawType == QString("flan")) { + } else if (rawType == QString("flan")) { return ATLauncher::ModType::Flan; - } - else if(rawType == QString("dependency") || rawType == QString("depandency")) { + } else if (rawType == QString("dependency") || rawType == QString("depandency")) { return ATLauncher::ModType::Dependency; - } - else if(rawType == QString("ic2lib")) { + } else if (rawType == QString("ic2lib")) { return ATLauncher::ModType::Ic2Lib; - } - else if(rawType == QString("denlib")) { + } else if (rawType == QString("denlib")) { return ATLauncher::ModType::DenLib; - } - else if(rawType == QString("coremods")) { + } else if (rawType == QString("coremods")) { return ATLauncher::ModType::Coremods; - } - else if(rawType == QString("mcpc")) { + } else if (rawType == QString("mcpc")) { return ATLauncher::ModType::MCPC; - } - else if(rawType == QString("plugins")) { + } else if (rawType == QString("plugins")) { return ATLauncher::ModType::Plugins; - } - else if(rawType == QString("extract")) { + } else if (rawType == QString("extract")) { return ATLauncher::ModType::Extract; - } - else if(rawType == QString("decomp")) { + } else if (rawType == QString("decomp")) { return ATLauncher::ModType::Decomp; - } - else if(rawType == QString("texturepack")) { + } else if (rawType == QString("texturepack")) { return ATLauncher::ModType::TexturePack; - } - else if(rawType == QString("resourcepack")) { + } else if (rawType == QString("resourcepack")) { return ATLauncher::ModType::ResourcePack; - } - else if(rawType == QString("shaderpack")) { + } else if (rawType == QString("shaderpack")) { return ATLauncher::ModType::ShaderPack; - } - else if(rawType == QString("texturepackextract")) { + } else if (rawType == QString("texturepackextract")) { return ATLauncher::ModType::TexturePackExtract; - } - else if(rawType == QString("resourcepackextract")) { + } else if (rawType == QString("resourcepackextract")) { return ATLauncher::ModType::ResourcePackExtract; - } - else if(rawType == QString("millenaire")) { + } else if (rawType == QString("millenaire")) { return ATLauncher::ModType::Millenaire; } return ATLauncher::ModType::Unknown; } -static void loadVersionLoader(ATLauncher::VersionLoader & p, QJsonObject & obj) { +static void loadVersionLoader(ATLauncher::VersionLoader& p, QJsonObject& obj) +{ p.type = Json::requireString(obj, "type"); p.choose = Json::ensureBoolean(obj, QString("choose"), false); @@ -134,7 +117,8 @@ static void loadVersionLoader(ATLauncher::VersionLoader & p, QJsonObject & obj) } } -static void loadVersionLibrary(ATLauncher::VersionLibrary & p, QJsonObject & obj) { +static void loadVersionLibrary(ATLauncher::VersionLibrary& p, QJsonObject& obj) +{ p.url = Json::requireString(obj, "url"); p.file = Json::requireString(obj, "file"); p.md5 = Json::requireString(obj, "md5"); @@ -145,12 +129,14 @@ static void loadVersionLibrary(ATLauncher::VersionLibrary & p, QJsonObject & obj p.server = Json::ensureString(obj, "server", ""); } -static void loadVersionConfigs(ATLauncher::VersionConfigs & p, QJsonObject & obj) { +static void loadVersionConfigs(ATLauncher::VersionConfigs& p, QJsonObject& obj) +{ p.filesize = Json::requireInteger(obj, "filesize"); p.sha1 = Json::requireString(obj, "sha1"); } -static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) { +static void loadVersionMod(ATLauncher::VersionMod& p, QJsonObject& obj) +{ p.name = Json::requireString(obj, "name"); p.version = Json::requireString(obj, "version"); p.url = Json::requireString(obj, "url"); @@ -167,18 +153,18 @@ static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) { // when the mod represents Forge. As there is little difference between "Jar" and "Forge, some // packs regretfully use "Jar". This will correct the type to "Forge" in these cases (as best // it can). - if(p.name == QString("Minecraft Forge") && p.type == ATLauncher::ModType::Jar) { + if (p.name == QString("Minecraft Forge") && p.type == ATLauncher::ModType::Jar) { p.type_raw = "forge"; p.type = ATLauncher::ModType::Forge; } - if(obj.contains("extractTo")) { + if (obj.contains("extractTo")) { p.extractTo_raw = Json::requireString(obj, "extractTo"); p.extractTo = parseModType(p.extractTo_raw); p.extractFolder = Json::ensureString(obj, "extractFolder", "").replace("%s%", "/"); } - if(obj.contains("decompType")) { + if (obj.contains("decompType")) { p.decompType_raw = Json::requireString(obj, "decompType"); p.decompType = parseModType(p.decompType_raw); p.decompFile = Json::requireString(obj, "decompFile"); @@ -191,7 +177,7 @@ static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) { p.hidden = Json::ensureBoolean(obj, QString("hidden"), false); p.library = Json::ensureBoolean(obj, QString("library"), false); p.group = Json::ensureString(obj, QString("group"), ""); - if(obj.contains("depends")) { + if (obj.contains("depends")) { auto dependsArr = Json::requireArray(obj, "depends"); for (const auto depends : dependsArr) { p.depends.append(Json::requireString(depends)); @@ -282,31 +268,30 @@ static void loadVersionDeletes(ATLauncher::VersionDeletes& d, QJsonObject& obj) } } -void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj) +void ATLauncher::loadVersion(PackVersion& v, QJsonObject& obj) { v.version = Json::requireString(obj, "version"); v.minecraft = Json::requireString(obj, "minecraft"); v.noConfigs = Json::ensureBoolean(obj, QString("noConfigs"), false); - if(obj.contains("mainClass")) { + if (obj.contains("mainClass")) { auto main = Json::requireObject(obj, "mainClass"); loadVersionMainClass(v.mainClass, main); } - if(obj.contains("extraArguments")) { + if (obj.contains("extraArguments")) { auto arguments = Json::requireObject(obj, "extraArguments"); loadVersionExtraArguments(v.extraArguments, arguments); } - if(obj.contains("loader")) { + if (obj.contains("loader")) { auto loader = Json::requireObject(obj, "loader"); loadVersionLoader(v.loader, loader); } - if(obj.contains("libraries")) { + if (obj.contains("libraries")) { auto libraries = Json::requireArray(obj, "libraries"); - for (const auto libraryRaw : libraries) - { + for (const auto libraryRaw : libraries) { auto libraryObj = Json::requireObject(libraryRaw); ATLauncher::VersionLibrary target; loadVersionLibrary(target, libraryObj); @@ -314,10 +299,9 @@ void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj) } } - if(obj.contains("mods")) { + if (obj.contains("mods")) { auto mods = Json::requireArray(obj, "mods"); - for (const auto modRaw : mods) - { + for (const auto modRaw : mods) { auto modObj = Json::requireObject(modRaw); ATLauncher::VersionMod mod; loadVersionMod(mod, modObj); @@ -325,18 +309,18 @@ void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj) } } - if(obj.contains("configs")) { + if (obj.contains("configs")) { auto configsObj = Json::requireObject(obj, "configs"); loadVersionConfigs(v.configs, configsObj); } auto colourObj = Json::ensureObject(obj, "colours"); - for (const auto &key : colourObj.keys()) { + for (const auto& key : colourObj.keys()) { v.colours[key] = Json::requireString(colourObj.value(key), "colour"); } auto warningsObj = Json::ensureObject(obj, "warnings"); - for (const auto &key : warningsObj.keys()) { + for (const auto& key : warningsObj.keys()) { v.warnings[key] = Json::requireString(warningsObj.value(key), "warning"); } diff --git a/launcher/modplatform/atlauncher/ATLPackManifest.h b/launcher/modplatform/atlauncher/ATLPackManifest.h index 571c976da..fec4bb576 100644 --- a/launcher/modplatform/atlauncher/ATLPackManifest.h +++ b/launcher/modplatform/atlauncher/ATLPackManifest.h @@ -40,17 +40,11 @@ #include #include -namespace ATLauncher -{ +namespace ATLauncher { -enum class PackType -{ - Public, - Private -}; +enum class PackType { Public, Private }; -enum class ModType -{ +enum class ModType { Root, Forge, Jar, @@ -73,16 +67,9 @@ enum class ModType Unknown }; -enum class DownloadType -{ - Server, - Browser, - Direct, - Unknown -}; +enum class DownloadType { Server, Browser, Direct, Unknown }; -struct VersionLoader -{ +struct VersionLoader { QString type; bool latest; bool recommended; @@ -91,8 +78,7 @@ struct VersionLoader QString version; }; -struct VersionLibrary -{ +struct VersionLibrary { QString url; QString file; QString server; @@ -101,8 +87,7 @@ struct VersionLibrary QString download_raw; }; -struct VersionMod -{ +struct VersionMod { QString name; QString version; QString url; @@ -138,14 +123,12 @@ struct VersionMod bool effectively_hidden; }; -struct VersionConfigs -{ +struct VersionConfigs { int filesize; QString sha1; }; -struct VersionMessages -{ +struct VersionMessages { QString install; QString update; }; @@ -170,20 +153,17 @@ struct VersionDeletes { QVector folders; }; -struct PackVersionMainClass -{ +struct PackVersionMainClass { QString mainClass; QString depends; }; -struct PackVersionExtraArguments -{ +struct PackVersionExtraArguments { QString arguments; QString depends; }; -struct PackVersion -{ +struct PackVersion { QString version; QString minecraft; bool noConfigs; @@ -203,6 +183,6 @@ struct PackVersion VersionDeletes deletes; }; -void loadVersion(PackVersion & v, QJsonObject & obj); +void loadVersion(PackVersion& v, QJsonObject& obj); -} +} // namespace ATLauncher diff --git a/launcher/modplatform/atlauncher/ATLShareCode.cpp b/launcher/modplatform/atlauncher/ATLShareCode.cpp index 59030c873..b49631024 100644 --- a/launcher/modplatform/atlauncher/ATLShareCode.cpp +++ b/launcher/modplatform/atlauncher/ATLShareCode.cpp @@ -57,4 +57,4 @@ void loadShareCodeResponse(ShareCodeResponse& r, QJsonObject& obj) } } -} +} // namespace ATLauncher diff --git a/launcher/modplatform/atlauncher/ATLShareCode.h b/launcher/modplatform/atlauncher/ATLShareCode.h index 88c30c98e..69a493f85 100644 --- a/launcher/modplatform/atlauncher/ATLShareCode.h +++ b/launcher/modplatform/atlauncher/ATLShareCode.h @@ -18,9 +18,9 @@ #pragma once +#include #include #include -#include namespace ATLauncher { @@ -44,4 +44,4 @@ struct ShareCodeResponse { void loadShareCodeResponse(ShareCodeResponse& r, QJsonObject& obj); -} +} // namespace ATLauncher diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 9c0cb35b3..860d7340f 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -1,9 +1,9 @@ #include "FileResolvingTask.h" #include "Json.h" +#include "net/ApiDownload.h" #include "net/ApiUpload.h" #include "net/Upload.h" -#include "net/ApiDownload.h" #include "modplatform/modrinth/ModrinthPackIndex.h" diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 7231b4664..73ed10112 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -8,9 +8,9 @@ #include "Application.h" #include "BuildConfig.h" #include "Json.h" +#include "net/ApiDownload.h" #include "net/ApiUpload.h" #include "net/NetJob.h" -#include "net/ApiDownload.h" #include "net/Upload.h" Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, std::shared_ptr response) @@ -75,8 +75,8 @@ auto FlameAPI::getModDescription(int modId) -> QString auto netJob = makeShared(QString("Flame::ModDescription"), APPLICATION->network()); auto response = std::make_shared(); - netJob->addNetAction( - Net::ApiDownload::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray( + QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response)); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { QJsonParseError parse_error{}; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.h b/launcher/modplatform/flame/FlameCheckUpdate.h index 4a98d684f..e3465d7e2 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.h +++ b/launcher/modplatform/flame/FlameCheckUpdate.h @@ -8,7 +8,10 @@ class FlameCheckUpdate : public CheckUpdateTask { Q_OBJECT public: - FlameCheckUpdate(QList& mods, std::list& mcVersions, std::optional loaders, std::shared_ptr mods_folder) + FlameCheckUpdate(QList& mods, + std::list& mcVersions, + std::optional loaders, + std::shared_ptr mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) {} diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 2215de190..19803cf6d 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -194,4 +194,3 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform:: std::sort(versions.begin(), versions.end(), orderSortPredicate); return versions.front(); } - diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp index ad48b7b6a..21835a543 100644 --- a/launcher/modplatform/flame/FlamePackIndex.cpp +++ b/launcher/modplatform/flame/FlamePackIndex.cpp @@ -54,23 +54,22 @@ void Flame::loadIndexedInfo(IndexedPack& pack, QJsonObject& obj) auto links_obj = Json::ensureObject(obj, "links"); pack.extra.websiteUrl = Json::ensureString(links_obj, "websiteUrl"); - if(pack.extra.websiteUrl.endsWith('/')) + if (pack.extra.websiteUrl.endsWith('/')) pack.extra.websiteUrl.chop(1); pack.extra.issuesUrl = Json::ensureString(links_obj, "issuesUrl"); - if(pack.extra.issuesUrl.endsWith('/')) + if (pack.extra.issuesUrl.endsWith('/')) pack.extra.issuesUrl.chop(1); pack.extra.sourceUrl = Json::ensureString(links_obj, "sourceUrl"); - if(pack.extra.sourceUrl.endsWith('/')) + if (pack.extra.sourceUrl.endsWith('/')) pack.extra.sourceUrl.chop(1); pack.extra.wikiUrl = Json::ensureString(links_obj, "wikiUrl"); - if(pack.extra.wikiUrl.endsWith('/')) + if (pack.extra.wikiUrl.endsWith('/')) pack.extra.wikiUrl.chop(1); pack.extraInfoLoaded = true; - } void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr) diff --git a/launcher/modplatform/flame/PackManifest.cpp b/launcher/modplatform/flame/PackManifest.cpp index ee4d07662..40a523d31 100644 --- a/launcher/modplatform/flame/PackManifest.cpp +++ b/launcher/modplatform/flame/PackManifest.cpp @@ -46,7 +46,7 @@ static void loadManifestV1(Flame::Manifest& pack, QJsonObject& manifest) Flame::File file; loadFileV1(file, obj); - pack.files.insert(file.fileId,file); + pack.files.insert(file.fileId, file); } pack.overrides = Json::ensureString(manifest, "overrides", "overrides"); @@ -69,7 +69,7 @@ void Flame::loadManifest(Flame::Manifest& m, const QString& filepath) loadManifestV1(m, obj); } -bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked) +bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked) { fileName = Json::requireString(obj, "fileName"); // This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience @@ -81,7 +81,7 @@ bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked // get the hash hash = QString(); auto hashes = Json::ensureArray(obj, "hashes"); - for(QJsonValueRef item : hashes) { + for (QJsonValueRef item : hashes) { auto hobj = Json::requireObject(item); auto algo = Json::requireInteger(hobj, "algo"); auto value = Json::requireString(hobj, "value"); @@ -90,7 +90,6 @@ bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked } } - // may throw, if the project is blocked QString rawUrl = Json::ensureString(obj, "downloadUrl"); url = QUrl(rawUrl, QUrl::TolerantMode); diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h index 0b7461d84..a608263c6 100644 --- a/launcher/modplatform/flame/PackManifest.h +++ b/launcher/modplatform/flame/PackManifest.h @@ -41,10 +41,8 @@ #include #include -namespace Flame -{ -struct File -{ +namespace Flame { +struct File { // NOTE: throws JSONValidationError bool parseFromObject(const QJsonObject& object, bool throw_on_blocked = true); @@ -61,45 +59,33 @@ struct File QString fileName; QUrl url; QString targetFolder = QStringLiteral("mods"); - enum class Type - { - Unknown, - Folder, - Ctoc, - SingleFile, - Cmod2, - Modpack, - Mod - } type = Type::Mod; + enum class Type { Unknown, Folder, Ctoc, SingleFile, Cmod2, Modpack, Mod } type = Type::Mod; }; -struct Modloader -{ +struct Modloader { QString id; bool primary = false; }; -struct Minecraft -{ +struct Minecraft { QString version; QString libraries; QVector modLoaders; }; -struct Manifest -{ +struct Manifest { QString manifestType; int manifestVersion = 0; Flame::Minecraft minecraft; QString name; QString version; QString author; - //File id -> File - QMap files; + // File id -> File + QMap files; QString overrides; bool is_loaded = false; }; -void loadManifest(Flame::Manifest & m, const QString &filepath); -} +void loadManifest(Flame::Manifest& m, const QString& filepath); +} // namespace Flame diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index 5c3f2003e..46b966620 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -148,4 +148,3 @@ Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args, return netJob; } - diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp index e5ad82444..767dbc65c 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp @@ -37,8 +37,8 @@ #include "PrivatePackManager.h" #include -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" #include "net/ApiDownload.h" diff --git a/launcher/modplatform/legacy_ftb/PackHelpers.h b/launcher/modplatform/legacy_ftb/PackHelpers.h index 566210d05..4fb535530 100644 --- a/launcher/modplatform/legacy_ftb/PackHelpers.h +++ b/launcher/modplatform/legacy_ftb/PackHelpers.h @@ -1,22 +1,16 @@ #pragma once #include +#include #include #include -#include namespace LegacyFTB { -//Header for structs etc... -enum class PackType -{ - Public, - ThirdParty, - Private -}; +// Header for structs etc... +enum class PackType { Public, ThirdParty, Private }; -struct Modpack -{ +struct Modpack { QString name; QString description; QString author; @@ -26,9 +20,9 @@ struct Modpack QString mods; QString logo; - //Technical data + // Technical data QString dir; - QString file; //<- Url in the xml, but doesn't make much sense + QString file; //<- Url in the xml, but doesn't make much sense bool bugged = false; bool broken = false; @@ -39,7 +33,7 @@ struct Modpack typedef QList ModpackList; -} +} // namespace LegacyFTB -//We need it for the proxy model +// We need it for the proxy model Q_DECLARE_METATYPE(LegacyFTB::Modpack) diff --git a/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp b/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp index 1a81f0265..7ab5e9d6b 100644 --- a/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp +++ b/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp @@ -43,8 +43,7 @@ namespace LegacyFTB { void PrivatePackManager::load() { - try - { + try { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) auto foo = QString::fromUtf8(FS::read(m_filename)).split('\n', Qt::SkipEmptyParts); currentPacks = QSet(foo.begin(), foo.end()); @@ -53,9 +52,7 @@ void PrivatePackManager::load() #endif dirty = false; - } - catch(...) - { + } catch (...) { currentPacks = {}; qWarning() << "Failed to read third party FTB pack codes from" << m_filename; } @@ -63,20 +60,16 @@ void PrivatePackManager::load() void PrivatePackManager::save() const { - if(!dirty) - { + if (!dirty) { return; } - try - { + try { QStringList list = currentPacks.values(); FS::write(m_filename, list.join('\n').toUtf8()); dirty = false; - } - catch(...) - { + } catch (...) { qWarning() << "Failed to write third party FTB pack codes to" << m_filename; } } -} +} // namespace LegacyFTB diff --git a/launcher/modplatform/legacy_ftb/PrivatePackManager.h b/launcher/modplatform/legacy_ftb/PrivatePackManager.h index 0e8146462..be811f832 100644 --- a/launcher/modplatform/legacy_ftb/PrivatePackManager.h +++ b/launcher/modplatform/legacy_ftb/PrivatePackManager.h @@ -1,43 +1,33 @@ #pragma once +#include #include #include -#include namespace LegacyFTB { -class PrivatePackManager -{ -public: - ~PrivatePackManager() - { - save(); - } +class PrivatePackManager { + public: + ~PrivatePackManager() { save(); } void load(); void save() const; - bool empty() const - { - return currentPacks.empty(); - } - const QSet &getCurrentPackCodes() const - { - return currentPacks; - } - void add(const QString &code) + bool empty() const { return currentPacks.empty(); } + const QSet& getCurrentPackCodes() const { return currentPacks; } + void add(const QString& code) { currentPacks.insert(code); dirty = true; } - void remove(const QString &code) + void remove(const QString& code) { currentPacks.remove(code); dirty = true; } -private: + private: QSet currentPacks; QString m_filename = "private_packs.txt"; mutable bool dirty = false; }; -} +} // namespace LegacyFTB diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h index 88e1a6751..4583dd6ce 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h @@ -8,7 +8,10 @@ class ModrinthCheckUpdate : public CheckUpdateTask { Q_OBJECT public: - ModrinthCheckUpdate(QList& mods, std::list& mcVersions, std::optional loaders, std::shared_ptr mods_folder) + ModrinthCheckUpdate(QList& mods, + std::list& mcVersions, + std::optional loaders, + std::shared_ptr mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) {} diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 2e42d6e7b..cdbbd42d0 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -11,8 +11,8 @@ #include "net/ChecksumValidator.h" -#include "net/NetJob.h" #include "net/ApiDownload.h" +#include "net/NetJob.h" #include "settings/INISettingsObject.h" #include "ui/dialogs/CustomMessageBox.h" @@ -134,10 +134,10 @@ bool ModrinthCreationTask::updateInstance() } } else { // We don't have an old index file, so we may duplicate stuff! - auto dialog = CustomMessageBox::selectable(m_parent, - tr("No index file."), - tr("We couldn't find a suitable index file for the older version. This may cause some of the files to be duplicated. Do you want to continue?"), - QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel); + auto dialog = CustomMessageBox::selectable(m_parent, tr("No index file."), + tr("We couldn't find a suitable index file for the older version. This may cause some " + "of the files to be duplicated. Do you want to continue?"), + QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel); if (dialog->exec() == QDialog::DialogCode::Rejected) { m_abort = true; @@ -145,7 +145,6 @@ bool ModrinthCreationTask::updateInstance() } } - setOverride(true, inst->id()); qDebug() << "Will override instance!"; @@ -234,7 +233,8 @@ bool ModrinthCreationTask::createInstance() auto file_path = FS::PathCombine(root_modpack_path, file.path); if (!root_modpack_url.isParentOf(QUrl::fromLocalFile(file_path))) { // This means we somehow got out of the root folder, so abort here to prevent exploits - setError(tr("One of the files has a path that leads to an arbitrary location (%1). This is a security risk and isn't allowed.").arg(file.path)); + setError(tr("One of the files has a path that leads to an arbitrary location (%1). This is a security risk and isn't allowed.") + .arg(file.path)); return false; } @@ -251,7 +251,8 @@ bool ModrinthCreationTask::createInstance() auto ndl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path); ndl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash)); m_files_job->addNetAction(ndl); - if (auto shared = param.lock()) shared->succeeded(); + if (auto shared = param.lock()) + shared->succeeded(); }); } } @@ -264,9 +265,9 @@ bool ModrinthCreationTask::createInstance() setError(reason); }); connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit); - connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { + connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); - setProgress(current, total); + setProgress(current, total); }); connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propagateStepProgress); @@ -294,7 +295,10 @@ bool ModrinthCreationTask::createInstance() return ended_well; } -bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector& files, bool set_internal_data, bool show_optional_dialog) +bool ModrinthCreationTask::parseManifest(const QString& index_path, + std::vector& files, + bool set_internal_data, + bool show_optional_dialog) { try { auto doc = Json::requireDocument(index_path); diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h index 6de24fd40..07e417be5 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h @@ -20,10 +20,7 @@ class ModrinthCreationTask final : public InstanceCreationTask { QString id, QString version_id = {}, QString original_instance_id = {}) - : InstanceCreationTask() - , m_parent(parent) - , m_managed_id(std::move(id)) - , m_managed_version_id(std::move(version_id)) + : InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id)) { setStagingPath(staging_path); setParentSettings(global_settings); diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 64d31f429..64c06d1ba 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -260,7 +260,6 @@ QByteArray ModrinthPackExportTask::generateIndex() out["dependencies"] = dependencies; } - QJsonArray filesOut; for (auto iterator = resolvedFiles.constBegin(); iterator != resolvedFiles.constEnd(); iterator++) { QJsonObject fileOut; @@ -288,7 +287,6 @@ QByteArray ModrinthPackExportTask::generateIndex() hashes["sha512"] = value.sha512; fileOut["hashes"] = hashes; - fileOut["fileSize"] = value.size; filesOut << fileOut; } diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index 4dca786f0..d4565191a 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -66,23 +66,23 @@ void loadIndexedInfo(Modpack& pack, QJsonObject& obj) pack.extra.projectUrl = QString("https://modrinth.com/modpack/%1").arg(Json::ensureString(obj, "slug")); pack.extra.issuesUrl = Json::ensureString(obj, "issues_url"); - if(pack.extra.issuesUrl.endsWith('/')) + if (pack.extra.issuesUrl.endsWith('/')) pack.extra.issuesUrl.chop(1); pack.extra.sourceUrl = Json::ensureString(obj, "source_url"); - if(pack.extra.sourceUrl.endsWith('/')) + if (pack.extra.sourceUrl.endsWith('/')) pack.extra.sourceUrl.chop(1); pack.extra.wikiUrl = Json::ensureString(obj, "wiki_url"); - if(pack.extra.wikiUrl.endsWith('/')) + if (pack.extra.wikiUrl.endsWith('/')) pack.extra.wikiUrl.chop(1); pack.extra.discordUrl = Json::ensureString(obj, "discord_url"); - if(pack.extra.discordUrl.endsWith('/')) + if (pack.extra.discordUrl.endsWith('/')) pack.extra.discordUrl.chop(1); auto donate_arr = Json::ensureArray(obj, "donation_urls"); - for(auto d : donate_arr){ + for (auto d : donate_arr) { auto d_obj = Json::requireObject(d); DonationData donate; @@ -107,7 +107,7 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc) auto obj = Json::requireObject(versionIter); auto file = loadIndexedVersion(obj); - if(!file.id.isEmpty()) // Heuristic to check if the returned value is valid + if (!file.id.isEmpty()) // Heuristic to check if the returned value is valid unsortedVersions.append(file); } auto orderSortPredicate = [](const ModpackVersion& a, const ModpackVersion& b) -> bool { @@ -122,7 +122,7 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc) pack.versionsLoaded = true; } -auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion +auto loadIndexedVersion(QJsonObject& obj) -> ModpackVersion { ModpackVersion file; @@ -132,12 +132,11 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion file.id = Json::requireString(obj, "id"); file.project_id = Json::requireString(obj, "project_id"); - + file.date = Json::requireString(obj, "date_published"); auto files = Json::requireArray(obj, "files"); - for (auto file_iter : files) { File indexed_file; auto parent = Json::requireObject(file_iter); @@ -146,21 +145,21 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion auto filename = Json::ensureString(parent, "filename"); // Checking suffix here is fine because it's the response from Modrinth, // so one would assume it will always be in English. - if(!filename.endsWith("mrpack") && !filename.endsWith("zip")) + if (!filename.endsWith("mrpack") && !filename.endsWith("zip")) continue; } auto url = Json::requireString(parent, "url"); file.download_url = url; - if(is_primary) + if (is_primary) break; } - if(file.download_url.isEmpty()) + if (file.download_url.isEmpty()) return {}; return file; -} +} } // namespace Modrinth diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.h b/launcher/modplatform/modrinth/ModrinthPackManifest.h index 2973dfba2..1af47cbc0 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.h +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.h @@ -74,7 +74,6 @@ struct ModpackExtra { QString discordUrl; QList donate; - }; struct ModpackVersion { @@ -97,10 +96,10 @@ struct Modpack { QString description; std::tuple author; QString iconName; - QUrl iconUrl; + QUrl iconUrl; - bool versionsLoaded = false; - bool extraInfoLoaded = false; + bool versionsLoaded = false; + bool extraInfoLoaded = false; ModpackExtra extra; QVector versions; @@ -113,7 +112,7 @@ auto loadIndexedVersion(QJsonObject&) -> ModpackVersion; auto validateDownloadUrl(QUrl) -> bool; -} +} // namespace Modrinth Q_DECLARE_METATYPE(Modrinth::Modpack) Q_DECLARE_METATYPE(Modrinth::ModpackVersion) diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 4b096eec7..6b13f74a9 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #pragma once @@ -36,22 +36,22 @@ auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool shoul class V1 { public: struct Mod { - QString slug {}; - QString name {}; - QString filename {}; + QString slug{}; + QString name{}; + QString filename{}; // FIXME: make side an enum - QString side {"both"}; + QString side{ "both" }; // [download] - QString mode {}; - QUrl url {}; - QString hash_format {}; - QString hash {}; + QString mode{}; + QUrl url{}; + QString hash_format{}; + QString hash{}; // [update] - ModPlatform::ResourceProvider provider {}; - QVariant file_id {}; - QVariant project_id {}; + ModPlatform::ResourceProvider provider{}; + QVariant file_id{}; + QVariant project_id{}; public: // This is a totally heuristic, but should work for now. @@ -95,4 +95,4 @@ class V1 { static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod; }; -} // namespace Packwiz +} // namespace Packwiz diff --git a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp index b2097c1df..ad08d72d4 100644 --- a/launcher/modplatform/technic/SingleZipPackInstallTask.cpp +++ b/launcher/modplatform/technic/SingleZipPackInstallTask.cpp @@ -17,23 +17,23 @@ #include +#include "FileSystem.h" #include "MMCZip.h" #include "TechnicPackProcessor.h" -#include "FileSystem.h" #include "Application.h" #include "net/ApiDownload.h" -Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion) +Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl& sourceUrl, const QString& minecraftVersion) { m_sourceUrl = sourceUrl; m_minecraftVersion = minecraftVersion; } -bool Technic::SingleZipPackInstallTask::abort() { - if(m_abortable) - { +bool Technic::SingleZipPackInstallTask::abort() +{ + if (m_abortable) { return m_filesNetJob->abort(); } return false; @@ -67,12 +67,12 @@ void Technic::SingleZipPackInstallTask::downloadSucceeded() // open the zip and find relevant files in it m_packZip.reset(new QuaZip(m_archivePath)); - if (!m_packZip->open(QuaZip::mdUnzip)) - { + if (!m_packZip->open(QuaZip::mdUnzip)) { emitFailed(tr("Unable to open supplied modpack zip file.")); return; } - m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), QString(""), extractDir.absolutePath()); + m_extractFuture = + QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), QString(""), extractDir.absolutePath()); connect(&m_extractFutureWatcher, &QFutureWatcher::finished, this, &Technic::SingleZipPackInstallTask::extractFinished); connect(&m_extractFutureWatcher, &QFutureWatcher::canceled, this, &Technic::SingleZipPackInstallTask::extractAborted); m_extractFutureWatcher.setFuture(m_extractFuture); @@ -95,8 +95,7 @@ void Technic::SingleZipPackInstallTask::downloadProgressChanged(qint64 current, void Technic::SingleZipPackInstallTask::extractFinished() { m_packZip.reset(); - if (!m_extractFuture.result()) - { + if (!m_extractFuture.result()) { emitFailed(tr("Failed to extract modpack")); return; } @@ -104,30 +103,22 @@ void Technic::SingleZipPackInstallTask::extractFinished() qDebug() << "Fixing permissions for extracted pack files..."; QDirIterator it(extractDir, QDirIterator::Subdirectories); - while (it.hasNext()) - { + while (it.hasNext()) { auto filepath = it.next(); QFileInfo file(filepath); auto permissions = QFile::permissions(filepath); auto origPermissions = permissions; - if (file.isDir()) - { + if (file.isDir()) { // Folder +rwx for current user permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser; - } - else - { + } else { // File +rw for current user permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser; } - if (origPermissions != permissions) - { - if (!QFile::setPermissions(filepath, permissions)) - { + if (origPermissions != permissions) { + if (!QFile::setPermissions(filepath, permissions)) { logWarning(tr("Could not fix permissions for %1").arg(filepath)); - } - else - { + } else { qDebug() << "Fixed" << filepath; } } diff --git a/launcher/modplatform/technic/SingleZipPackInstallTask.h b/launcher/modplatform/technic/SingleZipPackInstallTask.h index 981ccf8a7..d49d008b9 100644 --- a/launcher/modplatform/technic/SingleZipPackInstallTask.h +++ b/launcher/modplatform/technic/SingleZipPackInstallTask.h @@ -28,28 +28,26 @@ namespace Technic { -class SingleZipPackInstallTask : public InstanceTask -{ +class SingleZipPackInstallTask : public InstanceTask { Q_OBJECT -public: - SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion); + public: + SingleZipPackInstallTask(const QUrl& sourceUrl, const QString& minecraftVersion); bool canAbort() const override { return true; } bool abort() override; -protected: + protected: void executeTask() override; - -private slots: + private slots: void downloadSucceeded(); void downloadFailed(QString reason); void downloadProgressChanged(qint64 current, qint64 total); void extractFinished(); void extractAborted(); -private: + private: bool m_abortable = false; QUrl m_sourceUrl; @@ -61,4 +59,4 @@ private: QFutureWatcher> m_extractFutureWatcher; }; -} // namespace Technic +} // namespace Technic diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index d7e9f640b..6e4784f8b 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -42,8 +42,8 @@ #include "SolderPackManifest.h" #include "TechnicPackProcessor.h" -#include "net/ChecksumValidator.h" #include "net/ApiDownload.h" +#include "net/ChecksumValidator.h" Technic::SolderPackInstallTask::SolderPackInstallTask(shared_qobject_ptr network, const QUrl& solderUrl, @@ -97,8 +97,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded() TechnicSolder::PackBuild build; try { TechnicSolder::loadPackBuild(build, obj); - } - catch (const JSONValidationError& e) { + } catch (const JSONValidationError& e) { emitFailed(tr("Could not understand pack manifest:\n") + e.cause()); m_filesNetJob.reset(); return; @@ -139,17 +138,14 @@ void Technic::SolderPackInstallTask::downloadSucceeded() setStatus(tr("Extracting modpack")); m_filesNetJob.reset(); - m_extractFuture = QtConcurrent::run([this]() - { + m_extractFuture = QtConcurrent::run([this]() { int i = 0; QString extractDir = FS::PathCombine(m_stagingPath, ".minecraft"); FS::ensureFolderPathExists(extractDir); - while (m_modCount > i) - { + while (m_modCount > i) { auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i)); - if (!MMCZip::extractDir(path, extractDir)) - { + if (!MMCZip::extractDir(path, extractDir)) { return false; } i++; @@ -182,8 +178,7 @@ void Technic::SolderPackInstallTask::downloadAborted() void Technic::SolderPackInstallTask::extractFinished() { - if (!m_extractFuture.result()) - { + if (!m_extractFuture.result()) { emitFailed(tr("Failed to extract modpack")); return; } @@ -191,30 +186,22 @@ void Technic::SolderPackInstallTask::extractFinished() qDebug() << "Fixing permissions for extracted pack files..."; QDirIterator it(extractDir, QDirIterator::Subdirectories); - while (it.hasNext()) - { + while (it.hasNext()) { auto filepath = it.next(); QFileInfo file(filepath); auto permissions = QFile::permissions(filepath); auto origPermissions = permissions; - if(file.isDir()) - { + if (file.isDir()) { // Folder +rwx for current user permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser; - } - else - { + } else { // File +rw for current user permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser; } - if(origPermissions != permissions) - { - if(!QFile::setPermissions(filepath, permissions)) - { + if (origPermissions != permissions) { + if (!QFile::setPermissions(filepath, permissions)) { logWarning(tr("Could not fix permissions for %1").arg(filepath)); - } - else - { + } else { qDebug() << "Fixed" << filepath; } } @@ -230,4 +217,3 @@ void Technic::SolderPackInstallTask::extractAborted() { emitFailed(tr("Instance import has been aborted.")); } - diff --git a/launcher/modplatform/technic/SolderPackManifest.cpp b/launcher/modplatform/technic/SolderPackManifest.cpp index e52a7ec07..3d9a2ea11 100644 --- a/launcher/modplatform/technic/SolderPackManifest.cpp +++ b/launcher/modplatform/technic/SolderPackManifest.cpp @@ -55,4 +55,4 @@ void loadPackBuild(PackBuild& v, QJsonObject& obj) } } -} +} // namespace TechnicSolder diff --git a/launcher/modplatform/technic/SolderPackManifest.h b/launcher/modplatform/technic/SolderPackManifest.h index 09f18df02..917b4eefa 100644 --- a/launcher/modplatform/technic/SolderPackManifest.h +++ b/launcher/modplatform/technic/SolderPackManifest.h @@ -18,9 +18,9 @@ #pragma once +#include #include #include -#include namespace TechnicSolder { @@ -46,4 +46,4 @@ struct PackBuild { void loadPackBuild(PackBuild& v, QJsonObject& obj); -} +} // namespace TechnicSolder diff --git a/launcher/modplatform/technic/TechnicPackProcessor.cpp b/launcher/modplatform/technic/TechnicPackProcessor.cpp index e473c1704..3b9424bf8 100644 --- a/launcher/modplatform/technic/TechnicPackProcessor.cpp +++ b/launcher/modplatform/technic/TechnicPackProcessor.cpp @@ -40,8 +40,7 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, instance.setName(instName); - if (instIcon != "default") - { + if (instIcon != "default") { instance.setIconKey(instIcon); } @@ -53,23 +52,18 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, QString modpackJar = FS::PathCombine(minecraftPath, "bin", "modpack.jar"); QString versionJson = FS::PathCombine(minecraftPath, "bin", "version.json"); QString fmlMinecraftVersion; - if (QFile::exists(modpackJar)) - { + if (QFile::exists(modpackJar)) { QuaZip zipFile(modpackJar); - if (!zipFile.open(QuaZip::mdUnzip)) - { + if (!zipFile.open(QuaZip::mdUnzip)) { emit failed(tr("Unable to open \"bin/modpack.jar\" file!")); return; } QuaZipDir zipFileRoot(&zipFile, "/"); - if (zipFileRoot.exists("/version.json")) - { - if (zipFileRoot.exists("/fmlversion.properties")) - { + if (zipFileRoot.exists("/version.json")) { + if (zipFileRoot.exists("/fmlversion.properties")) { zipFile.setCurrentFile("fmlversion.properties"); QuaZipFile file(&zipFile); - if (!file.open(QIODevice::ReadOnly)) - { + if (!file.open(QIODevice::ReadOnly)) { emit failed(tr("Unable to open \"fmlversion.properties\"!")); return; } @@ -82,30 +76,25 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, } zipFile.setCurrentFile("version.json", QuaZip::csSensitive); QuaZipFile file(&zipFile); - if (!file.open(QIODevice::ReadOnly)) - { + if (!file.open(QIODevice::ReadOnly)) { emit failed(tr("Unable to open \"version.json\"!")); return; } data = file.readAll(); file.close(); - } - else - { + } else { if (minecraftVersion.isEmpty()) emit failed(tr("Could not find \"version.json\" inside \"bin/modpack.jar\", but Minecraft version is unknown")); components->setComponentVersion("net.minecraft", minecraftVersion, true); - components->installJarMods({modpackJar}); + components->installJarMods({ modpackJar }); // Forge for 1.4.7 and for 1.5.2 require extra libraries. // Figure out the forge version and add it as a component // (the code still comes from the jar mod installed above) - if (zipFileRoot.exists("/forgeversion.properties")) - { + if (zipFileRoot.exists("/forgeversion.properties")) { zipFile.setCurrentFile("forgeversion.properties", QuaZip::csSensitive); QuaZipFile file(&zipFile); - if (!file.open(QIODevice::ReadOnly)) - { + if (!file.open(QIODevice::ReadOnly)) { // Really shouldn't happen, but error handling shall not be forgotten emit failed(tr("Unable to open \"forgeversion.properties\"")); return; @@ -120,8 +109,7 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, revision = iniFile["forge.revision.number"].toString(); build = iniFile["forge.build.number"].toString(); - if (major.isEmpty() || minor.isEmpty() || revision.isEmpty() || build.isEmpty()) - { + if (major.isEmpty() || minor.isEmpty() || revision.isEmpty() || build.isEmpty()) { emit failed(tr("Invalid \"forgeversion.properties\"!")); return; } @@ -133,83 +121,63 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings, emit succeeded(); return; } - } - else if (QFile::exists(versionJson)) - { + } else if (QFile::exists(versionJson)) { QFile file(versionJson); - if (!file.open(QIODevice::ReadOnly)) - { + if (!file.open(QIODevice::ReadOnly)) { emit failed(tr("Unable to open \"version.json\"!")); return; } data = file.readAll(); file.close(); - } - else - { + } else { // This is the "Vanilla" modpack, excluded by the search code emit failed(tr("Unable to find a \"version.json\"!")); return; } - try - { + try { QJsonDocument doc = Json::requireDocument(data); QJsonObject root = Json::requireObject(doc, "version.json"); QString packMinecraftVersion = Json::ensureString(root, "inheritsFrom", QString(), ""); if (packMinecraftVersion.isEmpty()) { - if (fmlMinecraftVersion.isEmpty()) - { + if (fmlMinecraftVersion.isEmpty()) { emit failed(tr("Could not understand \"version.json\":\ninheritsFrom is missing")); return; } packMinecraftVersion = fmlMinecraftVersion; } components->setComponentVersion("net.minecraft", packMinecraftVersion, true); - for (auto library: Json::ensureArray(root, "libraries", {})) - { - if (!library.isObject()) - { + for (auto library : Json::ensureArray(root, "libraries", {})) { + if (!library.isObject()) { continue; } auto libraryObject = Json::ensureObject(library, {}, ""); auto libraryName = Json::ensureString(libraryObject, "name", "", ""); - if ((libraryName.startsWith("net.minecraftforge:forge:") || libraryName.startsWith("net.minecraftforge:fmlloader:")) && libraryName.contains('-')) - { + if ((libraryName.startsWith("net.minecraftforge:forge:") || libraryName.startsWith("net.minecraftforge:fmlloader:")) && + libraryName.contains('-')) { QString libraryVersion = libraryName.section(':', 2); - if (!libraryVersion.startsWith("1.7.10-")) - { + if (!libraryVersion.startsWith("1.7.10-")) { components->setComponentVersion("net.minecraftforge", libraryName.section('-', 1)); - } - else - { + } else { // 1.7.10 versions sometimes look like 1.7.10-10.13.4.1614-1.7.10, this filters out the 10.13.4.1614 part components->setComponentVersion("net.minecraftforge", libraryName.section('-', 1, 1)); } - } - else - { + } else { // -> - static QMap loaderMap { - {"net.minecraftforge:minecraftforge:", "net.minecraftforge"}, - {"net.fabricmc:fabric-loader:", "net.fabricmc.fabric-loader"}, - {"org.quiltmc:quilt-loader:", "org.quiltmc.quilt-loader"} - }; - for (const auto& loader : loaderMap.keys()) - { - if (libraryName.startsWith(loader)) - { + static QMap loaderMap{ { "net.minecraftforge:minecraftforge:", "net.minecraftforge" }, + { "net.fabricmc:fabric-loader:", "net.fabricmc.fabric-loader" }, + { "org.quiltmc:quilt-loader:", "org.quiltmc.quilt-loader" } }; + for (const auto& loader : loaderMap.keys()) { + if (libraryName.startsWith(loader)) { components->setComponentVersion(loaderMap.value(loader), libraryName.section(':', 2)); break; } } } } - } - catch (const JSONValidationError &e) - { + } catch (const JSONValidationError& e) { emit failed(tr("Could not understand \"version.json\":\n") + e.cause()); return; } diff --git a/launcher/modplatform/technic/TechnicPackProcessor.h b/launcher/modplatform/technic/TechnicPackProcessor.h index 2ad803b34..466bce596 100644 --- a/launcher/modplatform/technic/TechnicPackProcessor.h +++ b/launcher/modplatform/technic/TechnicPackProcessor.h @@ -18,18 +18,21 @@ #include #include "settings/SettingsObject.h" -namespace Technic -{ - // not exporting it, only used in SingleZipPackInstallTask, InstanceImportTask and SolderPackInstallTask - class TechnicPackProcessor : public QObject - { - Q_OBJECT +namespace Technic { +// not exporting it, only used in SingleZipPackInstallTask, InstanceImportTask and SolderPackInstallTask +class TechnicPackProcessor : public QObject { + Q_OBJECT - signals: - void succeeded(); - void failed(QString reason); + signals: + void succeeded(); + void failed(QString reason); - public: - void run(SettingsObjectPtr globalSettings, const QString &instName, const QString &instIcon, const QString &stagingPath, const QString &minecraftVersion=QString(), const bool isSolder = false); - }; -} + public: + void run(SettingsObjectPtr globalSettings, + const QString& instName, + const QString& instIcon, + const QString& stagingPath, + const QString& minecraftVersion = QString(), + const bool isSolder = false); +}; +} // namespace Technic diff --git a/launcher/net/HeaderProxy.h b/launcher/net/HeaderProxy.h index 213c04c58..20362924f 100644 --- a/launcher/net/HeaderProxy.h +++ b/launcher/net/HeaderProxy.h @@ -31,8 +31,8 @@ struct HeaderPair { class HeaderProxy { public: - HeaderProxy(){} - virtual ~HeaderProxy(){} + HeaderProxy() {} + virtual ~HeaderProxy() {} public: virtual QList headers(const QNetworkRequest& request) const = 0; diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp index 689dbac96..7809d40fc 100644 --- a/launcher/net/HttpMetaCache.cpp +++ b/launcher/net/HttpMetaCache.cpp @@ -125,8 +125,9 @@ auto HttpMetaCache::resolveEntry(QString base, QString resource_path, QString ex // Get rid of old entries, to prevent cache problems auto current_time = QDateTime::currentSecsSinceEpoch(); - if (entry->isExpired(current_time - ( file_last_changed / 1000 ))) { - qCWarning(taskNetLogC) << "[HttpMetaCache]" << "Removing cache entry because of old age!"; + if (entry->isExpired(current_time - (file_last_changed / 1000))) { + qCWarning(taskNetLogC) << "[HttpMetaCache]" + << "Removing cache entry because of old age!"; selected_base.entry_list.remove(resource_path); return staleEntry(base, resource_path); } diff --git a/launcher/net/Logging.h b/launcher/net/Logging.h index b692e7075..4deed2b49 100644 --- a/launcher/net/Logging.h +++ b/launcher/net/Logging.h @@ -16,8 +16,8 @@ * along with this program. If not, see . * */ - -#pragma once + +#pragma once #include diff --git a/launcher/net/MetaCacheSink.cpp b/launcher/net/MetaCacheSink.cpp index e203bc06d..889588a11 100644 --- a/launcher/net/MetaCacheSink.cpp +++ b/launcher/net/MetaCacheSink.cpp @@ -46,32 +46,27 @@ namespace Net { /** Maximum time to hold a cache entry * = 1 week in seconds */ -#define MAX_TIME_TO_EXPIRE 1*7*24*60*60 +#define MAX_TIME_TO_EXPIRE 1 * 7 * 24 * 60 * 60 - -MetaCacheSink::MetaCacheSink(MetaEntryPtr entry, ChecksumValidator * md5sum, bool is_eternal) - :Net::FileSink(entry->getFullPath()), m_entry(entry), m_md5Node(md5sum), m_is_eternal(is_eternal) +MetaCacheSink::MetaCacheSink(MetaEntryPtr entry, ChecksumValidator* md5sum, bool is_eternal) + : Net::FileSink(entry->getFullPath()), m_entry(entry), m_md5Node(md5sum), m_is_eternal(is_eternal) { addValidator(md5sum); } Task::State MetaCacheSink::initCache(QNetworkRequest& request) { - if (!m_entry->isStale()) - { + if (!m_entry->isStale()) { return Task::State::Succeeded; } // check if file exists, if it does, use its information for the request QFile current(m_filename); - if(current.exists() && current.size() != 0) - { - if (m_entry->getRemoteChangedTimestamp().size()) - { + if (current.exists() && current.size() != 0) { + if (m_entry->getRemoteChangedTimestamp().size()) { request.setRawHeader(QString("If-Modified-Since").toLatin1(), m_entry->getRemoteChangedTimestamp().toLatin1()); } - if (m_entry->getETag().size()) - { + if (m_entry->getETag().size()) { request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1()); } } @@ -79,25 +74,23 @@ Task::State MetaCacheSink::initCache(QNetworkRequest& request) return Task::State::Running; } -Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply) +Task::State MetaCacheSink::finalizeCache(QNetworkReply& reply) { QFileInfo output_file_info(m_filename); - if(wroteAnyData) - { + if (wroteAnyData) { m_entry->setMD5Sum(m_md5Node->hash().toHex().constData()); } m_entry->setETag(reply.rawHeader("ETag").constData()); - if (reply.hasRawHeader("Last-Modified")) - { + if (reply.hasRawHeader("Last-Modified")) { m_entry->setRemoteChangedTimestamp(reply.rawHeader("Last-Modified").constData()); } m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch()); - { // Cache lifetime + { // Cache lifetime if (m_is_eternal) { qCDebug(taskMetaCacheLogC) << "Adding eternal cache entry:" << m_entry->getFullPath(); m_entry->makeEternal(true); @@ -141,4 +134,4 @@ bool MetaCacheSink::hasLocalData() QFileInfo info(m_filename); return info.exists() && info.size() != 0; } -} +} // namespace Net diff --git a/launcher/net/NetAction.h b/launcher/net/NetAction.h index 247b34c01..b66b91941 100644 --- a/launcher/net/NetAction.h +++ b/launcher/net/NetAction.h @@ -47,7 +47,7 @@ class NetAction : public Task { Q_OBJECT protected: - explicit NetAction() : Task(){} + explicit NetAction() : Task() {} public: using Ptr = shared_qobject_ptr; @@ -86,7 +86,7 @@ class NetAction : public Task { } protected: - void executeTask() override{} + void executeTask() override {} public: shared_qobject_ptr m_network; diff --git a/launcher/net/NetJob.h b/launcher/net/NetJob.h index 764cec18b..cc63f4497 100644 --- a/launcher/net/NetJob.h +++ b/launcher/net/NetJob.h @@ -52,7 +52,9 @@ class NetJob : public ConcurrentTask { public: using Ptr = shared_qobject_ptr; - explicit NetJob(QString job_name, shared_qobject_ptr network) : ConcurrentTask(nullptr, job_name), m_network(network) {} + explicit NetJob(QString job_name, shared_qobject_ptr network) + : ConcurrentTask(nullptr, job_name), m_network(network) + {} ~NetJob() override = default; void startNext() override; diff --git a/launcher/net/NetRequest.h b/launcher/net/NetRequest.h index f91207ef3..ee47ab2a6 100644 --- a/launcher/net/NetRequest.h +++ b/launcher/net/NetRequest.h @@ -52,7 +52,7 @@ namespace Net { class NetRequest : public NetAction { Q_OBJECT protected: - explicit NetRequest() : NetAction(){} + explicit NetRequest() : NetAction() {} public: using Ptr = shared_qobject_ptr; @@ -62,7 +62,7 @@ class NetRequest : public NetAction { public: ~NetRequest() override = default; - void init() override{} + void init() override {} public: void addValidator(Validator* v); diff --git a/launcher/net/NetUtils.h b/launcher/net/NetUtils.h index fa3bd8c03..afaf7b5f3 100644 --- a/launcher/net/NetUtils.h +++ b/launcher/net/NetUtils.h @@ -22,23 +22,22 @@ #include namespace Net { - inline bool isApplicationError(QNetworkReply::NetworkError x) { - // Mainly taken from https://github.com/qt/qtbase/blob/dev/src/network/access/qhttpthreaddelegate.cpp - static QSet errors = { - QNetworkReply::ProtocolInvalidOperationError, - QNetworkReply::AuthenticationRequiredError, - QNetworkReply::ContentAccessDenied, - QNetworkReply::ContentNotFoundError, - QNetworkReply::ContentOperationNotPermittedError, - QNetworkReply::ProxyAuthenticationRequiredError, - QNetworkReply::ContentConflictError, - QNetworkReply::ContentGoneError, - QNetworkReply::InternalServerError, - QNetworkReply::OperationNotImplementedError, - QNetworkReply::ServiceUnavailableError, - QNetworkReply::UnknownServerError, - QNetworkReply::UnknownContentError - }; - return errors.contains(x); - } +inline bool isApplicationError(QNetworkReply::NetworkError x) +{ + // Mainly taken from https://github.com/qt/qtbase/blob/dev/src/network/access/qhttpthreaddelegate.cpp + static QSet errors = { QNetworkReply::ProtocolInvalidOperationError, + QNetworkReply::AuthenticationRequiredError, + QNetworkReply::ContentAccessDenied, + QNetworkReply::ContentNotFoundError, + QNetworkReply::ContentOperationNotPermittedError, + QNetworkReply::ProxyAuthenticationRequiredError, + QNetworkReply::ContentConflictError, + QNetworkReply::ContentGoneError, + QNetworkReply::InternalServerError, + QNetworkReply::OperationNotImplementedError, + QNetworkReply::ServiceUnavailableError, + QNetworkReply::UnknownServerError, + QNetworkReply::UnknownContentError }; + return errors.contains(x); +} } // namespace Net diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index 595279a3a..c67d3b23c 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -36,26 +36,26 @@ */ #include "PasteUpload.h" -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" #include -#include +#include #include #include #include -#include +#include #include #include "net/Logging.h" -std::array PasteUpload::PasteTypes = { - {{"0x0.st", "https://0x0.st", ""}, - {"hastebin", "https://hst.sh", "/documents"}, - {"paste.gg", "https://paste.gg", "/api/v1/pastes"}, - {"mclo.gs", "https://api.mclo.gs", "/1/log"}}}; +std::array PasteUpload::PasteTypes = { { { "0x0.st", "https://0x0.st", "" }, + { "hastebin", "https://hst.sh", "/documents" }, + { "paste.gg", "https://paste.gg", "/api/v1/pastes" }, + { "mclo.gs", "https://api.mclo.gs", "/1/log" } } }; -PasteUpload::PasteUpload(QWidget *window, QString text, QString baseUrl, PasteType pasteType) : m_window(window), m_baseUrl(baseUrl), m_pasteType(pasteType), m_text(text.toUtf8()) +PasteUpload::PasteUpload(QWidget* window, QString text, QString baseUrl, PasteType pasteType) + : m_window(window), m_baseUrl(baseUrl), m_pasteType(pasteType), m_text(text.toUtf8()) { if (m_baseUrl == "") m_baseUrl = PasteTypes.at(pasteType).defaultBase; @@ -67,68 +67,64 @@ PasteUpload::PasteUpload(QWidget *window, QString text, QString baseUrl, PasteTy m_uploadUrl = m_baseUrl + PasteTypes.at(pasteType).endpointPath; } -PasteUpload::~PasteUpload() -{ -} +PasteUpload::~PasteUpload() {} void PasteUpload::executeTask() { - QNetworkRequest request{QUrl(m_uploadUrl)}; - QNetworkReply *rep{}; + QNetworkRequest request{ QUrl(m_uploadUrl) }; + QNetworkReply* rep{}; request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgentUncached().toUtf8()); switch (m_pasteType) { - case NullPointer: { - QHttpMultiPart *multiPart = - new QHttpMultiPart{QHttpMultiPart::FormDataType}; + case NullPointer: { + QHttpMultiPart* multiPart = new QHttpMultiPart{ QHttpMultiPart::FormDataType }; - QHttpPart filePart; - filePart.setBody(m_text); - filePart.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain"); - filePart.setHeader(QNetworkRequest::ContentDispositionHeader, - "form-data; name=\"file\"; filename=\"log.txt\""); - multiPart->append(filePart); + QHttpPart filePart; + filePart.setBody(m_text); + filePart.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain"); + filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"file\"; filename=\"log.txt\""); + multiPart->append(filePart); - rep = APPLICATION->network()->post(request, multiPart); - multiPart->setParent(rep); + rep = APPLICATION->network()->post(request, multiPart); + multiPart->setParent(rep); - break; - } - case Hastebin: { - request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgentUncached().toUtf8()); - rep = APPLICATION->network()->post(request, m_text); - break; - } - case Mclogs: { - QUrlQuery postData; - postData.addQueryItem("content", m_text); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); - rep = APPLICATION->network()->post(request, postData.toString().toUtf8()); - break; - } - case PasteGG: { - QJsonObject obj; - QJsonDocument doc; - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + break; + } + case Hastebin: { + request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgentUncached().toUtf8()); + rep = APPLICATION->network()->post(request, m_text); + break; + } + case Mclogs: { + QUrlQuery postData; + postData.addQueryItem("content", m_text); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + rep = APPLICATION->network()->post(request, postData.toString().toUtf8()); + break; + } + case PasteGG: { + QJsonObject obj; + QJsonDocument doc; + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - obj.insert("expires", QDateTime::currentDateTimeUtc().addDays(100).toString(Qt::DateFormat::ISODate)); + obj.insert("expires", QDateTime::currentDateTimeUtc().addDays(100).toString(Qt::DateFormat::ISODate)); - QJsonArray files; - QJsonObject logFileInfo; - QJsonObject logFileContentInfo; - logFileContentInfo.insert("format", "text"); - logFileContentInfo.insert("value", QString::fromUtf8(m_text)); - logFileInfo.insert("name", "log.txt"); - logFileInfo.insert("content", logFileContentInfo); - files.append(logFileInfo); + QJsonArray files; + QJsonObject logFileInfo; + QJsonObject logFileContentInfo; + logFileContentInfo.insert("format", "text"); + logFileContentInfo.insert("value", QString::fromUtf8(m_text)); + logFileInfo.insert("name", "log.txt"); + logFileInfo.insert("content", logFileContentInfo); + files.append(logFileInfo); - obj.insert("files", files); + obj.insert("files", files); - doc.setObject(obj); - rep = APPLICATION->network()->post(request, doc.toJson()); - break; - } + doc.setObject(obj); + rep = APPLICATION->network()->post(request, doc.toJson()); + break; + } } connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress); @@ -140,7 +136,6 @@ void PasteUpload::executeTask() connect(rep, QOverload::of(&QNetworkReply::error), this, &PasteUpload::downloadError); #endif - m_reply = std::shared_ptr(rep); setStatus(tr("Uploading to %1").arg(m_uploadUrl)); @@ -158,97 +153,81 @@ void PasteUpload::downloadFinished() QByteArray data = m_reply->readAll(); int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (m_reply->error() != QNetworkReply::NetworkError::NoError) - { + if (m_reply->error() != QNetworkReply::NetworkError::NoError) { emitFailed(tr("Network error: %1").arg(m_reply->errorString())); m_reply.reset(); return; - } - else if (statusCode != 200 && statusCode != 201) - { + } else if (statusCode != 200 && statusCode != 201) { QString reasonPhrase = m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); emitFailed(tr("Error: %1 returned unexpected status code %2 %3").arg(m_uploadUrl).arg(statusCode).arg(reasonPhrase)); - qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned unexpected status code " << statusCode << " with body: " << data; + qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned unexpected status code " << statusCode + << " with body: " << data; m_reply.reset(); return; } - switch (m_pasteType) - { - case NullPointer: - m_pasteLink = QString::fromUtf8(data).trimmed(); - break; - case Hastebin: { - QJsonDocument jsonDoc{QJsonDocument::fromJson(data)}; - QJsonObject jsonObj{jsonDoc.object()}; - if (jsonObj.contains("key") && jsonObj["key"].isString()) - { - QString key = jsonDoc.object()["key"].toString(); - m_pasteLink = m_baseUrl + "/" + key; - } - else - { - emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); - qCCritical(taskUploadLogC) << getUid().toString() << getUid().toString() << m_uploadUrl << " returned malformed response body: " << data; - return; - } - break; - } - case Mclogs: { - QJsonDocument jsonDoc{QJsonDocument::fromJson(data)}; - QJsonObject jsonObj{jsonDoc.object()}; - if (jsonObj.contains("success") && jsonObj["success"].isBool()) - { - bool success = jsonObj["success"].toBool(); - if (success) - { - m_pasteLink = jsonObj["url"].toString(); - } - else - { - QString error = jsonObj["error"].toString(); - emitFailed(tr("Error: %1 returned an error: %2").arg(m_uploadUrl, error)); - qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned error: " << error; - qCCritical(taskUploadLogC) << getUid().toString() << "Response body: " << data; + switch (m_pasteType) { + case NullPointer: + m_pasteLink = QString::fromUtf8(data).trimmed(); + break; + case Hastebin: { + QJsonDocument jsonDoc{ QJsonDocument::fromJson(data) }; + QJsonObject jsonObj{ jsonDoc.object() }; + if (jsonObj.contains("key") && jsonObj["key"].isString()) { + QString key = jsonDoc.object()["key"].toString(); + m_pasteLink = m_baseUrl + "/" + key; + } else { + emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); + qCCritical(taskUploadLogC) << getUid().toString() << getUid().toString() << m_uploadUrl + << " returned malformed response body: " << data; return; } + break; } - else - { - emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); - qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned malformed response body: " << data; - return; - } - break; - } - case PasteGG: - QJsonDocument jsonDoc{QJsonDocument::fromJson(data)}; - QJsonObject jsonObj{jsonDoc.object()}; - if (jsonObj.contains("status") && jsonObj["status"].isString()) - { - QString status = jsonObj["status"].toString(); - if (status == "success") - { - m_pasteLink = m_baseUrl + "/p/anonymous/" + jsonObj["result"].toObject()["id"].toString(); - } - else - { - QString error = jsonObj["error"].toString(); - QString message = (jsonObj.contains("message") && jsonObj["message"].isString()) ? jsonObj["message"].toString() : "none"; - emitFailed(tr("Error: %1 returned an error code: %2\nError message: %3").arg(m_uploadUrl, error, message)); - qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned error: " << error; - qCCritical(taskUploadLogC) << getUid().toString() << "Error message: " << message; - qCCritical(taskUploadLogC) << getUid().toString() << "Response body: " << data; + case Mclogs: { + QJsonDocument jsonDoc{ QJsonDocument::fromJson(data) }; + QJsonObject jsonObj{ jsonDoc.object() }; + if (jsonObj.contains("success") && jsonObj["success"].isBool()) { + bool success = jsonObj["success"].toBool(); + if (success) { + m_pasteLink = jsonObj["url"].toString(); + } else { + QString error = jsonObj["error"].toString(); + emitFailed(tr("Error: %1 returned an error: %2").arg(m_uploadUrl, error)); + qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned error: " << error; + qCCritical(taskUploadLogC) << getUid().toString() << "Response body: " << data; + return; + } + } else { + emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); + qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned malformed response body: " << data; return; } + break; } - else - { - emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); - qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned malformed response body: " << data; - return; - } - break; + case PasteGG: + QJsonDocument jsonDoc{ QJsonDocument::fromJson(data) }; + QJsonObject jsonObj{ jsonDoc.object() }; + if (jsonObj.contains("status") && jsonObj["status"].isString()) { + QString status = jsonObj["status"].toString(); + if (status == "success") { + m_pasteLink = m_baseUrl + "/p/anonymous/" + jsonObj["result"].toObject()["id"].toString(); + } else { + QString error = jsonObj["error"].toString(); + QString message = + (jsonObj.contains("message") && jsonObj["message"].isString()) ? jsonObj["message"].toString() : "none"; + emitFailed(tr("Error: %1 returned an error code: %2\nError message: %3").arg(m_uploadUrl, error, message)); + qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned error: " << error; + qCCritical(taskUploadLogC) << getUid().toString() << "Error message: " << message; + qCCritical(taskUploadLogC) << getUid().toString() << "Response body: " << data; + return; + } + } else { + emitFailed(tr("Error: %1 returned a malformed response body").arg(m_uploadUrl)); + qCCritical(taskUploadLogC) << getUid().toString() << m_uploadUrl << " returned malformed response body: " << data; + return; + } + break; } emitSucceeded(); } diff --git a/launcher/net/PasteUpload.h b/launcher/net/PasteUpload.h index b72ab5b00..2ba6067c3 100644 --- a/launcher/net/PasteUpload.h +++ b/launcher/net/PasteUpload.h @@ -35,17 +35,16 @@ #pragma once -#include "tasks/Task.h" +#include #include #include -#include -#include #include +#include +#include "tasks/Task.h" -class PasteUpload : public Task -{ +class PasteUpload : public Task { Q_OBJECT -public: + public: enum PasteType : int { // 0x0.st NullPointer, @@ -68,26 +67,23 @@ public: static std::array PasteTypes; - PasteUpload(QWidget *window, QString text, QString url, PasteType pasteType); + PasteUpload(QWidget* window, QString text, QString url, PasteType pasteType); virtual ~PasteUpload(); - QString pasteLink() - { - return m_pasteLink; - } -protected: + QString pasteLink() { return m_pasteLink; } + + protected: virtual void executeTask(); -private: - QWidget *m_window; + private: + QWidget* m_window; QString m_pasteLink; QString m_baseUrl; QString m_uploadUrl; PasteType m_pasteType; QByteArray m_text; std::shared_ptr m_reply; -public -slots: + public slots: void downloadError(QNetworkReply::NetworkError); void downloadFinished(); }; diff --git a/launcher/net/Validator.h b/launcher/net/Validator.h index c8ce79223..7d35ec387 100644 --- a/launcher/net/Validator.h +++ b/launcher/net/Validator.h @@ -37,17 +37,16 @@ #include "net/NetAction.h" namespace Net { -class Validator -{ -public: /* con/des */ +class Validator { + public: /* con/des */ Validator() {} virtual ~Validator() {} -public: /* methods */ - virtual bool init(QNetworkRequest & request) = 0; - virtual bool write(QByteArray & data) = 0; + public: /* methods */ + virtual bool init(QNetworkRequest& request) = 0; + virtual bool write(QByteArray& data) = 0; virtual bool abort() = 0; - virtual bool validate(QNetworkReply & reply) = 0; + virtual bool validate(QNetworkReply& reply) = 0; }; -} +} // namespace Net diff --git a/launcher/news/NewsChecker.cpp b/launcher/news/NewsChecker.cpp index 4f02bf5e0..11ba5311b 100644 --- a/launcher/news/NewsChecker.cpp +++ b/launcher/news/NewsChecker.cpp @@ -49,8 +49,7 @@ NewsChecker::NewsChecker(shared_qobject_ptr network, cons void NewsChecker::reloadNews() { // Start a netjob to download the RSS feed and call rssDownloadFinished() when it's done. - if (isLoadingNews()) - { + if (isLoadingNews()) { qDebug() << "Ignored request to reload news. Currently reloading already."; return; } @@ -113,7 +112,6 @@ void NewsChecker::rssDownloadFailed(QString reason) fail(tr("Failed to load news RSS feed:\n%1").arg(reason)); } - QList NewsChecker::getNewsEntries() const { return m_newsEntries; @@ -144,4 +142,3 @@ void NewsChecker::fail(const QString& errorMsg) m_newsNetJob.reset(); emit newsLoadingFailed(errorMsg); } - diff --git a/launcher/news/NewsChecker.h b/launcher/news/NewsChecker.h index 41babfff7..cdd621a20 100644 --- a/launcher/news/NewsChecker.h +++ b/launcher/news/NewsChecker.h @@ -15,18 +15,17 @@ #pragma once +#include #include #include -#include #include #include "NewsEntry.h" -class NewsChecker : public QObject -{ +class NewsChecker : public QObject { Q_OBJECT -public: + public: /*! * Constructs a news reader to read from the given RSS feed URL. */ @@ -57,7 +56,7 @@ public: */ void Q_SLOT reloadNews(); -signals: + signals: /*! * Signal fired after the news has finished loading. */ @@ -68,11 +67,11 @@ signals: */ void newsLoadingFailed(QString errorMsg); -protected slots: + protected slots: void rssDownloadFinished(); void rssDownloadFailed(QString reason); -protected: /* data */ + protected: /* data */ //! The URL for the RSS feed to fetch. QString m_feedUrl; @@ -95,11 +94,10 @@ protected: /* data */ shared_qobject_ptr m_network; -protected slots: + protected slots: /// Emits newsLoaded() and sets m_lastLoadError to empty string. void succeed(); /// Emits newsLoadingFailed() and sets m_lastLoadError to the given message. void fail(const QString& errorMsg); }; - diff --git a/launcher/news/NewsEntry.cpp b/launcher/news/NewsEntry.cpp index 9726cab24..ea25f2e54 100644 --- a/launcher/news/NewsEntry.cpp +++ b/launcher/news/NewsEntry.cpp @@ -18,16 +18,14 @@ #include #include -NewsEntry::NewsEntry(QObject* parent) : - QObject(parent) +NewsEntry::NewsEntry(QObject* parent) : QObject(parent) { this->title = tr("Untitled"); this->content = tr("No content."); this->link = ""; } -NewsEntry::NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent) : - QObject(parent) +NewsEntry::NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent) : QObject(parent) { this->title = title; this->content = content; @@ -37,16 +35,13 @@ NewsEntry::NewsEntry(const QString& title, const QString& content, const QString /*! * Gets the text content of the given child element as a QVariant. */ -inline QString childValue(const QDomElement& element, const QString& childName, QString defaultVal="") +inline QString childValue(const QDomElement& element, const QString& childName, QString defaultVal = "") { QDomNodeList nodes = element.elementsByTagName(childName); - if (nodes.count() > 0) - { + if (nodes.count() > 0) { QDomElement elem = nodes.at(0).toElement(); return elem.text(); - } - else - { + } else { return defaultVal; } } diff --git a/launcher/news/NewsEntry.h b/launcher/news/NewsEntry.h index 1fe95623d..2d409a9fb 100644 --- a/launcher/news/NewsEntry.h +++ b/launcher/news/NewsEntry.h @@ -15,33 +15,31 @@ #pragma once +#include #include #include -#include #include -class NewsEntry : public QObject -{ +class NewsEntry : public QObject { Q_OBJECT -public: + public: /*! * Constructs an empty news entry. */ - explicit NewsEntry(QObject* parent=0); + explicit NewsEntry(QObject* parent = 0); /*! * Constructs a new news entry. * Note that content may contain HTML. */ - NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent=0); + NewsEntry(const QString& title, const QString& content, const QString& link, QObject* parent = 0); /*! * Attempts to load information from the given XML element into the given news entry pointer. * If this fails, the function will return false and store an error message in the errorMsg pointer. */ - static bool fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg=0); - + static bool fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg = 0); //! The post title. QString title; @@ -54,4 +52,3 @@ public: }; typedef std::shared_ptr NewsEntryPtr; - diff --git a/launcher/pathmatcher/FSTreeMatcher.h b/launcher/pathmatcher/FSTreeMatcher.h index b84af2945..52f1404df 100644 --- a/launcher/pathmatcher/FSTreeMatcher.h +++ b/launcher/pathmatcher/FSTreeMatcher.h @@ -1,21 +1,15 @@ #pragma once -#include "IPathMatcher.h" #include #include +#include "IPathMatcher.h" -class FSTreeMatcher : public IPathMatcher -{ -public: - virtual ~FSTreeMatcher() {}; - FSTreeMatcher(SeparatorPrefixTree<'/'> & tree) : m_fsTree(tree) - { - } +class FSTreeMatcher : public IPathMatcher { + public: + virtual ~FSTreeMatcher(){}; + FSTreeMatcher(SeparatorPrefixTree<'/'>& tree) : m_fsTree(tree) {} - bool matches(const QString &string) const override - { - return m_fsTree.covers(string); - } + bool matches(const QString& string) const override { return m_fsTree.covers(string); } - SeparatorPrefixTree<'/'> & m_fsTree; + SeparatorPrefixTree<'/'>& m_fsTree; }; diff --git a/launcher/pathmatcher/IPathMatcher.h b/launcher/pathmatcher/IPathMatcher.h index 1457d3e5b..cd6121979 100644 --- a/launcher/pathmatcher/IPathMatcher.h +++ b/launcher/pathmatcher/IPathMatcher.h @@ -1,13 +1,12 @@ #pragma once -#include #include +#include -class IPathMatcher -{ -public: +class IPathMatcher { + public: typedef std::shared_ptr Ptr; -public: + public: virtual ~IPathMatcher() {} - virtual bool matches(const QString &string) const = 0; + virtual bool matches(const QString& string) const = 0; }; diff --git a/launcher/pathmatcher/MultiMatcher.h b/launcher/pathmatcher/MultiMatcher.h index 8bc1b6eed..101595809 100644 --- a/launcher/pathmatcher/MultiMatcher.h +++ b/launcher/pathmatcher/MultiMatcher.h @@ -1,26 +1,21 @@ -#include "IPathMatcher.h" #include #include +#include "IPathMatcher.h" -class MultiMatcher : public IPathMatcher -{ -public: - virtual ~MultiMatcher() {}; - MultiMatcher() - { - } - MultiMatcher &add(Ptr add) +class MultiMatcher : public IPathMatcher { + public: + virtual ~MultiMatcher(){}; + MultiMatcher() {} + MultiMatcher& add(Ptr add) { m_matchers.append(add); return *this; } - virtual bool matches(const QString &string) const override + virtual bool matches(const QString& string) const override { - for(auto iter: m_matchers) - { - if(iter->matches(string)) - { + for (auto iter : m_matchers) { + if (iter->matches(string)) { return true; } } diff --git a/launcher/pathmatcher/RegexpMatcher.h b/launcher/pathmatcher/RegexpMatcher.h index 6da651ef1..a6a3e616d 100644 --- a/launcher/pathmatcher/RegexpMatcher.h +++ b/launcher/pathmatcher/RegexpMatcher.h @@ -1,36 +1,30 @@ -#include "IPathMatcher.h" #include +#include "IPathMatcher.h" -class RegexpMatcher : public IPathMatcher -{ -public: +class RegexpMatcher : public IPathMatcher { + public: virtual ~RegexpMatcher() {} - RegexpMatcher(const QString ®exp) + RegexpMatcher(const QString& regexp) { m_regexp.setPattern(regexp); m_onlyFilenamePart = !regexp.contains('/'); } - RegexpMatcher &caseSensitive(bool cs = true) + RegexpMatcher& caseSensitive(bool cs = true) { - if(cs) - { + if (cs) { m_regexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption); - } - else - { + } else { m_regexp.setPatternOptions(QRegularExpression::NoPatternOption); } return *this; } - virtual bool matches(const QString &string) const override + virtual bool matches(const QString& string) const override { - if(m_onlyFilenamePart) - { + if (m_onlyFilenamePart) { auto slash = string.lastIndexOf('/'); - if(slash != -1) - { + if (slash != -1) { auto part = string.mid(slash + 1); return m_regexp.match(part).hasMatch(); } diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp index 78bf111e7..4f087b0fd 100644 --- a/launcher/screenshots/ImgurAlbumCreation.cpp +++ b/launcher/screenshots/ImgurAlbumCreation.cpp @@ -36,15 +36,15 @@ #include "ImgurAlbumCreation.h" -#include +#include #include #include -#include +#include #include -#include +#include -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" ImgurAlbumCreation::ImgurAlbumCreation(QList screenshots) : NetAction(), m_screenshots(screenshots) { @@ -62,19 +62,18 @@ void ImgurAlbumCreation::executeTask() request.setRawHeader("Accept", "application/json"); QStringList hashes; - for (auto shot : m_screenshots) - { + for (auto shot : m_screenshots) { hashes.append(shot->m_imgurDeleteHash); } const QByteArray data = "deletehashes=" + hashes.join(',').toUtf8() + "&title=Minecraft%20Screenshots&privacy=hidden"; - QNetworkReply *rep = APPLICATION->network()->post(request, data); + QNetworkReply* rep = APPLICATION->network()->post(request, data); m_reply.reset(rep); connect(rep, &QNetworkReply::uploadProgress, this, &ImgurAlbumCreation::downloadProgress); connect(rep, &QNetworkReply::finished, this, &ImgurAlbumCreation::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(rep, &QNetworkReply::errorOccurred, this, &ImgurAlbumCreation::downloadError); #else connect(rep, QOverload::of(&QNetworkReply::error), this, &ImgurAlbumCreation::downloadError); @@ -90,21 +89,18 @@ void ImgurAlbumCreation::downloadError([[maybe_unused]] QNetworkReply::NetworkEr void ImgurAlbumCreation::downloadFinished() { - if (m_state != State::Failed) - { + if (m_state != State::Failed) { QByteArray data = m_reply->readAll(); m_reply.reset(); QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if (jsonError.error != QJsonParseError::NoError) - { + if (jsonError.error != QJsonParseError::NoError) { qDebug() << jsonError.errorString(); emitFailed(); return; } auto object = doc.object(); - if (!object.value("success").toBool()) - { + if (!object.value("success").toBool()) { qDebug() << doc.toJson(); emitFailed(); return; @@ -114,9 +110,7 @@ void ImgurAlbumCreation::downloadFinished() m_state = State::Succeeded; emit succeeded(); return; - } - else - { + } else { qDebug() << m_reply->readAll(); m_reply.reset(); emitFailed(); diff --git a/launcher/screenshots/ImgurAlbumCreation.h b/launcher/screenshots/ImgurAlbumCreation.h index a2b70d8b0..d47bcaa74 100644 --- a/launcher/screenshots/ImgurAlbumCreation.h +++ b/launcher/screenshots/ImgurAlbumCreation.h @@ -35,42 +35,33 @@ #pragma once -#include "net/NetAction.h" #include "Screenshot.h" +#include "net/NetAction.h" typedef shared_qobject_ptr ImgurAlbumCreationPtr; -class ImgurAlbumCreation : public NetAction -{ -public: +class ImgurAlbumCreation : public NetAction { + public: explicit ImgurAlbumCreation(QList screenshots); static ImgurAlbumCreationPtr make(QList screenshots) { return ImgurAlbumCreationPtr(new ImgurAlbumCreation(screenshots)); } - QString deleteHash() const - { - return m_deleteHash; - } - QString id() const - { - return m_id; - } + QString deleteHash() const { return m_deleteHash; } + QString id() const { return m_id; } - void init() override {}; + void init() override{}; -protected -slots: + protected slots: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; void downloadError(QNetworkReply::NetworkError error) override; void downloadFinished() override; void downloadReadyRead() override {} -public -slots: + public slots: void executeTask() override; -private: + private: QList m_screenshots; QString m_deleteHash; diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index 4f7587672..2d8c0db8c 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -35,17 +35,17 @@ */ #include "ImgurUpload.h" -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" -#include +#include +#include #include +#include #include #include -#include -#include +#include #include -#include ImgurUpload::ImgurUpload(ScreenShot::Ptr shot) : NetAction(), m_shot(shot) { @@ -63,13 +63,12 @@ void ImgurUpload::executeTask() request.setRawHeader("Accept", "application/json"); QFile f(m_shot->m_file.absoluteFilePath()); - if (!f.open(QFile::ReadOnly)) - { + if (!f.open(QFile::ReadOnly)) { emitFailed(); return; } - QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart filePart; filePart.setBody(f.readAll().toBase64()); filePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png"); @@ -84,12 +83,12 @@ void ImgurUpload::executeTask() namePart.setBody(m_shot->m_file.baseName().toUtf8()); multipart->append(namePart); - QNetworkReply *rep = m_network->post(request, multipart); + QNetworkReply* rep = m_network->post(request, multipart); m_reply.reset(rep); connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress); connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(rep, &QNetworkReply::errorOccurred, this, &ImgurUpload::downloadError); #else connect(rep, QOverload::of(&QNetworkReply::error), this, &ImgurUpload::downloadError); @@ -100,8 +99,7 @@ void ImgurUpload::executeTask() void ImgurUpload::downloadError([[maybe_unused]] QNetworkReply::NetworkError error) { qCritical() << "ImgurUpload failed with error" << m_reply->errorString() << "Server reply:\n" << m_reply->readAll(); - if(finished) - { + if (finished) { qCritical() << "Double finished ImgurUpload!"; return; } @@ -113,8 +111,7 @@ void ImgurUpload::downloadError([[maybe_unused]] QNetworkReply::NetworkError err void ImgurUpload::downloadFinished() { - if(finished) - { + if (finished) { qCritical() << "Double finished ImgurUpload!"; return; } @@ -122,8 +119,7 @@ void ImgurUpload::downloadFinished() m_reply.reset(); QJsonParseError jsonError; QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); - if (jsonError.error != QJsonParseError::NoError) - { + if (jsonError.error != QJsonParseError::NoError) { qDebug() << "imgur server did not reply with JSON" << jsonError.errorString(); finished = true; m_reply.reset(); @@ -131,8 +127,7 @@ void ImgurUpload::downloadFinished() return; } auto object = doc.object(); - if (!object.value("success").toBool()) - { + if (!object.value("success").toBool()) { qDebug() << "Screenshot upload not successful:" << doc.toJson(); finished = true; m_reply.reset(); diff --git a/launcher/screenshots/ImgurUpload.h b/launcher/screenshots/ImgurUpload.h index e8a6d8d70..14994d64e 100644 --- a/launcher/screenshots/ImgurUpload.h +++ b/launcher/screenshots/ImgurUpload.h @@ -35,31 +35,27 @@ #pragma once -#include "net/NetAction.h" #include "Screenshot.h" +#include "net/NetAction.h" class ImgurUpload : public NetAction { -public: + public: using Ptr = shared_qobject_ptr; explicit ImgurUpload(ScreenShot::Ptr shot); - static Ptr make(ScreenShot::Ptr shot) { - return Ptr(new ImgurUpload(shot)); - } - void init() override {}; + static Ptr make(ScreenShot::Ptr shot) { return Ptr(new ImgurUpload(shot)); } + void init() override{}; -protected -slots: + protected slots: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; void downloadError(QNetworkReply::NetworkError error) override; void downloadFinished() override; void downloadReadyRead() override {} -public -slots: + public slots: void executeTask() override; -private: + private: ScreenShot::Ptr m_shot; bool finished = true; }; diff --git a/launcher/screenshots/Screenshot.h b/launcher/screenshots/Screenshot.h index ca45aabff..767f39061 100644 --- a/launcher/screenshots/Screenshot.h +++ b/launcher/screenshots/Screenshot.h @@ -1,16 +1,14 @@ #pragma once #include -#include #include +#include #include struct ScreenShot { using Ptr = std::shared_ptr; - ScreenShot(QFileInfo file) { - m_file = file; - } + ScreenShot(QFileInfo file) { m_file = file; } QFileInfo m_file; QString m_url; QString m_imgurId; diff --git a/launcher/settings/INIFile.h b/launcher/settings/INIFile.h index 4ee543cf1..c15578f6d 100644 --- a/launcher/settings/INIFile.h +++ b/launcher/settings/INIFile.h @@ -36,17 +36,16 @@ #pragma once +#include #include #include -#include -#include #include +#include // Sectionless INI parser (for instance config files) -class INIFile : public QMap -{ -public: +class INIFile : public QMap { + public: explicit INIFile(); bool loadFile(QString fileName); diff --git a/launcher/settings/INISettingsObject.cpp b/launcher/settings/INISettingsObject.cpp index da962ee97..519b8193e 100644 --- a/launcher/settings/INISettingsObject.cpp +++ b/launcher/settings/INISettingsObject.cpp @@ -19,8 +19,7 @@ #include #include -INISettingsObject::INISettingsObject(QStringList paths, QObject *parent) - : SettingsObject(parent) +INISettingsObject::INISettingsObject(QStringList paths, QObject* parent) : SettingsObject(parent) { auto first_path = paths.constFirst(); for (auto path : paths) { @@ -39,14 +38,13 @@ INISettingsObject::INISettingsObject(QStringList paths, QObject *parent) m_ini.loadFile(first_path); } -INISettingsObject::INISettingsObject(QString path, QObject* parent) - : SettingsObject(parent) +INISettingsObject::INISettingsObject(QString path, QObject* parent) : SettingsObject(parent) { m_filePath = path; m_ini.loadFile(path); } -void INISettingsObject::setFilePath(const QString &filePath) +void INISettingsObject::setFilePath(const QString& filePath) { m_filePath = filePath; } @@ -64,28 +62,24 @@ void INISettingsObject::suspendSave() void INISettingsObject::resumeSave() { m_suspendSave = false; - if(m_doSave) - { + if (m_doSave) { m_ini.saveFile(m_filePath); } } -void INISettingsObject::changeSetting(const Setting &setting, QVariant value) +void INISettingsObject::changeSetting(const Setting& setting, QVariant value) { - if (contains(setting.id())) - { + if (contains(setting.id())) { // valid value -> set the main config, remove all the sysnonyms - if (value.isValid()) - { + if (value.isValid()) { auto list = setting.configKeys(); m_ini.set(list.takeFirst(), value); - for(auto iter: list) + for (auto iter : list) m_ini.remove(iter); } // invalid -> remove all (just like resetSetting) - else - { - for(auto iter: setting.configKeys()) + else { + for (auto iter : setting.configKeys()) m_ini.remove(iter); } doSave(); @@ -94,35 +88,29 @@ void INISettingsObject::changeSetting(const Setting &setting, QVariant value) void INISettingsObject::doSave() { - if(m_suspendSave) - { + if (m_suspendSave) { m_doSave = true; - } - else - { + } else { m_ini.saveFile(m_filePath); } } -void INISettingsObject::resetSetting(const Setting &setting) +void INISettingsObject::resetSetting(const Setting& setting) { // if we have the setting, remove all the synonyms. ALL OF THEM - if (contains(setting.id())) - { - for(auto iter: setting.configKeys()) + if (contains(setting.id())) { + for (auto iter : setting.configKeys()) m_ini.remove(iter); doSave(); } } -QVariant INISettingsObject::retrieveValue(const Setting &setting) +QVariant INISettingsObject::retrieveValue(const Setting& setting) { // if we have the setting, return value of the first matching synonym - if (contains(setting.id())) - { - for(auto iter: setting.configKeys()) - { - if(m_ini.contains(iter)) + if (contains(setting.id())) { + for (auto iter : setting.configKeys()) { + if (m_ini.contains(iter)) return m_ini[iter]; } } diff --git a/launcher/settings/INISettingsObject.h b/launcher/settings/INISettingsObject.h index d2f448a9c..4cc808580 100644 --- a/launcher/settings/INISettingsObject.h +++ b/launcher/settings/INISettingsObject.h @@ -24,44 +24,40 @@ /*! * \brief A settings object that stores its settings in an INIFile. */ -class INISettingsObject : public SettingsObject -{ +class INISettingsObject : public SettingsObject { Q_OBJECT -public: + public: /** 'paths' is a list of INI files to try, in order, for fallback support. */ explicit INISettingsObject(QStringList paths, QObject* parent = nullptr); - explicit INISettingsObject(QString path, QObject* parent = nullptr); + explicit INISettingsObject(QString path, QObject* parent = nullptr); /*! * \brief Gets the path to the INI file. * \return The path to the INI file. */ - virtual QString filePath() const - { - return m_filePath; - } + virtual QString filePath() const { return m_filePath; } /*! * \brief Sets the path to the INI file and reloads it. * \param filePath The INI file's new path. */ - virtual void setFilePath(const QString &filePath); + virtual void setFilePath(const QString& filePath); bool reload() override; void suspendSave() override; void resumeSave() override; -protected slots: - virtual void changeSetting(const Setting &setting, QVariant value) override; - virtual void resetSetting(const Setting &setting) override; + protected slots: + virtual void changeSetting(const Setting& setting, QVariant value) override; + virtual void resetSetting(const Setting& setting) override; -protected: - virtual QVariant retrieveValue(const Setting &setting) override; + protected: + virtual QVariant retrieveValue(const Setting& setting) override; void doSave(); -protected: + protected: INIFile m_ini; QString m_filePath; }; diff --git a/launcher/settings/OverrideSetting.cpp b/launcher/settings/OverrideSetting.cpp index 4396a3817..fee65b8db 100644 --- a/launcher/settings/OverrideSetting.cpp +++ b/launcher/settings/OverrideSetting.cpp @@ -15,8 +15,7 @@ #include "OverrideSetting.h" -OverrideSetting::OverrideSetting(std::shared_ptr other, std::shared_ptr gate) - : Setting(other->configKeys(), QVariant()) +OverrideSetting::OverrideSetting(std::shared_ptr other, std::shared_ptr gate) : Setting(other->configKeys(), QVariant()) { Q_ASSERT(other); Q_ASSERT(gate); @@ -36,8 +35,7 @@ QVariant OverrideSetting::defValue() const QVariant OverrideSetting::get() const { - if(isOverriding()) - { + if (isOverriding()) { return Setting::get(); } return m_other->get(); diff --git a/launcher/settings/OverrideSetting.h b/launcher/settings/OverrideSetting.h index 9f0c98b52..faa3e7948 100644 --- a/launcher/settings/OverrideSetting.h +++ b/launcher/settings/OverrideSetting.h @@ -26,21 +26,20 @@ * The other setting can be (and usually is) a part of a different SettingsObject * than this one. */ -class OverrideSetting : public Setting -{ +class OverrideSetting : public Setting { Q_OBJECT -public: + public: explicit OverrideSetting(std::shared_ptr overriden, std::shared_ptr gate); virtual QVariant defValue() const; virtual QVariant get() const; - virtual void set (QVariant value); + virtual void set(QVariant value); virtual void reset(); -private: + private: bool isOverriding() const; -protected: + protected: std::shared_ptr m_other; std::shared_ptr m_gate; }; diff --git a/launcher/settings/PassthroughSetting.cpp b/launcher/settings/PassthroughSetting.cpp index 8f93b2519..86bb861e4 100644 --- a/launcher/settings/PassthroughSetting.cpp +++ b/launcher/settings/PassthroughSetting.cpp @@ -25,8 +25,7 @@ PassthroughSetting::PassthroughSetting(std::shared_ptr other, std::shar bool PassthroughSetting::isOverriding() const { - if(!m_gate) - { + if (!m_gate) { return false; } return m_gate->get().toBool(); @@ -34,8 +33,7 @@ bool PassthroughSetting::isOverriding() const QVariant PassthroughSetting::defValue() const { - if(isOverriding()) - { + if (isOverriding()) { return m_other->get(); } return m_other->defValue(); @@ -43,8 +41,7 @@ QVariant PassthroughSetting::defValue() const QVariant PassthroughSetting::get() const { - if(isOverriding()) - { + if (isOverriding()) { return Setting::get(); } return m_other->get(); @@ -52,8 +49,7 @@ QVariant PassthroughSetting::get() const void PassthroughSetting::reset() { - if(isOverriding()) - { + if (isOverriding()) { Setting::reset(); } m_other->reset(); @@ -61,8 +57,7 @@ void PassthroughSetting::reset() void PassthroughSetting::set(QVariant value) { - if(isOverriding()) - { + if (isOverriding()) { Setting::set(value); } m_other->set(value); diff --git a/launcher/settings/PassthroughSetting.h b/launcher/settings/PassthroughSetting.h index 22008f83d..c776ca951 100644 --- a/launcher/settings/PassthroughSetting.h +++ b/launcher/settings/PassthroughSetting.h @@ -25,21 +25,20 @@ * If 'gate' evaluates to true, the override stores and returns data * If 'gate' evaluates to false, the original does, */ -class PassthroughSetting : public Setting -{ +class PassthroughSetting : public Setting { Q_OBJECT -public: + public: explicit PassthroughSetting(std::shared_ptr overriden, std::shared_ptr gate); virtual QVariant defValue() const; virtual QVariant get() const; - virtual void set (QVariant value); + virtual void set(QVariant value); virtual void reset(); -private: + private: bool isOverriding() const; -protected: + protected: std::shared_ptr m_other; std::shared_ptr m_gate; }; diff --git a/launcher/settings/Setting.cpp b/launcher/settings/Setting.cpp index cfe5a7f92..1e861e36b 100644 --- a/launcher/settings/Setting.cpp +++ b/launcher/settings/Setting.cpp @@ -16,20 +16,14 @@ #include "Setting.h" #include "settings/SettingsObject.h" -Setting::Setting(QStringList synonyms, QVariant defVal) - : QObject(), m_synonyms(synonyms), m_defVal(defVal) -{ -} +Setting::Setting(QStringList synonyms, QVariant defVal) : QObject(), m_synonyms(synonyms), m_defVal(defVal) {} QVariant Setting::get() const { - SettingsObject *sbase = m_storage; - if (!sbase) - { + SettingsObject* sbase = m_storage; + if (!sbase) { return defValue(); - } - else - { + } else { QVariant test = sbase->retrieveValue(*this); if (!test.isValid()) return defValue(); diff --git a/launcher/settings/Setting.h b/launcher/settings/Setting.h index 86007c13d..44b350379 100644 --- a/launcher/settings/Setting.h +++ b/launcher/settings/Setting.h @@ -16,8 +16,8 @@ #pragma once #include -#include #include +#include #include class SettingsObject; @@ -25,10 +25,9 @@ class SettingsObject; /*! * */ -class Setting : public QObject -{ +class Setting : public QObject { Q_OBJECT -public: + public: /** * Construct a Setting * @@ -47,10 +46,7 @@ public: * undefined behavior. * \return The ID of the setting. */ - virtual QString id() const - { - return m_synonyms.first(); - } + virtual QString id() const { return m_synonyms.first(); } /*! * \brief Gets this setting's config file key. @@ -58,10 +54,7 @@ public: * the same as the setting's ID, but it can be different. * \return The setting's config file key. */ - virtual QStringList configKeys() const - { - return m_synonyms; - } + virtual QStringList configKeys() const { return m_synonyms; } /*! * \brief Gets this setting's value as a QVariant. @@ -78,22 +71,21 @@ public: */ virtual QVariant defValue() const; -signals: + signals: /*! * \brief Signal emitted when this Setting object's value changes. * \param setting A reference to the Setting that changed. * \param value This Setting object's new value. */ - void SettingChanged(const Setting &setting, QVariant value); + void SettingChanged(const Setting& setting, QVariant value); /*! * \brief Signal emitted when this Setting object's value resets to default. * \param setting A reference to the Setting that changed. */ - void settingReset(const Setting &setting); + void settingReset(const Setting& setting); -public -slots: + public slots: /*! * \brief Changes the setting's value. * This is done by emitting the SettingChanged() signal which will then be @@ -109,10 +101,9 @@ slots: */ virtual void reset(); -protected: + protected: friend class SettingsObject; - SettingsObject * m_storage; + SettingsObject* m_storage; QStringList m_synonyms; QVariant m_defVal; }; - diff --git a/launcher/settings/SettingsObject.cpp b/launcher/settings/SettingsObject.cpp index 634acd341..1e5dce251 100644 --- a/launcher/settings/SettingsObject.cpp +++ b/launcher/settings/SettingsObject.cpp @@ -14,30 +14,25 @@ */ #include "settings/SettingsObject.h" -#include "settings/Setting.h" -#include "settings/OverrideSetting.h" -#include "PassthroughSetting.h" #include +#include "PassthroughSetting.h" +#include "settings/OverrideSetting.h" +#include "settings/Setting.h" #include -SettingsObject::SettingsObject(QObject *parent) : QObject(parent) -{ -} +SettingsObject::SettingsObject(QObject* parent) : QObject(parent) {} SettingsObject::~SettingsObject() { m_settings.clear(); } -std::shared_ptr SettingsObject::registerOverride(std::shared_ptr original, - std::shared_ptr gate) +std::shared_ptr SettingsObject::registerOverride(std::shared_ptr original, std::shared_ptr gate) { - if (contains(original->id())) - { - qCritical() << QString("Failed to register setting %1. ID already exists.") - .arg(original->id()); - return nullptr; // Fail + if (contains(original->id())) { + qCritical() << QString("Failed to register setting %1. ID already exists.").arg(original->id()); + return nullptr; // Fail } auto override = std::make_shared(original, gate); override->m_storage = this; @@ -46,14 +41,11 @@ std::shared_ptr SettingsObject::registerOverride(std::shared_ptr SettingsObject::registerPassthrough(std::shared_ptr original, - std::shared_ptr gate) +std::shared_ptr SettingsObject::registerPassthrough(std::shared_ptr original, std::shared_ptr gate) { - if (contains(original->id())) - { - qCritical() << QString("Failed to register setting %1. ID already exists.") - .arg(original->id()); - return nullptr; // Fail + if (contains(original->id())) { + qCritical() << QString("Failed to register setting %1. ID already exists.").arg(original->id()); + return nullptr; // Fail } auto passthrough = std::make_shared(original, gate); passthrough->m_storage = this; @@ -66,11 +58,9 @@ std::shared_ptr SettingsObject::registerSetting(QStringList synonyms, Q { if (synonyms.empty()) return nullptr; - if (contains(synonyms.first())) - { - qCritical() << QString("Failed to register setting %1. ID already exists.") - .arg(synonyms.first()); - return nullptr; // Fail + if (contains(synonyms.first())) { + qCritical() << QString("Failed to register setting %1. ID already exists.").arg(synonyms.first()); + return nullptr; // Fail } auto setting = std::make_shared(synonyms, defVal); setting->m_storage = this; @@ -79,7 +69,7 @@ std::shared_ptr SettingsObject::registerSetting(QStringList synonyms, Q return setting; } -std::shared_ptr SettingsObject::getSetting(const QString &id) const +std::shared_ptr SettingsObject::getSetting(const QString& id) const { // Make sure there is a setting with the given ID. if (!m_settings.contains(id)) @@ -88,54 +78,49 @@ std::shared_ptr SettingsObject::getSetting(const QString &id) const return m_settings[id]; } -QVariant SettingsObject::get(const QString &id) const +QVariant SettingsObject::get(const QString& id) const { auto setting = getSetting(id); return (setting ? setting->get() : QVariant()); } -bool SettingsObject::set(const QString &id, QVariant value) +bool SettingsObject::set(const QString& id, QVariant value) { auto setting = getSetting(id); - if (!setting) - { + if (!setting) { qCritical() << QString("Error changing setting %1. Setting doesn't exist.").arg(id); return false; - } - else - { + } else { setting->set(value); return true; } } -void SettingsObject::reset(const QString &id) const +void SettingsObject::reset(const QString& id) const { auto setting = getSetting(id); if (setting) setting->reset(); } -bool SettingsObject::contains(const QString &id) +bool SettingsObject::contains(const QString& id) { return m_settings.contains(id); } bool SettingsObject::reload() { - for (auto setting : m_settings.values()) - { + for (auto setting : m_settings.values()) { setting->set(setting->get()); } return true; } -void SettingsObject::connectSignals(const Setting &setting) +void SettingsObject::connectSignals(const Setting& setting) { connect(&setting, &Setting::SettingChanged, this, &SettingsObject::changeSetting); - connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)), this, - SIGNAL(SettingChanged(const Setting &, QVariant))); + connect(&setting, SIGNAL(SettingChanged(const Setting&, QVariant)), this, SIGNAL(SettingChanged(const Setting&, QVariant))); connect(&setting, &Setting::settingReset, this, &SettingsObject::resetSetting); - connect(&setting, SIGNAL(settingReset(Setting)), this, SIGNAL(settingReset(const Setting &))); + connect(&setting, SIGNAL(settingReset(Setting)), this, SIGNAL(settingReset(const Setting&))); } diff --git a/launcher/settings/SettingsObject.h b/launcher/settings/SettingsObject.h index 4d735511c..75631f247 100644 --- a/launcher/settings/SettingsObject.h +++ b/launcher/settings/SettingsObject.h @@ -15,12 +15,12 @@ #pragma once -#include +#include +#include #include +#include #include #include -#include -#include #include class Setting; @@ -41,27 +41,20 @@ typedef std::weak_ptr SettingsObjectWeakPtr; * * \sa Setting */ -class SettingsObject : public QObject -{ +class SettingsObject : public QObject { Q_OBJECT -public: - class Lock - { - public: - Lock(SettingsObjectPtr locked) - :m_locked(locked) - { - m_locked->suspendSave(); - } - ~Lock() - { - m_locked->resumeSave(); - } - private: + public: + class Lock { + public: + Lock(SettingsObjectPtr locked) : m_locked(locked) { m_locked->suspendSave(); } + ~Lock() { m_locked->resumeSave(); } + + private: SettingsObjectPtr m_locked; }; -public: - explicit SettingsObject(QObject *parent = 0); + + public: + explicit SettingsObject(QObject* parent = 0); virtual ~SettingsObject(); /*! * Registers an override setting for the given original setting in this settings object @@ -90,8 +83,7 @@ public: * the one that is being registered. * \return A valid Setting shared pointer if successful. */ - std::shared_ptr registerSetting(QStringList synonyms, - QVariant defVal = QVariant()); + std::shared_ptr registerSetting(QStringList synonyms, QVariant defVal = QVariant()); /*! * Registers the given setting with this SettingsObject and connects the necessary signals. @@ -100,10 +92,7 @@ public: * the one that is being registered. * \return A valid Setting shared pointer if successful. */ - std::shared_ptr registerSetting(QString id, QVariant defVal = QVariant()) - { - return registerSetting(QStringList(id), defVal); - } + std::shared_ptr registerSetting(QString id, QVariant defVal = QVariant()) { return registerSetting(QStringList(id), defVal); } /*! * \brief Gets the setting with the given ID. @@ -112,7 +101,7 @@ public: * Returns null if there is no setting with the given ID. * \sa operator []() */ - std::shared_ptr getSetting(const QString &id) const; + std::shared_ptr getSetting(const QString& id) const; /*! * \brief Gets the value of the setting with the given ID. @@ -120,7 +109,7 @@ public: * \return The setting's value as a QVariant. * If no setting with the given ID exists, returns an invalid QVariant. */ - QVariant get(const QString &id) const; + QVariant get(const QString& id) const; /*! * \brief Sets the value of the setting with the given ID. @@ -129,20 +118,20 @@ public: * \param value The new value of the setting. * \return True if successful, false if it failed. */ - bool set(const QString &id, QVariant value); + bool set(const QString& id, QVariant value); /*! * \brief Reverts the setting with the given ID to default. * \param id The ID of the setting to reset. */ - void reset(const QString &id) const; + void reset(const QString& id) const; /*! * \brief Checks if this SettingsObject contains a setting with the given ID. * \param id The ID to check for. * \return True if the SettingsObject has a setting with the given ID. */ - bool contains(const QString &id); + bool contains(const QString& id); /*! * \brief Reloads the settings and emit signals for changed settings @@ -152,7 +141,7 @@ public: virtual void suspendSave() = 0; virtual void resumeSave() = 0; -signals: + signals: /*! * \brief Signal emitted when one of this SettingsObject object's settings changes. * This is usually just connected directly to each Setting object's @@ -160,7 +149,7 @@ signals: * \param setting A reference to the Setting object that changed. * \param value The Setting object's new value. */ - void SettingChanged(const Setting &setting, QVariant value); + void SettingChanged(const Setting& setting, QVariant value); /*! * \brief Signal emitted when one of this SettingsObject object's settings resets. @@ -168,10 +157,9 @@ signals: * settingReset() signals. * \param setting A reference to the Setting object that changed. */ - void settingReset(const Setting &setting); + void settingReset(const Setting& setting); -protected -slots: + protected slots: /*! * \brief Changes a setting. * This slot is usually connected to each Setting object's @@ -180,7 +168,7 @@ slots: * \param setting A reference to the Setting object that changed. * \param value The setting's new value. */ - virtual void changeSetting(const Setting &setting, QVariant value) = 0; + virtual void changeSetting(const Setting& setting, QVariant value) = 0; /*! * \brief Resets a setting. @@ -189,27 +177,28 @@ slots: * to update the setting's value in the config file. * \param setting A reference to the Setting object that changed. */ - virtual void resetSetting(const Setting &setting) = 0; + virtual void resetSetting(const Setting& setting) = 0; -protected: + protected: /*! * \brief Connects the necessary signals to the given Setting. * \param setting The setting to connect. */ - void connectSignals(const Setting &setting); + void connectSignals(const Setting& setting); /*! * \brief Function used by Setting objects to get their values from the SettingsObject. * \param setting The * \return */ - virtual QVariant retrieveValue(const Setting &setting) = 0; + virtual QVariant retrieveValue(const Setting& setting) = 0; friend class Setting; -private: + private: QMap> m_settings; -protected: + + protected: bool m_suspendSave = false; bool m_doSave = false; }; diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index 0f835369a..6a916ff03 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -194,7 +194,7 @@ void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg) auto task_progress = m_task_progress.value(task->getUid()); task_progress->status = msg; task_progress->state = TaskStepState::Running; - + emit stepProgress(*task_progress); if (totalSize() == 1) { @@ -207,7 +207,7 @@ void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg) auto task_progress = m_task_progress.value(task->getUid()); task_progress->details = msg; task_progress->state = TaskStepState::Running; - + emit stepProgress(*task_progress); if (totalSize() == 1) { @@ -220,7 +220,7 @@ void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 tota auto task_progress = m_task_progress.value(task->getUid()); task_progress->update(current, total); - + emit stepProgress(*task_progress); updateStepProgress(*task_progress, Operation::CHANGED); updateState(); @@ -233,7 +233,7 @@ void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 tota void ConcurrentTask::subTaskStepProgress(Task::Ptr task, TaskStepProgress const& task_progress) { Operation op = Operation::ADDED; - + if (!m_task_progress.contains(task_progress.uid)) { m_task_progress.insert(task_progress.uid, std::make_shared(task_progress)); op = Operation::ADDED; @@ -254,12 +254,10 @@ void ConcurrentTask::subTaskStepProgress(Task::Ptr task, TaskStepProgress const& emit stepProgress(*tp.get()); updateStepProgress(*tp.get(), op); } - } void ConcurrentTask::updateStepProgress(TaskStepProgress const& changed_progress, Operation op) { - switch (op) { case Operation::ADDED: m_stepProgress += changed_progress.current; @@ -274,9 +272,8 @@ void ConcurrentTask::updateStepProgress(TaskStepProgress const& changed_progress m_stepTotalProgress -= changed_progress.old_total; m_stepProgress += changed_progress.current; m_stepTotalProgress += changed_progress.total; - break; + break; } - } void ConcurrentTask::updateState() diff --git a/launcher/tasks/ConcurrentTask.h b/launcher/tasks/ConcurrentTask.h index 481ebf852..8b696bf58 100644 --- a/launcher/tasks/ConcurrentTask.h +++ b/launcher/tasks/ConcurrentTask.h @@ -80,7 +80,7 @@ class ConcurrentTask : public Task { protected: // NOTE: This is not thread-safe. - [[nodiscard]] unsigned int totalSize() const { return static_cast(m_queue.size() + m_doing.size() + m_done.size()); } + [[nodiscard]] unsigned int totalSize() const { return static_cast(m_queue.size() + m_doing.size() + m_done.size()); } enum class Operation { ADDED, REMOVED, CHANGED }; void updateStepProgress(TaskStepProgress const& changed_progress, Operation); diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index fd82ec001..a8097ffd6 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -40,16 +40,15 @@ Q_LOGGING_CATEGORY(taskLogC, "launcher.task") -Task::Task(QObject *parent, bool show_debug) : QObject(parent), m_show_debug(show_debug) +Task::Task(QObject* parent, bool show_debug) : QObject(parent), m_show_debug(show_debug) { m_uid = QUuid::createUuid(); setAutoDelete(false); } -void Task::setStatus(const QString &new_status) +void Task::setStatus(const QString& new_status) { - if(m_status != new_status) - { + if (m_status != new_status) { m_status = new_status; emit status(m_status); } @@ -57,8 +56,7 @@ void Task::setStatus(const QString &new_status) void Task::setDetails(const QString& new_details) { - if (m_details != new_details) - { + if (m_details != new_details) { m_details = new_details; emit details(m_details); } @@ -69,41 +67,35 @@ void Task::setProgress(qint64 current, qint64 total) if ((m_progress != current) || (m_progressTotal != total)) { m_progress = current; m_progressTotal = total; - + emit progress(m_progress, m_progressTotal); - } + } } void Task::start() { - switch(m_state) - { - case State::Inactive: - { + switch (m_state) { + case State::Inactive: { if (m_show_debug) qCDebug(taskLogC) << "Task" << describe() << "starting for the first time"; break; } - case State::AbortedByUser: - { + case State::AbortedByUser: { if (m_show_debug) qCDebug(taskLogC) << "Task" << describe() << "restarting for after being aborted by user"; break; } - case State::Failed: - { + case State::Failed: { if (m_show_debug) qCDebug(taskLogC) << "Task" << describe() << "restarting for after failing at first"; break; } - case State::Succeeded: - { + case State::Succeeded: { if (m_show_debug) qCDebug(taskLogC) << "Task" << describe() << "restarting for after succeeding at first"; break; } - case State::Running: - { + case State::Running: { if (m_show_debug) qCWarning(taskLogC) << "The launcher tried to start task" << describe() << "while it was already running!"; return; @@ -118,8 +110,7 @@ void Task::start() void Task::emitFailed(QString reason) { // Don't fail twice. - if (!isRunning()) - { + if (!isRunning()) { qCCritical(taskLogC) << "Task" << describe() << "failed while not running!!!!: " << reason; return; } @@ -133,8 +124,7 @@ void Task::emitFailed(QString reason) void Task::emitAborted() { // Don't abort twice. - if (!isRunning()) - { + if (!isRunning()) { qCCritical(taskLogC) << "Task" << describe() << "aborted while not running!!!!"; return; } @@ -149,8 +139,7 @@ void Task::emitAborted() void Task::emitSucceeded() { // Don't succeed twice. - if (!isRunning()) - { + if (!isRunning()) { qCCritical(taskLogC) << "Task" << describe() << "succeeded while not running!!!!"; return; } @@ -172,12 +161,9 @@ QString Task::describe() QTextStream out(&outStr); out << metaObject()->className() << QChar('('); auto name = objectName(); - if(name.isEmpty()) - { + if (name.isEmpty()) { out << QString("0x%1").arg(reinterpret_cast(this), 0, 16); - } - else - { + } else { out << name; } out << " ID: " << m_uid.toString(QUuid::WithoutBraces); diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index 25c7f8be7..a6f039de3 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -36,25 +36,20 @@ #pragma once +#include #include #include -#include #include "QObjectPtr.h" Q_DECLARE_LOGGING_CATEGORY(taskLogC) -enum class TaskStepState { - Waiting, - Running, - Failed, - Succeeded -}; +enum class TaskStepState { Waiting, Running, Failed, Succeeded }; Q_DECLARE_METATYPE(TaskStepState) struct TaskStepProgress { - QUuid uid; + QUuid uid; qint64 current = 0; qint64 total = -1; @@ -64,15 +59,14 @@ struct TaskStepProgress { QString status = ""; QString details = ""; TaskStepState state = TaskStepState::Waiting; - - TaskStepProgress() { - this->uid = QUuid::createUuid(); - } - TaskStepProgress(QUuid uid_): uid(uid_) {} + TaskStepProgress() { this->uid = QUuid::createUuid(); } + + TaskStepProgress(QUuid uid_) : uid(uid_) {} bool isDone() const { return (state == TaskStepState::Failed) || (state == TaskStepState::Succeeded); } - void update(qint64 new_current, qint64 new_total) { + void update(qint64 new_current, qint64 new_total) + { this->old_current = this->current; this->old_total = this->total; @@ -101,8 +95,8 @@ class Task : public QObject, public QRunnable { bool isFinished() const; bool wasSuccessful() const; - /*! - * MultiStep tasks are combinations of multiple tasks into a single logical task. + /*! + * MultiStep tasks are combinations of multiple tasks into a single logical task. * The main usage of this is in SequencialTask. */ virtual auto isMultiStep() const -> bool { return false; } @@ -126,8 +120,6 @@ class Task : public QObject, public QRunnable { qint64 getTotalProgress() { return m_progressTotal; } virtual auto getStepProgress() const -> TaskStepProgressList { return {}; } - - QUuid getUid() { return m_uid; } protected: @@ -156,9 +148,18 @@ class Task : public QObject, public QRunnable { void run() override { start(); } virtual void start(); - virtual bool abort() { if(canAbort()) emitAborted(); return canAbort(); } + virtual bool abort() + { + if (canAbort()) + emitAborted(); + return canAbort(); + } - void setAbortable(bool can_abort) { m_can_abort = can_abort; emit abortStatusChanged(can_abort); } + void setAbortable(bool can_abort) + { + m_can_abort = can_abort; + emit abortStatusChanged(can_abort); + } protected: virtual void executeTask() = 0; @@ -191,5 +192,4 @@ class Task : public QObject, public QRunnable { // Change using setAbortStatus bool m_can_abort = false; QUuid m_uid; - }; diff --git a/launcher/tools/BaseExternalTool.cpp b/launcher/tools/BaseExternalTool.cpp index 38d817887..9e4b91cd8 100644 --- a/launcher/tools/BaseExternalTool.cpp +++ b/launcher/tools/BaseExternalTool.cpp @@ -1,7 +1,7 @@ #include "BaseExternalTool.h" -#include #include +#include #ifdef Q_OS_WIN #include @@ -9,33 +9,24 @@ #include "BaseInstance.h" -BaseExternalTool::BaseExternalTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent) +BaseExternalTool::BaseExternalTool(SettingsObjectPtr settings, InstancePtr instance, QObject* parent) : QObject(parent), m_instance(instance), globalSettings(settings) -{ -} +{} -BaseExternalTool::~BaseExternalTool() -{ -} +BaseExternalTool::~BaseExternalTool() {} -BaseDetachedTool::BaseDetachedTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent) +BaseDetachedTool::BaseDetachedTool(SettingsObjectPtr settings, InstancePtr instance, QObject* parent) : BaseExternalTool(settings, instance, parent) -{ - -} +{} void BaseDetachedTool::run() { runImpl(); } +BaseExternalToolFactory::~BaseExternalToolFactory() {} -BaseExternalToolFactory::~BaseExternalToolFactory() +BaseDetachedTool* BaseDetachedToolFactory::createDetachedTool(InstancePtr instance, QObject* parent) { -} - -BaseDetachedTool *BaseDetachedToolFactory::createDetachedTool(InstancePtr instance, - QObject *parent) -{ - return qobject_cast(createTool(instance, parent)); + return qobject_cast(createTool(instance, parent)); } diff --git a/launcher/tools/BaseExternalTool.h b/launcher/tools/BaseExternalTool.h index 1ebed6ae2..eb2d07e1e 100644 --- a/launcher/tools/BaseExternalTool.h +++ b/launcher/tools/BaseExternalTool.h @@ -1,58 +1,53 @@ #pragma once -#include #include +#include class BaseInstance; class SettingsObject; class QProcess; -class BaseExternalTool : public QObject -{ +class BaseExternalTool : public QObject { Q_OBJECT -public: - explicit BaseExternalTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0); + public: + explicit BaseExternalTool(SettingsObjectPtr settings, InstancePtr instance, QObject* parent = 0); virtual ~BaseExternalTool(); -protected: + protected: InstancePtr m_instance; SettingsObjectPtr globalSettings; }; -class BaseDetachedTool : public BaseExternalTool -{ +class BaseDetachedTool : public BaseExternalTool { Q_OBJECT -public: - explicit BaseDetachedTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0); + public: + explicit BaseDetachedTool(SettingsObjectPtr settings, InstancePtr instance, QObject* parent = 0); -public -slots: + public slots: void run(); -protected: + protected: virtual void runImpl() = 0; }; -class BaseExternalToolFactory -{ -public: +class BaseExternalToolFactory { + public: virtual ~BaseExternalToolFactory(); virtual QString name() const = 0; virtual void registerSettings(SettingsObjectPtr settings) = 0; - virtual BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) = 0; + virtual BaseExternalTool* createTool(InstancePtr instance, QObject* parent = 0) = 0; - virtual bool check(QString *error) = 0; - virtual bool check(const QString &path, QString *error) = 0; + virtual bool check(QString* error) = 0; + virtual bool check(const QString& path, QString* error) = 0; -protected: + protected: SettingsObjectPtr globalSettings; }; -class BaseDetachedToolFactory : public BaseExternalToolFactory -{ -public: - virtual BaseDetachedTool *createDetachedTool(InstancePtr instance, QObject *parent = 0); +class BaseDetachedToolFactory : public BaseExternalToolFactory { + public: + virtual BaseDetachedTool* createDetachedTool(InstancePtr instance, QObject* parent = 0); }; diff --git a/launcher/tools/BaseProfiler.cpp b/launcher/tools/BaseProfiler.cpp index 300d1a736..2ab1254e9 100644 --- a/launcher/tools/BaseProfiler.cpp +++ b/launcher/tools/BaseProfiler.cpp @@ -3,10 +3,8 @@ #include -BaseProfiler::BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent) - : BaseExternalTool(settings, instance, parent) -{ -} +BaseProfiler::BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject* parent) : BaseExternalTool(settings, instance, parent) +{} void BaseProfiler::beginProfiling(shared_qobject_ptr process) { @@ -20,8 +18,7 @@ void BaseProfiler::abortProfiling() void BaseProfiler::abortProfilingImpl() { - if (!m_profilerProcess) - { + if (!m_profilerProcess) { return; } m_profilerProcess->terminate(); @@ -30,7 +27,7 @@ void BaseProfiler::abortProfilingImpl() emit abortLaunch(tr("Profiler aborted")); } -BaseProfiler *BaseProfilerFactory::createProfiler(InstancePtr instance, QObject *parent) +BaseProfiler* BaseProfilerFactory::createProfiler(InstancePtr instance, QObject* parent) { - return qobject_cast(createTool(instance, parent)); + return qobject_cast(createTool(instance, parent)); } diff --git a/launcher/tools/BaseProfiler.h b/launcher/tools/BaseProfiler.h index 1c934aa35..ac0f3a786 100644 --- a/launcher/tools/BaseProfiler.h +++ b/launcher/tools/BaseProfiler.h @@ -8,30 +8,27 @@ class SettingsObject; class LaunchTask; class QProcess; -class BaseProfiler : public BaseExternalTool -{ +class BaseProfiler : public BaseExternalTool { Q_OBJECT -public: - explicit BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0); + public: + explicit BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject* parent = 0); -public -slots: + public slots: void beginProfiling(shared_qobject_ptr process); void abortProfiling(); -protected: - QProcess *m_profilerProcess; + protected: + QProcess* m_profilerProcess; virtual void beginProfilingImpl(shared_qobject_ptr process) = 0; virtual void abortProfilingImpl(); -signals: - void readyToLaunch(const QString &message); - void abortLaunch(const QString &message); + signals: + void readyToLaunch(const QString& message); + void abortLaunch(const QString& message); }; -class BaseProfilerFactory : public BaseExternalToolFactory -{ -public: - virtual BaseProfiler *createProfiler(InstancePtr instance, QObject *parent = 0); +class BaseProfilerFactory : public BaseExternalToolFactory { + public: + virtual BaseProfiler* createProfiler(InstancePtr instance, QObject* parent = 0); }; diff --git a/launcher/tools/JProfiler.cpp b/launcher/tools/JProfiler.cpp index f08ee73df..7a532a3d2 100644 --- a/launcher/tools/JProfiler.cpp +++ b/launcher/tools/JProfiler.cpp @@ -2,32 +2,27 @@ #include -#include "settings/SettingsObject.h" -#include "launch/LaunchTask.h" #include "BaseInstance.h" +#include "launch/LaunchTask.h" +#include "settings/SettingsObject.h" -class JProfiler : public BaseProfiler -{ +class JProfiler : public BaseProfiler { Q_OBJECT -public: - JProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0); + public: + JProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject* parent = 0); -private slots: + private slots: void profilerStarted(); void profilerFinished(int exit, QProcess::ExitStatus status); -protected: + protected: void beginProfilingImpl(shared_qobject_ptr process); -private: + private: int listeningPort = 0; }; -JProfiler::JProfiler(SettingsObjectPtr settings, InstancePtr instance, - QObject *parent) - : BaseProfiler(settings, instance, parent) -{ -} +JProfiler::JProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject* parent) : BaseProfiler(settings, instance, parent) {} void JProfiler::profilerStarted() { @@ -36,12 +31,10 @@ void JProfiler::profilerStarted() void JProfiler::profilerFinished([[maybe_unused]] int exit, QProcess::ExitStatus status) { - if (status == QProcess::CrashExit) - { + if (status == QProcess::CrashExit) { emit abortLaunch(tr("Profiler aborted")); } - if (m_profilerProcess) - { + if (m_profilerProcess) { m_profilerProcess->deleteLater(); m_profilerProcess = 0; } @@ -50,13 +43,8 @@ void JProfiler::profilerFinished([[maybe_unused]] int exit, QProcess::ExitStatus void JProfiler::beginProfilingImpl(shared_qobject_ptr process) { listeningPort = globalSettings->get("JProfilerPort").toInt(); - QProcess *profiler = new QProcess(this); - QStringList profilerArgs = - { - "-d", QString::number(process->pid()), - "--gui", - "-p", QString::number(listeningPort) - }; + QProcess* profiler = new QProcess(this); + QStringList profilerArgs = { "-d", QString::number(process->pid()), "--gui", "-p", QString::number(listeningPort) }; auto basePath = globalSettings->get("JProfilerPath").toString(); #ifdef Q_OS_WIN @@ -82,31 +70,28 @@ void JProfilerFactory::registerSettings(SettingsObjectPtr settings) globalSettings = settings; } -BaseExternalTool *JProfilerFactory::createTool(InstancePtr instance, QObject *parent) +BaseExternalTool* JProfilerFactory::createTool(InstancePtr instance, QObject* parent) { return new JProfiler(globalSettings, instance, parent); } -bool JProfilerFactory::check(QString *error) +bool JProfilerFactory::check(QString* error) { return check(globalSettings->get("JProfilerPath").toString(), error); } -bool JProfilerFactory::check(const QString &path, QString *error) +bool JProfilerFactory::check(const QString& path, QString* error) { - if (path.isEmpty()) - { + if (path.isEmpty()) { *error = QObject::tr("Empty path"); return false; } QDir dir(path); - if (!dir.exists()) - { + if (!dir.exists()) { *error = QObject::tr("Path does not exist"); return false; } - if (!dir.exists("bin") || !(dir.exists("bin/jprofiler") || dir.exists("bin/jprofiler.exe")) || !dir.exists("bin/agent.jar")) - { + if (!dir.exists("bin") || !(dir.exists("bin/jprofiler") || dir.exists("bin/jprofiler.exe")) || !dir.exists("bin/agent.jar")) { *error = QObject::tr("Invalid JProfiler install"); return false; } diff --git a/launcher/tools/JProfiler.h b/launcher/tools/JProfiler.h index 0e9a3a85a..55715df32 100644 --- a/launcher/tools/JProfiler.h +++ b/launcher/tools/JProfiler.h @@ -2,12 +2,11 @@ #include "BaseProfiler.h" -class JProfilerFactory : public BaseProfilerFactory -{ -public: +class JProfilerFactory : public BaseProfilerFactory { + public: QString name() const override { return "JProfiler"; } void registerSettings(SettingsObjectPtr settings) override; - BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) override; - bool check(QString *error) override; - bool check(const QString &path, QString *error) override; + BaseExternalTool* createTool(InstancePtr instance, QObject* parent = 0) override; + bool check(QString* error) override; + bool check(const QString& path, QString* error) override; }; diff --git a/launcher/tools/JVisualVM.cpp b/launcher/tools/JVisualVM.cpp index 2734f5ab8..4da4e1e54 100644 --- a/launcher/tools/JVisualVM.cpp +++ b/launcher/tools/JVisualVM.cpp @@ -3,29 +3,24 @@ #include #include -#include "settings/SettingsObject.h" -#include "launch/LaunchTask.h" #include "BaseInstance.h" +#include "launch/LaunchTask.h" +#include "settings/SettingsObject.h" -class JVisualVM : public BaseProfiler -{ +class JVisualVM : public BaseProfiler { Q_OBJECT -public: - JVisualVM(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0); + public: + JVisualVM(SettingsObjectPtr settings, InstancePtr instance, QObject* parent = 0); -private slots: + private slots: void profilerStarted(); void profilerFinished(int exit, QProcess::ExitStatus status); -protected: + protected: void beginProfilingImpl(shared_qobject_ptr process); }; - -JVisualVM::JVisualVM(SettingsObjectPtr settings, InstancePtr instance, QObject *parent) - : BaseProfiler(settings, instance, parent) -{ -} +JVisualVM::JVisualVM(SettingsObjectPtr settings, InstancePtr instance, QObject* parent) : BaseProfiler(settings, instance, parent) {} void JVisualVM::profilerStarted() { @@ -34,12 +29,10 @@ void JVisualVM::profilerStarted() void JVisualVM::profilerFinished([[maybe_unused]] int exit, QProcess::ExitStatus status) { - if (status == QProcess::CrashExit) - { + if (status == QProcess::CrashExit) { emit abortLaunch(tr("Profiler aborted")); } - if (m_profilerProcess) - { + if (m_profilerProcess) { m_profilerProcess->deleteLater(); m_profilerProcess = 0; } @@ -47,18 +40,15 @@ void JVisualVM::profilerFinished([[maybe_unused]] int exit, QProcess::ExitStatus void JVisualVM::beginProfilingImpl(shared_qobject_ptr process) { - QProcess *profiler = new QProcess(this); - QStringList profilerArgs = - { - "--openpid", QString::number(process->pid()) - }; + QProcess* profiler = new QProcess(this); + QStringList profilerArgs = { "--openpid", QString::number(process->pid()) }; auto programPath = globalSettings->get("JVisualVMPath").toString(); profiler->setArguments(profilerArgs); profiler->setProgram(programPath); connect(profiler, &QProcess::started, this, &JVisualVM::profilerStarted); - connect(profiler, QOverload::of(&QProcess::finished), this, &JVisualVM::profilerFinished); + connect(profiler, QOverload::of(&QProcess::finished), this, &JVisualVM::profilerFinished); profiler->start(); m_profilerProcess = profiler; @@ -67,34 +57,31 @@ void JVisualVM::beginProfilingImpl(shared_qobject_ptr process) void JVisualVMFactory::registerSettings(SettingsObjectPtr settings) { QString defaultValue = QStandardPaths::findExecutable("jvisualvm"); - if (defaultValue.isNull()) - { + if (defaultValue.isNull()) { defaultValue = QStandardPaths::findExecutable("visualvm"); } settings->registerSetting("JVisualVMPath", defaultValue); globalSettings = settings; } -BaseExternalTool *JVisualVMFactory::createTool(InstancePtr instance, QObject *parent) +BaseExternalTool* JVisualVMFactory::createTool(InstancePtr instance, QObject* parent) { return new JVisualVM(globalSettings, instance, parent); } -bool JVisualVMFactory::check(QString *error) +bool JVisualVMFactory::check(QString* error) { return check(globalSettings->get("JVisualVMPath").toString(), error); } -bool JVisualVMFactory::check(const QString &path, QString *error) +bool JVisualVMFactory::check(const QString& path, QString* error) { - if (path.isEmpty()) - { + if (path.isEmpty()) { *error = QObject::tr("Empty path"); return false; } QFileInfo finfo(path); - if (!finfo.isExecutable() || !finfo.fileName().contains("visualvm")) - { + if (!finfo.isExecutable() || !finfo.fileName().contains("visualvm")) { *error = QObject::tr("Invalid path to JVisualVM"); return false; } diff --git a/launcher/tools/JVisualVM.h b/launcher/tools/JVisualVM.h index ebdea9f33..2828119a1 100644 --- a/launcher/tools/JVisualVM.h +++ b/launcher/tools/JVisualVM.h @@ -2,12 +2,11 @@ #include "BaseProfiler.h" -class JVisualVMFactory : public BaseProfilerFactory -{ -public: +class JVisualVMFactory : public BaseProfilerFactory { + public: QString name() const override { return "JVisualVM"; } void registerSettings(SettingsObjectPtr settings) override; - BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) override; - bool check(QString *error) override; - bool check(const QString &path, QString *error) override; + BaseExternalTool* createTool(InstancePtr instance, QObject* parent = 0) override; + bool check(QString* error) override; + bool check(const QString& path, QString* error) override; }; diff --git a/launcher/tools/MCEditTool.cpp b/launcher/tools/MCEditTool.cpp index 2c1ec613c..19bd5a062 100644 --- a/launcher/tools/MCEditTool.cpp +++ b/launcher/tools/MCEditTool.cpp @@ -4,9 +4,9 @@ #include #include -#include "settings/SettingsObject.h" #include "BaseInstance.h" #include "minecraft/MinecraftInstance.h" +#include "settings/SettingsObject.h" MCEditTool::MCEditTool(SettingsObjectPtr settings) { @@ -26,19 +26,17 @@ QString MCEditTool::path() const bool MCEditTool::check(const QString& toolPath, QString& error) { - if (toolPath.isEmpty()) - { + if (toolPath.isEmpty()) { error = QObject::tr("Path is empty"); return false; } const QDir dir(toolPath); - if (!dir.exists()) - { + if (!dir.exists()) { error = QObject::tr("Path does not exist"); return false; } - if (!dir.exists("mcedit.sh") && !dir.exists("mcedit.py") && !dir.exists("mcedit.exe") && !dir.exists("Contents") && !dir.exists("mcedit2.exe")) - { + if (!dir.exists("mcedit.sh") && !dir.exists("mcedit.py") && !dir.exists("mcedit.exe") && !dir.exists("Contents") && + !dir.exists("mcedit2.exe")) { error = QObject::tr("Path does not seem to be a MCEdit path"); return false; } @@ -53,22 +51,16 @@ QString MCEditTool::getProgramPath() const QString mceditPath = path(); QDir mceditDir(mceditPath); #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - if (mceditDir.exists("mcedit.sh")) - { + if (mceditDir.exists("mcedit.sh")) { return mceditDir.absoluteFilePath("mcedit.sh"); - } - else if (mceditDir.exists("mcedit.py")) - { + } else if (mceditDir.exists("mcedit.py")) { return mceditDir.absoluteFilePath("mcedit.py"); } return QString(); #elif defined(Q_OS_WIN32) - if (mceditDir.exists("mcedit.exe")) - { + if (mceditDir.exists("mcedit.exe")) { return mceditDir.absoluteFilePath("mcedit.exe"); - } - else if (mceditDir.exists("mcedit2.exe")) - { + } else if (mceditDir.exists("mcedit2.exe")) { return mceditDir.absoluteFilePath("mcedit2.exe"); } return QString(); diff --git a/launcher/tools/MCEditTool.h b/launcher/tools/MCEditTool.h index 733dff866..fd2de1b6d 100644 --- a/launcher/tools/MCEditTool.h +++ b/launcher/tools/MCEditTool.h @@ -3,14 +3,14 @@ #include #include "settings/SettingsObject.h" -class MCEditTool -{ -public: +class MCEditTool { + public: MCEditTool(SettingsObjectPtr settings); - void setPath(QString & path); + void setPath(QString& path); QString path() const; - bool check(const QString &toolPath, QString &error); + bool check(const QString& toolPath, QString& error); QString getProgramPath(); -private: + + private: SettingsObjectPtr m_settings; }; diff --git a/launcher/translations/POTranslator.cpp b/launcher/translations/POTranslator.cpp index 910a7f2c7..51ef4852b 100644 --- a/launcher/translations/POTranslator.cpp +++ b/launcher/translations/POTranslator.cpp @@ -3,14 +3,12 @@ #include #include "FileSystem.h" -struct POEntry -{ +struct POEntry { QString text; bool fuzzy; }; -struct POTranslatorPrivate -{ +struct POTranslatorPrivate { QString filename; QHash mapping; QHash mapping_disambiguatrion; @@ -19,47 +17,37 @@ struct POTranslatorPrivate void reload(); }; -class ParserArray : public QByteArray -{ -public: - ParserArray(const QByteArray &in) : QByteArray(in) +class ParserArray : public QByteArray { + public: + ParserArray(const QByteArray& in) : QByteArray(in) {} + bool chomp(const char* data, int length) { - } - bool chomp(const char * data, int length) - { - if(startsWith(data)) - { + if (startsWith(data)) { remove(0, length); return true; } return false; } - bool chompString(QByteArray & appendHere) + bool chompString(QByteArray& appendHere) { QByteArray msg; bool escape = false; - if(size() < 2) - { + if (size() < 2) { qDebug() << "String fragment is too short"; return false; } - if(!startsWith('"')) - { + if (!startsWith('"')) { qDebug() << "String fragment does not start with \""; return false; } - if(!endsWith('"')) - { + if (!endsWith('"')) { qDebug() << "String fragment does not end with \", instead, there is" << at(size() - 1); return false; } - for(int i = 1; i < size() - 1; i++) - { + for (int i = 1; i < size() - 1; i++) { char c = operator[](i); - if(escape) - { - switch(c) - { + if (escape) { + switch (c) { case 'r': msg += '\r'; break; @@ -94,14 +82,11 @@ public: case '4': case '5': case '6': - case '7': - { + case '7': { int octal_start = i; - while ((c = operator[](i)) >= '0' && c <= '7') - { + while ((c = operator[](i)) >= '0' && c <= '7') { i++; - if (i == length() - 1) - { + if (i == length() - 1) { qDebug() << "Something went bad while parsing an octal escape string..."; return false; } @@ -109,16 +94,13 @@ public: msg += mid(octal_start, i - octal_start).toUInt(0, 8); break; } - case 'x': - { + case 'x': { // chomp the 'x' i++; int hex_start = i; - while (isxdigit(operator[](i))) - { + while (isxdigit(operator[](i))) { i++; - if (i == length() - 1) - { + if (i == length() - 1) { qDebug() << "Something went bad while parsing a hex escape string..."; return false; } @@ -126,25 +108,19 @@ public: msg += mid(hex_start, i - hex_start).toUInt(0, 16); break; } - default: - { + default: { qDebug() << "Invalid escape sequence character:" << c; return false; } } escape = false; - } - else if(c == '\\') - { + } else if (c == '\\') { escape = true; - } - else - { + } else { msg += c; } } - if(escape) - { + if (escape) { qDebug() << "Unterminated escape sequence..."; return false; } @@ -156,8 +132,7 @@ public: void POTranslatorPrivate::reload() { QFile file(filename); - if(!file.open(QFile::OpenMode::enum_type::ReadOnly | QFile::OpenMode::enum_type::Text)) - { + if (!file.open(QFile::OpenMode::enum_type::ReadOnly | QFile::OpenMode::enum_type::Text)) { qDebug() << "Failed to open PO file:" << filename; return; } @@ -169,13 +144,7 @@ void POTranslatorPrivate::reload() bool fuzzy = false; bool nextFuzzy = false; - enum class Mode - { - First, - MessageContext, - MessageId, - MessageString - } mode = Mode::First; + enum class Mode { First, MessageContext, MessageId, MessageString } mode = Mode::First; int lineNumber = 0; QHash newMapping; @@ -183,14 +152,12 @@ void POTranslatorPrivate::reload() auto endEntry = [&]() { auto strStr = QString::fromUtf8(str); // NOTE: PO header has empty id. We skip it. - if(!id.isEmpty()) - { + if (!id.isEmpty()) { auto normalKey = context + "|" + id; - newMapping.insert(normalKey, {strStr, fuzzy}); - if(!disambiguation.isEmpty()) - { + newMapping.insert(normalKey, { strStr, fuzzy }); + if (!disambiguation.isEmpty()) { auto disambiguationKey = context + "|" + id + "@" + disambiguation; - newMapping_disambiguation.insert(disambiguationKey, {strStr, fuzzy}); + newMapping_disambiguation.insert(disambiguationKey, { strStr, fuzzy }); } } context.clear(); @@ -200,36 +167,26 @@ void POTranslatorPrivate::reload() fuzzy = nextFuzzy; nextFuzzy = false; }; - while (!file.atEnd()) - { + while (!file.atEnd()) { ParserArray line = file.readLine(); - if(line.endsWith('\n')) - { + if (line.endsWith('\n')) { line.resize(line.size() - 1); } - if(line.endsWith('\r')) - { + if (line.endsWith('\r')) { line.resize(line.size() - 1); } - if(!line.size()) - { + if (!line.size()) { // NIL - } - else if(line[0] == '#') - { - if(line.contains(", fuzzy")) - { + } else if (line[0] == '#') { + if (line.contains(", fuzzy")) { nextFuzzy = true; } - } - else if(line.startsWith('"')) - { + } else if (line.startsWith('"')) { QByteArray temp; - QByteArray *out = &temp; + QByteArray* out = &temp; - switch(mode) - { + switch (mode) { case Mode::First: qDebug() << "Unexpected escaped string during initial state... line:" << lineNumber; return; @@ -243,16 +200,12 @@ void POTranslatorPrivate::reload() out = &id; break; } - if(!line.chompString(*out)) - { + if (!line.chompString(*out)) { qDebug() << "Badly formatted string on line:" << lineNumber; return; } - } - else if(line.chomp("msgctxt ", 8)) - { - switch(mode) - { + } else if (line.chomp("msgctxt ", 8)) { + switch (mode) { case Mode::First: break; case Mode::MessageString: @@ -263,21 +216,16 @@ void POTranslatorPrivate::reload() qDebug() << "Unexpected msgctxt line:" << lineNumber; return; } - if(line.chompString(context)) - { + if (line.chompString(context)) { auto parts = context.split('|'); context = parts[0]; - if(parts.size() > 1 && !parts[1].isEmpty()) - { + if (parts.size() > 1 && !parts[1].isEmpty()) { disambiguation = parts[1]; } mode = Mode::MessageContext; } - } - else if (line.chomp("msgid ", 6)) - { - switch(mode) - { + } else if (line.chomp("msgid ", 6)) { + switch (mode) { case Mode::MessageContext: case Mode::First: break; @@ -288,15 +236,11 @@ void POTranslatorPrivate::reload() qDebug() << "Unexpected msgid line:" << lineNumber; return; } - if(line.chompString(id)) - { + if (line.chompString(id)) { mode = Mode::MessageId; } - } - else if (line.chomp("msgstr ", 7)) - { - switch(mode) - { + } else if (line.chomp("msgstr ", 7)) { + switch (mode) { case Mode::First: case Mode::MessageString: case Mode::MessageContext: @@ -305,13 +249,10 @@ void POTranslatorPrivate::reload() case Mode::MessageId: break; } - if(line.chompString(str)) - { + if (line.chompString(str)) { mode = Mode::MessageString; } - } - else - { + } else { qDebug() << "I did not understand line: " << lineNumber << ":" << QString::fromUtf8(line); } lineNumber++; @@ -336,19 +277,15 @@ POTranslator::~POTranslator() QString POTranslator::translate(const char* context, const char* sourceText, const char* disambiguation, [[maybe_unused]] int n) const { - if(disambiguation) - { + if (disambiguation) { auto disambiguationKey = QByteArray(context) + "|" + QByteArray(sourceText) + "@" + QByteArray(disambiguation); auto iter = d->mapping_disambiguatrion.find(disambiguationKey); - if(iter != d->mapping_disambiguatrion.end()) - { - auto & entry = *iter; - if(entry.text.isEmpty()) - { + if (iter != d->mapping_disambiguatrion.end()) { + auto& entry = *iter; + if (entry.text.isEmpty()) { qDebug() << "Translation entry has no content:" << disambiguationKey; } - if(entry.fuzzy) - { + if (entry.fuzzy) { qDebug() << "Translation entry is fuzzy:" << disambiguationKey << "->" << entry.text; } return entry.text; @@ -356,15 +293,12 @@ QString POTranslator::translate(const char* context, const char* sourceText, con } auto key = QByteArray(context) + "|" + QByteArray(sourceText); auto iter = d->mapping.find(key); - if(iter != d->mapping.end()) - { - auto & entry = *iter; - if(entry.text.isEmpty()) - { + if (iter != d->mapping.end()) { + auto& entry = *iter; + if (entry.text.isEmpty()) { qDebug() << "Translation entry has no content:" << key; } - if(entry.fuzzy) - { + if (entry.fuzzy) { qDebug() << "Translation entry is fuzzy:" << key << "->" << entry.text; } return entry.text; diff --git a/launcher/translations/POTranslator.h b/launcher/translations/POTranslator.h index 1634018cc..58451e459 100644 --- a/launcher/translations/POTranslator.h +++ b/launcher/translations/POTranslator.h @@ -4,14 +4,14 @@ struct POTranslatorPrivate; -class POTranslator : public QTranslator -{ +class POTranslator : public QTranslator { Q_OBJECT -public: - explicit POTranslator(const QString& filename, QObject * parent = nullptr); + public: + explicit POTranslator(const QString& filename, QObject* parent = nullptr); virtual ~POTranslator(); - QString translate(const char * context, const char * sourceText, const char * disambiguation, int n) const override; + QString translate(const char* context, const char* sourceText, const char* disambiguation, int n) const override; bool isEmpty() const override; -private: - POTranslatorPrivate * d; + + private: + POTranslatorPrivate* d; }; diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 4c633e153..97affc071 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -37,18 +37,18 @@ #include "TranslationsModel.h" #include -#include -#include +#include #include #include -#include +#include +#include #include -#include "FileSystem.h" -#include "net/NetJob.h" -#include "net/ChecksumValidator.h" #include "BuildConfig.h" +#include "FileSystem.h" #include "Json.h" +#include "net/ChecksumValidator.h" +#include "net/NetJob.h" #include "POTranslator.h" @@ -56,50 +56,35 @@ const static QLatin1String defaultLangCode("en_US"); -enum class FileType -{ - NONE, - QM, - PO -}; +enum class FileType { NONE, QM, PO }; -struct Language -{ - Language() - { - updated = true; - } - Language(const QString & _key) +struct Language { + Language() { updated = true; } + Language(const QString& _key) { key = _key; locale = QLocale(key); updated = (key == defaultLangCode); } - QString languageName() const { + QString languageName() const + { QString result; - if(key == "ja_KANJI") { + if (key == "ja_KANJI") { result = locale.nativeLanguageName() + u8" (漢字)"; - } - else if(key == "es_UY") { + } else if (key == "es_UY") { result = u8"español de Latinoamérica"; - } - else if(key == "en_NZ") { - result = u8"New Zealand English"; // No idea why qt translates this to just english and not to New Zealand English - } - else if(key == "en@pirate") { + } else if (key == "en_NZ") { + result = u8"New Zealand English"; // No idea why qt translates this to just english and not to New Zealand English + } else if (key == "en@pirate") { result = u8"Tongue of the High Seas"; - } - else if(key == "en@uwu") { + } else if (key == "en@uwu") { result = u8"Cute Engwish"; - } - else if(key == "tok") { + } else if (key == "tok") { result = u8"toki pona"; - } - else if(key == "nan") { + } else if (key == "nan") { result = u8"閩南語"; // Using traditional Chinese script. Not sure if we should use simplified instead? - } - else { + } else { result = locale.nativeLanguageName(); } @@ -111,8 +96,7 @@ struct Language float percentTranslated() const { - if (total == 0) - { + if (total == 0) { return 100.0f; } return 100.0f * float(translated) / float(total); @@ -126,30 +110,17 @@ struct Language total = translated + untranslated + fuzzy; } - bool isOfSameNameAs(const Language& other) const - { - return key == other.key; - } + bool isOfSameNameAs(const Language& other) const { return key == other.key; } bool isIdenticalTo(const Language& other) const { - return - ( - key == other.key && - file_name == other.file_name && - file_size == other.file_size && - file_sha1 == other.file_sha1 && - translated == other.translated && - fuzzy == other.fuzzy && - total == other.fuzzy && - localFileType == other.localFileType - ); + return (key == other.key && file_name == other.file_name && file_size == other.file_size && file_sha1 == other.file_sha1 && + translated == other.translated && fuzzy == other.fuzzy && total == other.fuzzy && localFileType == other.localFileType); } - Language & apply(Language & other) + Language& apply(Language& other) { - if(!isOfSameNameAs(other)) - { + if (!isOfSameNameAs(other)) { return *this; } file_name = other.file_name; @@ -178,14 +149,11 @@ struct Language FileType localFileType = FileType::NONE; }; - - -struct TranslationsModel::Private -{ +struct TranslationsModel::Private { QDir m_dir; // initial state is just english - QVector m_languages = {Language (defaultLangCode)}; + QVector m_languages = { Language(defaultLangCode) }; QString m_selectedLanguage = defaultLangCode; std::unique_ptr m_qt_translator; @@ -198,7 +166,7 @@ struct TranslationsModel::Private QString m_nextDownload; std::unique_ptr m_po_translator; - QFileSystemWatcher *watcher; + QFileSystemWatcher* watcher; const QString m_system_locale = QLocale::system().name(); const QString m_system_language = m_system_locale.split('_').front(); @@ -206,7 +174,7 @@ struct TranslationsModel::Private bool no_language_set = false; }; -TranslationsModel::TranslationsModel(QString path, QObject* parent): QAbstractListModel(parent) +TranslationsModel::TranslationsModel(QString path, QObject* parent) : QAbstractListModel(parent) { d.reset(new Private); d->m_dir.setPath(path); @@ -218,15 +186,12 @@ TranslationsModel::TranslationsModel(QString path, QObject* parent): QAbstractLi d->watcher->addPath(d->m_dir.canonicalPath()); } -TranslationsModel::~TranslationsModel() -{ -} +TranslationsModel::~TranslationsModel() {} void TranslationsModel::translationDirChanged(const QString& path) { qDebug() << "Dir changed:" << path; - if (!d->no_language_set) - { + if (!d->no_language_set) { reloadLocalFiles(); } selectLanguage(selectedLanguage()); @@ -237,69 +202,57 @@ void TranslationsModel::indexReceived() qDebug() << "Got translations index!"; d->m_index_job.reset(); - if (d->no_language_set) - { + if (d->no_language_set) { reloadLocalFiles(); auto language = d->m_system_locale; - if (!findLanguage(language)) - { + if (!findLanguage(language)) { language = d->m_system_language; } selectLanguage(language); - if (selectedLanguage() != defaultLangCode) - { + if (selectedLanguage() != defaultLangCode) { updateLanguage(selectedLanguage()); } APPLICATION->settings()->set("Language", selectedLanguage()); d->no_language_set = false; } - else if(d->m_selectedLanguage != defaultLangCode) - { + else if (d->m_selectedLanguage != defaultLangCode) { downloadTranslation(d->m_selectedLanguage); } } namespace { -void readIndex(const QString & path, QMap& languages) +void readIndex(const QString& path, QMap& languages) { QByteArray data; - try - { + try { data = FS::read(path); } catch ([[maybe_unused]] const Exception& e) { qCritical() << "Translations Download Failed: index file not readable"; return; } - try - { + try { auto toplevel_doc = Json::requireDocument(data); auto doc = Json::requireObject(toplevel_doc); auto file_type = Json::requireString(doc, "file_type"); - if(file_type != "MMC-TRANSLATION-INDEX") - { + if (file_type != "MMC-TRANSLATION-INDEX") { qCritical() << "Translations Download Failed: index file is of unknown file type" << file_type; return; } auto version = Json::requireInteger(doc, "version"); - if(version > 2) - { + if (version > 2) { qCritical() << "Translations Download Failed: index file is of unknown format version" << file_type; return; } auto langObjs = Json::requireObject(doc, "languages"); - for(auto iter = langObjs.begin(); iter != langObjs.end(); iter++) - { + for (auto iter = langObjs.begin(); iter != langObjs.end(); iter++) { Language lang(iter.key()); - auto langObj = Json::requireObject(iter.value()); - lang.setTranslationStats( - Json::ensureInteger(langObj, "translated", 0), - Json::ensureInteger(langObj, "untranslated", 0), - Json::ensureInteger(langObj, "fuzzy", 0) - ); + auto langObj = Json::requireObject(iter.value()); + lang.setTranslationStats(Json::ensureInteger(langObj, "translated", 0), Json::ensureInteger(langObj, "untranslated", 0), + Json::ensureInteger(langObj, "fuzzy", 0)); lang.file_name = Json::requireString(langObj, "file"); lang.file_sha1 = Json::requireString(langObj, "sha1"); lang.file_size = Json::requireInteger(langObj, "size"); @@ -310,47 +263,36 @@ void readIndex(const QString & path, QMap& languages) qCritical() << "Translations Download Failed: index file could not be parsed as json"; } } -} +} // namespace void TranslationsModel::reloadLocalFiles() { - QMap languages = {{defaultLangCode, Language(defaultLangCode)}}; + QMap languages = { { defaultLangCode, Language(defaultLangCode) } }; readIndex(d->m_dir.absoluteFilePath("index_v2.json"), languages); - auto entries = d->m_dir.entryInfoList({"mmc_*.qm", "*.po"}, QDir::Files | QDir::NoDotAndDotDot); - for(auto & entry: entries) - { + auto entries = d->m_dir.entryInfoList({ "mmc_*.qm", "*.po" }, QDir::Files | QDir::NoDotAndDotDot); + for (auto& entry : entries) { auto completeSuffix = entry.completeSuffix(); QString langCode; FileType fileType = FileType::NONE; - if(completeSuffix == "qm") - { - langCode = entry.baseName().remove(0,4); + if (completeSuffix == "qm") { + langCode = entry.baseName().remove(0, 4); fileType = FileType::QM; - } - else if(completeSuffix == "po") - { + } else if (completeSuffix == "po") { langCode = entry.baseName(); fileType = FileType::PO; - } - else - { + } else { continue; } auto langIter = languages.find(langCode); - if(langIter != languages.end()) - { - auto & language = *langIter; - if(int(fileType) > int(language.localFileType)) - { + if (langIter != languages.end()) { + auto& language = *langIter; + if (int(fileType) > int(language.localFileType)) { language.localFileType = fileType; } - } - else - { - if(fileType == FileType::PO) - { + } else { + if (fileType == FileType::PO) { Language localFound(langCode); localFound.localFileType = FileType::PO; languages.insert(langCode, localFound); @@ -359,52 +301,40 @@ void TranslationsModel::reloadLocalFiles() } // changed and removed languages - for(auto iter = d->m_languages.begin(); iter != d->m_languages.end();) - { - auto &language = *iter; + for (auto iter = d->m_languages.begin(); iter != d->m_languages.end();) { + auto& language = *iter; auto row = iter - d->m_languages.begin(); auto updatedLanguageIter = languages.find(language.key); - if(updatedLanguageIter != languages.end()) - { - if(language.isIdenticalTo(*updatedLanguageIter)) - { + if (updatedLanguageIter != languages.end()) { + if (language.isIdenticalTo(*updatedLanguageIter)) { languages.remove(language.key); - } - else - { + } else { language.apply(*updatedLanguageIter); emit dataChanged(index(row), index(row)); languages.remove(language.key); } iter++; - } - else - { + } else { beginRemoveRows(QModelIndex(), row, row); iter = d->m_languages.erase(iter); endRemoveRows(); } } // added languages - if(languages.isEmpty()) - { + if (languages.isEmpty()) { return; } beginInsertRows(QModelIndex(), 0, d->m_languages.size() + languages.size() - 1); - for(auto & language: languages) - { + for (auto& language : languages) { d->m_languages.append(language); } std::sort(d->m_languages.begin(), d->m_languages.end(), [this](const Language& a, const Language& b) { - if (a.key != b.key) - { - if (a.key == d->m_system_locale || a.key == d->m_system_language) - { + if (a.key != b.key) { + if (a.key == d->m_system_locale || a.key == d->m_system_language) { return true; } - if (b.key == d->m_system_locale || b.key == d->m_system_language) - { + if (b.key == d->m_system_locale || b.key == d->m_system_language) { return false; } } @@ -414,14 +344,9 @@ void TranslationsModel::reloadLocalFiles() } namespace { -enum class Column -{ - Language, - Completeness -}; +enum class Column { Language, Completeness }; } - QVariant TranslationsModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) @@ -433,62 +358,48 @@ QVariant TranslationsModel::data(const QModelIndex& index, int role) const if (row < 0 || row >= d->m_languages.size()) return QVariant(); - auto & lang = d->m_languages[row]; - switch (role) - { - case Qt::DisplayRole: - { - switch(column) - { - case Column::Language: - { - return lang.languageName(); - } - case Column::Completeness: - { - return QString("%1%").arg(lang.percentTranslated(), 3, 'f', 1); + auto& lang = d->m_languages[row]; + switch (role) { + case Qt::DisplayRole: { + switch (column) { + case Column::Language: { + return lang.languageName(); + } + case Column::Completeness: { + return QString("%1%").arg(lang.percentTranslated(), 3, 'f', 1); + } } + qWarning("TranslationModel::data not implemented when role is DisplayRole"); } - qWarning("TranslationModel::data not implemented when role is DisplayRole"); - } - case Qt::ToolTipRole: - { - return tr("%1:\n%2 translated\n%3 fuzzy\n%4 total").arg(lang.key, QString::number(lang.translated), QString::number(lang.fuzzy), QString::number(lang.total)); - } - case Qt::UserRole: - return lang.key; - default: - return QVariant(); + case Qt::ToolTipRole: { + return tr("%1:\n%2 translated\n%3 fuzzy\n%4 total") + .arg(lang.key, QString::number(lang.translated), QString::number(lang.fuzzy), QString::number(lang.total)); + } + case Qt::UserRole: + return lang.key; + default: + return QVariant(); } } QVariant TranslationsModel::headerData(int section, Qt::Orientation orientation, int role) const { auto column = static_cast(section); - if(role == Qt::DisplayRole) - { - switch(column) - { - case Column::Language: - { + if (role == Qt::DisplayRole) { + switch (column) { + case Column::Language: { return tr("Language"); } - case Column::Completeness: - { + case Column::Completeness: { return tr("Completeness"); } } - } - else if(role == Qt::ToolTipRole) - { - switch(column) - { - case Column::Language: - { + } else if (role == Qt::ToolTipRole) { + switch (column) { + case Column::Language: { return tr("The native language name."); } - case Column::Completeness: - { + case Column::Completeness: { return tr("Completeness is the percentage of fully translated strings, not counting automatically guessed ones."); } } @@ -506,18 +417,12 @@ int TranslationsModel::columnCount([[maybe_unused]] const QModelIndex& parent) c return 2; } -Language * TranslationsModel::findLanguage(const QString& key) +Language* TranslationsModel::findLanguage(const QString& key) { - auto found = std::find_if(d->m_languages.begin(), d->m_languages.end(), [&](Language & lang) - { - return lang.key == key; - }); - if(found == d->m_languages.end()) - { + auto found = std::find_if(d->m_languages.begin(), d->m_languages.end(), [&](Language& lang) { return lang.key == key; }); + if (found == d->m_languages.end()) { return nullptr; - } - else - { + } else { return found; } } @@ -562,10 +467,8 @@ bool TranslationsModel::selectLanguage(QString key) QLocale::setDefault( QLocale(APPLICATION->settings()->get("UseSystemLocale").toBool() ? QString::fromStdString(std::locale().name()) : langCode)); - // if it's the default UI language, finish - if(langCode == defaultLangCode) - { + if (langCode == defaultLangCode) { d->m_selectedLanguage = langCode; return true; } @@ -574,70 +477,47 @@ bool TranslationsModel::selectLanguage(QString key) bool successful = false; // FIXME: this is likely never present. FIX IT. d->m_qt_translator.reset(new QTranslator()); - if (d->m_qt_translator->load("qt_" + langCode, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - { + if (d->m_qt_translator->load("qt_" + langCode, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qDebug() << "Loading Qt Language File for" << langCode.toLocal8Bit().constData() << "..."; - if (!QCoreApplication::installTranslator(d->m_qt_translator.get())) - { + if (!QCoreApplication::installTranslator(d->m_qt_translator.get())) { qCritical() << "Loading Qt Language File failed."; d->m_qt_translator.reset(); - } - else - { + } else { successful = true; } - } - else - { + } else { d->m_qt_translator.reset(); } - if(langPtr->localFileType == FileType::PO) - { + if (langPtr->localFileType == FileType::PO) { qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "..."; auto poTranslator = new POTranslator(FS::PathCombine(d->m_dir.path(), langCode + ".po")); - if(!poTranslator->isEmpty()) - { - if (!QCoreApplication::installTranslator(poTranslator)) - { + if (!poTranslator->isEmpty()) { + if (!QCoreApplication::installTranslator(poTranslator)) { delete poTranslator; qCritical() << "Installing Application Language File failed."; - } - else - { + } else { d->m_app_translator.reset(poTranslator); successful = true; } - } - else - { + } else { qCritical() << "Loading Application Language File failed."; d->m_app_translator.reset(); } - } - else if(langPtr->localFileType == FileType::QM) - { + } else if (langPtr->localFileType == FileType::QM) { d->m_app_translator.reset(new QTranslator()); - if (d->m_app_translator->load("mmc_" + langCode, d->m_dir.path())) - { + if (d->m_app_translator->load("mmc_" + langCode, d->m_dir.path())) { qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "..."; - if (!QCoreApplication::installTranslator(d->m_app_translator.get())) - { + if (!QCoreApplication::installTranslator(d->m_app_translator.get())) { qCritical() << "Installing Application Language File failed."; d->m_app_translator.reset(); - } - else - { + } else { successful = true; } - } - else - { + } else { d->m_app_translator.reset(); } - } - else - { + } else { d->m_app_translator.reset(); } d->m_selectedLanguage = langCode; @@ -647,8 +527,7 @@ bool TranslationsModel::selectLanguage(QString key) QModelIndex TranslationsModel::selectedIndex() { auto found = findLanguage(d->m_selectedLanguage); - if(found) - { + if (found) { // QVector iterator freely converts to pointer to contained type return index(found - d->m_languages.begin(), 0, QModelIndex()); } @@ -662,8 +541,7 @@ QString TranslationsModel::selectedLanguage() void TranslationsModel::downloadIndex() { - if(d->m_index_job || d->m_dl_job) - { + if (d->m_index_job || d->m_dl_job) { return; } qDebug() << "Downloading Translations Index..."; @@ -680,33 +558,28 @@ void TranslationsModel::downloadIndex() void TranslationsModel::updateLanguage(QString key) { - if(key == defaultLangCode) - { + if (key == defaultLangCode) { qWarning() << "Cannot update builtin language" << key; return; } auto found = findLanguage(key); - if(!found) - { + if (!found) { qWarning() << "Cannot update invalid language" << key; return; } - if(!found->updated) - { + if (!found->updated) { downloadTranslation(key); } } void TranslationsModel::downloadTranslation(QString key) { - if(d->m_dl_job) - { + if (d->m_dl_job) { d->m_nextDownload = key; return; } auto lang = findLanguage(key); - if(!lang) - { + if (!lang) { qWarning() << "Will not download an unknown translation" << key; return; } @@ -731,8 +604,7 @@ void TranslationsModel::downloadTranslation(QString key) void TranslationsModel::downloadNext() { - if(!d->m_nextDownload.isEmpty()) - { + if (!d->m_nextDownload.isEmpty()) { downloadTranslation(d->m_nextDownload); d->m_nextDownload.clear(); } @@ -749,8 +621,7 @@ void TranslationsModel::dlGood() { qDebug() << "Got translation:" << d->m_downloadingTranslation; - if(d->m_downloadingTranslation == d->m_selectedLanguage) - { + if (d->m_downloadingTranslation == d->m_selectedLanguage) { selectLanguage(d->m_selectedLanguage); } d->m_dl_job.reset(); diff --git a/launcher/ui/ColorCache.cpp b/launcher/ui/ColorCache.cpp index ef268dd2b..f941a6093 100644 --- a/launcher/ui/ColorCache.cpp +++ b/launcher/ui/ColorCache.cpp @@ -1,13 +1,11 @@ #include "ColorCache.h" - /** * Blend the color with the front color, adapting to the back color */ QColor ColorCache::blend(QColor color) { - if (Rainbow::luma(m_front) > Rainbow::luma(m_back)) - { + if (Rainbow::luma(m_front) > Rainbow::luma(m_back)) { // for dark color schemes, produce a fitting color first color = Rainbow::tint(m_front, color, 0.5); } @@ -27,8 +25,7 @@ QColor ColorCache::blendBackground(QColor color) void ColorCache::recolorAll() { auto iter = m_colors.begin(); - while(iter != m_colors.end()) - { + while (iter != m_colors.end()) { iter->front = blend(iter->original); iter->back = blendBackground(iter->original); } diff --git a/launcher/ui/ColorCache.h b/launcher/ui/ColorCache.h index a840664da..1cf292c13 100644 --- a/launcher/ui/ColorCache.h +++ b/launcher/ui/ColorCache.h @@ -1,12 +1,11 @@ #pragma once -#include -#include #include +#include #include +#include -class ColorCache -{ -public: +class ColorCache { + public: ColorCache(QColor front, QColor back, qreal bias) { m_front = front; @@ -14,15 +13,11 @@ public: m_bias = bias; }; - void addColor(int key, QColor color) - { - m_colors[key] = {color, blend(color), blendBackground(color)}; - } + void addColor(int key, QColor color) { m_colors[key] = { color, blend(color), blendBackground(color) }; } void setForeground(QColor front) { - if(m_front != front) - { + if (m_front != front) { m_front = front; recolorAll(); } @@ -30,8 +25,7 @@ public: void setBackground(QColor back) { - if(m_back != back) - { + if (m_back != back) { m_back = back; recolorAll(); } @@ -40,8 +34,7 @@ public: QColor getFront(int key) { auto iter = m_colors.find(key); - if(iter == m_colors.end()) - { + if (iter == m_colors.end()) { return QColor(); } return (*iter).front; @@ -50,8 +43,7 @@ public: QColor getBack(int key) { auto iter = m_colors.find(key); - if(iter == m_colors.end()) - { + if (iter == m_colors.end()) { return QColor(); } return (*iter).back; @@ -67,29 +59,26 @@ public: */ QColor blendBackground(QColor color); -protected: + protected: void recolorAll(); -protected: - struct ColorEntry - { + protected: + struct ColorEntry { QColor original; QColor front; QColor back; }; -protected: + protected: qreal m_bias; QColor m_front; QColor m_back; QMap m_colors; }; -class LogColorCache : public ColorCache -{ -public: - LogColorCache(QColor front, QColor back) - : ColorCache(front, back, 1.0) +class LogColorCache : public ColorCache { + public: + LogColorCache(QColor front, QColor back) : ColorCache(front, back, 1.0) { addColor((int)MessageLevel::Launcher, QColor("purple")); addColor((int)MessageLevel::Debug, QColor("green")); @@ -101,8 +90,7 @@ public: QColor getFront(MessageLevel::Enum level) { - if(!m_colors.contains((int) level)) - { + if (!m_colors.contains((int)level)) { return ColorCache::getFront((int)MessageLevel::Message); } return ColorCache::getFront((int)level); @@ -110,8 +98,7 @@ public: QColor getBack(MessageLevel::Enum level) { - if(level == MessageLevel::Fatal) - { + if (level == MessageLevel::Fatal) { return QColor(Qt::black); } return QColor(Qt::transparent); diff --git a/launcher/ui/GuiUtil.cpp b/launcher/ui/GuiUtil.cpp index 930e088a7..584a34710 100644 --- a/launcher/ui/GuiUtil.cpp +++ b/launcher/ui/GuiUtil.cpp @@ -37,21 +37,21 @@ #include "GuiUtil.h" -#include #include +#include #include #include -#include "ui/dialogs/ProgressDialog.h" -#include "ui/dialogs/CustomMessageBox.h" #include "net/PasteUpload.h" +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" -#include "Application.h" -#include -#include #include +#include +#include +#include "Application.h" -std::optional GuiUtil::uploadPaste(const QString &name, const QString &text, QWidget *parentWidget) +std::optional GuiUtil::uploadPaste(const QString& name, const QString& text, QWidget* parentWidget) { ProgressDialog dialog(parentWidget); auto pasteTypeSetting = static_cast(APPLICATION->settings()->get("PastebinType").toInt()); @@ -64,8 +64,7 @@ std::optional GuiUtil::uploadPaste(const QString &name, const QString & else baseUrl = pasteCustomAPIBaseSetting; - if (baseUrl.isValid()) - { + if (baseUrl.isValid()) { auto response = CustomMessageBox::selectable(parentWidget, QObject::tr("Confirm Upload"), QObject::tr("You are about to upload \"%1\" to %2.\n" "You should double-check for personal information.\n\n" @@ -82,41 +81,38 @@ std::optional GuiUtil::uploadPaste(const QString &name, const QString & std::unique_ptr paste(new PasteUpload(parentWidget, text, pasteCustomAPIBaseSetting, pasteTypeSetting)); dialog.execWithTask(paste.get()); - if (!paste->wasSuccessful()) - { - CustomMessageBox::selectable( - parentWidget, - QObject::tr("Upload failed"), - paste->failReason(), - QMessageBox::Critical - )->exec(); + if (!paste->wasSuccessful()) { + CustomMessageBox::selectable(parentWidget, QObject::tr("Upload failed"), paste->failReason(), QMessageBox::Critical)->exec(); return QString(); - } - else - { + } else { const QString link = paste->pasteLink(); setClipboardText(link); CustomMessageBox::selectable( parentWidget, QObject::tr("Upload finished"), QObject::tr("The link to the uploaded log has been placed in your clipboard.").arg(link), - QMessageBox::Information)->exec(); + QMessageBox::Information) + ->exec(); return link; } } -void GuiUtil::setClipboardText(const QString &text) +void GuiUtil::setClipboardText(const QString& text) { QApplication::clipboard()->setText(text); } -static QStringList BrowseForFileInternal(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget, bool single) +static QStringList BrowseForFileInternal(QString context, + QString caption, + QString filter, + QString defaultPath, + QWidget* parentWidget, + bool single) { static QMap savedPaths; QFileDialog w(parentWidget, caption); QSet locations; - auto f = [&](QStandardPaths::StandardLocation l) - { + auto f = [&](QStandardPaths::StandardLocation l) { QString location = QStandardPaths::writableLocation(l); QFileInfo finfo(location); if (!finfo.exists()) { @@ -129,8 +125,7 @@ static QStringList BrowseForFileInternal(QString context, QString caption, QStri f(QStandardPaths::DownloadLocation); f(QStandardPaths::HomeLocation); QList urls; - for (auto location : locations) - { + for (auto location : locations) { urls.append(QUrl::fromLocalFile(location)); } urls.append(QUrl::fromLocalFile(defaultPath)); @@ -140,27 +135,21 @@ static QStringList BrowseForFileInternal(QString context, QString caption, QStri w.setNameFilter(filter); QString pathToOpen; - if(savedPaths.contains(context)) - { + if (savedPaths.contains(context)) { pathToOpen = savedPaths[context]; - } - else - { + } else { pathToOpen = defaultPath; } - if(!pathToOpen.isEmpty()) - { + if (!pathToOpen.isEmpty()) { QFileInfo finfo(pathToOpen); - if(finfo.exists() && finfo.isDir()) - { + if (finfo.exists() && finfo.isDir()) { w.setDirectory(finfo.absoluteFilePath()); } } w.setSidebarUrls(urls); - if (w.exec()) - { + if (w.exec()) { savedPaths[context] = w.directory().absolutePath(); return w.selectedFiles(); } @@ -168,18 +157,16 @@ static QStringList BrowseForFileInternal(QString context, QString caption, QStri return {}; } -QString GuiUtil::BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget) +QString GuiUtil::BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget* parentWidget) { auto resultList = BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, true); - if(resultList.size()) - { + if (resultList.size()) { return resultList[0]; } return QString(); } - -QStringList GuiUtil::BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget) +QStringList GuiUtil::BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget* parentWidget) { return BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, false); } diff --git a/launcher/ui/GuiUtil.h b/launcher/ui/GuiUtil.h index 96ebd9a2d..8d384d3f6 100644 --- a/launcher/ui/GuiUtil.h +++ b/launcher/ui/GuiUtil.h @@ -3,10 +3,9 @@ #include #include -namespace GuiUtil -{ -std::optional uploadPaste(const QString &name, const QString &text, QWidget *parentWidget); -void setClipboardText(const QString &text); -QStringList BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget); -QString BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget); -} +namespace GuiUtil { +std::optional uploadPaste(const QString& name, const QString& text, QWidget* parentWidget); +void setClipboardText(const QString& text); +QStringList BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget* parentWidget); +QString BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget* parentWidget); +} // namespace GuiUtil diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp index d784a40fc..7025cb795 100644 --- a/launcher/ui/InstanceWindow.cpp +++ b/launcher/ui/InstanceWindow.cpp @@ -37,12 +37,12 @@ #include "InstanceWindow.h" #include "Application.h" -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" @@ -52,8 +52,7 @@ #include "icons/IconList.h" -InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) - : QMainWindow(parent), m_instance(instance) +InstanceWindow::InstanceWindow(InstancePtr instance, QWidget* parent) : QMainWindow(parent), m_instance(instance) { setAttribute(Qt::WA_DeleteOnClose); @@ -144,8 +143,7 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent) void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus) { - if(newStatus == BaseInstance::Status::Gone) - { + if (newStatus == BaseInstance::Status::Gone) { m_doNotSave = true; close(); } @@ -153,25 +151,20 @@ void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance void InstanceWindow::updateLaunchButtons() { - if(m_instance->isRunning()) - { + if (m_instance->isRunning()) { m_launchOfflineButton->setEnabled(false); m_launchDemoButton->setEnabled(false); m_killButton->setText(tr("Kill")); m_killButton->setObjectName("killButton"); m_killButton->setToolTip(tr("Kill the running instance")); - } - else if(!m_instance->canLaunch()) - { + } else if (!m_instance->canLaunch()) { m_launchOfflineButton->setEnabled(false); m_launchDemoButton->setEnabled(false); m_killButton->setText(tr("Launch")); m_killButton->setObjectName("launchButton"); m_killButton->setToolTip(tr("Launch the instance")); m_killButton->setEnabled(false); - } - else - { + } else { m_launchOfflineButton->setEnabled(true); // Disable demo-mode if not available. @@ -208,7 +201,7 @@ void InstanceWindow::runningStateChanged(bool running) { updateLaunchButtons(); m_container->refreshContainer(); - if(running) { + if (running) { selectPage("log"); } } @@ -218,16 +211,14 @@ void InstanceWindow::on_closeButton_clicked() close(); } -void InstanceWindow::closeEvent(QCloseEvent *event) +void InstanceWindow::closeEvent(QCloseEvent* event) { bool proceed = true; - if(!m_doNotSave) - { + if (!m_doNotSave) { proceed &= m_container->prepareToClose(); } - if(!proceed) - { + if (!proceed) { return; } @@ -244,12 +235,9 @@ bool InstanceWindow::saveAll() void InstanceWindow::on_btnKillMinecraft_clicked() { - if(m_instance->isRunning()) - { + if (m_instance->isRunning()) { APPLICATION->kill(m_instance); - } - else - { + } else { APPLICATION->launch(m_instance, true, false, nullptr); } } @@ -274,14 +262,11 @@ void InstanceWindow::refreshContainer() m_container->refreshContainer(); } -InstanceWindow::~InstanceWindow() -{ -} +InstanceWindow::~InstanceWindow() {} bool InstanceWindow::requestClose() { - if(m_container->prepareToClose()) - { + if (m_container->prepareToClose()) { close(); return true; } diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index 582cff138..70f206f28 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -48,12 +48,11 @@ class QPushButton; class PageContainer; -class InstanceWindow : public QMainWindow, public BasePageContainer -{ +class InstanceWindow : public QMainWindow, public BasePageContainer { Q_OBJECT -public: - explicit InstanceWindow(InstancePtr proc, QWidget *parent = 0); + public: + explicit InstanceWindow(InstancePtr proc, QWidget* parent = 0); virtual ~InstanceWindow(); bool selectPage(QString pageId) override; @@ -68,11 +67,10 @@ public: // request closing the window (from a page) bool requestClose() override; -signals: + signals: void isClosing(); -private -slots: + private slots: void on_closeButton_clicked(); void on_btnKillMinecraft_clicked(); void on_btnLaunchMinecraftOffline_clicked(); @@ -82,19 +80,19 @@ slots: void runningStateChanged(bool running); void on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus); -protected: - void closeEvent(QCloseEvent *) override; + protected: + void closeEvent(QCloseEvent*) override; -private: + private: void updateLaunchButtons(); -private: + private: shared_qobject_ptr m_proc; InstancePtr m_instance; bool m_doNotSave = false; - PageContainer *m_container = nullptr; - QPushButton *m_closeButton = nullptr; - QPushButton *m_killButton = nullptr; - QPushButton *m_launchOfflineButton = nullptr; - QPushButton *m_launchDemoButton = nullptr; + PageContainer* m_container = nullptr; + QPushButton* m_closeButton = nullptr; + QPushButton* m_killButton = nullptr; + QPushButton* m_launchOfflineButton = nullptr; + QPushButton* m_launchDemoButton = nullptr; }; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 423cd48d6..bb88d74e3 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -514,8 +514,7 @@ void MainWindow::showInstanceContextMenu(const QPoint& pos) QAction* actionCreateInstance = new QAction(tr("Create instance"), this); actionCreateInstance->setToolTip(ui->actionAddInstance->toolTip()); - if(!group.isNull()) - { + if (!group.isNull()) { QVariantMap instance_action_data; instance_action_data["group"] = group; actionCreateInstance->setData(instance_action_data); @@ -526,9 +525,8 @@ void MainWindow::showInstanceContextMenu(const QPoint& pos) actions.prepend(actionSep); actions.prepend(actionVoid); actions.append(actionCreateInstance); - if(!group.isNull()) - { - QAction *actionDeleteGroup = new QAction(tr("Delete group '%1'").arg(group), this); + if (!group.isNull()) { + QAction* actionDeleteGroup = new QAction(tr("Delete group '%1'").arg(group), this); QVariantMap delete_group_action_data; delete_group_action_data["group"] = group; actionDeleteGroup->setData(delete_group_action_data); @@ -749,7 +747,7 @@ void MainWindow::changeActiveAccount() QVariant action_data = sAction->data(); bool valid = false; int index = action_data.toInt(&valid); - if(!valid) { + if (!valid) { index = -1; } auto accounts = APPLICATION->accounts(); @@ -1062,8 +1060,7 @@ void MainWindow::on_actionChangeInstIcon_triggered() void MainWindow::iconUpdated(QString icon) { - if (icon == m_currentInstIcon) - { + if (icon == m_currentInstIcon) { auto new_icon = APPLICATION->icons()->getIcon(m_currentInstIcon); ui->actionChangeInstIcon->setIcon(new_icon); changeIconButton->setIcon(new_icon); @@ -1733,4 +1730,3 @@ void MainWindow::refreshCurrentInstance([[maybe_unused]] bool running) auto current = view->selectionModel()->currentIndex(); instanceChanged(current, current); } - diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 27c2756f6..e6434dae2 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -63,34 +63,32 @@ class KonamiCode; class InstanceTask; class LabeledToolButton; -namespace Ui -{ +namespace Ui { class MainWindow; } -class MainWindow : public QMainWindow -{ +class MainWindow : public QMainWindow { Q_OBJECT -public: - explicit MainWindow(QWidget *parent = 0); + public: + explicit MainWindow(QWidget* parent = 0); ~MainWindow(); - bool eventFilter(QObject *obj, QEvent *ev) override; - void closeEvent(QCloseEvent *event) override; - void changeEvent(QEvent * event) override; + bool eventFilter(QObject* obj, QEvent* ev) override; + void closeEvent(QCloseEvent* event) override; + void changeEvent(QEvent* event) override; void checkInstancePathForProblems(); void updatesAllowedChanged(bool allowed); void processURLs(QList urls); -signals: + signals: void isClosing(); -protected: - QMenu * createPopupMenu() override; + protected: + QMenu* createPopupMenu() override; -private slots: + private slots: void onCatToggled(bool); void onCatChanged(int); @@ -131,9 +129,9 @@ private slots: void on_actionClearMetadata_triggered(); - #ifdef Q_OS_MAC +#ifdef Q_OS_MAC void on_actionAddToPATH_triggered(); - #endif +#endif void on_actionOpenWiki_triggered(); @@ -154,7 +152,10 @@ private slots: void deleteGroup(); void undoTrashInstance(); - inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } + inline void on_actionExportInstance_triggered() + { + on_actionExportInstanceZip_triggered(); + } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); void on_actionExportInstanceFlamePack_triggered(); @@ -173,7 +174,7 @@ private slots: */ void iconUpdated(QString); - void showInstanceContextMenu(const QPoint &); + void showInstanceContextMenu(const QPoint&); void updateMainToolBar(); @@ -183,15 +184,15 @@ private slots: void instanceActivated(QModelIndex); - void instanceChanged(const QModelIndex ¤t, const QModelIndex &previous); + void instanceChanged(const QModelIndex& current, const QModelIndex& previous); void instanceSelectRequest(QString id); - void instanceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void instanceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); void selectionBad(); - void startTask(Task *task); + void startTask(Task* task); void defaultAccountChanged(); @@ -201,7 +202,6 @@ private slots: void updateNewsLabel(); - void konamiTriggered(); void globalSettingsClosed(); @@ -209,38 +209,38 @@ private slots: void lockToolbars(bool); #ifndef Q_OS_MAC - void keyReleaseEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent* event) override; #endif void refreshCurrentInstance(bool running); -private: + private: void retranslateUi(); void addInstance(QString url = QString()); void activateInstance(InstancePtr instance); void setCatBackground(bool enabled); void updateInstanceToolIcon(QString new_icon); - void setSelectedInstanceById(const QString &id); + void setSelectedInstanceById(const QString& id); void updateStatusCenter(); void setInstanceActionsEnabled(bool enabled); - void runModalTask(Task *task); - void instanceFromInstanceTask(InstanceTask *task); + void runModalTask(Task* task); + void instanceFromInstanceTask(InstanceTask* task); void finalizeInstance(InstancePtr inst); -private: - Ui::MainWindow *ui; + private: + Ui::MainWindow* ui; // these are managed by Qt's memory management model! - InstanceView *view = nullptr; - InstanceProxyModel *proxymodel = nullptr; - QToolButton *newsLabel = nullptr; - QLabel *m_statusLeft = nullptr; - QLabel *m_statusCenter = nullptr; - LabeledToolButton *changeIconButton = nullptr; - LabeledToolButton *renameButton = nullptr; - QToolButton *helpMenuButton = nullptr; - KonamiCode * secretEventFilter = nullptr; + InstanceView* view = nullptr; + InstanceProxyModel* proxymodel = nullptr; + QToolButton* newsLabel = nullptr; + QLabel* m_statusLeft = nullptr; + QLabel* m_statusCenter = nullptr; + LabeledToolButton* changeIconButton = nullptr; + LabeledToolButton* renameButton = nullptr; + QToolButton* helpMenuButton = nullptr; + KonamiCode* secretEventFilter = nullptr; std::shared_ptr instanceToolbarSetting = nullptr; @@ -250,5 +250,5 @@ private: QString m_currentInstIcon; // managed by the application object - Task *m_versionLoadTask = nullptr; + Task* m_versionLoadTask = nullptr; }; diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp index b1734eff3..bac30b010 100644 --- a/launcher/ui/dialogs/AboutDialog.cpp +++ b/launcher/ui/dialogs/AboutDialog.cpp @@ -34,26 +34,28 @@ */ #include "AboutDialog.h" -#include "BuildConfig.h" -#include "ui_AboutDialog.h" #include #include "Application.h" #include "BuildConfig.h" #include "Markdown.h" +#include "ui_AboutDialog.h" #include #include namespace { -QString getLink(QString link, QString name) { +QString getLink(QString link, QString name) +{ return QString("<%2>").arg(link).arg(name); } -QString getWebsite(QString link) { +QString getWebsite(QString link) +{ return getLink(link, QObject::tr("Website")); } -QString getGitHub(QString username) { +QString getGitHub(QString username) +{ return getLink("https://github.com/" + username, "GitHub"); } @@ -70,19 +72,19 @@ QString getCreditsHtml() //: %1 is the name of the launcher, determined at build time, e.g. "Prism Launcher Developers" stream << "

" << QObject::tr("%1 Developers", "About Credits").arg(BuildConfig.LAUNCHER_DISPLAYNAME) << "

\n"; - stream << QString("

Sefa Eyeoglu (Scrumplex) %1

\n") .arg(getWebsite("https://scrumplex.net")); - stream << QString("

d-513 %1

\n") .arg(getGitHub("d-513")); - stream << QString("

txtsd %1

\n") .arg(getWebsite("https://ihavea.quest")); - stream << QString("

timoreo %1

\n") .arg(getGitHub("timoreo22")); - stream << QString("

Ezekiel Smith (ZekeSmith) %1

\n") .arg(getGitHub("ZekeSmith")); - stream << QString("

cozyGalvinism %1

\n") .arg(getGitHub("cozyGalvinism")); - stream << QString("

DioEgizio %1

\n") .arg(getGitHub("DioEgizio")); - stream << QString("

flowln %1

\n") .arg(getGitHub("flowln")); - stream << QString("

ViRb3 %1

\n") .arg(getGitHub("ViRb3")); - stream << QString("

Rachel Powers (Ryex) %1

\n") .arg(getGitHub("Ryex")); - stream << QString("

TayouVR %1

\n") .arg(getGitHub("TayouVR")); - stream << QString("

TheKodeToad %1

\n") .arg(getGitHub("TheKodeToad")); - stream << QString("

getchoo %1

\n") .arg(getGitHub("getchoo")); + stream << QString("

Sefa Eyeoglu (Scrumplex) %1

\n").arg(getWebsite("https://scrumplex.net")); + stream << QString("

d-513 %1

\n").arg(getGitHub("d-513")); + stream << QString("

txtsd %1

\n").arg(getWebsite("https://ihavea.quest")); + stream << QString("

timoreo %1

\n").arg(getGitHub("timoreo22")); + stream << QString("

Ezekiel Smith (ZekeSmith) %1

\n").arg(getGitHub("ZekeSmith")); + stream << QString("

cozyGalvinism %1

\n").arg(getGitHub("cozyGalvinism")); + stream << QString("

DioEgizio %1

\n").arg(getGitHub("DioEgizio")); + stream << QString("

flowln %1

\n").arg(getGitHub("flowln")); + stream << QString("

ViRb3 %1

\n").arg(getGitHub("ViRb3")); + stream << QString("

Rachel Powers (Ryex) %1

\n").arg(getGitHub("Ryex")); + stream << QString("

TayouVR %1

\n").arg(getGitHub("TayouVR")); + stream << QString("

TheKodeToad %1

\n").arg(getGitHub("TheKodeToad")); + stream << QString("

getchoo %1

\n").arg(getGitHub("getchoo")); stream << "
\n"; // TODO: possibly retrieve from git history at build time? @@ -96,20 +98,21 @@ QString getCreditsHtml() stream << "
\n"; stream << "

" << QObject::tr("With thanks to", "About Credits") << "

\n"; - stream << QString("

Boba %1

\n") .arg(getWebsite("https://bobaonline.neocities.org/")); - stream << QString("

Davi Rafael %1

\n") .arg(getWebsite("https://auti.one/")); - stream << QString("

Fulmine %1

\n") .arg(getWebsite("https://www.fulmine.xyz/")); - stream << QString("

ely %1

\n") .arg(getGitHub("elyrodso")); - stream << QString("

gon sawa %1

\n") .arg(getGitHub("gonsawa")); + stream << QString("

Boba %1

\n").arg(getWebsite("https://bobaonline.neocities.org/")); + stream << QString("

Davi Rafael %1

\n").arg(getWebsite("https://auti.one/")); + stream << QString("

Fulmine %1

\n").arg(getWebsite("https://www.fulmine.xyz/")); + stream << QString("

ely %1

\n").arg(getGitHub("elyrodso")); + stream << QString("

gon sawa %1

\n").arg(getGitHub("gonsawa")); stream << QString("

Pankakes

\n"); - stream << QString("

tobimori %1

\n") .arg(getGitHub("tobimori")); + stream << QString("

tobimori %1

\n").arg(getGitHub("tobimori")); stream << "

Orochimarufan <orochimarufan.x3@gmail.com>

\n"; stream << "

TakSuyu <taksuyu@gmail.com>

\n"; stream << "

Kilobyte <stiepen22@gmx.de>

\n"; stream << "

Rootbear75 <@rootbear75>

\n"; stream << "

Zeker Zhayard <@Zeker_Zhayard>

\n"; stream << "

Everyone who helped establish our branding!

\n"; - stream << "

And everyone else who contributed!

\n"; + stream + << "

And everyone else who contributed!

\n"; stream << "
\n"; stream << "\n"; @@ -124,9 +127,9 @@ QString getLicenseHtml() return output; } -} +} // namespace -AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog) +AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { ui->setupUi(this); @@ -148,7 +151,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia ui->versionLabel->setText(BuildConfig.printableVersionString()); if (!BuildConfig.BUILD_PLATFORM.isEmpty()) - ui->platformLabel->setText(tr("Platform") +": " + BuildConfig.BUILD_PLATFORM); + ui->platformLabel->setText(tr("Platform") + ": " + BuildConfig.BUILD_PLATFORM); else ui->platformLabel->setVisible(false); @@ -163,7 +166,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia ui->buildDateLabel->setVisible(false); if (!BuildConfig.VERSION_CHANNEL.isEmpty()) - ui->channelLabel->setText(tr("Channel") +": " + BuildConfig.VERSION_CHANNEL); + ui->channelLabel->setText(tr("Channel") + ": " + BuildConfig.VERSION_CHANNEL); else ui->channelLabel->setVisible(false); diff --git a/launcher/ui/dialogs/AboutDialog.h b/launcher/ui/dialogs/AboutDialog.h index 814fd98c6..356f005e0 100644 --- a/launcher/ui/dialogs/AboutDialog.h +++ b/launcher/ui/dialogs/AboutDialog.h @@ -15,26 +15,23 @@ #pragma once -#include #include +#include -namespace Ui -{ +namespace Ui { class AboutDialog; } -class AboutDialog : public QDialog -{ +class AboutDialog : public QDialog { Q_OBJECT -public: - explicit AboutDialog(QWidget *parent = 0); + public: + explicit AboutDialog(QWidget* parent = 0); ~AboutDialog(); -private: - Ui::AboutDialog *ui; + private: + Ui::AboutDialog* ui; NetJob::Ptr netJob; QByteArray dataSink; }; - diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index fdfae5973..727c06148 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -313,7 +313,7 @@ bool BlockedModsDialog::checkValidPath(QString path) // efectivly compare two strings ignoring all separators and case auto laxCompare = [](QString fsfilename, QString metadataFilename) { // allowed character seperators - QList allowedSeperators = { '-', '+', '.' , '_'}; + QList allowedSeperators = { '-', '+', '.', '_' }; // copy in lowercase auto fsName = fsfilename.toLower(); diff --git a/launcher/ui/dialogs/CopyInstanceDialog.cpp b/launcher/ui/dialogs/CopyInstanceDialog.cpp index ffa1e31b9..2c98fad16 100644 --- a/launcher/ui/dialogs/CopyInstanceDialog.cpp +++ b/launcher/ui/dialogs/CopyInstanceDialog.cpp @@ -107,8 +107,8 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget* parent) #if defined(Q_OS_WIN) ui->symbolicLinksCheckbox->setIcon(style()->standardIcon(QStyle::SP_VistaShield)); - ui->symbolicLinksCheckbox->setToolTip(tr("Use symbolic links instead of copying files.") + - "\n" + tr("On Windows, symbolic links may require admin permission to create.")); + ui->symbolicLinksCheckbox->setToolTip(tr("Use symbolic links instead of copying files.") + "\n" + + tr("On Windows, symbolic links may require admin permission to create.")); #endif updateLinkOptions(); diff --git a/launcher/ui/dialogs/CustomMessageBox.cpp b/launcher/ui/dialogs/CustomMessageBox.cpp index 19029f682..1af47a449 100644 --- a/launcher/ui/dialogs/CustomMessageBox.cpp +++ b/launcher/ui/dialogs/CustomMessageBox.cpp @@ -15,13 +15,15 @@ #include "CustomMessageBox.h" -namespace CustomMessageBox -{ -QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text, - QMessageBox::Icon icon, QMessageBox::StandardButtons buttons, +namespace CustomMessageBox { +QMessageBox* selectable(QWidget* parent, + const QString& title, + const QString& text, + QMessageBox::Icon icon, + QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - QMessageBox *messageBox = new QMessageBox(parent); + QMessageBox* messageBox = new QMessageBox(parent); messageBox->setWindowTitle(title); messageBox->setText(text); messageBox->setStandardButtons(buttons); @@ -32,4 +34,4 @@ QMessageBox *selectable(QWidget *parent, const QString &title, const QString &te return messageBox; } -} +} // namespace CustomMessageBox diff --git a/launcher/ui/dialogs/CustomMessageBox.h b/launcher/ui/dialogs/CustomMessageBox.h index 712c65186..a9bc6a24a 100644 --- a/launcher/ui/dialogs/CustomMessageBox.h +++ b/launcher/ui/dialogs/CustomMessageBox.h @@ -17,9 +17,10 @@ #include -namespace CustomMessageBox -{ -QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text, +namespace CustomMessageBox { +QMessageBox* selectable(QWidget* parent, + const QString& title, + const QString& text, QMessageBox::Icon icon = QMessageBox::NoIcon, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); diff --git a/launcher/ui/dialogs/EditAccountDialog.cpp b/launcher/ui/dialogs/EditAccountDialog.cpp index 002c064b4..58036fd82 100644 --- a/launcher/ui/dialogs/EditAccountDialog.cpp +++ b/launcher/ui/dialogs/EditAccountDialog.cpp @@ -14,12 +14,11 @@ */ #include "EditAccountDialog.h" -#include "ui_EditAccountDialog.h" #include #include +#include "ui_EditAccountDialog.h" -EditAccountDialog::EditAccountDialog(const QString &text, QWidget *parent, int flags) - : QDialog(parent), ui(new Ui::EditAccountDialog) +EditAccountDialog::EditAccountDialog(const QString& text, QWidget* parent, int flags) : QDialog(parent), ui(new Ui::EditAccountDialog) { ui->setupUi(this); @@ -35,12 +34,12 @@ EditAccountDialog::~EditAccountDialog() delete ui; } -void EditAccountDialog::on_label_linkActivated(const QString &link) +void EditAccountDialog::on_label_linkActivated(const QString& link) { DesktopServices::openUrl(QUrl(link)); } -void EditAccountDialog::setUsername(const QString & user) const +void EditAccountDialog::setUsername(const QString& user) const { ui->userTextBox->setText(user); } @@ -50,7 +49,7 @@ QString EditAccountDialog::username() const return ui->userTextBox->text(); } -void EditAccountDialog::setPassword(const QString & pass) const +void EditAccountDialog::setPassword(const QString& pass) const { ui->passTextBox->setText(pass); } diff --git a/launcher/ui/dialogs/EditAccountDialog.h b/launcher/ui/dialogs/EditAccountDialog.h index 6b5eb4aa9..7a9ccba79 100644 --- a/launcher/ui/dialogs/EditAccountDialog.h +++ b/launcher/ui/dialogs/EditAccountDialog.h @@ -17,28 +17,24 @@ #include -namespace Ui -{ +namespace Ui { class EditAccountDialog; } -class EditAccountDialog : public QDialog -{ +class EditAccountDialog : public QDialog { Q_OBJECT -public: - explicit EditAccountDialog(const QString &text = "", QWidget *parent = 0, - int flags = UsernameField | PasswordField); + public: + explicit EditAccountDialog(const QString& text = "", QWidget* parent = 0, int flags = UsernameField | PasswordField); ~EditAccountDialog(); - void setUsername(const QString & user) const; - void setPassword(const QString & pass) const; + void setUsername(const QString& user) const; + void setPassword(const QString& pass) const; QString username() const; QString password() const; - enum Flags - { + enum Flags { NoFlags = 0, //! Specifies that the dialog should have a username field. @@ -48,9 +44,9 @@ public: PasswordField, }; -private slots: - void on_label_linkActivated(const QString &link); + private slots: + void on_label_linkActivated(const QString& link); -private: - Ui::EditAccountDialog *ui; + private: + Ui::EditAccountDialog* ui; }; diff --git a/launcher/ui/dialogs/IconPickerDialog.cpp b/launcher/ui/dialogs/IconPickerDialog.cpp index 5131686af..faad3ce75 100644 --- a/launcher/ui/dialogs/IconPickerDialog.cpp +++ b/launcher/ui/dialogs/IconPickerDialog.cpp @@ -13,9 +13,9 @@ * limitations under the License. */ +#include #include #include -#include #include "Application.h" @@ -24,12 +24,11 @@ #include "ui/instanceview/InstanceDelegate.h" +#include #include "icons/IconList.h" #include "icons/IconUtils.h" -#include -IconPickerDialog::IconPickerDialog(QWidget *parent) - : QDialog(parent), ui(new Ui::IconPickerDialog) +IconPickerDialog::IconPickerDialog(QWidget* parent) : QDialog(parent), ui(new Ui::IconPickerDialog) { ui->setupUi(this); setWindowModality(Qt::WindowModal); @@ -69,31 +68,30 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) connect(contentsWidget, SIGNAL(doubleClicked(QModelIndex)), SLOT(activated(QModelIndex))); - connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection))); + connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + SLOT(selectionChanged(QItemSelection, QItemSelection))); auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole); connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder); } -bool IconPickerDialog::eventFilter(QObject *obj, QEvent *evt) +bool IconPickerDialog::eventFilter(QObject* obj, QEvent* evt) { if (obj != ui->iconView) return QDialog::eventFilter(obj, evt); - if (evt->type() != QEvent::KeyPress) - { + if (evt->type() != QEvent::KeyPress) { return QDialog::eventFilter(obj, evt); } - QKeyEvent *keyEvent = static_cast(evt); - switch (keyEvent->key()) - { - case Qt::Key_Delete: - removeSelectedIcon(); - return true; - case Qt::Key_Plus: - addNewIcon(); - return true; - default: - break; + QKeyEvent* keyEvent = static_cast(evt); + switch (keyEvent->key()) { + case Qt::Key_Delete: + removeSelectedIcon(); + return true; + case Qt::Key_Plus: + addNewIcon(); + return true; + default: + break; } return QDialog::eventFilter(obj, evt); } @@ -142,8 +140,7 @@ int IconPickerDialog::execWithSelection(QString selection) int index_nr = list->getIconIndex(selection); auto model_index = list->index(index_nr); - contentsWidget->selectionModel()->select( - model_index, QItemSelectionModel::Current | QItemSelectionModel::Select); + contentsWidget->selectionModel()->select(model_index, QItemSelectionModel::Current | QItemSelectionModel::Select); QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection, Q_ARG(QModelIndex, model_index)); return QDialog::exec(); diff --git a/launcher/ui/dialogs/IconPickerDialog.h b/launcher/ui/dialogs/IconPickerDialog.h index c93f565f1..37e53dcce 100644 --- a/launcher/ui/dialogs/IconPickerDialog.h +++ b/launcher/ui/dialogs/IconPickerDialog.h @@ -17,30 +17,27 @@ #include #include -namespace Ui -{ +namespace Ui { class IconPickerDialog; } -class IconPickerDialog : public QDialog -{ +class IconPickerDialog : public QDialog { Q_OBJECT -public: - explicit IconPickerDialog(QWidget *parent = 0); + public: + explicit IconPickerDialog(QWidget* parent = 0); ~IconPickerDialog(); int execWithSelection(QString selection); QString selectedIconKey; -protected: - virtual bool eventFilter(QObject *, QEvent *); + protected: + virtual bool eventFilter(QObject*, QEvent*); -private: - Ui::IconPickerDialog *ui; - QPushButton *buttonRemove; + private: + Ui::IconPickerDialog* ui; + QPushButton* buttonRemove; -private -slots: + private slots: void selectionChanged(QItemSelection, QItemSelection); void activated(QModelIndex); void delayed_scroll(QModelIndex); diff --git a/launcher/ui/dialogs/ImportResourceDialog.h b/launcher/ui/dialogs/ImportResourceDialog.h index 5f2f7a92e..bbde1ba7b 100644 --- a/launcher/ui/dialogs/ImportResourceDialog.h +++ b/launcher/ui/dialogs/ImportResourceDialog.h @@ -17,7 +17,7 @@ class ImportResourceDialog : public QDialog { explicit ImportResourceDialog(QString file_path, PackedResourceType type, QWidget* parent = nullptr); ~ImportResourceDialog() override; QString selectedInstanceKey; - + private: Ui::ImportResourceDialog* ui; PackedResourceType m_resource_type; diff --git a/launcher/ui/dialogs/LoginDialog.cpp b/launcher/ui/dialogs/LoginDialog.cpp index 30394b725..7296a13ef 100644 --- a/launcher/ui/dialogs/LoginDialog.cpp +++ b/launcher/ui/dialogs/LoginDialog.cpp @@ -20,7 +20,7 @@ #include -LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog) +LoginDialog::LoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LoginDialog) { ui->setupUi(this); ui->progressBar->setVisible(false); @@ -59,27 +59,24 @@ void LoginDialog::setUserInputsEnabled(bool enable) } // Enable the OK button only when both textboxes contain something. -void LoginDialog::on_userTextBox_textEdited(const QString &newText) +void LoginDialog::on_userTextBox_textEdited(const QString& newText) { - ui->buttonBox->button(QDialogButtonBox::Ok) - ->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty()); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty()); } -void LoginDialog::on_passTextBox_textEdited(const QString &newText) +void LoginDialog::on_passTextBox_textEdited(const QString& newText) { - ui->buttonBox->button(QDialogButtonBox::Ok) - ->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty()); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty()); } -void LoginDialog::onTaskFailed(const QString &reason) +void LoginDialog::onTaskFailed(const QString& reason) { // Set message auto lines = reason.split('\n'); QString processed; - for(auto line: lines) { - if(line.size()) { + for (auto line : lines) { + if (line.size()) { processed += "" + line + "
"; - } - else { + } else { processed += "
"; } } @@ -95,7 +92,7 @@ void LoginDialog::onTaskSucceeded() QDialog::accept(); } -void LoginDialog::onTaskStatus(const QString &status) +void LoginDialog::onTaskStatus(const QString& status) { ui->label->setText(status); } @@ -107,12 +104,11 @@ void LoginDialog::onTaskProgress(qint64 current, qint64 total) } // Public interface -MinecraftAccountPtr LoginDialog::newAccount(QWidget *parent, QString msg) +MinecraftAccountPtr LoginDialog::newAccount(QWidget* parent, QString msg) { LoginDialog dlg(parent); dlg.ui->label->setText(msg); - if (dlg.exec() == QDialog::Accepted) - { + if (dlg.exec() == QDialog::Accepted) { return dlg.m_account; } return nullptr; diff --git a/launcher/ui/dialogs/LoginDialog.h b/launcher/ui/dialogs/LoginDialog.h index f8101ff57..601b5fa77 100644 --- a/launcher/ui/dialogs/LoginDialog.h +++ b/launcher/ui/dialogs/LoginDialog.h @@ -15,45 +15,42 @@ #pragma once -#include #include +#include #include "minecraft/auth/MinecraftAccount.h" #include "tasks/Task.h" -namespace Ui -{ +namespace Ui { class LoginDialog; } -class LoginDialog : public QDialog -{ +class LoginDialog : public QDialog { Q_OBJECT -public: + public: ~LoginDialog(); - static MinecraftAccountPtr newAccount(QWidget *parent, QString message); + static MinecraftAccountPtr newAccount(QWidget* parent, QString message); -private: - explicit LoginDialog(QWidget *parent = 0); + private: + explicit LoginDialog(QWidget* parent = 0); void setUserInputsEnabled(bool enable); -protected -slots: + protected slots: void accept(); - void onTaskFailed(const QString &reason); + void onTaskFailed(const QString& reason); void onTaskSucceeded(); - void onTaskStatus(const QString &status); + void onTaskStatus(const QString& status); void onTaskProgress(qint64 current, qint64 total); - void on_userTextBox_textEdited(const QString &newText); - void on_passTextBox_textEdited(const QString &newText); + void on_userTextBox_textEdited(const QString& newText); + void on_passTextBox_textEdited(const QString& newText); -private: - Ui::LoginDialog *ui; + private: + Ui::LoginDialog* ui; MinecraftAccountPtr m_account; Task::Ptr m_loginTask; }; diff --git a/launcher/ui/dialogs/MSALoginDialog.cpp b/launcher/ui/dialogs/MSALoginDialog.cpp index be49babba..f8aab34d9 100644 --- a/launcher/ui/dialogs/MSALoginDialog.cpp +++ b/launcher/ui/dialogs/MSALoginDialog.cpp @@ -39,12 +39,12 @@ #include "DesktopServices.h" #include "minecraft/auth/AccountTask.h" -#include -#include #include #include +#include +#include -MSALoginDialog::MSALoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MSALoginDialog) +MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MSALoginDialog) { ui->setupUi(this); ui->progressBar->setVisible(false); @@ -55,7 +55,8 @@ MSALoginDialog::MSALoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MS connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); } -int MSALoginDialog::exec() { +int MSALoginDialog::exec() +{ setUserInputsEnabled(false); ui->progressBar->setVisible(true); @@ -74,24 +75,24 @@ int MSALoginDialog::exec() { return QDialog::exec(); } - MSALoginDialog::~MSALoginDialog() { delete ui; } -void MSALoginDialog::externalLoginTick() { +void MSALoginDialog::externalLoginTick() +{ m_externalLoginElapsed++; ui->progressBar->setValue(m_externalLoginElapsed); ui->progressBar->repaint(); - if(m_externalLoginElapsed >= m_externalLoginTimeout) { + if (m_externalLoginElapsed >= m_externalLoginTimeout) { m_externalLoginTimer.stop(); } } - -void MSALoginDialog::showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn) { +void MSALoginDialog::showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn) +{ m_externalLoginElapsed = 0; m_externalLoginTimeout = expiresIn; @@ -104,7 +105,8 @@ void MSALoginDialog::showVerificationUriAndCode(const QUrl& uri, const QString& QString urlString = uri.toString(); QString linkString = QString("%2").arg(urlString, urlString); - ui->label->setText(tr("

Please open up %1 in a browser and put in the code %2 to proceed with login.

").arg(linkString, code)); + ui->label->setText( + tr("

Please open up %1 in a browser and put in the code %2 to proceed with login.

").arg(linkString, code)); ui->actionButton->setVisible(true); connect(ui->actionButton, &QPushButton::clicked, [=]() { DesktopServices::openUrl(uri); @@ -113,7 +115,8 @@ void MSALoginDialog::showVerificationUriAndCode(const QUrl& uri, const QString& }); } -void MSALoginDialog::hideVerificationUriAndCode() { +void MSALoginDialog::hideVerificationUriAndCode() +{ m_externalLoginTimer.stop(); ui->actionButton->setVisible(false); } @@ -123,16 +126,15 @@ void MSALoginDialog::setUserInputsEnabled(bool enable) ui->buttonBox->setEnabled(enable); } -void MSALoginDialog::onTaskFailed(const QString &reason) +void MSALoginDialog::onTaskFailed(const QString& reason) { // Set message auto lines = reason.split('\n'); QString processed; - for(auto line: lines) { - if(line.size()) { + for (auto line : lines) { + if (line.size()) { processed += "" + line + "
"; - } - else { + } else { processed += "
"; } } @@ -149,7 +151,7 @@ void MSALoginDialog::onTaskSucceeded() QDialog::accept(); } -void MSALoginDialog::onTaskStatus(const QString &status) +void MSALoginDialog::onTaskStatus(const QString& status) { ui->label->setText(status); } @@ -161,12 +163,11 @@ void MSALoginDialog::onTaskProgress(qint64 current, qint64 total) } // Public interface -MinecraftAccountPtr MSALoginDialog::newAccount(QWidget *parent, QString msg) +MinecraftAccountPtr MSALoginDialog::newAccount(QWidget* parent, QString msg) { MSALoginDialog dlg(parent); dlg.ui->label->setText(msg); - if (dlg.exec() == QDialog::Accepted) - { + if (dlg.exec() == QDialog::Accepted) { return dlg.m_account; } return nullptr; diff --git a/launcher/ui/dialogs/MSALoginDialog.h b/launcher/ui/dialogs/MSALoginDialog.h index 4cf146ab3..03e276bc0 100644 --- a/launcher/ui/dialogs/MSALoginDialog.h +++ b/launcher/ui/dialogs/MSALoginDialog.h @@ -15,49 +15,45 @@ #pragma once -#include -#include #include +#include +#include #include "minecraft/auth/MinecraftAccount.h" -namespace Ui -{ +namespace Ui { class MSALoginDialog; } -class MSALoginDialog : public QDialog -{ +class MSALoginDialog : public QDialog { Q_OBJECT -public: + public: ~MSALoginDialog(); - static MinecraftAccountPtr newAccount(QWidget *parent, QString message); + static MinecraftAccountPtr newAccount(QWidget* parent, QString message); int exec() override; -private: - explicit MSALoginDialog(QWidget *parent = 0); + private: + explicit MSALoginDialog(QWidget* parent = 0); void setUserInputsEnabled(bool enable); -protected -slots: - void onTaskFailed(const QString &reason); + protected slots: + void onTaskFailed(const QString& reason); void onTaskSucceeded(); - void onTaskStatus(const QString &status); + void onTaskStatus(const QString& status); void onTaskProgress(qint64 current, qint64 total); - void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn); + void showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn); void hideVerificationUriAndCode(); void externalLoginTick(); -private: - Ui::MSALoginDialog *ui; + private: + Ui::MSALoginDialog* ui; MinecraftAccountPtr m_account; shared_qobject_ptr m_loginTask; QTimer m_externalLoginTimer; int m_externalLoginElapsed = 0; int m_externalLoginTimeout = 0; }; - diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 8618b9240..0af1ec59b 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -89,15 +89,17 @@ void ModUpdateDialog::checkCandidates() if (!m_modrinth_to_update.empty()) { m_modrinth_check_task.reset(new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, m_mod_model)); - connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_modrinth_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_modrinth_check_task); } if (!m_flame_to_update.empty()) { m_flame_check_task.reset(new FlameCheckUpdate(m_flame_to_update, versions, loaders, m_mod_model)); - connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, - [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.append({mod, reason, recover_url}); }); + connect(m_flame_check_task.get(), &CheckUpdateTask::checkFailed, this, [this](Mod* mod, QString reason, QUrl recover_url) { + m_failed_check_update.append({ mod, reason, recover_url }); + }); check_task.addTask(m_flame_check_task); } @@ -162,7 +164,7 @@ void ModUpdateDialog::checkCandidates() if (!recover_url.isEmpty()) //: %1 is the link to download it manually text += tr("Possible solution: Getting the latest version manually:
%1
") - .arg(QString("%1").arg(recover_url.toString())); + .arg(QString("%1").arg(recover_url.toString())); text += "
"; } @@ -342,7 +344,7 @@ void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::R } else { QString reason{ tr("Couldn't find a valid version on the selected mod provider(s)") }; - m_failed_metadata.append({mod, reason}); + m_failed_metadata.append({ mod, reason }); } } diff --git a/launcher/ui/dialogs/ModUpdateDialog.h b/launcher/ui/dialogs/ModUpdateDialog.h index 1a92f6134..12dddf5e1 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.h +++ b/launcher/ui/dialogs/ModUpdateDialog.h @@ -36,7 +36,9 @@ class ModUpdateDialog final : public ReviewMessageBox { private slots: void onMetadataEnsured(Mod*); - void onMetadataFailed(Mod*, bool try_others = false, ModPlatform::ResourceProvider first_choice = ModPlatform::ResourceProvider::MODRINTH); + void onMetadataFailed(Mod*, + bool try_others = false, + ModPlatform::ResourceProvider first_choice = ModPlatform::ResourceProvider::MODRINTH); private: QWidget* m_parent; diff --git a/launcher/ui/dialogs/NewComponentDialog.cpp b/launcher/ui/dialogs/NewComponentDialog.cpp index ea790e8c2..0d90b02e3 100644 --- a/launcher/ui/dialogs/NewComponentDialog.cpp +++ b/launcher/ui/dialogs/NewComponentDialog.cpp @@ -33,28 +33,28 @@ * limitations under the License. */ -#include "Application.h" #include "NewComponentDialog.h" +#include "Application.h" #include "ui_NewComponentDialog.h" #include +#include #include #include -#include -#include "VersionSelectDialog.h" -#include "ProgressDialog.h" #include "IconPickerDialog.h" +#include "ProgressDialog.h" +#include "VersionSelectDialog.h" +#include #include #include -#include #include #include #include -NewComponentDialog::NewComponentDialog(const QString & initialName, const QString & initialUid, QWidget *parent) +NewComponentDialog::NewComponentDialog(const QString& initialName, const QString& initialUid, QWidget* parent) : QDialog(parent), ui(new Ui::NewComponentDialog) { ui->setupUi(this); @@ -81,12 +81,9 @@ void NewComponentDialog::updateDialogState() { auto protoUid = ui->nameTextBox->text().toLower(); protoUid.remove(QRegularExpression("[^a-z]")); - if(protoUid.isEmpty()) - { + if (protoUid.isEmpty()) { ui->uidTextBox->setPlaceholderText(originalPlaceholderText); - } - else - { + } else { QString suggestedUid = "org.multimc.custom." + protoUid; ui->uidTextBox->setPlaceholderText(suggestedUid); } @@ -97,8 +94,7 @@ void NewComponentDialog::updateDialogState() QString NewComponentDialog::name() const { auto result = ui->nameTextBox->text(); - if(result.size()) - { + if (result.size()) { return result.trimmed(); } return QString(); @@ -107,13 +103,11 @@ QString NewComponentDialog::name() const QString NewComponentDialog::uid() const { auto result = ui->uidTextBox->text(); - if(result.size()) - { + if (result.size()) { return result.trimmed(); } result = ui->uidTextBox->placeholderText(); - if(result.size() && result != originalPlaceholderText) - { + if (result.size() && result != originalPlaceholderText) { return result.trimmed(); } return QString(); diff --git a/launcher/ui/dialogs/NewComponentDialog.h b/launcher/ui/dialogs/NewComponentDialog.h index 8c790beb3..4fb68ff2f 100644 --- a/launcher/ui/dialogs/NewComponentDialog.h +++ b/launcher/ui/dialogs/NewComponentDialog.h @@ -20,28 +20,26 @@ #include #include -namespace Ui -{ +namespace Ui { class NewComponentDialog; } -class NewComponentDialog : public QDialog -{ +class NewComponentDialog : public QDialog { Q_OBJECT -public: - explicit NewComponentDialog(const QString & initialName = QString(), const QString & initialUid = QString(), QWidget *parent = 0); + public: + explicit NewComponentDialog(const QString& initialName = QString(), const QString& initialUid = QString(), QWidget* parent = 0); virtual ~NewComponentDialog(); void setBlacklist(QStringList badUids); QString name() const; QString uid() const; -private slots: + private slots: void updateDialogState(); -private: - Ui::NewComponentDialog *ui; + private: + Ui::NewComponentDialog* ui; QString originalPlaceholderText; QStringList uidBlacklist; diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 3e6456bc2..fba689067 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -87,15 +87,14 @@ NewInstanceDialog::NewInstanceDialog(const QString& initialGroup, const QString& groupList.push_front(""); ui->groupBox->addItems(groupList); int index = groupList.indexOf(initialGroup); - if(index == -1) - { + if (index == -1) { index = 0; } ui->groupBox->setCurrentIndex(index); ui->groupBox->lineEdit()->setPlaceholderText(tr("No group")); - - // NOTE: m_buttons must be initialized before PageContainer, because it indirectly accesses m_buttons through setSuggestedPack! Do not move this below. + // NOTE: m_buttons must be initialized before PageContainer, because it indirectly accesses m_buttons through setSuggestedPack! Do not + // move this below. m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel); m_container = new PageContainer(this, {}, this); @@ -122,8 +121,7 @@ NewInstanceDialog::NewInstanceDialog(const QString& initialGroup, const QString& HelpButton->setAutoDefault(false); connect(HelpButton, &QPushButton::clicked, m_container, &PageContainer::help); - if(!url.isEmpty()) - { + if (!url.isEmpty()) { QUrl actualUrl(url); m_container->selectPage("import"); importPage->setUrl(url); @@ -155,9 +153,9 @@ void NewInstanceDialog::accept() QDialog::accept(); } -QList NewInstanceDialog::getPages() +QList NewInstanceDialog::getPages() { - QList pages; + QList pages; importPage = new ImportPage(this); @@ -216,17 +214,17 @@ void NewInstanceDialog::setSuggestedPack(const QString& name, QString version, I m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK); } -void NewInstanceDialog::setSuggestedIconFromFile(const QString &path, const QString &name) +void NewInstanceDialog::setSuggestedIconFromFile(const QString& path, const QString& name) { importIcon = true; importIconPath = path; importIconName = name; - //Hmm, for some reason they can be to small + // Hmm, for some reason they can be to small ui->iconButton->setIcon(QIcon(path)); } -void NewInstanceDialog::setSuggestedIcon(const QString &key) +void NewInstanceDialog::setSuggestedIcon(const QString& key) { auto icon = APPLICATION->icons()->getIcon(key); importIcon = false; @@ -234,9 +232,9 @@ void NewInstanceDialog::setSuggestedIcon(const QString &key) ui->iconButton->setIcon(icon); } -InstanceTask * NewInstanceDialog::extractTask() +InstanceTask* NewInstanceDialog::extractTask() { - InstanceTask * extracted = creationTask.get(); + InstanceTask* extracted = creationTask.get(); creationTask.release(); InstanceName inst_name(ui->instNameTextBox->placeholderText().trimmed(), importVersion); @@ -252,8 +250,7 @@ void NewInstanceDialog::updateDialogState() { auto allowOK = creationTask && !instName().isEmpty(); auto OkButton = m_buttons->button(QDialogButtonBox::Ok); - if(OkButton->isEnabled() != allowOK) - { + if (OkButton->isEnabled() != allowOK) { OkButton->setEnabled(allowOK); } } @@ -261,13 +258,11 @@ void NewInstanceDialog::updateDialogState() QString NewInstanceDialog::instName() const { auto result = ui->instNameTextBox->text().trimmed(); - if(result.size()) - { + if (result.size()) { return result; } result = ui->instNameTextBox->placeholderText().trimmed(); - if(result.size()) - { + if (result.size()) { return result; } return QString(); diff --git a/launcher/ui/dialogs/NewInstanceDialog.h b/launcher/ui/dialogs/NewInstanceDialog.h index 961f512e2..de054cf7a 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.h +++ b/launcher/ui/dialogs/NewInstanceDialog.h @@ -37,11 +37,10 @@ #include -#include "ui/pages/BasePageProvider.h" #include "InstanceTask.h" +#include "ui/pages/BasePageProvider.h" -namespace Ui -{ +namespace Ui { class NewInstanceDialog; } @@ -50,45 +49,44 @@ class QDialogButtonBox; class ImportPage; class FlamePage; -class NewInstanceDialog : public QDialog, public BasePageProvider -{ +class NewInstanceDialog : public QDialog, public BasePageProvider { Q_OBJECT -public: - explicit NewInstanceDialog(const QString & initialGroup, const QString & url = QString(), QWidget *parent = 0); + public: + explicit NewInstanceDialog(const QString& initialGroup, const QString& url = QString(), QWidget* parent = 0); ~NewInstanceDialog(); void updateDialogState(); - void setSuggestedPack(const QString& name = QString(), InstanceTask * task = nullptr); - void setSuggestedPack(const QString& name, QString version, InstanceTask * task = nullptr); - void setSuggestedIconFromFile(const QString &path, const QString &name); - void setSuggestedIcon(const QString &key); + void setSuggestedPack(const QString& name = QString(), InstanceTask* task = nullptr); + void setSuggestedPack(const QString& name, QString version, InstanceTask* task = nullptr); + void setSuggestedIconFromFile(const QString& path, const QString& name); + void setSuggestedIcon(const QString& key); - InstanceTask * extractTask(); + InstanceTask* extractTask(); QString dialogTitle() override; - QList getPages() override; + QList getPages() override; QString instName() const; QString instGroup() const; QString iconKey() const; -public slots: + public slots: void accept() override; void reject() override; -private slots: + private slots: void on_iconButton_clicked(); - void on_instNameTextBox_textChanged(const QString &arg1); + void on_instNameTextBox_textChanged(const QString& arg1); -private: - Ui::NewInstanceDialog *ui = nullptr; - PageContainer * m_container = nullptr; - QDialogButtonBox * m_buttons = nullptr; + private: + Ui::NewInstanceDialog* ui = nullptr; + PageContainer* m_container = nullptr; + QDialogButtonBox* m_buttons = nullptr; QString InstIconKey; - ImportPage *importPage = nullptr; + ImportPage* importPage = nullptr; std::unique_ptr creationTask; bool importIcon = false; diff --git a/launcher/ui/dialogs/OfflineLoginDialog.cpp b/launcher/ui/dialogs/OfflineLoginDialog.cpp index a69537abb..137620be4 100644 --- a/launcher/ui/dialogs/OfflineLoginDialog.cpp +++ b/launcher/ui/dialogs/OfflineLoginDialog.cpp @@ -5,7 +5,7 @@ #include -OfflineLoginDialog::OfflineLoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::OfflineLoginDialog) +OfflineLoginDialog::OfflineLoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::OfflineLoginDialog) { ui->setupUi(this); ui->progressBar->setVisible(false); @@ -52,22 +52,20 @@ void OfflineLoginDialog::on_allowLongUsernames_stateChanged(int value) } // Enable the OK button only when the textbox contains something. -void OfflineLoginDialog::on_userTextBox_textEdited(const QString &newText) +void OfflineLoginDialog::on_userTextBox_textEdited(const QString& newText) { - ui->buttonBox->button(QDialogButtonBox::Ok) - ->setEnabled(!newText.isEmpty()); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!newText.isEmpty()); } -void OfflineLoginDialog::onTaskFailed(const QString &reason) +void OfflineLoginDialog::onTaskFailed(const QString& reason) { // Set message auto lines = reason.split('\n'); QString processed; - for(auto line: lines) { - if(line.size()) { + for (auto line : lines) { + if (line.size()) { processed += "" + line + "
"; - } - else { + } else { processed += "
"; } } @@ -83,7 +81,7 @@ void OfflineLoginDialog::onTaskSucceeded() QDialog::accept(); } -void OfflineLoginDialog::onTaskStatus(const QString &status) +void OfflineLoginDialog::onTaskStatus(const QString& status) { ui->label->setText(status); } @@ -95,12 +93,11 @@ void OfflineLoginDialog::onTaskProgress(qint64 current, qint64 total) } // Public interface -MinecraftAccountPtr OfflineLoginDialog::newAccount(QWidget *parent, QString msg) +MinecraftAccountPtr OfflineLoginDialog::newAccount(QWidget* parent, QString msg) { OfflineLoginDialog dlg(parent); dlg.ui->label->setText(msg); - if (dlg.exec() == QDialog::Accepted) - { + if (dlg.exec() == QDialog::Accepted) { return dlg.m_account; } return nullptr; diff --git a/launcher/ui/dialogs/OfflineLoginDialog.h b/launcher/ui/dialogs/OfflineLoginDialog.h index fdb3d91fa..a50024a6c 100644 --- a/launcher/ui/dialogs/OfflineLoginDialog.h +++ b/launcher/ui/dialogs/OfflineLoginDialog.h @@ -1,44 +1,41 @@ #pragma once -#include #include +#include #include "minecraft/auth/MinecraftAccount.h" #include "tasks/Task.h" -namespace Ui -{ +namespace Ui { class OfflineLoginDialog; } -class OfflineLoginDialog : public QDialog -{ +class OfflineLoginDialog : public QDialog { Q_OBJECT -public: + public: ~OfflineLoginDialog(); - static MinecraftAccountPtr newAccount(QWidget *parent, QString message); + static MinecraftAccountPtr newAccount(QWidget* parent, QString message); -private: - explicit OfflineLoginDialog(QWidget *parent = 0); + private: + explicit OfflineLoginDialog(QWidget* parent = 0); void setUserInputsEnabled(bool enable); -protected -slots: + protected slots: void accept(); - void onTaskFailed(const QString &reason); + void onTaskFailed(const QString& reason); void onTaskSucceeded(); - void onTaskStatus(const QString &status); + void onTaskStatus(const QString& status); void onTaskProgress(qint64 current, qint64 total); - void on_userTextBox_textEdited(const QString &newText); + void on_userTextBox_textEdited(const QString& newText); void on_allowLongUsernames_stateChanged(int value); -private: - Ui::OfflineLoginDialog *ui; + private: + Ui::OfflineLoginDialog* ui; MinecraftAccountPtr m_account; Task::Ptr m_loginTask; }; diff --git a/launcher/ui/dialogs/ProfileSelectDialog.cpp b/launcher/ui/dialogs/ProfileSelectDialog.cpp index 7882cf45e..a62238bdb 100644 --- a/launcher/ui/dialogs/ProfileSelectDialog.cpp +++ b/launcher/ui/dialogs/ProfileSelectDialog.cpp @@ -16,43 +16,38 @@ #include "ProfileSelectDialog.h" #include "ui_ProfileSelectDialog.h" -#include #include +#include -#include "SkinUtils.h" #include "Application.h" +#include "SkinUtils.h" #include "ui/dialogs/ProgressDialog.h" -ProfileSelectDialog::ProfileSelectDialog(const QString &message, int flags, QWidget *parent) +ProfileSelectDialog::ProfileSelectDialog(const QString& message, int flags, QWidget* parent) : QDialog(parent), ui(new Ui::ProfileSelectDialog) { ui->setupUi(this); m_accounts = APPLICATION->accounts(); auto view = ui->listView; - //view->setModel(m_accounts.get()); - //view->hideColumn(AccountList::ActiveColumn); + // view->setModel(m_accounts.get()); + // view->hideColumn(AccountList::ActiveColumn); view->setColumnCount(1); view->setRootIsDecorated(false); // FIXME: use a real model, not this - if(QTreeWidgetItem* header = view->headerItem()) - { + if (QTreeWidgetItem* header = view->headerItem()) { header->setText(0, tr("Name")); - } - else - { + } else { view->setHeaderLabel(tr("Name")); } - QList items; - for (int i = 0; i < m_accounts->count(); i++) - { + QList items; + for (int i = 0; i < m_accounts->count(); i++) { MinecraftAccountPtr account = m_accounts->at(i); QString profileLabel; - if(account->isInUse()) { + if (account->isInUse()) { profileLabel = tr("%1 (in use)").arg(account->profileName()); - } - else { + } else { profileLabel = account->profileName(); } auto item = new QTreeWidgetItem(view); @@ -101,8 +96,7 @@ bool ProfileSelectDialog::useAsInstDefaullt() const void ProfileSelectDialog::on_buttonBox_accepted() { QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.size() > 0) - { + if (selection.size() > 0) { QModelIndex selected = selection.first(); m_selected = selected.data(AccountList::PointerRole).value(); } diff --git a/launcher/ui/dialogs/ProfileSelectDialog.h b/launcher/ui/dialogs/ProfileSelectDialog.h index 38aa42496..e56ba0527 100644 --- a/launcher/ui/dialogs/ProfileSelectDialog.h +++ b/launcher/ui/dialogs/ProfileSelectDialog.h @@ -21,17 +21,14 @@ #include "minecraft/auth/AccountList.h" -namespace Ui -{ +namespace Ui { class ProfileSelectDialog; } -class ProfileSelectDialog : public QDialog -{ +class ProfileSelectDialog : public QDialog { Q_OBJECT -public: - enum Flags - { + public: + enum Flags { NoFlags = 0, /*! @@ -52,7 +49,7 @@ public: * Constructs a new account select dialog with the given parent and message. * The message will be shown at the top of the dialog. It is an empty string by default. */ - explicit ProfileSelectDialog(const QString& message="", int flags=0, QWidget *parent = 0); + explicit ProfileSelectDialog(const QString& message = "", int flags = 0, QWidget* parent = 0); ~ProfileSelectDialog(); /*! @@ -73,18 +70,17 @@ public: */ bool useAsInstDefaullt() const; -public -slots: + public slots: void on_buttonBox_accepted(); void on_buttonBox_rejected(); -protected: + protected: shared_qobject_ptr m_accounts; //! The account that was selected when the user clicked OK. MinecraftAccountPtr m_selected; -private: - Ui::ProfileSelectDialog *ui; + private: + Ui::ProfileSelectDialog* ui; }; diff --git a/launcher/ui/dialogs/ProfileSetupDialog.cpp b/launcher/ui/dialogs/ProfileSetupDialog.cpp index 758f7f233..207733bbf 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.cpp +++ b/launcher/ui/dialogs/ProfileSetupDialog.cpp @@ -36,11 +36,11 @@ #include "ProfileSetupDialog.h" #include "ui_ProfileSetupDialog.h" -#include #include -#include -#include #include +#include +#include +#include #include "ui/dialogs/ProgressDialog.h" @@ -48,8 +48,7 @@ #include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/Parsers.h" - -ProfileSetupDialog::ProfileSetupDialog(MinecraftAccountPtr accountToSetup, QWidget *parent) +ProfileSetupDialog::ProfileSetupDialog(MinecraftAccountPtr accountToSetup, QWidget* parent) : QDialog(parent), m_accountToSetup(accountToSetup), ui(new Ui::ProfileSetupDialog) { ui->setupUi(this); @@ -91,13 +90,11 @@ void ProfileSetupDialog::setNameStatus(ProfileSetupDialog::NameStatus status, QS { nameStatus = status; auto okButton = ui->buttonBox->button(QDialogButtonBox::Ok); - switch(nameStatus) - { + switch (nameStatus) { case NameStatus::Available: { validityAction->setIcon(goodIcon); okButton->setEnabled(true); - } - break; + } break; case NameStatus::NotSet: case NameStatus::Pending: validityAction->setIcon(yellowIcon); @@ -109,43 +106,44 @@ void ProfileSetupDialog::setNameStatus(ProfileSetupDialog::NameStatus status, QS okButton->setEnabled(false); break; } - if(!errorString.isEmpty()) { + if (!errorString.isEmpty()) { ui->errorLabel->setText(errorString); ui->errorLabel->setVisible(true); - } - else { + } else { ui->errorLabel->setVisible(false); } } void ProfileSetupDialog::nameEdited(const QString& name) { - if(!ui->nameEdit->hasAcceptableInput()) { + if (!ui->nameEdit->hasAcceptableInput()) { setNameStatus(NameStatus::NotSet, tr("Name is too short - must be between 3 and 16 characters long.")); return; } scheduleCheck(name); } -void ProfileSetupDialog::scheduleCheck(const QString& name) { +void ProfileSetupDialog::scheduleCheck(const QString& name) +{ queuedCheck = name; setNameStatus(NameStatus::Pending); checkStartTimer.start(1000); } -void ProfileSetupDialog::startCheck() { - if(isChecking) { +void ProfileSetupDialog::startCheck() +{ + if (isChecking) { return; } - if(queuedCheck.isNull()) { + if (queuedCheck.isNull()) { return; } checkName(queuedCheck); } - -void ProfileSetupDialog::checkName(const QString &name) { - if(isChecking) { +void ProfileSetupDialog::checkName(const QString& name) +{ + if (isChecking) { return; } @@ -160,44 +158,40 @@ void ProfileSetupDialog::checkName(const QString &name) { request.setRawHeader("Accept", "application/json"); request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8()); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &ProfileSetupDialog::checkFinished); requestor->get(request); } -void ProfileSetupDialog::checkFinished( - QNetworkReply::NetworkError error, - QByteArray profileData, - [[maybe_unused]] QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void ProfileSetupDialog::checkFinished(QNetworkReply::NetworkError error, + QByteArray profileData, + [[maybe_unused]] QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); - if(error == QNetworkReply::NoError) { + if (error == QNetworkReply::NoError) { auto doc = QJsonDocument::fromJson(profileData); auto root = doc.object(); auto statusValue = root.value("status").toString("INVALID"); - if(statusValue == "AVAILABLE") { + if (statusValue == "AVAILABLE") { setNameStatus(NameStatus::Available); - } - else if (statusValue == "DUPLICATE") { + } else if (statusValue == "DUPLICATE") { setNameStatus(NameStatus::Exists, tr("Minecraft profile with name %1 already exists.").arg(currentCheck)); - } - else if (statusValue == "NOT_ALLOWED") { + } else if (statusValue == "NOT_ALLOWED") { setNameStatus(NameStatus::Exists, tr("The name %1 is not allowed.").arg(currentCheck)); - } - else { + } else { setNameStatus(NameStatus::Error, tr("Unhandled profile name status: %1").arg(statusValue)); } - } - else { + } else { setNameStatus(NameStatus::Error, tr("Failed to check name availability.")); } isChecking = false; } -void ProfileSetupDialog::setupProfile(const QString &profileName) { - if(isWorking) { +void ProfileSetupDialog::setupProfile(const QString& profileName) +{ + if (isWorking) { return; } @@ -212,7 +206,7 @@ void ProfileSetupDialog::setupProfile(const QString &profileName) { QString payloadTemplate("{\"profileName\":\"%1\"}"); auto profileData = payloadTemplate.arg(profileName).toUtf8(); - AuthRequest *requestor = new AuthRequest(this); + AuthRequest* requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &ProfileSetupDialog::setupProfileFinished); requestor->post(request, profileData); isWorking = true; @@ -223,8 +217,9 @@ void ProfileSetupDialog::setupProfile(const QString &profileName) { namespace { -struct MojangError{ - static MojangError fromJSON(QByteArray data) { +struct MojangError { + static MojangError fromJSON(QByteArray data) + { MojangError out; out.error = QString::fromUtf8(data); auto doc = QJsonDocument::fromJson(data, &out.parseError); @@ -247,25 +242,23 @@ struct MojangError{ QString errorMessage; }; -} +} // namespace -void ProfileSetupDialog::setupProfileFinished( - QNetworkReply::NetworkError error, - QByteArray errorData, - [[maybe_unused]] QList headers -) { - auto requestor = qobject_cast(QObject::sender()); +void ProfileSetupDialog::setupProfileFinished(QNetworkReply::NetworkError error, + QByteArray errorData, + [[maybe_unused]] QList headers) +{ + auto requestor = qobject_cast(QObject::sender()); requestor->deleteLater(); isWorking = false; - if(error == QNetworkReply::NoError) { + if (error == QNetworkReply::NoError) { /* * data contains the profile in the response * ... we could parse it and update the account, but let's just return back to the normal login flow instead... */ accept(); - } - else { + } else { auto parsedError = MojangError::fromJSON(errorData); ui->errorLabel->setVisible(true); ui->errorLabel->setText(tr("The server returned the following error:") + "\n\n" + parsedError.errorMessage); diff --git a/launcher/ui/dialogs/ProfileSetupDialog.h b/launcher/ui/dialogs/ProfileSetupDialog.h index 6f413ebdf..09f8124e2 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.h +++ b/launcher/ui/dialogs/ProfileSetupDialog.h @@ -17,65 +17,48 @@ #include #include -#include #include +#include -#include #include +#include -namespace Ui -{ +namespace Ui { class ProfileSetupDialog; } -class ProfileSetupDialog : public QDialog -{ +class ProfileSetupDialog : public QDialog { Q_OBJECT -public: - - explicit ProfileSetupDialog(MinecraftAccountPtr accountToSetup, QWidget *parent = 0); + public: + explicit ProfileSetupDialog(MinecraftAccountPtr accountToSetup, QWidget* parent = 0); ~ProfileSetupDialog(); - enum class NameStatus - { - NotSet, - Pending, - Available, - Exists, - Error - } nameStatus = NameStatus::NotSet; + enum class NameStatus { NotSet, Pending, Available, Exists, Error } nameStatus = NameStatus::NotSet; -private slots: + private slots: void on_buttonBox_accepted(); void on_buttonBox_rejected(); - void nameEdited(const QString &name); - void checkFinished( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers - ); + void nameEdited(const QString& name); + void checkFinished(QNetworkReply::NetworkError error, QByteArray data, QList headers); void startCheck(); - void setupProfileFinished( - QNetworkReply::NetworkError error, - QByteArray data, - QList headers - ); -protected: - void scheduleCheck(const QString &name); - void checkName(const QString &name); + void setupProfileFinished(QNetworkReply::NetworkError error, QByteArray data, QList headers); + + protected: + void scheduleCheck(const QString& name); + void checkName(const QString& name); void setNameStatus(NameStatus status, QString errorString); - void setupProfile(const QString & profileName); + void setupProfile(const QString& profileName); -private: + private: MinecraftAccountPtr m_accountToSetup; - Ui::ProfileSetupDialog *ui; + Ui::ProfileSetupDialog* ui; QIcon goodIcon; QIcon yellowIcon; QIcon badIcon; - QAction * validityAction = nullptr; + QAction* validityAction = nullptr; QString queuedCheck; @@ -85,4 +68,3 @@ private: QTimer checkStartTimer; }; - diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 222ce9735..0ca3a1bd9 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -37,18 +37,17 @@ #include #include "ui_ProgressDialog.h" -#include #include #include +#include #include "tasks/Task.h" #include "ui/widgets/SubTaskProgressBar.h" - // map a value in a numeric range of an arbitrary type to between 0 and INT_MAX // for getting the best precision out of the qt progress bar -template, bool> = true> +template , bool> = true> std::tuple map_int_zero_max(T current, T range_max, T range_min) { int int_max = std::numeric_limits::max(); @@ -57,10 +56,9 @@ std::tuple map_int_zero_max(T current, T range_max, T range_min) double percentage = static_cast(current - range_min) / static_cast(type_range); int mapped_current = percentage * int_max; - return {mapped_current, int_max}; + return { mapped_current, int_max }; } - ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ProgressDialog) { ui->setupUi(this); @@ -96,7 +94,7 @@ ProgressDialog::~ProgressDialog() } void ProgressDialog::updateSize(bool recenterParent) -{ +{ QSize lastSize = this->size(); QPoint lastPos = this->pos(); int minHeight = ui->globalStatusDetailsLabel->minimumSize().height() + (ui->verticalLayout->spacing() * 2); @@ -118,16 +116,13 @@ void ProgressDialog::updateSize(bool recenterParent) auto newX = std::max(0, parent->x() + ((parent->width() - newSize.width()) / 2)); auto newY = std::max(0, parent->y() + ((parent->height() - newSize.height()) / 2)); this->move(newX, newY); - } - else if (lastSize != newSize) - { + } else if (lastSize != newSize) { // center on old position after resize - QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative + QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative auto newX = std::max(0, lastPos.x() + (sizeDiff.width() / 2)); auto newY = std::max(0, lastPos.y() + (sizeDiff.height() / 2)); this->move(newX, newY); } - } int ProgressDialog::execWithTask(Task* task) @@ -139,7 +134,7 @@ int ProgressDialog::execWithTask(Task* task) return QDialog::DialogCode::Accepted; } - QDialog::DialogCode result {}; + QDialog::DialogCode result{}; if (handleImmediateResult(result)) { return result; } @@ -221,7 +216,6 @@ void ProgressDialog::changeStatus([[maybe_unused]] const QString& status) ui->globalStatusDetailsLabel->setText(m_task->getDetails()); ui->globalStatusDetailsLabel->adjustSize(); - updateSize(); } @@ -235,16 +229,15 @@ void ProgressDialog::addTaskProgress(TaskStepProgress const& progress) void ProgressDialog::changeStepProgress(TaskStepProgress const& task_progress) { m_is_multi_step = true; - if(ui->taskProgressScrollArea->isHidden()) { + if (ui->taskProgressScrollArea->isHidden()) { ui->taskProgressScrollArea->setHidden(false); updateSize(); } - + if (!taskProgress.contains(task_progress.uid)) addTaskProgress(task_progress); auto task_bar = taskProgress.value(task_progress.uid); - auto const [mapped_current, mapped_total] = map_int_zero_max(task_progress.current, task_progress.total, 0); if (task_progress.total <= 0) { task_bar->setRange(0, 0); @@ -259,14 +252,12 @@ void ProgressDialog::changeStepProgress(TaskStepProgress const& task_progress) if (task_progress.isDone()) { task_bar->setVisible(false); } - } void ProgressDialog::changeProgress(qint64 current, qint64 total) { ui->globalProgressBar->setMaximum(total); ui->globalProgressBar->setValue(current); - } void ProgressDialog::keyPressEvent(QKeyEvent* e) diff --git a/launcher/ui/dialogs/ProgressDialog.h b/launcher/ui/dialogs/ProgressDialog.h index 51700d870..15eadf4e7 100644 --- a/launcher/ui/dialogs/ProgressDialog.h +++ b/launcher/ui/dialogs/ProgressDialog.h @@ -33,13 +33,12 @@ * limitations under the License. */ - #pragma once #include -#include #include #include +#include #include "QObjectPtr.h" #include "tasks/Task.h" @@ -49,60 +48,52 @@ class Task; class SequentialTask; -namespace Ui -{ +namespace Ui { class ProgressDialog; } -class ProgressDialog : public QDialog -{ +class ProgressDialog : public QDialog { Q_OBJECT -public: - explicit ProgressDialog(QWidget *parent = 0); + public: + explicit ProgressDialog(QWidget* parent = 0); ~ProgressDialog(); void updateSize(bool recenterParent = false); int execWithTask(Task* task); - int execWithTask(std::unique_ptr &&task); - int execWithTask(std::unique_ptr &task); + int execWithTask(std::unique_ptr&& task); + int execWithTask(std::unique_ptr& task); void setSkipButton(bool present, QString label = QString()); - Task *getTask(); + Task* getTask(); -public -slots: + public slots: void onTaskStarted(); void onTaskFailed(QString failure); void onTaskSucceeded(); - void changeStatus(const QString &status); + void changeStatus(const QString& status); void changeProgress(qint64 current, qint64 total); void changeStepProgress(TaskStepProgress const& task_progress); - -private -slots: + private slots: void on_skipButton_clicked(bool checked); -protected: - virtual void keyPressEvent(QKeyEvent *e); - virtual void closeEvent(QCloseEvent *e); + protected: + virtual void keyPressEvent(QKeyEvent* e); + virtual void closeEvent(QCloseEvent* e); -private: - bool handleImmediateResult(QDialog::DialogCode &result); + private: + bool handleImmediateResult(QDialog::DialogCode& result); void addTaskProgress(TaskStepProgress const& progress); -private: - Ui::ProgressDialog *ui; + private: + Ui::ProgressDialog* ui; - Task *m_task; + Task* m_task; bool m_is_multi_step = false; QHash taskProgress; - - }; - diff --git a/launcher/ui/dialogs/ScrollMessageBox.cpp b/launcher/ui/dialogs/ScrollMessageBox.cpp index afdc4bae1..c04d87842 100644 --- a/launcher/ui/dialogs/ScrollMessageBox.cpp +++ b/launcher/ui/dialogs/ScrollMessageBox.cpp @@ -1,15 +1,16 @@ #include "ScrollMessageBox.h" #include "ui_ScrollMessageBox.h" - -ScrollMessageBox::ScrollMessageBox(QWidget *parent, const QString &title, const QString &text, const QString &body) : - QDialog(parent), ui(new Ui::ScrollMessageBox) { +ScrollMessageBox::ScrollMessageBox(QWidget* parent, const QString& title, const QString& text, const QString& body) + : QDialog(parent), ui(new Ui::ScrollMessageBox) +{ ui->setupUi(this); this->setWindowTitle(title); ui->label->setText(text); ui->textBrowser->setText(body); } -ScrollMessageBox::~ScrollMessageBox() { +ScrollMessageBox::~ScrollMessageBox() +{ delete ui; } diff --git a/launcher/ui/dialogs/ScrollMessageBox.h b/launcher/ui/dialogs/ScrollMessageBox.h index 84aa253a9..8fd6769c4 100644 --- a/launcher/ui/dialogs/ScrollMessageBox.h +++ b/launcher/ui/dialogs/ScrollMessageBox.h @@ -2,19 +2,20 @@ #include - QT_BEGIN_NAMESPACE -namespace Ui { class ScrollMessageBox; } +namespace Ui { +class ScrollMessageBox; +} QT_END_NAMESPACE class ScrollMessageBox : public QDialog { -Q_OBJECT + Q_OBJECT -public: - ScrollMessageBox(QWidget *parent, const QString &title, const QString &text, const QString &body); + public: + ScrollMessageBox(QWidget* parent, const QString& title, const QString& text, const QString& body); ~ScrollMessageBox() override; -private: - Ui::ScrollMessageBox *ui; + private: + Ui::ScrollMessageBox* ui; }; diff --git a/launcher/ui/dialogs/SkinUploadDialog.cpp b/launcher/ui/dialogs/SkinUploadDialog.cpp index 1ff15c877..9422b8d68 100644 --- a/launcher/ui/dialogs/SkinUploadDialog.cpp +++ b/launcher/ui/dialogs/SkinUploadDialog.cpp @@ -33,20 +33,20 @@ * limitations under the License. */ -#include #include +#include #include #include -#include #include +#include #include +#include "CustomMessageBox.h" +#include "ProgressDialog.h" #include "SkinUploadDialog.h" #include "ui_SkinUploadDialog.h" -#include "ProgressDialog.h" -#include "CustomMessageBox.h" void SkinUploadDialog::on_buttonBox_rejected() { @@ -64,71 +64,51 @@ void SkinUploadDialog::on_buttonBox_accepted() QRegularExpression urlPrefixMatcher(QRegularExpression::anchoredPattern("^([a-z]+)://.+$")); bool isLocalFile = false; // it has an URL prefix -> it is an URL - if(urlPrefixMatcher.match(input).hasMatch()) - { + if (urlPrefixMatcher.match(input).hasMatch()) { QUrl fileURL = input; - if(fileURL.isValid()) - { + if (fileURL.isValid()) { // local? - if(fileURL.isLocalFile()) - { + if (fileURL.isLocalFile()) { isLocalFile = true; fileName = fileURL.toLocalFile(); - } - else - { - CustomMessageBox::selectable( - this, - tr("Skin Upload"), - tr("Using remote URLs for setting skins is not implemented yet."), - QMessageBox::Warning - )->exec(); + } else { + CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Using remote URLs for setting skins is not implemented yet."), + QMessageBox::Warning) + ->exec(); close(); return; } - } - else - { - CustomMessageBox::selectable( - this, - tr("Skin Upload"), - tr("You cannot use an invalid URL for uploading skins."), - QMessageBox::Warning - )->exec(); + } else { + CustomMessageBox::selectable(this, tr("Skin Upload"), tr("You cannot use an invalid URL for uploading skins."), + QMessageBox::Warning) + ->exec(); close(); return; } - } - else - { + } else { // just assume it's a path then isLocalFile = true; fileName = ui->skinPathTextBox->text(); } - if (isLocalFile && !QFile::exists(fileName)) - { + if (isLocalFile && !QFile::exists(fileName)) { CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Skin file does not exist!"), QMessageBox::Warning)->exec(); close(); return; } SkinUpload::Model model = SkinUpload::STEVE; - if (ui->steveBtn->isChecked()) - { + if (ui->steveBtn->isChecked()) { model = SkinUpload::STEVE; - } - else if (ui->alexBtn->isChecked()) - { + } else if (ui->alexBtn->isChecked()) { model = SkinUpload::ALEX; } skinUpload.addTask(shared_qobject_ptr(new SkinUpload(this, m_acct->accessToken(), FS::read(fileName), model))); } auto selectedCape = ui->capeCombo->currentData().toString(); - if(selectedCape != m_acct->accountData()->minecraftProfile.currentCape) { + if (selectedCape != m_acct->accountData()->minecraftProfile.currentCape) { skinUpload.addTask(shared_qobject_ptr(new CapeChange(this, m_acct->accessToken(), selectedCape))); } - if (prog.execWithTask(&skinUpload) != QDialog::Accepted) - { + if (prog.execWithTask(&skinUpload) != QDialog::Accepted) { CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to upload skin!"), QMessageBox::Warning)->exec(); close(); return; @@ -141,45 +121,43 @@ void SkinUploadDialog::on_skinBrowseBtn_clicked() { auto filter = QMimeDatabase().mimeTypeForName("image/png").filterString(); QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), filter); - if (raw_path.isEmpty() || !QFileInfo::exists(raw_path)) - { + if (raw_path.isEmpty() || !QFileInfo::exists(raw_path)) { return; } QString cooked_path = FS::NormalizePath(raw_path); ui->skinPathTextBox->setText(cooked_path); } -SkinUploadDialog::SkinUploadDialog(MinecraftAccountPtr acct, QWidget *parent) - :QDialog(parent), m_acct(acct), ui(new Ui::SkinUploadDialog) +SkinUploadDialog::SkinUploadDialog(MinecraftAccountPtr acct, QWidget* parent) : QDialog(parent), m_acct(acct), ui(new Ui::SkinUploadDialog) { ui->setupUi(this); // FIXME: add a model for this, download/refresh the capes on demand - auto &accountData = *acct->accountData(); + auto& accountData = *acct->accountData(); int index = 0; ui->capeCombo->addItem(tr("No Cape"), QVariant()); auto currentCape = accountData.minecraftProfile.currentCape; - if(currentCape.isEmpty()) { + if (currentCape.isEmpty()) { ui->capeCombo->setCurrentIndex(index); } - for(auto & cape: accountData.minecraftProfile.capes) { + for (auto& cape : accountData.minecraftProfile.capes) { index++; - if(cape.data.size()) { + if (cape.data.size()) { QPixmap capeImage; - if(capeImage.loadFromData(cape.data, "PNG")) { + if (capeImage.loadFromData(cape.data, "PNG")) { QPixmap preview = QPixmap(10, 16); QPainter painter(&preview); painter.drawPixmap(0, 0, capeImage.copy(1, 1, 10, 16)); ui->capeCombo->addItem(capeImage, cape.alias, cape.id); - if(currentCape == cape.id) { + if (currentCape == cape.id) { ui->capeCombo->setCurrentIndex(index); } continue; } } ui->capeCombo->addItem(cape.alias, cape.id); - if(currentCape == cape.id) { + if (currentCape == cape.id) { ui->capeCombo->setCurrentIndex(index); } } diff --git a/launcher/ui/dialogs/SkinUploadDialog.h b/launcher/ui/dialogs/SkinUploadDialog.h index 84d17dc6f..81d6140cc 100644 --- a/launcher/ui/dialogs/SkinUploadDialog.h +++ b/launcher/ui/dialogs/SkinUploadDialog.h @@ -1,29 +1,28 @@ #pragma once -#include #include +#include -namespace Ui -{ - class SkinUploadDialog; +namespace Ui { +class SkinUploadDialog; } class SkinUploadDialog : public QDialog { Q_OBJECT -public: - explicit SkinUploadDialog(MinecraftAccountPtr acct, QWidget *parent = 0); - virtual ~SkinUploadDialog() {}; + public: + explicit SkinUploadDialog(MinecraftAccountPtr acct, QWidget* parent = 0); + virtual ~SkinUploadDialog(){}; -public slots: + public slots: void on_buttonBox_accepted(); void on_buttonBox_rejected(); void on_skinBrowseBtn_clicked(); -protected: + protected: MinecraftAccountPtr m_acct; -private: - Ui::SkinUploadDialog *ui; + private: + Ui::SkinUploadDialog* ui; }; diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index 9fa3c90f4..c61d10578 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -35,20 +35,19 @@ #include "VersionSelectDialog.h" +#include #include #include #include #include #include -#include #include "ui/widgets/VersionSelectWidget.h" #include "BaseVersion.h" #include "BaseVersionList.h" -VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable) - : QDialog(parent) +VersionSelectDialog::VersionSelectDialog(BaseVersionList* vlist, QString title, QWidget* parent, bool cancelable) : QDialog(parent) { setObjectName(QStringLiteral("VersionSelectDialog")); resize(400, 347); @@ -68,7 +67,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, m_buttonBox = new QDialogButtonBox(this); m_buttonBox->setObjectName(QStringLiteral("buttonBox")); m_buttonBox->setOrientation(Qt::Horizontal); - m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); m_horizontalLayout->addWidget(m_buttonBox); m_verticalLayout->addLayout(m_horizontalLayout); @@ -85,8 +84,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, m_vlist = vlist; - if (!cancelable) - { + if (!cancelable) { m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); } } @@ -125,8 +123,7 @@ int VersionSelectDialog::exec() QDialog::open(); m_versionWidget->initialize(m_vlist); m_versionWidget->selectSearch(); - if(resizeOnColumn != -1) - { + if (resizeOnColumn != -1) { m_versionWidget->setResizeOn(resizeOnColumn); } return QDialog::exec(); @@ -152,7 +149,8 @@ void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QStri m_versionWidget->setExactFilter(role, filter); } -void VersionSelectDialog::setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter) { +void VersionSelectDialog::setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter) +{ m_versionWidget->setExactIfPresentFilter(role, filter); } diff --git a/launcher/ui/dialogs/VersionSelectDialog.h b/launcher/ui/dialogs/VersionSelectDialog.h index c20a9ed58..0ccd45e74 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.h +++ b/launcher/ui/dialogs/VersionSelectDialog.h @@ -18,7 +18,6 @@ #include #include - #include "BaseVersionList.h" class QVBoxLayout; @@ -27,26 +26,24 @@ class QDialogButtonBox; class VersionSelectWidget; class QPushButton; -namespace Ui -{ +namespace Ui { class VersionSelectDialog; } class VersionProxyModel; -class VersionSelectDialog : public QDialog -{ +class VersionSelectDialog : public QDialog { Q_OBJECT -public: - explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true); - virtual ~VersionSelectDialog() {}; + public: + explicit VersionSelectDialog(BaseVersionList* vlist, QString title, QWidget* parent = 0, bool cancelable = true); + virtual ~VersionSelectDialog(){}; int exec() override; BaseVersion::Ptr selectedVersion() const; - void setCurrentVersion(const QString & version); + void setCurrentVersion(const QString& version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); void setExactFilter(BaseVersionList::ModelRoles role, QString filter); void setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter); @@ -54,26 +51,26 @@ public: void setEmptyErrorString(QString emptyErrorString); void setResizeOn(int column); -private slots: + private slots: void on_refreshButton_clicked(); -private: + private: void retranslate(); void selectRecommended(); -private: + private: QString m_currentVersion; - VersionSelectWidget *m_versionWidget = nullptr; - QVBoxLayout *m_verticalLayout = nullptr; - QHBoxLayout *m_horizontalLayout = nullptr; - QPushButton *m_refreshButton = nullptr; - QDialogButtonBox *m_buttonBox = nullptr; + VersionSelectWidget* m_versionWidget = nullptr; + QVBoxLayout* m_verticalLayout = nullptr; + QHBoxLayout* m_horizontalLayout = nullptr; + QPushButton* m_refreshButton = nullptr; + QDialogButtonBox* m_buttonBox = nullptr; - BaseVersionList *m_vlist = nullptr; + BaseVersionList* m_vlist = nullptr; - VersionProxyModel *m_proxyModel = nullptr; + VersionProxyModel* m_proxyModel = nullptr; int resizeOnColumn = -1; - Task * loadTask = nullptr; + Task* loadTask = nullptr; }; diff --git a/launcher/ui/instanceview/AccessibleInstanceView.cpp b/launcher/ui/instanceview/AccessibleInstanceView.cpp index 2e7b83000..c99fe541a 100644 --- a/launcher/ui/instanceview/AccessibleInstanceView.cpp +++ b/launcher/ui/instanceview/AccessibleInstanceView.cpp @@ -1,42 +1,40 @@ -#include "InstanceView.h" #include "AccessibleInstanceView.h" #include "AccessibleInstanceView_p.h" +#include "InstanceView.h" -#include #include #include +#include #ifndef QT_NO_ACCESSIBILITY -QAccessibleInterface *groupViewAccessibleFactory(const QString &classname, QObject *object) +QAccessibleInterface* groupViewAccessibleFactory(const QString& classname, QObject* object) { - QAccessibleInterface *iface = 0; + QAccessibleInterface* iface = 0; if (!object || !object->isWidgetType()) return iface; - QWidget *widget = static_cast(object); + QWidget* widget = static_cast(object); if (classname == QLatin1String("InstanceView")) { - iface = new AccessibleInstanceView((InstanceView *)widget); + iface = new AccessibleInstanceView((InstanceView*)widget); } return iface; } - -QAbstractItemView *AccessibleInstanceView::view() const +QAbstractItemView* AccessibleInstanceView::view() const { return qobject_cast(object()); } -int AccessibleInstanceView::logicalIndex(const QModelIndex &index) const +int AccessibleInstanceView::logicalIndex(const QModelIndex& index) const { if (!view()->model() || !index.isValid()) return -1; return index.row() * (index.model()->columnCount()) + index.column(); } -AccessibleInstanceView::AccessibleInstanceView(QWidget *w) - : QAccessibleObject(w) +AccessibleInstanceView::AccessibleInstanceView(QWidget* w) : QAccessibleObject(w) { Q_ASSERT(view()); } @@ -53,7 +51,7 @@ AccessibleInstanceView::~AccessibleInstanceView() } } -QAccessibleInterface *AccessibleInstanceView::cellAt(int row, int column) const +QAccessibleInterface* AccessibleInstanceView::cellAt(int row, int column) const { if (!view()->model()) { return 0; @@ -68,7 +66,7 @@ QAccessibleInterface *AccessibleInstanceView::cellAt(int row, int column) const return child(logicalIndex(index)); } -QAccessibleInterface *AccessibleInstanceView::caption() const +QAccessibleInterface* AccessibleInstanceView::caption() const { return 0; } @@ -123,14 +121,14 @@ QString AccessibleInstanceView::rowDescription(int row) const return view()->model()->headerData(row, Qt::Vertical).toString(); } -QList AccessibleInstanceView::selectedCells() const +QList AccessibleInstanceView::selectedCells() const { QList cells; if (!view()->selectionModel()) return cells; const QModelIndexList selectedIndexes = view()->selectionModel()->selectedIndexes(); cells.reserve(selectedIndexes.size()); - for (const QModelIndex &index : selectedIndexes) + for (const QModelIndex& index : selectedIndexes) cells.append(child(logicalIndex(index))); return cells; } @@ -145,7 +143,7 @@ QList AccessibleInstanceView::selectedColumns() const QList columns; columns.reserve(selectedColumns.size()); - for (const QModelIndex &index : selectedColumns) { + for (const QModelIndex& index : selectedColumns) { columns.append(index.column()); } @@ -163,14 +161,14 @@ QList AccessibleInstanceView::selectedRows() const const QModelIndexList selectedRows = view()->selectionModel()->selectedRows(); rows.reserve(selectedRows.size()); - for (const QModelIndex &index : selectedRows) { + for (const QModelIndex& index : selectedRows) { rows.append(index.row()); } return rows; } -QAccessibleInterface *AccessibleInstanceView::summary() const +QAccessibleInterface* AccessibleInstanceView::summary() const { return 0; } @@ -209,16 +207,17 @@ bool AccessibleInstanceView::selectRow(int row) return false; } case QAbstractItemView::SingleSelection: { - if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 ) + if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1) return false; view()->clearSelection(); break; } case QAbstractItemView::ContiguousSelection: { - if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex())) && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex())) { + if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex())) && + !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex())) { view()->clearSelection(); } - break; + break; } default: { break; @@ -251,7 +250,8 @@ bool AccessibleInstanceView::selectColumn(int column) } /* fallthrough */ case QAbstractItemView::ContiguousSelection: { - if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) && !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) { + if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) && + !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) { view()->clearSelection(); } break; @@ -292,10 +292,10 @@ bool AccessibleInstanceView::unselectRow(int row) return false; } - - if ((!row || selectionModel->isRowSelected(row - 1, view()->rootIndex())) && selectionModel->isRowSelected(row + 1, view()->rootIndex())) { - //If there are rows selected both up the current row and down the current rown, - //the ones which are down the current row will be deselected + if ((!row || selectionModel->isRowSelected(row - 1, view()->rootIndex())) && + selectionModel->isRowSelected(row + 1, view()->rootIndex())) { + // If there are rows selected both up the current row and down the current rown, + // the ones which are down the current row will be deselected selection = QItemSelection(index, view()->model()->index(rowCount() - 1, 0, view()->rootIndex())); } } @@ -324,8 +324,8 @@ bool AccessibleInstanceView::unselectColumn(int column) switch (view()->selectionMode()) { case QAbstractItemView::SingleSelection: { - //In SingleSelection and ContiguousSelection once an item - //is selected, there's no way for the user to unselect all items + // In SingleSelection and ContiguousSelection once an item + // is selected, there's no way for the user to unselect all items if (selectedColumnCount() == 1) { return false; } @@ -336,10 +336,10 @@ bool AccessibleInstanceView::unselectColumn(int column) return false; } - if ((!column || view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) - && view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) { - //If there are columns selected both at the left of the current row and at the right - //of the current row, the ones which are at the right will be deselected + if ((!column || view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) && + view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) { + // If there are columns selected both at the left of the current row and at the right + // of the current row, the ones which are at the right will be deselected selection = QItemSelection(index, model->index(0, columnCount() - 1, view()->rootIndex())); } default: @@ -360,9 +360,9 @@ QAccessible::State AccessibleInstanceView::state() const return QAccessible::State(); } -QAccessibleInterface *AccessibleInstanceView::childAt(int x, int y) const +QAccessibleInterface* AccessibleInstanceView::childAt(int x, int y) const { - QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0)); + QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0, 0)); QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset); // FIXME: if indexPosition < 0 in one coordinate, return header @@ -381,22 +381,23 @@ int AccessibleInstanceView::childCount() const return (view()->model()->rowCount()) * (view()->model()->columnCount()); } -int AccessibleInstanceView::indexOfChild(const QAccessibleInterface *iface) const +int AccessibleInstanceView::indexOfChild(const QAccessibleInterface* iface) const { if (!view()->model()) return -1; - QAccessibleInterface *parent = iface->parent(); + QAccessibleInterface* parent = iface->parent(); if (parent->object() != view()) return -1; - Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class + Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { const AccessibleInstanceViewItem* cell = static_cast(iface); return logicalIndex(cell->m_index); } else if (iface->role() == QAccessible::Pane) { - return 0; // corner button + return 0; // corner button } else { - qWarning() << "AccessibleInstanceView::indexOfChild has a child with unknown role..." << iface->role() << iface->text(QAccessible::Name); + qWarning() << "AccessibleInstanceView::indexOfChild has a child with unknown role..." << iface->role() + << iface->text(QAccessible::Name); } // FIXME: we are in denial of our children. this should stop. return -1; @@ -417,7 +418,7 @@ QRect AccessibleInstanceView::rect() const return QRect(pos.x(), pos.y(), view()->width(), view()->height()); } -QAccessibleInterface *AccessibleInstanceView::parent() const +QAccessibleInterface* AccessibleInstanceView::parent() const { if (view() && view()->parent()) { if (qstrcmp("QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) { @@ -428,7 +429,7 @@ QAccessibleInterface *AccessibleInstanceView::parent() const return 0; } -QAccessibleInterface *AccessibleInstanceView::child(int logicalIndex) const +QAccessibleInterface* AccessibleInstanceView::child(int logicalIndex) const { if (!view()->model()) return 0; @@ -442,7 +443,7 @@ QAccessibleInterface *AccessibleInstanceView::child(int logicalIndex) const int row = logicalIndex / columns; int column = logicalIndex % columns; - QAccessibleInterface *iface = 0; + QAccessibleInterface* iface = 0; QModelIndex index = view()->model()->index(row, column, view()->rootIndex()); if (Q_UNLIKELY(!index.isValid())) { @@ -456,14 +457,14 @@ QAccessibleInterface *AccessibleInstanceView::child(int logicalIndex) const return iface; } -void *AccessibleInstanceView::interface_cast(QAccessible::InterfaceType t) +void* AccessibleInstanceView::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::TableInterface) - return static_cast(this); - return 0; + return static_cast(this); + return 0; } -void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event) +void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent* event) { // if there is no cache yet, we don't update anything if (childToId.isEmpty()) @@ -479,13 +480,12 @@ void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event // rows are inserted: move every row after that case QAccessibleTableModelChangeEvent::RowsInserted: case QAccessibleTableModelChangeEvent::ColumnsInserted: { - ChildCache newCache; ChildCache::ConstIterator iter = childToId.constBegin(); while (iter != childToId.constEnd()) { QAccessible::Id id = iter.value(); - QAccessibleInterface *iface = QAccessible::accessibleInterface(id); + QAccessibleInterface* iface = QAccessible::accessibleInterface(id); Q_ASSERT(iface); if (indexOfChild(iface) >= 0) { newCache.insert(indexOfChild(iface), id); @@ -507,11 +507,11 @@ void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event ChildCache::ConstIterator iter = childToId.constBegin(); while (iter != childToId.constEnd()) { QAccessible::Id id = iter.value(); - QAccessibleInterface *iface = QAccessible::accessibleInterface(id); + QAccessibleInterface* iface = QAccessible::accessibleInterface(id); Q_ASSERT(iface); if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { Q_ASSERT(iface->tableCellInterface()); - AccessibleInstanceViewItem *cell = static_cast(iface->tableCellInterface()); + AccessibleInstanceViewItem* cell = static_cast(iface->tableCellInterface()); // Since it is a QPersistentModelIndex, we only need to check if it is valid if (cell->m_index.isValid()) newCache.insert(indexOfChild(cell), id); @@ -532,14 +532,13 @@ void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event // TABLE CELL -AccessibleInstanceViewItem::AccessibleInstanceViewItem(QAbstractItemView *view_, const QModelIndex &index_) - : view(view_), m_index(index_) +AccessibleInstanceViewItem::AccessibleInstanceViewItem(QAbstractItemView* view_, const QModelIndex& index_) : view(view_), m_index(index_) { if (Q_UNLIKELY(!index_.isValid())) qWarning() << "AccessibleInstanceViewItem::AccessibleInstanceViewItem with invalid index: " << index_; } -void *AccessibleInstanceViewItem::interface_cast(QAccessible::InterfaceType t) +void* AccessibleInstanceViewItem::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::TableCellInterface) return static_cast(this); @@ -548,8 +547,14 @@ void *AccessibleInstanceViewItem::interface_cast(QAccessible::InterfaceType t) return 0; } -int AccessibleInstanceViewItem::columnExtent() const { return 1; } -int AccessibleInstanceViewItem::rowExtent() const { return 1; } +int AccessibleInstanceViewItem::columnExtent() const +{ + return 1; +} +int AccessibleInstanceViewItem::rowExtent() const +{ + return 1; +} QList AccessibleInstanceViewItem::rowHeaderCells() const { @@ -600,19 +605,17 @@ void AccessibleInstanceViewItem::doAction(const QString& actionName) if (actionName == toggleAction()) { if (isSelected()) { unselectCell(); - } - else { + } else { selectCell(); } } } -QStringList AccessibleInstanceViewItem::keyBindingsForAction(const QString &) const +QStringList AccessibleInstanceViewItem::keyBindingsForAction(const QString&) const { return QStringList(); } - void AccessibleInstanceViewItem::selectCell() { if (!isValid()) { @@ -624,7 +627,7 @@ void AccessibleInstanceViewItem::selectCell() } Q_ASSERT(table()); - QAccessibleTableInterface *cellTable = table()->tableInterface(); + QAccessibleTableInterface* cellTable = table()->tableInterface(); switch (view->selectionBehavior()) { case QAbstractItemView::SelectItems: @@ -654,7 +657,7 @@ void AccessibleInstanceViewItem::unselectCell() if (selectionMode == QAbstractItemView::NoSelection) return; - QAccessibleTableInterface *cellTable = table()->tableInterface(); + QAccessibleTableInterface* cellTable = table()->tableInterface(); switch (view->selectionBehavior()) { case QAbstractItemView::SelectItems: @@ -669,15 +672,16 @@ void AccessibleInstanceViewItem::unselectCell() return; } - //If the mode is not MultiSelection or ExtendedSelection and only - //one cell is selected it cannot be unselected by the user - if ((selectionMode != QAbstractItemView::MultiSelection) && (selectionMode != QAbstractItemView::ExtendedSelection) && (view->selectionModel()->selectedIndexes().count() <= 1)) + // If the mode is not MultiSelection or ExtendedSelection and only + // one cell is selected it cannot be unselected by the user + if ((selectionMode != QAbstractItemView::MultiSelection) && (selectionMode != QAbstractItemView::ExtendedSelection) && + (view->selectionModel()->selectedIndexes().count() <= 1)) return; view->selectionModel()->select(m_index, QItemSelectionModel::Deselect); } -QAccessibleInterface *AccessibleInstanceViewItem::table() const +QAccessibleInterface* AccessibleInstanceViewItem::table() const { return QAccessible::queryAccessibleInterface(view); } @@ -694,7 +698,7 @@ QAccessible::State AccessibleInstanceViewItem::state() const return st; QRect globalRect = view->rect(); - globalRect.translate(view->mapToGlobal(QPoint(0,0))); + globalRect.translate(view->mapToGlobal(QPoint(0, 0))); if (!globalRect.intersects(rect())) st.invisible = true; @@ -717,7 +721,6 @@ QAccessible::State AccessibleInstanceViewItem::state() const return st; } - QRect AccessibleInstanceViewItem::rect() const { QRect r; @@ -726,7 +729,7 @@ QRect AccessibleInstanceViewItem::rect() const r = view->visualRect(m_index); if (!r.isNull()) { - r.translate(view->viewport()->mapTo(view, QPoint(0,0))); + r.translate(view->viewport()->mapTo(view, QPoint(0, 0))); r.translate(view->mapToGlobal(QPoint(0, 0))); } return r; @@ -737,7 +740,7 @@ QString AccessibleInstanceViewItem::text(QAccessible::Text t) const QString value; if (!isValid()) return value; - QAbstractItemModel *model = view->model(); + QAbstractItemModel* model = view->model(); switch (t) { case QAccessible::Name: value = model->data(m_index, Qt::AccessibleTextRole).toString(); @@ -753,7 +756,7 @@ QString AccessibleInstanceViewItem::text(QAccessible::Text t) const return value; } -void AccessibleInstanceViewItem::setText(QAccessible::Text /*t*/, const QString &text) +void AccessibleInstanceViewItem::setText(QAccessible::Text /*t*/, const QString& text) { if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable)) return; @@ -765,12 +768,12 @@ bool AccessibleInstanceViewItem::isValid() const return view && view->model() && m_index.isValid(); } -QAccessibleInterface *AccessibleInstanceViewItem::parent() const +QAccessibleInterface* AccessibleInstanceViewItem::parent() const { return QAccessible::queryAccessibleInterface(view); } -QAccessibleInterface *AccessibleInstanceViewItem::child(int) const +QAccessibleInterface* AccessibleInstanceViewItem::child(int) const { return 0; } diff --git a/launcher/ui/instanceview/AccessibleInstanceView.h b/launcher/ui/instanceview/AccessibleInstanceView.h index eb4222f50..19522805a 100644 --- a/launcher/ui/instanceview/AccessibleInstanceView.h +++ b/launcher/ui/instanceview/AccessibleInstanceView.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include class QAccessibleInterface; -QAccessibleInterface *groupViewAccessibleFactory(const QString &classname, QObject *object); +QAccessibleInterface* groupViewAccessibleFactory(const QString& classname, QObject* object); diff --git a/launcher/ui/instanceview/AccessibleInstanceView_p.h b/launcher/ui/instanceview/AccessibleInstanceView_p.h index 26462f51e..e99f85069 100644 --- a/launcher/ui/instanceview/AccessibleInstanceView_p.h +++ b/launcher/ui/instanceview/AccessibleInstanceView_p.h @@ -1,9 +1,9 @@ #pragma once -#include "QtCore/qpointer.h" #include -#include #include +#include +#include "QtCore/qpointer.h" #ifndef QT_NO_ACCESSIBILITY #include "InstanceView.h" // #include @@ -11,10 +11,9 @@ class QAccessibleTableCell; class QAccessibleTableHeaderCell; -class AccessibleInstanceView :public QAccessibleTableInterface, public QAccessibleObject -{ -public: - explicit AccessibleInstanceView(QWidget *w); +class AccessibleInstanceView : public QAccessibleTableInterface, public QAccessibleObject { + public: + explicit AccessibleInstanceView(QWidget* w); bool isValid() const override; QAccessible::Role role() const override; @@ -22,19 +21,19 @@ public: QString text(QAccessible::Text t) const override; QRect rect() const override; - QAccessibleInterface *childAt(int x, int y) const override; + QAccessibleInterface* childAt(int x, int y) const override; int childCount() const override; - int indexOfChild(const QAccessibleInterface *) const override; + int indexOfChild(const QAccessibleInterface*) const override; - QAccessibleInterface *parent() const override; - QAccessibleInterface *child(int index) const override; + QAccessibleInterface* parent() const override; + QAccessibleInterface* child(int index) const override; - void *interface_cast(QAccessible::InterfaceType t) override; + void* interface_cast(QAccessible::InterfaceType t) override; // table interface - QAccessibleInterface *cellAt(int row, int column) const override; - QAccessibleInterface *caption() const override; - QAccessibleInterface *summary() const override; + QAccessibleInterface* cellAt(int row, int column) const override; + QAccessibleInterface* caption() const override; + QAccessibleInterface* summary() const override; QString columnDescription(int column) const override; QString rowDescription(int row) const override; int columnCount() const override; @@ -54,42 +53,41 @@ public: bool unselectRow(int row) override; bool unselectColumn(int column) override; - QAbstractItemView *view() const; + QAbstractItemView* view() const; - void modelChange(QAccessibleTableModelChangeEvent *event) override; + void modelChange(QAccessibleTableModelChangeEvent* event) override; -protected: + protected: // maybe vector typedef QHash ChildCache; mutable ChildCache childToId; virtual ~AccessibleInstanceView(); -private: - inline int logicalIndex(const QModelIndex &index) const; + private: + inline int logicalIndex(const QModelIndex& index) const; }; -class AccessibleInstanceViewItem: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface -{ -public: - AccessibleInstanceViewItem(QAbstractItemView *view, const QModelIndex &m_index); +class AccessibleInstanceViewItem : public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface { + public: + AccessibleInstanceViewItem(QAbstractItemView* view, const QModelIndex& m_index); - void *interface_cast(QAccessible::InterfaceType t) override; - QObject *object() const override { return nullptr; } + void* interface_cast(QAccessible::InterfaceType t) override; + QObject* object() const override { return nullptr; } QAccessible::Role role() const override; QAccessible::State state() const override; QRect rect() const override; bool isValid() const override; - QAccessibleInterface *childAt(int, int) const override { return nullptr; } + QAccessibleInterface* childAt(int, int) const override { return nullptr; } int childCount() const override { return 0; } - int indexOfChild(const QAccessibleInterface *) const override { return -1; } + int indexOfChild(const QAccessibleInterface*) const override { return -1; } QString text(QAccessible::Text t) const override; - void setText(QAccessible::Text t, const QString &text) override; + void setText(QAccessible::Text t, const QString& text) override; - QAccessibleInterface *parent() const override; - QAccessibleInterface *child(int) const override; + QAccessibleInterface* parent() const override; + QAccessibleInterface* child(int) const override; // cell interface int columnExtent() const override; @@ -101,13 +99,13 @@ public: bool isSelected() const override; QAccessibleInterface* table() const override; - //action interface + // action interface QStringList actionNames() const override; - void doAction(const QString &actionName) override; - QStringList keyBindingsForAction(const QString &actionName) const override; + void doAction(const QString& actionName) override; + QStringList keyBindingsForAction(const QString& actionName) const override; -private: - QPointer view; + private: + QPointer view; QPersistentModelIndex m_index; void selectCell(); diff --git a/launcher/ui/instanceview/InstanceDelegate.cpp b/launcher/ui/instanceview/InstanceDelegate.cpp index 384c33f3f..9427836dc 100644 --- a/launcher/ui/instanceview/InstanceDelegate.cpp +++ b/launcher/ui/instanceview/InstanceDelegate.cpp @@ -34,29 +34,27 @@ */ #include "InstanceDelegate.h" -#include -#include -#include #include -#include #include +#include +#include +#include +#include -#include "InstanceView.h" -#include "BaseInstance.h" -#include "InstanceList.h" #include #include +#include "BaseInstance.h" +#include "InstanceList.h" +#include "InstanceView.h" // Origin: Qt -static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height, - qreal &widthUsed) +static void viewItemTextLayout(QTextLayout& textLayout, int lineWidth, qreal& height, qreal& widthUsed) { height = 0; widthUsed = 0; textLayout.beginLayout(); QString str = textLayout.text(); - while (true) - { + while (true) { QTextLine line = textLayout.createLine(); if (!line.isValid()) break; @@ -70,24 +68,20 @@ static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &he textLayout.endLayout(); } -ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent) -{ -} +ListViewDelegate::ListViewDelegate(QObject* parent) : QStyledItemDelegate(parent) {} -void drawSelectionRect(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect) +void drawSelectionRect(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect) { if ((option.state & QStyle::State_Selected)) painter->fillRect(rect, option.palette.brush(QPalette::Highlight)); - else - { + else { QColor backgroundColor = option.palette.color(QPalette::Window); backgroundColor.setAlpha(160); painter->fillRect(rect, QBrush(backgroundColor)); } } -void drawFocusRect(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) +void drawFocusRect(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect) { if (!(option.state & QStyle::State_HasFocus)) return; @@ -103,7 +97,7 @@ void drawFocusRect(QPainter *painter, const QStyleOptionViewItem &option, const // Apparently some widget styles expect this hint to not be set painter->setRenderHint(QPainter::Antialiasing, false); - QStyle *style = option.widget ? option.widget->style() : QApplication::style(); + QStyle* style = option.widget ? option.widget->style() : QApplication::style(); style->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, painter, option.widget); @@ -111,11 +105,9 @@ void drawFocusRect(QPainter *painter, const QStyleOptionViewItem &option, const } // TODO this can be made a lot prettier -void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItem &option, - const int value, const int maximum) +void drawProgressOverlay(QPainter* painter, const QStyleOptionViewItem& option, const int value, const int maximum) { - if (maximum == 0 || value == maximum) - { + if (maximum == 0 || value == maximum) { return; } @@ -131,19 +123,15 @@ void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItem &option, painter->restore(); } -void drawBadges(QPainter *painter, const QStyleOptionViewItem &option, BaseInstance *instance, QIcon::Mode mode, QIcon::State state) +void drawBadges(QPainter* painter, const QStyleOptionViewItem& option, BaseInstance* instance, QIcon::Mode mode, QIcon::State state) { QList pixmaps; - if (instance->isRunning()) - { + if (instance->isRunning()) { pixmaps.append("status-running"); - } - else if (instance->hasCrashed() || instance->hasVersionBroken()) - { + } else if (instance->hasCrashed() || instance->hasVersionBroken()) { pixmaps.append("status-bad"); } - if (instance->hasUpdateAvailable()) - { + if (instance->hasUpdateAvailable()) { pixmaps.append("checkupdate"); } @@ -153,12 +141,9 @@ void drawBadges(QPainter *painter, const QStyleOptionViewItem &option, BaseInsta const int rows = qCeil((double)pixmaps.size() / (double)itemsPerRow); QListIterator it(pixmaps); painter->translate(option.rect.topLeft()); - for (int y = 0; y < rows; ++y) - { - for (int x = 0; x < itemsPerRow; ++x) - { - if (!it.hasNext()) - { + for (int y = 0; y < rows; ++y) { + for (int x = 0; x < itemsPerRow; ++x) { + if (!it.hasNext()) { return; } // FIXME: inject this. @@ -166,21 +151,17 @@ void drawBadges(QPainter *painter, const QStyleOptionViewItem &option, BaseInsta // opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state); const QPixmap pixmap; // itemSide - QRect badgeRect( - option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide, - y * itemSide + qMax(y - 1, 0) * spacing, - itemSide, - itemSide - ); + QRect badgeRect(option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide, + y * itemSide + qMax(y - 1, 0) * spacing, itemSide, itemSide); icon.paint(painter, badgeRect, Qt::AlignCenter, mode, state); } } painter->translate(-option.rect.topLeft()); } -static QSize viewItemTextSize(const QStyleOptionViewItem *option) +static QSize viewItemTextSize(const QStyleOptionViewItem* option) { - QStyle *style = option->widget ? option->widget->style() : QApplication::style(); + QStyle* style = option->widget ? option->widget->style() : QApplication::style(); QTextOption textOption; textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); QTextLayout textLayout; @@ -195,8 +176,7 @@ static QSize viewItemTextSize(const QStyleOptionViewItem *option) return QSize(size.width() + 2 * textMargin, size.height()); } -void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const +void ListViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); @@ -208,7 +188,7 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti opt.textElideMode = Qt::ElideRight; opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter; - QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); + QStyle* style = opt.widget ? opt.widget->style() : QApplication::style(); // const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize); const int iconSize = 48; @@ -296,16 +276,12 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state); } // set the text colors - QPalette::ColorGroup cg = - opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) cg = QPalette::Inactive; - if (opt.state & QStyle::State_Selected) - { + if (opt.state & QStyle::State_Selected) { painter->setPen(opt.palette.color(cg, QPalette::HighlightedText)); - } - else - { + } else { painter->setPen(opt.palette.color(cg, QPalette::Text)); } @@ -324,20 +300,16 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti const int lineCount = textLayout.lineCount(); - const QRect layoutRect = QStyle::alignedRect( - opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect); + const QRect layoutRect = QStyle::alignedRect(opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect); const QPointF position = layoutRect.topLeft(); - for (int i = 0; i < lineCount; ++i) - { + for (int i = 0; i < lineCount; ++i) { const QTextLine line = textLayout.lineAt(i); line.draw(painter, position); } // FIXME: this really has no business of being here. Make generic. - auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole) - .value(); - if (instance) - { + auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole).value(); + if (instance) { drawBadges(painter, opt, instance, mode, state); } @@ -347,8 +319,7 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti painter->restore(); } -QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option, - const QModelIndex &index) const +QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); @@ -357,9 +328,9 @@ QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option, opt.textElideMode = Qt::ElideRight; opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter; - QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); + QStyle* style = opt.widget ? opt.widget->style() : QApplication::style(); const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, opt.widget) + 1; - int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables + int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables QSize szz = viewItemTextSize(&opt); height += szz.height(); // FIXME: maybe the icon items could scale and keep proportions? @@ -367,36 +338,32 @@ QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option, return sz; } -class NoReturnTextEdit: public QTextEdit -{ +class NoReturnTextEdit : public QTextEdit { Q_OBJECT -public: - explicit NoReturnTextEdit(QWidget *parent) : QTextEdit(parent) + public: + explicit NoReturnTextEdit(QWidget* parent) : QTextEdit(parent) { setTextInteractionFlags(Qt::TextEditorInteraction); setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); } - bool event(QEvent * event) override + bool event(QEvent* event) override { auto eventType = event->type(); - if(eventType == QEvent::KeyPress || eventType == QEvent::KeyRelease) - { - QKeyEvent *keyEvent = static_cast(event); + if (eventType == QEvent::KeyPress || eventType == QEvent::KeyRelease) { + QKeyEvent* keyEvent = static_cast(event); auto key = keyEvent->key(); - if ((key == Qt::Key_Return || key == Qt::Key_Enter) && eventType == QEvent::KeyPress) - { + if ((key == Qt::Key_Return || key == Qt::Key_Enter) && eventType == QEvent::KeyPress) { emit editingDone(); return true; } - if(key == Qt::Key_Tab) - { + if (key == Qt::Key_Tab) { return true; } } return QTextEdit::event(event); } -signals: + signals: void editingDone(); }; @@ -423,14 +390,13 @@ void ListViewDelegate::setEditorData(QWidget* editor, const QModelIndex& index) void ListViewDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { - QTextEdit * realEditor = qobject_cast(editor); + QTextEdit* realEditor = qobject_cast(editor); QString text = realEditor->toPlainText(); text.replace(QChar('\n'), QChar(' ')); text = text.trimmed(); // Prevent instance names longer than 128 chars text.truncate(128); - if(text.size() != 0) - { + if (text.size() != 0) { model->setData(index, text); } } @@ -446,7 +412,7 @@ QWidget* ListViewDelegate::createEditor(QWidget* parent, void ListViewDelegate::editingDone() { - NoReturnTextEdit *editor = qobject_cast(sender()); + NoReturnTextEdit* editor = qobject_cast(sender()); emit commitData(editor); emit closeEditor(editor); } diff --git a/launcher/ui/instanceview/InstanceDelegate.h b/launcher/ui/instanceview/InstanceDelegate.h index d95279f32..69dd32ba7 100644 --- a/launcher/ui/instanceview/InstanceDelegate.h +++ b/launcher/ui/instanceview/InstanceDelegate.h @@ -15,25 +15,24 @@ #pragma once -#include #include +#include -class ListViewDelegate : public QStyledItemDelegate -{ +class ListViewDelegate : public QStyledItemDelegate { Q_OBJECT -public: - explicit ListViewDelegate(QObject *parent = 0); + public: + explicit ListViewDelegate(QObject* parent = 0); virtual ~ListViewDelegate() {} - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; - void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const override; - QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override; + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; + void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - void setEditorData(QWidget * editor, const QModelIndex & index) const override; - void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override; + void setEditorData(QWidget* editor, const QModelIndex& index) const override; + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; -private slots: + private slots: void editingDone(); }; diff --git a/launcher/ui/instanceview/InstanceProxyModel.cpp b/launcher/ui/instanceview/InstanceProxyModel.cpp index d8de93edc..ab6bef696 100644 --- a/launcher/ui/instanceview/InstanceProxyModel.cpp +++ b/launcher/ui/instanceview/InstanceProxyModel.cpp @@ -15,57 +15,54 @@ #include "InstanceProxyModel.h" -#include "InstanceView.h" -#include "Application.h" #include #include +#include "Application.h" +#include "InstanceView.h" #include -InstanceProxyModel::InstanceProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { +InstanceProxyModel::InstanceProxyModel(QObject* parent) : QSortFilterProxyModel(parent) +{ m_naturalSort.setNumericMode(true); m_naturalSort.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); // FIXME: use loaded translation as source of locale instead, hook this up to translation changes m_naturalSort.setLocale(QLocale::system()); } -QVariant InstanceProxyModel::data(const QModelIndex & index, int role) const +QVariant InstanceProxyModel::data(const QModelIndex& index, int role) const { QVariant data = QSortFilterProxyModel::data(index, role); - if(role == Qt::DecorationRole) - { + if (role == Qt::DecorationRole) { return QVariant(APPLICATION->icons()->getIcon(data.toString())); } return data; } -bool InstanceProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { +bool InstanceProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const +{ const QString leftCategory = left.data(InstanceViewRoles::GroupRole).toString(); const QString rightCategory = right.data(InstanceViewRoles::GroupRole).toString(); if (leftCategory == rightCategory) { return subSortLessThan(left, right); - } - else { + } else { // FIXME: real group sorting happens in InstanceView::updateGeometries(), see LocaleString auto result = leftCategory.localeAwareCompare(rightCategory); - if(result == 0) { + if (result == 0) { return subSortLessThan(left, right); } return result < 0; } } -bool InstanceProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const +bool InstanceProxyModel::subSortLessThan(const QModelIndex& left, const QModelIndex& right) const { - BaseInstance *pdataLeft = static_cast(left.internalPointer()); - BaseInstance *pdataRight = static_cast(right.internalPointer()); + BaseInstance* pdataLeft = static_cast(left.internalPointer()); + BaseInstance* pdataRight = static_cast(right.internalPointer()); QString sortMode = APPLICATION->settings()->get("InstSortMode").toString(); - if (sortMode == "LastLaunch") - { + if (sortMode == "LastLaunch") { return pdataLeft->lastLaunch() > pdataRight->lastLaunch(); - } - else - { + } else { return m_naturalSort.compare(pdataLeft->name(), pdataRight->name()) < 0; } } diff --git a/launcher/ui/instanceview/InstanceProxyModel.h b/launcher/ui/instanceview/InstanceProxyModel.h index bba8d2b50..13fec1bca 100644 --- a/launcher/ui/instanceview/InstanceProxyModel.h +++ b/launcher/ui/instanceview/InstanceProxyModel.h @@ -15,21 +15,20 @@ #pragma once -#include #include +#include -class InstanceProxyModel : public QSortFilterProxyModel -{ +class InstanceProxyModel : public QSortFilterProxyModel { Q_OBJECT -public: - InstanceProxyModel(QObject *parent = 0); + public: + InstanceProxyModel(QObject* parent = 0); -protected: - QVariant data(const QModelIndex & index, int role) const override; - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; - bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const; + protected: + QVariant data(const QModelIndex& index, int role) const override; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; + bool subSortLessThan(const QModelIndex& left, const QModelIndex& right) const; -private: + private: QCollator m_naturalSort; }; diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 6cbada3ec..8fb71ff6a 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -35,39 +35,36 @@ #include "InstanceView.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "VisualGroup.h" #include +#include "VisualGroup.h" #include #include - -template bool listsIntersect(const QList &l1, const QList t2) +template +bool listsIntersect(const QList& l1, const QList t2) { - for (auto &item : l1) - { - if (t2.contains(item)) - { + for (auto& item : l1) { + if (t2.contains(item)) { return true; } } return false; } -InstanceView::InstanceView(QWidget *parent) - : QAbstractItemView(parent) +InstanceView::InstanceView(QWidget* parent) : QAbstractItemView(parent) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -82,7 +79,7 @@ InstanceView::~InstanceView() m_groups.clear(); } -void InstanceView::setModel(QAbstractItemModel *model) +void InstanceView::setModel(QAbstractItemModel* model) { QAbstractItemView::setModel(model); connect(model, &QAbstractItemModel::modelReset, this, &InstanceView::modelReset); @@ -118,7 +115,8 @@ void InstanceView::rowsRemoved() void InstanceView::currentChanged(const QModelIndex& current, const QModelIndex& previous) { QAbstractItemView::currentChanged(current, previous); - // TODO: for accessibility support, implement+register a factory, steal QAccessibleTable from Qt and return an instance of it for InstanceView. + // TODO: for accessibility support, implement+register a factory, steal QAccessibleTable from Qt and return an instance of it for + // InstanceView. #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive() && current.isValid()) { QAccessibleEvent event(this, QAccessible::Focus); @@ -128,19 +126,13 @@ void InstanceView::currentChanged(const QModelIndex& current, const QModelIndex& #endif /* !QT_NO_ACCESSIBILITY */ } - -class LocaleString : public QString -{ -public: - LocaleString(const char *s) : QString(s) - { - } - LocaleString(const QString &s) : QString(s) - { - } +class LocaleString : public QString { + public: + LocaleString(const char* s) : QString(s) {} + LocaleString(const QString& s) : QString(s) {} }; -inline bool operator<(const LocaleString &lhs, const LocaleString &rhs) +inline bool operator<(const LocaleString& lhs, const LocaleString& rhs) { return (QString::localeAwareCompare(lhs, rhs) < 0); } @@ -148,33 +140,28 @@ inline bool operator<(const LocaleString &lhs, const LocaleString &rhs) void InstanceView::updateScrollbar() { int previousScroll = verticalScrollBar()->value(); - if (m_groups.isEmpty()) - { + if (m_groups.isEmpty()) { verticalScrollBar()->setRange(0, 0); - } - else - { + } else { int totalHeight = 0; // top margin totalHeight += m_categoryMargin; int itemScroll = 0; - for (auto category : m_groups) - { + for (auto category : m_groups) { category->m_verticalPosition = totalHeight; totalHeight += category->totalHeight() + m_categoryMargin; - if(!itemScroll && category->totalHeight() != 0) - { + if (!itemScroll && category->totalHeight() != 0) { itemScroll = category->contentHeight() / category->numRows(); } } // do not divide by zero - if(itemScroll == 0) + if (itemScroll == 0) itemScroll = 64; totalHeight += m_bottomMargin; - verticalScrollBar()->setSingleStep ( itemScroll ); - const int rowsPerPage = qMax ( viewport()->height() / itemScroll, 1 ); - verticalScrollBar()->setPageStep ( rowsPerPage * itemScroll ); + verticalScrollBar()->setSingleStep(itemScroll); + const int rowsPerPage = qMax(viewport()->height() / itemScroll, 1); + verticalScrollBar()->setPageStep(rowsPerPage * itemScroll); verticalScrollBar()->setRange(0, totalHeight - height()); } @@ -186,24 +173,19 @@ void InstanceView::updateGeometries() { geometryCache.clear(); - QMap cats; + QMap cats; - for (int i = 0; i < model()->rowCount(); ++i) - { + for (int i = 0; i < model()->rowCount(); ++i) { const QString groupName = model()->index(i, 0).data(InstanceViewRoles::GroupRole).toString(); - if (!cats.contains(groupName)) - { - VisualGroup *old = this->category(groupName); - if (old) - { + if (!cats.contains(groupName)) { + VisualGroup* old = this->category(groupName); + if (old) { auto cat = new VisualGroup(old); cats.insert(groupName, cat); cat->update(); - } - else - { + } else { auto cat = new VisualGroup(groupName, this); - if(fVisibility) { + if (fVisibility) { cat->collapsed = fVisibility(groupName); } cats.insert(groupName, cat); @@ -218,43 +200,36 @@ void InstanceView::updateGeometries() viewport()->update(); } -bool InstanceView::isIndexHidden(const QModelIndex &index) const +bool InstanceView::isIndexHidden(const QModelIndex& index) const { - VisualGroup *cat = category(index); - if (cat) - { + VisualGroup* cat = category(index); + if (cat) { return cat->collapsed; - } - else - { + } else { return false; } } -VisualGroup *InstanceView::category(const QModelIndex &index) const +VisualGroup* InstanceView::category(const QModelIndex& index) const { return category(index.data(InstanceViewRoles::GroupRole).toString()); } -VisualGroup *InstanceView::category(const QString &cat) const +VisualGroup* InstanceView::category(const QString& cat) const { - for (auto group : m_groups) - { - if (group->text == cat) - { + for (auto group : m_groups) { + if (group->text == cat) { return group; } } return nullptr; } -VisualGroup *InstanceView::categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const +VisualGroup* InstanceView::categoryAt(const QPoint& pos, VisualGroup::HitResults& result) const { - for (auto group : m_groups) - { + for (auto group : m_groups) { result = group->hitScan(pos); - if(result != VisualGroup::NoHit) - { + if (result != VisualGroup::NoHit) { return group; } } @@ -262,14 +237,13 @@ VisualGroup *InstanceView::categoryAt(const QPoint &pos, VisualGroup::HitResults return nullptr; } -QString InstanceView::groupNameAt(const QPoint &point) +QString InstanceView::groupNameAt(const QPoint& point) { executeDelayedItemsLayout(); VisualGroup::HitResults hitResult; auto group = categoryAt(point + offset(), hitResult); - if(group && (hitResult & (VisualGroup::HeaderHit | VisualGroup::BodyHit))) - { + if (group && (hitResult & (VisualGroup::HeaderHit | VisualGroup::BodyHit))) { return group->text; } return QString(); @@ -290,7 +264,7 @@ int InstanceView::itemWidth() const return m_itemWidth; } -void InstanceView::mousePressEvent(QMouseEvent *event) +void InstanceView::mousePressEvent(QMouseEvent* event) { executeDelayedItemsLayout(); @@ -305,17 +279,14 @@ void InstanceView::mousePressEvent(QMouseEvent *event) VisualGroup::HitResults hitResult; m_pressedCategory = categoryAt(geometryPos, hitResult); - if (m_pressedCategory && hitResult & VisualGroup::CheckboxHit) - { + if (m_pressedCategory && hitResult & VisualGroup::CheckboxHit) { setState(m_pressedCategory->collapsed ? ExpandingState : CollapsingState); event->accept(); return; } - if (index.isValid() && (index.flags() & Qt::ItemIsEnabled)) - { - if(index != currentIndex()) - { + if (index.isValid() && (index.flags() & Qt::ItemIsEnabled)) { + if (index != currentIndex()) { // FIXME: better! m_currentCursorColumn = -1; } @@ -331,15 +302,13 @@ void InstanceView::mousePressEvent(QMouseEvent *event) // signal handlers may change the model emit pressed(index); - } - else - { + } else { // Forces a finalize() even if mouse is pressed, but not on a item selectionModel()->select(QModelIndex(), QItemSelectionModel::Select); } } -void InstanceView::mouseMoveEvent(QMouseEvent *event) +void InstanceView::mouseMoveEvent(QMouseEvent* event) { executeDelayedItemsLayout(); @@ -347,16 +316,13 @@ void InstanceView::mouseMoveEvent(QMouseEvent *event) QPoint visualPos = event->pos(); QPoint geometryPos = event->pos() + offset(); - if (state() == ExpandingState || state() == CollapsingState) - { + if (state() == ExpandingState || state() == CollapsingState) { return; } - if (state() == DraggingState) - { + if (state() == DraggingState) { topLeft = m_pressedPosition - offset(); - if ((topLeft - event->pos()).manhattanLength() > QApplication::startDragDistance()) - { + if ((topLeft - event->pos()).manhattanLength() > QApplication::startDragDistance()) { m_pressedIndex = QModelIndex(); startDrag(model()->supportedDragActions()); setState(NoState); @@ -365,39 +331,31 @@ void InstanceView::mouseMoveEvent(QMouseEvent *event) return; } - if (selectionMode() != SingleSelection) - { + if (selectionMode() != SingleSelection) { topLeft = m_pressedPosition - offset(); - } - else - { + } else { topLeft = geometryPos; } - if (m_pressedIndex.isValid() && (state() != DragSelectingState) && - (event->buttons() != Qt::NoButton) && !selectedIndexes().isEmpty()) - { + if (m_pressedIndex.isValid() && (state() != DragSelectingState) && (event->buttons() != Qt::NoButton) && !selectedIndexes().isEmpty()) { setState(DraggingState); return; } - if ((event->buttons() & Qt::LeftButton) && selectionModel()) - { + if ((event->buttons() & Qt::LeftButton) && selectionModel()) { setState(DragSelectingState); setSelection(QRect(visualPos, visualPos), QItemSelectionModel::ClearAndSelect); QModelIndex index = indexAt(visualPos); // set at the end because it might scroll the view - if (index.isValid() && (index != selectionModel()->currentIndex()) && - (index.flags() & Qt::ItemIsEnabled)) - { + if (index.isValid() && (index != selectionModel()->currentIndex()) && (index.flags() & Qt::ItemIsEnabled)) { selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate); } } } -void InstanceView::mouseReleaseEvent(QMouseEvent *event) +void InstanceView::mouseReleaseEvent(QMouseEvent* event) { executeDelayedItemsLayout(); @@ -407,13 +365,11 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event) VisualGroup::HitResults hitResult; - bool click = (index == m_pressedIndex && index.isValid()) || - (m_pressedCategory && m_pressedCategory == categoryAt(geometryPos, hitResult)); + bool click = + (index == m_pressedIndex && index.isValid()) || (m_pressedCategory && m_pressedCategory == categoryAt(geometryPos, hitResult)); - if (click && m_pressedCategory) - { - if (state() == ExpandingState) - { + if (click && m_pressedCategory) { + if (state() == ExpandingState) { m_pressedCategory->collapsed = false; emit groupStateChanged(m_pressedCategory->text, false); @@ -423,9 +379,7 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event) m_pressedCategory = nullptr; setState(NoState); return; - } - else if (state() == CollapsingState) - { + } else if (state() == CollapsingState) { m_pressedCategory->collapsed = true; emit groupStateChanged(m_pressedCategory->text, true); @@ -442,10 +396,8 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event) setState(NoState); - if (click) - { - if (event->button() == Qt::LeftButton) - { + if (click) { + if (event->button() == Qt::LeftButton) { emit clicked(index); } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -454,34 +406,24 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event) #else QStyleOptionViewItem option = viewOptions(); #endif - if (m_pressedAlreadySelected) - { + if (m_pressedAlreadySelected) { option.state |= QStyle::State_Selected; } if ((model()->flags(index) & Qt::ItemIsEnabled) && - style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this)) - { + style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this)) { emit activated(index); } } } -void InstanceView::mouseDoubleClickEvent(QMouseEvent *event) +void InstanceView::mouseDoubleClickEvent(QMouseEvent* event) { executeDelayedItemsLayout(); QModelIndex index = indexAt(event->pos()); - if (!index.isValid() || !(index.flags() & Qt::ItemIsEnabled) || (m_pressedIndex != index)) - { - QMouseEvent me( - QEvent::MouseButtonPress, - event->localPos(), - event->windowPos(), - event->screenPos(), - event->button(), - event->buttons(), - event->modifiers() - ); + if (!index.isValid() || !(index.flags() & Qt::ItemIsEnabled) || (m_pressedIndex != index)) { + QMouseEvent me(QEvent::MouseButtonPress, event->localPos(), event->windowPos(), event->screenPos(), event->button(), + event->buttons(), event->modifiers()); mousePressEvent(&me); return; } @@ -495,13 +437,11 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent *event) #else QStyleOptionViewItem option = viewOptions(); #endif - if ((model()->flags(index) & Qt::ItemIsEnabled) && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this)) - { + if ((model()->flags(index) & Qt::ItemIsEnabled) && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this)) { emit activated(index); } } - void InstanceView::setPaintCat(bool visible) { m_catVisible = visible; @@ -511,7 +451,7 @@ void InstanceView::setPaintCat(bool visible) m_catPixmap = QPixmap(); } -void InstanceView::paintEvent([[maybe_unused]] QPaintEvent *event) +void InstanceView::paintEvent([[maybe_unused]] QPaintEvent* event) { executeDelayedItemsLayout(); @@ -540,9 +480,8 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent *event) int wpWidth = viewport()->width(); option.rect.setWidth(wpWidth); - for (int i = 0; i < m_groups.size(); ++i) - { - VisualGroup *category = m_groups.at(i); + for (int i = 0; i < m_groups.size(); ++i) { + VisualGroup* category = m_groups.at(i); int y = category->verticalPosition(); y -= verticalOffset(); QRect backup = option.rect; @@ -556,28 +495,21 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent *event) option.rect = backup; } - for (int i = 0; i < model()->rowCount(); ++i) - { + for (int i = 0; i < model()->rowCount(); ++i) { const QModelIndex index = model()->index(i, 0); - if (isIndexHidden(index)) - { + if (isIndexHidden(index)) { continue; } Qt::ItemFlags flags = index.flags(); option.rect = visualRect(index); option.features |= QStyleOptionViewItem::WrapText; - if (flags & Qt::ItemIsSelectable && selectionModel()->isSelected(index)) - { - option.state |= selectionModel()->isSelected(index) ? QStyle::State_Selected - : QStyle::State_None; - } - else - { + if (flags & Qt::ItemIsSelectable && selectionModel()->isSelected(index)) { + option.state |= selectionModel()->isSelected(index) ? QStyle::State_Selected : QStyle::State_None; + } else { option.state &= ~QStyle::State_Selected; } option.state |= (index == currentIndex()) ? QStyle::State_HasFocus : QStyle::State_None; - if (!(flags & Qt::ItemIsEnabled)) - { + if (!(flags & Qt::ItemIsEnabled)) { option.state &= ~QStyle::State_Enabled; } itemDelegate()->paint(&painter, option, index); @@ -615,27 +547,23 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent *event) #endif } -void InstanceView::resizeEvent([[maybe_unused]] QResizeEvent *event) +void InstanceView::resizeEvent([[maybe_unused]] QResizeEvent* event) { int newItemsPerRow = calculateItemsPerRow(); - if(newItemsPerRow != m_currentItemsPerRow) - { + if (newItemsPerRow != m_currentItemsPerRow) { m_currentCursorColumn = -1; m_currentItemsPerRow = newItemsPerRow; updateGeometries(); - } - else - { + } else { updateScrollbar(); } } -void InstanceView::dragEnterEvent(QDragEnterEvent *event) +void InstanceView::dragEnterEvent(QDragEnterEvent* event) { executeDelayedItemsLayout(); - if (!isDragEventAccepted(event)) - { + if (!isDragEventAccepted(event)) { return; } m_lastDragPosition = event->pos() + offset(); @@ -643,12 +571,11 @@ void InstanceView::dragEnterEvent(QDragEnterEvent *event) event->accept(); } -void InstanceView::dragMoveEvent(QDragMoveEvent *event) +void InstanceView::dragMoveEvent(QDragMoveEvent* event) { executeDelayedItemsLayout(); - if (!isDragEventAccepted(event)) - { + if (!isDragEventAccepted(event)) { return; } m_lastDragPosition = event->pos() + offset(); @@ -656,7 +583,7 @@ void InstanceView::dragMoveEvent(QDragMoveEvent *event) event->accept(); } -void InstanceView::dragLeaveEvent([[maybe_unused]] QDragLeaveEvent *event) +void InstanceView::dragLeaveEvent([[maybe_unused]] QDragLeaveEvent* event) { executeDelayedItemsLayout(); @@ -664,7 +591,7 @@ void InstanceView::dragLeaveEvent([[maybe_unused]] QDragLeaveEvent *event) viewport()->update(); } -void InstanceView::dropEvent(QDropEvent *event) +void InstanceView::dropEvent(QDropEvent* event) { executeDelayedItemsLayout(); @@ -675,16 +602,13 @@ void InstanceView::dropEvent(QDropEvent *event) auto mimedata = event->mimeData(); - if (event->source() == this) - { - if(event->possibleActions() & Qt::MoveAction) - { - std::pair dropPos = rowDropPos(event->pos()); - const VisualGroup *group = dropPos.first; + if (event->source() == this) { + if (event->possibleActions() & Qt::MoveAction) { + std::pair dropPos = rowDropPos(event->pos()); + const VisualGroup* group = dropPos.first; auto hitResult = dropPos.second; - if (hitResult == VisualGroup::HitResult::NoHit) - { + if (hitResult == VisualGroup::HitResult::NoHit) { viewport()->update(); return; } @@ -701,14 +625,12 @@ void InstanceView::dropEvent(QDropEvent *event) } // check if the action is supported - if (!mimedata) - { + if (!mimedata) { return; } // files dropped from outside? - if (mimedata->hasUrls()) - { + if (mimedata->hasUrls()) { auto urls = mimedata->urls(); event->accept(); emit droppedURLs(urls); @@ -720,57 +642,52 @@ void InstanceView::startDrag(Qt::DropActions supportedActions) executeDelayedItemsLayout(); QModelIndexList indexes = selectionModel()->selectedIndexes(); - if(indexes.count() == 0) + if (indexes.count() == 0) return; - QMimeData *mimeData = model()->mimeData(indexes); - if (!mimeData) - { + QMimeData* mimeData = model()->mimeData(indexes); + if (!mimeData) { return; } QRect rect; QPixmap pixmap = renderToPixmap(indexes, &rect); - QDrag *drag = new QDrag(this); + QDrag* drag = new QDrag(this); drag->setPixmap(pixmap); drag->setMimeData(mimeData); drag->setHotSpot(m_pressedPosition - rect.topLeft()); Qt::DropAction defaultDropAction = Qt::IgnoreAction; - if (this->defaultDropAction() != Qt::IgnoreAction && (supportedActions & this->defaultDropAction())) - { + if (this->defaultDropAction() != Qt::IgnoreAction && (supportedActions & this->defaultDropAction())) { defaultDropAction = this->defaultDropAction(); } /*auto action = */ drag->exec(supportedActions, defaultDropAction); } -QRect InstanceView::visualRect(const QModelIndex &index) const +QRect InstanceView::visualRect(const QModelIndex& index) const { const_cast(this)->executeDelayedItemsLayout(); return geometryRect(index).translated(-offset()); } -QRect InstanceView::geometryRect(const QModelIndex &index) const +QRect InstanceView::geometryRect(const QModelIndex& index) const { const_cast(this)->executeDelayedItemsLayout(); - if (!index.isValid() || isIndexHidden(index) || index.column() > 0) - { + if (!index.isValid() || isIndexHidden(index) || index.column() > 0) { return QRect(); } int row = index.row(); - if(geometryCache.contains(row)) - { + if (geometryCache.contains(row)) { return *geometryCache[row]; } - const VisualGroup *cat = category(index); + const VisualGroup* cat = category(index); QPair pos = cat->positionOf(index); int x = pos.first; // int y = pos.second; - #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QStyleOptionViewItem option; initViewItemOption(&option); @@ -786,43 +703,38 @@ QRect InstanceView::geometryRect(const QModelIndex &index) const return out; } -QModelIndex InstanceView::indexAt(const QPoint &point) const +QModelIndex InstanceView::indexAt(const QPoint& point) const { const_cast(this)->executeDelayedItemsLayout(); - for (int i = 0; i < model()->rowCount(); ++i) - { + for (int i = 0; i < model()->rowCount(); ++i) { QModelIndex index = model()->index(i, 0); - if (visualRect(index).contains(point)) - { + if (visualRect(index).contains(point)) { return index; } } return QModelIndex(); } -void InstanceView::setSelection(const QRect &rect, const QItemSelectionModel::SelectionFlags commands) +void InstanceView::setSelection(const QRect& rect, const QItemSelectionModel::SelectionFlags commands) { executeDelayedItemsLayout(); - for (int i = 0; i < model()->rowCount(); ++i) - { + for (int i = 0; i < model()->rowCount(); ++i) { QModelIndex index = model()->index(i, 0); QRect itemRect = visualRect(index); - if (itemRect.intersects(rect)) - { + if (itemRect.intersects(rect)) { selectionModel()->select(index, commands); update(itemRect.translated(-offset())); } } } -QPixmap InstanceView::renderToPixmap(const QModelIndexList &indices, QRect *r) const +QPixmap InstanceView::renderToPixmap(const QModelIndexList& indices, QRect* r) const { Q_ASSERT(r); auto paintPairs = draggablePaintPairs(indices, r); - if (paintPairs.isEmpty()) - { + if (paintPairs.isEmpty()) { return QPixmap(); } QPixmap pixmap(r->size()); @@ -835,23 +747,21 @@ QPixmap InstanceView::renderToPixmap(const QModelIndexList &indices, QRect *r) c QStyleOptionViewItem option = viewOptions(); #endif option.state |= QStyle::State_Selected; - for (int j = 0; j < paintPairs.count(); ++j) - { + for (int j = 0; j < paintPairs.count(); ++j) { option.rect = paintPairs.at(j).first.translated(-r->topLeft()); - const QModelIndex ¤t = paintPairs.at(j).second; + const QModelIndex& current = paintPairs.at(j).second; itemDelegate()->paint(&painter, option, current); } return pixmap; } -QList> InstanceView::draggablePaintPairs(const QModelIndexList &indices, QRect *r) const +QList> InstanceView::draggablePaintPairs(const QModelIndexList& indices, QRect* r) const { Q_ASSERT(r); - QRect &rect = *r; + QRect& rect = *r; QList> ret; - for (int i = 0; i < indices.count(); ++i) - { - const QModelIndex &index = indices.at(i); + for (int i = 0; i < indices.count(); ++i) { + const QModelIndex& index = indices.at(i); const QRect current = geometryRect(index); ret += std::make_pair(current, index); rect |= current; @@ -859,12 +769,12 @@ QList> InstanceView::draggablePaintPairs(const QMo return ret; } -bool InstanceView::isDragEventAccepted([[maybe_unused]] QDropEvent *event) +bool InstanceView::isDragEventAccepted([[maybe_unused]] QDropEvent* event) { return true; } -std::pair InstanceView::rowDropPos(const QPoint &pos) +std::pair InstanceView::rowDropPos(const QPoint& pos) { VisualGroup::HitResults hitResult; auto group = categoryAt(pos + offset(), hitResult); @@ -876,21 +786,18 @@ QPoint InstanceView::offset() const return QPoint(horizontalOffset(), verticalOffset()); } -QRegion InstanceView::visualRegionForSelection(const QItemSelection &selection) const +QRegion InstanceView::visualRegionForSelection(const QItemSelection& selection) const { QRegion region; - for (auto &range : selection) - { + for (auto& range : selection) { int start_row = range.top(); int end_row = range.bottom(); - for (int row = start_row; row <= end_row; ++row) - { + for (int row = start_row; row <= end_row; ++row) { int start_column = range.left(); int end_column = range.right(); - for (int column = start_column; column <= end_column; ++column) - { + for (int column = start_column; column <= end_column; ++column) { QModelIndex index = model()->index(row, column, rootIndex()); - region += visualRect(index); // OK + region += visualRect(index); // OK } } } @@ -900,122 +807,97 @@ QRegion InstanceView::visualRegionForSelection(const QItemSelection &selection) QModelIndex InstanceView::moveCursor(QAbstractItemView::CursorAction cursorAction, [[maybe_unused]] Qt::KeyboardModifiers modifiers) { auto current = currentIndex(); - if(!current.isValid()) - { + if (!current.isValid()) { return current; } auto cat = category(current); int group_index = m_groups.indexOf(cat); - if(group_index < 0) + if (group_index < 0) return current; QPair pos = cat->positionOf(current); int column = pos.first; int row = pos.second; - if(m_currentCursorColumn < 0) - { + if (m_currentCursorColumn < 0) { m_currentCursorColumn = column; } - switch(cursorAction) - { - case MoveUp: - { - if(row == 0) - { - int prevGroupIndex = group_index-1; - while(prevGroupIndex >= 0) - { + switch (cursorAction) { + case MoveUp: { + if (row == 0) { + int prevGroupIndex = group_index - 1; + while (prevGroupIndex >= 0) { auto prevGroup = m_groups[prevGroupIndex]; - if(prevGroup->collapsed) - { + if (prevGroup->collapsed) { prevGroupIndex--; continue; } int newRow = prevGroup->numRows() - 1; int newRowSize = prevGroup->rows[newRow].size(); int newColumn = m_currentCursorColumn; - if (m_currentCursorColumn >= newRowSize) - { + if (m_currentCursorColumn >= newRowSize) { newColumn = newRowSize - 1; } return prevGroup->rows[newRow][newColumn]; } - } - else - { + } else { int newRow = row - 1; int newRowSize = cat->rows[newRow].size(); int newColumn = m_currentCursorColumn; - if (m_currentCursorColumn >= newRowSize) - { + if (m_currentCursorColumn >= newRowSize) { newColumn = newRowSize - 1; } return cat->rows[newRow][newColumn]; } return current; } - case MoveDown: - { - if(row == cat->rows.size() - 1) - { - int nextGroupIndex = group_index+1; - while (nextGroupIndex < m_groups.size()) - { + case MoveDown: { + if (row == cat->rows.size() - 1) { + int nextGroupIndex = group_index + 1; + while (nextGroupIndex < m_groups.size()) { auto nextGroup = m_groups[nextGroupIndex]; - if(nextGroup->collapsed) - { + if (nextGroup->collapsed) { nextGroupIndex++; continue; } int newRowSize = nextGroup->rows[0].size(); int newColumn = m_currentCursorColumn; - if (m_currentCursorColumn >= newRowSize) - { + if (m_currentCursorColumn >= newRowSize) { newColumn = newRowSize - 1; } return nextGroup->rows[0][newColumn]; } - } - else - { + } else { int newRow = row + 1; int newRowSize = cat->rows[newRow].size(); int newColumn = m_currentCursorColumn; - if (m_currentCursorColumn >= newRowSize) - { + if (m_currentCursorColumn >= newRowSize) { newColumn = newRowSize - 1; } return cat->rows[newRow][newColumn]; } return current; } - case MoveLeft: - { - if(column > 0) - { + case MoveLeft: { + if (column > 0) { m_currentCursorColumn = column - 1; return cat->rows[row][column - 1]; } // TODO: moving to previous line return current; } - case MoveRight: - { - if(column < cat->rows[row].size() - 1) - { + case MoveRight: { + if (column < cat->rows[row].size() - 1) { m_currentCursorColumn = column + 1; return cat->rows[row][column + 1]; } // TODO: moving to next line return current; } - case MoveHome: - { + case MoveHome: { m_currentCursorColumn = 0; return cat->rows[row][0]; } - case MoveEnd: - { + case MoveEnd: { auto last = cat->rows[row].size() - 1; m_currentCursorColumn = last; return cat->rows[row][last]; @@ -1042,14 +924,13 @@ void InstanceView::scrollContentsBy(int dx, int dy) viewport()->scroll(dx, dy); } -void InstanceView::scrollTo(const QModelIndex &index, ScrollHint hint) +void InstanceView::scrollTo(const QModelIndex& index, ScrollHint hint) { if (!index.isValid()) return; const QRect rect = visualRect(index); - if (hint == EnsureVisible && viewport()->rect().contains(rect)) - { + if (hint == EnsureVisible && viewport()->rect().contains(rect)) { viewport()->update(rect); return; } @@ -1057,7 +938,7 @@ void InstanceView::scrollTo(const QModelIndex &index, ScrollHint hint) verticalScrollBar()->setValue(verticalScrollToValue(index, rect, hint)); } -int InstanceView::verticalScrollToValue([[maybe_unused]] const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const +int InstanceView::verticalScrollToValue([[maybe_unused]] const QModelIndex& index, const QRect& rect, QListView::ScrollHint hint) const { const QRect area = viewport()->rect(); const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top()); diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h index 364056751..11892b227 100644 --- a/launcher/ui/instanceview/InstanceView.h +++ b/launcher/ui/instanceview/InstanceView.h @@ -35,95 +35,86 @@ #pragma once -#include -#include -#include #include -#include "VisualGroup.h" +#include +#include +#include #include +#include "VisualGroup.h" -struct InstanceViewRoles -{ - enum - { - GroupRole = Qt::UserRole, - ProgressValueRole, - ProgressMaximumRole - }; +struct InstanceViewRoles { + enum { GroupRole = Qt::UserRole, ProgressValueRole, ProgressMaximumRole }; }; -class InstanceView : public QAbstractItemView -{ +class InstanceView : public QAbstractItemView { Q_OBJECT -public: - InstanceView(QWidget *parent = 0); + public: + InstanceView(QWidget* parent = 0); ~InstanceView(); - void setModel(QAbstractItemModel *model) override; + void setModel(QAbstractItemModel* model) override; - using visibilityFunction = std::function; - void setSourceOfGroupCollapseStatus(visibilityFunction f) { - fVisibility = f; - } + using visibilityFunction = std::function; + void setSourceOfGroupCollapseStatus(visibilityFunction f) { fVisibility = f; } /// return geometry rectangle occupied by the specified model item - QRect geometryRect(const QModelIndex &index) const; + QRect geometryRect(const QModelIndex& index) const; /// return visual rectangle occupied by the specified model item - virtual QRect visualRect(const QModelIndex &index) const override; + virtual QRect visualRect(const QModelIndex& index) const override; /// get the model index at the specified visual point - virtual QModelIndex indexAt(const QPoint &point) const override; - QString groupNameAt(const QPoint &point); - void setSelection(const QRect &rect, const QItemSelectionModel::SelectionFlags commands) override; + virtual QModelIndex indexAt(const QPoint& point) const override; + QString groupNameAt(const QPoint& point); + void setSelection(const QRect& rect, const QItemSelectionModel::SelectionFlags commands) override; virtual int horizontalOffset() const override; virtual int verticalOffset() const override; virtual void scrollContentsBy(int dx, int dy) override; - virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override; + virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible) override; virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override; - virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override; + virtual QRegion visualRegionForSelection(const QItemSelection& selection) const override; int spacing() const { return m_spacing; }; void setPaintCat(bool visible); -public slots: + public slots: virtual void updateGeometries() override; -protected slots: - virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) override; - virtual void rowsInserted(const QModelIndex &parent, int start, int end) override; - virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override; + protected slots: + virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles) override; + virtual void rowsInserted(const QModelIndex& parent, int start, int end) override; + virtual void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override; void modelReset(); void rowsRemoved(); - void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override; + void currentChanged(const QModelIndex& current, const QModelIndex& previous) override; -signals: + signals: void droppedURLs(QList urls); void groupStateChanged(QString group, bool collapsed); -protected: - bool isIndexHidden(const QModelIndex &index) const override; - void mousePressEvent(QMouseEvent *event) override; - void mouseMoveEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - void mouseDoubleClickEvent(QMouseEvent *event) override; - void paintEvent(QPaintEvent *event) override; - void resizeEvent(QResizeEvent *event) override; + protected: + bool isIndexHidden(const QModelIndex& index) const override; + void mousePressEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + void mouseDoubleClickEvent(QMouseEvent* event) override; + void paintEvent(QPaintEvent* event) override; + void resizeEvent(QResizeEvent* event) override; - void dragEnterEvent(QDragEnterEvent *event) override; - void dragMoveEvent(QDragMoveEvent *event) override; - void dragLeaveEvent(QDragLeaveEvent *event) override; - void dropEvent(QDropEvent *event) override; + void dragEnterEvent(QDragEnterEvent* event) override; + void dragMoveEvent(QDragMoveEvent* event) override; + void dragLeaveEvent(QDragLeaveEvent* event) override; + void dropEvent(QDropEvent* event) override; void startDrag(Qt::DropActions supportedActions) override; void updateScrollbar(); -private: + private: friend struct VisualGroup; - QList m_groups; + QList m_groups; visibilityFunction fVisibility; @@ -135,7 +126,7 @@ private: int m_spacing = 5; int m_itemWidth = 100; int m_currentItemsPerRow = -1; - int m_currentCursorColumn= -1; + int m_currentCursorColumn = -1; mutable QCache geometryCache; bool m_catVisible = false; QPixmap m_catPixmap; @@ -144,30 +135,27 @@ private: QPoint m_pressedPosition; QPersistentModelIndex m_pressedIndex; bool m_pressedAlreadySelected; - VisualGroup *m_pressedCategory; + VisualGroup* m_pressedCategory; QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag; QPoint m_lastDragPosition; - VisualGroup *category(const QModelIndex &index) const; - VisualGroup *category(const QString &cat) const; - VisualGroup *categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const; + VisualGroup* category(const QModelIndex& index) const; + VisualGroup* category(const QString& cat) const; + VisualGroup* categoryAt(const QPoint& pos, VisualGroup::HitResults& result) const; - int itemsPerRow() const - { - return m_currentItemsPerRow; - }; + int itemsPerRow() const { return m_currentItemsPerRow; }; int contentWidth() const; -private: /* methods */ + private: /* methods */ int itemWidth() const; int calculateItemsPerRow() const; - int verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const; - QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const; - QList> draggablePaintPairs(const QModelIndexList &indices, QRect *r) const; + int verticalScrollToValue(const QModelIndex& index, const QRect& rect, QListView::ScrollHint hint) const; + QPixmap renderToPixmap(const QModelIndexList& indices, QRect* r) const; + QList> draggablePaintPairs(const QModelIndexList& indices, QRect* r) const; - bool isDragEventAccepted(QDropEvent *event); + bool isDragEventAccepted(QDropEvent* event); - std::pair rowDropPos(const QPoint &pos); + std::pair rowDropPos(const QPoint& pos); QPoint offset() const; }; diff --git a/launcher/ui/instanceview/VisualGroup.h b/launcher/ui/instanceview/VisualGroup.h index 697298c2d..8c6f06bcc 100644 --- a/launcher/ui/instanceview/VisualGroup.h +++ b/launcher/ui/instanceview/VisualGroup.h @@ -35,56 +35,48 @@ #pragma once -#include #include -#include +#include #include +#include class InstanceView; class QPainter; class QModelIndex; -struct VisualRow -{ +struct VisualRow { QList items; int height = 0; int top = 0; - inline int size() const - { - return items.size(); - } - inline QModelIndex &operator[](int i) - { - return items[i]; - } + inline int size() const { return items.size(); } + inline QModelIndex& operator[](int i) { return items[i]; } }; -struct VisualGroup -{ -/* constructors */ - VisualGroup(QString text, InstanceView *view); - explicit VisualGroup(const VisualGroup *other); +struct VisualGroup { + /* constructors */ + VisualGroup(QString text, InstanceView* view); + explicit VisualGroup(const VisualGroup* other); -/* data */ - InstanceView *view = nullptr; + /* data */ + InstanceView* view = nullptr; QString text; bool collapsed = false; QVector rows; int firstItemIndex = 0; int m_verticalPosition = 0; -/* logic */ + /* logic */ /// update the internal list of items and flow them into the rows. void update(); /// draw the header at y-position. - void drawHeader(QPainter *painter, const QStyleOptionViewItem &option) const; + void drawHeader(QPainter* painter, const QStyleOptionViewItem& option) const; /// height of the group, in total. includes a small bit of padding. int totalHeight() const; /// height of the group header, in pixels - static int headerHeight() ; + static int headerHeight(); /// height of the group content, in pixels int contentHeight() const; @@ -99,26 +91,19 @@ struct VisualGroup int verticalPosition() const; /// relative geometry - top of the row of the given item - int rowTopOf(const QModelIndex &index) const; + int rowTopOf(const QModelIndex& index) const; /// height of the row of the given item - int rowHeightOf(const QModelIndex &index) const; + int rowHeightOf(const QModelIndex& index) const; /// x/y position of the given item inside the group (in items!) - QPair positionOf(const QModelIndex &index) const; + QPair positionOf(const QModelIndex& index) const; - enum HitResult - { - NoHit = 0x0, - TextHit = 0x1, - CheckboxHit = 0x2, - HeaderHit = 0x4, - BodyHit = 0x8 - }; + enum HitResult { NoHit = 0x0, TextHit = 0x1, CheckboxHit = 0x2, HeaderHit = 0x4, BodyHit = 0x8 }; Q_DECLARE_FLAGS(HitResults, HitResult) /// shoot! BANG! what did we hit? - HitResults hitScan (const QPoint &pos) const; + HitResults hitScan(const QPoint& pos) const; QList items() const; }; diff --git a/launcher/ui/pagedialog/PageDialog.cpp b/launcher/ui/pagedialog/PageDialog.cpp index 18d61dc2f..6514217cd 100644 --- a/launcher/ui/pagedialog/PageDialog.cpp +++ b/launcher/ui/pagedialog/PageDialog.cpp @@ -16,9 +16,9 @@ #include "PageDialog.h" #include +#include #include #include -#include #include "Application.h" #include "settings/SettingsObject.h" @@ -26,19 +26,18 @@ #include "ui/widgets/IconLabel.h" #include "ui/widgets/PageContainer.h" -PageDialog::PageDialog(BasePageProvider *pageProvider, QString defaultId, QWidget *parent) - : QDialog(parent) +PageDialog::PageDialog(BasePageProvider* pageProvider, QString defaultId, QWidget* parent) : QDialog(parent) { setWindowTitle(pageProvider->dialogTitle()); m_container = new PageContainer(pageProvider, defaultId, this); - QVBoxLayout *mainLayout = new QVBoxLayout; + QVBoxLayout* mainLayout = new QVBoxLayout; mainLayout->addWidget(m_container); mainLayout->setSpacing(0); mainLayout->setContentsMargins(0, 0, 0, 0); setLayout(mainLayout); - QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close); + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close); buttons->button(QDialogButtonBox::Close)->setDefault(true); buttons->setContentsMargins(6, 0, 6, 0); m_container->addButtons(buttons); @@ -49,11 +48,10 @@ PageDialog::PageDialog(BasePageProvider *pageProvider, QString defaultId, QWidge restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("PagedGeometry").toByteArray())); } -void PageDialog::closeEvent(QCloseEvent *event) +void PageDialog::closeEvent(QCloseEvent* event) { qDebug() << "Paged dialog close requested"; - if (m_container->prepareToClose()) - { + if (m_container->prepareToClose()) { qDebug() << "Paged dialog close approved"; APPLICATION->settings()->set("PagedGeometry", saveGeometry().toBase64()); qDebug() << "Paged dialog geometry saved"; diff --git a/launcher/ui/pagedialog/PageDialog.h b/launcher/ui/pagedialog/PageDialog.h index 00d8b725b..aa50bc5e1 100644 --- a/launcher/ui/pagedialog/PageDialog.h +++ b/launcher/ui/pagedialog/PageDialog.h @@ -19,17 +19,15 @@ #include "ui/pages/BasePageProvider.h" class PageContainer; -class PageDialog : public QDialog -{ +class PageDialog : public QDialog { Q_OBJECT -public: - explicit PageDialog(BasePageProvider *pageProvider, QString defaultId = QString(), QWidget *parent = 0); + public: + explicit PageDialog(BasePageProvider* pageProvider, QString defaultId = QString(), QWidget* parent = 0); virtual ~PageDialog() {} -private -slots: - virtual void closeEvent(QCloseEvent *event); + private slots: + virtual void closeEvent(QCloseEvent* event); -private: - PageContainer * m_container; + private: + PageContainer* m_container; }; diff --git a/launcher/ui/pages/BasePageContainer.h b/launcher/ui/pages/BasePageContainer.h index eb3c94272..a497ef7b3 100644 --- a/launcher/ui/pages/BasePageContainer.h +++ b/launcher/ui/pages/BasePageContainer.h @@ -2,9 +2,8 @@ class BasePage; -class BasePageContainer -{ -public: +class BasePageContainer { + public: virtual ~BasePageContainer(){}; virtual bool selectPage(QString pageId) = 0; virtual BasePage* selectedPage() const = 0; diff --git a/launcher/ui/pages/BasePageProvider.h b/launcher/ui/pages/BasePageProvider.h index 873e8dce2..4c3ecd6c1 100644 --- a/launcher/ui/pages/BasePageProvider.h +++ b/launcher/ui/pages/BasePageProvider.h @@ -15,54 +15,43 @@ #pragma once -#include "ui/pages/BasePage.h" -#include #include +#include +#include "ui/pages/BasePage.h" -class BasePageProvider -{ -public: - virtual QList getPages() = 0; +class BasePageProvider { + public: + virtual QList getPages() = 0; virtual QString dialogTitle() = 0; }; -class GenericPageProvider : public BasePageProvider -{ - typedef std::function PageCreator; -public: - explicit GenericPageProvider(const QString &dialogTitle) - : m_dialogTitle(dialogTitle) - { - } +class GenericPageProvider : public BasePageProvider { + typedef std::function PageCreator; + + public: + explicit GenericPageProvider(const QString& dialogTitle) : m_dialogTitle(dialogTitle) {} virtual ~GenericPageProvider() {} - QList getPages() override + QList getPages() override { - QList pages; - for (PageCreator creator : m_creators) - { + QList pages; + for (PageCreator creator : m_creators) { pages.append(creator()); } return pages; } QString dialogTitle() override { return m_dialogTitle; } - void setDialogTitle(const QString &title) - { - m_dialogTitle = title; - } - void addPageCreator(PageCreator page) - { - m_creators.append(page); - } + void setDialogTitle(const QString& title) { m_dialogTitle = title; } + void addPageCreator(PageCreator page) { m_creators.append(page); } - template + template void addPage() { - addPageCreator([](){return new PageClass();}); + addPageCreator([]() { return new PageClass(); }); } -private: + private: QList m_creators; QString m_dialogTitle; }; diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index 668aa0078..82aa76a4f 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -39,37 +39,30 @@ #include "APIPage.h" #include "ui_APIPage.h" -#include #include +#include #include #include #include #include #include +#include "Application.h" +#include "BuildConfig.h" +#include "net/PasteUpload.h" #include "settings/SettingsObject.h" #include "tools/BaseProfiler.h" -#include "Application.h" -#include "net/PasteUpload.h" -#include "BuildConfig.h" -APIPage::APIPage(QWidget *parent) : - QWidget(parent), - ui(new Ui::APIPage) +APIPage::APIPage(QWidget* parent) : QWidget(parent), ui(new Ui::APIPage) { // This is here so you can reorder the entries in the combobox without messing stuff up - int comboBoxEntries[] = { - PasteUpload::PasteType::Mclogs, - PasteUpload::PasteType::NullPointer, - PasteUpload::PasteType::PasteGG, - PasteUpload::PasteType::Hastebin - }; + int comboBoxEntries[] = { PasteUpload::PasteType::Mclogs, PasteUpload::PasteType::NullPointer, PasteUpload::PasteType::PasteGG, + PasteUpload::PasteType::Hastebin }; static QRegularExpression validUrlRegExp("https?://.+"); - static QRegularExpression validMSAClientID(QRegularExpression::anchoredPattern( - "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}")); - static QRegularExpression validFlameKey(QRegularExpression::anchoredPattern( - "\\$2[ayb]\\$.{56}")); + static QRegularExpression validMSAClientID( + QRegularExpression::anchoredPattern("[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}")); + static QRegularExpression validFlameKey(QRegularExpression::anchoredPattern("\\$2[ayb]\\$.{56}")); ui->setupUi(this); @@ -77,7 +70,7 @@ APIPage::APIPage(QWidget *parent) : ui->pasteTypeComboBox->addItem(PasteUpload::PasteTypes.at(pasteType).name, pasteType); } - void (QComboBox::*currentIndexChangedSignal)(int) (&QComboBox::currentIndexChanged); + void (QComboBox::*currentIndexChangedSignal)(int)(&QComboBox::currentIndexChanged); connect(ui->pasteTypeComboBox, currentIndexChangedSignal, this, &APIPage::updateBaseURLPlaceholder); // This function needs to be called even when the ComboBox's index is still in its default state. updateBaseURLPlaceholder(ui->pasteTypeComboBox->currentIndex()); @@ -110,12 +103,9 @@ void APIPage::resetBaseURLNote() void APIPage::updateBaseURLNote(int index) { - if (baseURLPasteType == index) - { + if (baseURLPasteType == index) { ui->baseURLNote->hide(); - } - else if (!ui->baseURLEntry->text().isEmpty()) - { + } else if (!ui->baseURLEntry->text().isEmpty()) { ui->baseURLNote->show(); } } @@ -136,8 +126,7 @@ void APIPage::loadSettings() ui->baseURLEntry->setText(pastebinURL); int pasteTypeIndex = ui->pasteTypeComboBox->findData(pasteType); - if (pasteTypeIndex == -1) - { + if (pasteTypeIndex == -1) { pasteTypeIndex = ui->pasteTypeComboBox->findData(PasteUpload::PasteType::Mclogs); ui->baseURLEntry->clear(); } @@ -167,15 +156,13 @@ void APIPage::applySettings() s->set("MSAClientIDOverride", msaClientID); QUrl metaURL(ui->metaURL->text()); // Add required trailing slash - if (!metaURL.isEmpty() && !metaURL.path().endsWith('/')) - { + if (!metaURL.isEmpty() && !metaURL.path().endsWith('/')) { QString path = metaURL.path(); path.append('/'); metaURL.setPath(path); } // Don't allow HTTP, since meta is basically RCE with all the jar files. - if(!metaURL.isEmpty() && metaURL.scheme() == "http") - { + if (!metaURL.isEmpty() && metaURL.scheme() == "http") { metaURL.setScheme("https"); } diff --git a/launcher/ui/pages/global/APIPage.h b/launcher/ui/pages/global/APIPage.h index 17e62ae7f..8d8f06454 100644 --- a/launcher/ui/pages/global/APIPage.h +++ b/launcher/ui/pages/global/APIPage.h @@ -39,41 +39,28 @@ #include -#include "ui/pages/BasePage.h" #include +#include "ui/pages/BasePage.h" namespace Ui { class APIPage; } -class APIPage : public QWidget, public BasePage -{ +class APIPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit APIPage(QWidget *parent = 0); + public: + explicit APIPage(QWidget* parent = 0); ~APIPage(); - QString displayName() const override - { - return tr("APIs"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("worlds"); - } - QString id() const override - { - return "apis"; - } - QString helpPage() const override - { - return "APIs"; - } + QString displayName() const override { return tr("APIs"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("worlds"); } + QString id() const override { return "apis"; } + QString helpPage() const override { return "APIs"; } virtual bool apply() override; void retranslate() override; -private: + private: int baseURLPasteType; void resetBaseURLNote(); void updateBaseURLNote(int index); @@ -81,7 +68,6 @@ private: void loadSettings(); void applySettings(); -private: - Ui::APIPage *ui; + private: + Ui::APIPage* ui; }; - diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index 37df1a31c..caaa4b069 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -44,29 +44,27 @@ #include "net/NetJob.h" -#include "ui/dialogs/ProgressDialog.h" -#include "ui/dialogs/OfflineLoginDialog.h" +#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/LoginDialog.h" #include "ui/dialogs/MSALoginDialog.h" -#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/OfflineLoginDialog.h" +#include "ui/dialogs/ProgressDialog.h" #include "ui/dialogs/SkinUploadDialog.h" -#include "tasks/Task.h" #include "minecraft/auth/AccountTask.h" #include "minecraft/services/SkinDelete.h" +#include "tasks/Task.h" #include "Application.h" #include "BuildConfig.h" -AccountListPage::AccountListPage(QWidget *parent) - : QMainWindow(parent), ui(new Ui::AccountListPage) +AccountListPage::AccountListPage(QWidget* parent) : QMainWindow(parent), ui(new Ui::AccountListPage) { ui->setupUi(this); - ui->listView->setEmptyString(tr( - "Welcome!\n" - "If you're new here, you can click the \"Add\" button to add your Mojang or Minecraft account." - )); + ui->listView->setEmptyString( + tr("Welcome!\n" + "If you're new here, you can click the \"Add\" button to add your Mojang or Minecraft account.")); ui->listView->setEmptyMode(VersionListView::String); ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -82,7 +80,7 @@ AccountListPage::AccountListPage(QWidget *parent) // Expand the account column - QItemSelectionModel *selectionModel = ui->listView->selectionModel(); + QItemSelectionModel* selectionModel = ui->listView->selectionModel(); connect(selectionModel, &QItemSelectionModel::selectionChanged, [this]([[maybe_unused]] const QItemSelection& sel, [[maybe_unused]] const QItemSelection& dsel) { updateButtonStates(); }); @@ -120,21 +118,19 @@ void AccountListPage::ShowContextMenu(const QPoint& pos) void AccountListPage::changeEvent(QEvent* event) { - if (event->type() == QEvent::LanguageChange) - { + if (event->type() == QEvent::LanguageChange) { ui->retranslateUi(this); } QMainWindow::changeEvent(event); } -QMenu * AccountListPage::createPopupMenu() +QMenu* AccountListPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction(ui->toolBar->toggleViewAction() ); + filteredMenu->removeAction(ui->toolBar->toggleViewAction()); return filteredMenu; } - void AccountListPage::listChanged() { updateButtonStates(); @@ -142,13 +138,10 @@ void AccountListPage::listChanged() void AccountListPage::on_actionAddMojang_triggered() { - MinecraftAccountPtr account = LoginDialog::newAccount( - this, - tr("Please enter your Mojang account email and password to add your account.") - ); + MinecraftAccountPtr account = + LoginDialog::newAccount(this, tr("Please enter your Mojang account email and password to add your account.")); - if (account) - { + if (account) { m_accounts->addAccount(account); if (m_accounts->count() == 1) { m_accounts->setDefaultAccount(account); @@ -158,13 +151,10 @@ void AccountListPage::on_actionAddMojang_triggered() void AccountListPage::on_actionAddMicrosoft_triggered() { - MinecraftAccountPtr account = MSALoginDialog::newAccount( - this, - tr("Please enter your Mojang account email and password to add your account.") - ); + MinecraftAccountPtr account = + MSALoginDialog::newAccount(this, tr("Please enter your Mojang account email and password to add your account.")); - if (account) - { + if (account) { m_accounts->addAccount(account); if (m_accounts->count() == 1) { m_accounts->setDefaultAccount(account); @@ -175,25 +165,17 @@ void AccountListPage::on_actionAddMicrosoft_triggered() void AccountListPage::on_actionAddOffline_triggered() { if (!m_accounts->anyAccountIsValid()) { - QMessageBox::warning( - this, - tr("Error"), - tr( - "You must add a Microsoft or Mojang account that owns Minecraft before you can add an offline account." - "

" - "If you have lost your account you can contact Microsoft for support." - ) - ); + QMessageBox::warning(this, tr("Error"), + tr("You must add a Microsoft or Mojang account that owns Minecraft before you can add an offline account." + "

" + "If you have lost your account you can contact Microsoft for support.")); return; } - MinecraftAccountPtr account = OfflineLoginDialog::newAccount( - this, - tr("Please enter your desired username to add your offline account.") - ); + MinecraftAccountPtr account = + OfflineLoginDialog::newAccount(this, tr("Please enter your desired username to add your offline account.")); - if (account) - { + if (account) { m_accounts->addAccount(account); if (m_accounts->count() == 1) { m_accounts->setDefaultAccount(account); @@ -204,14 +186,14 @@ void AccountListPage::on_actionAddOffline_triggered() void AccountListPage::on_actionRemove_triggered() { QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.size() > 0) - { + if (selection.size() > 0) { QModelIndex selected = selection.first(); m_accounts->removeAccount(selected); } } -void AccountListPage::on_actionRefresh_triggered() { +void AccountListPage::on_actionRefresh_triggered() +{ QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); if (selection.size() > 0) { QModelIndex selected = selection.first(); @@ -220,12 +202,10 @@ void AccountListPage::on_actionRefresh_triggered() { } } - void AccountListPage::on_actionSetDefault_triggered() { QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.size() > 0) - { + if (selection.size() > 0) { QModelIndex selected = selection.first(); MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); m_accounts->setDefaultAccount(account); @@ -244,8 +224,7 @@ void AccountListPage::updateButtonStates() bool hasSelection = !selection.empty(); bool accountIsReady = false; bool accountIsOnline = false; - if (hasSelection) - { + if (hasSelection) { QModelIndex selected = selection.first(); MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); accountIsReady = !account->isActive(); @@ -257,11 +236,10 @@ void AccountListPage::updateButtonStates() ui->actionDeleteSkin->setEnabled(accountIsReady && accountIsOnline); ui->actionRefresh->setEnabled(accountIsReady && accountIsOnline); - if(m_accounts->defaultAccount().get() == nullptr) { + if (m_accounts->defaultAccount().get() == nullptr) { ui->actionNoDefault->setEnabled(false); ui->actionNoDefault->setChecked(true); - } - else { + } else { ui->actionNoDefault->setEnabled(true); ui->actionNoDefault->setChecked(false); } @@ -270,8 +248,7 @@ void AccountListPage::updateButtonStates() void AccountListPage::on_actionUploadSkin_triggered() { QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.size() > 0) - { + if (selection.size() > 0) { QModelIndex selected = selection.first(); MinecraftAccountPtr account = selected.data(AccountList::PointerRole).value(); SkinUploadDialog dialog(account, this); diff --git a/launcher/ui/pages/global/AccountListPage.h b/launcher/ui/pages/global/AccountListPage.h index 9395e92bf..483d7924f 100644 --- a/launcher/ui/pages/global/AccountListPage.h +++ b/launcher/ui/pages/global/AccountListPage.h @@ -41,47 +41,35 @@ #include "ui/pages/BasePage.h" -#include "minecraft/auth/AccountList.h" #include "Application.h" +#include "minecraft/auth/AccountList.h" -namespace Ui -{ +namespace Ui { class AccountListPage; } class AuthenticateTask; -class AccountListPage : public QMainWindow, public BasePage -{ +class AccountListPage : public QMainWindow, public BasePage { Q_OBJECT -public: - explicit AccountListPage(QWidget *parent = 0); + public: + explicit AccountListPage(QWidget* parent = 0); ~AccountListPage(); - QString displayName() const override - { - return tr("Accounts"); - } + QString displayName() const override { return tr("Accounts"); } QIcon icon() const override { auto icon = APPLICATION->getThemedIcon("accounts"); - if(icon.isNull()) - { + if (icon.isNull()) { icon = APPLICATION->getThemedIcon("noaccount"); } return icon; } - QString id() const override - { - return "accounts"; - } - QString helpPage() const override - { - return "Getting-Started#adding-an-account"; - } + QString id() const override { return "accounts"; } + QString helpPage() const override { return "Getting-Started#adding-an-account"; } void retranslate() override; -public slots: + public slots: void on_actionAddMojang_triggered(); void on_actionAddMicrosoft_triggered(); void on_actionAddOffline_triggered(); @@ -97,12 +85,12 @@ public slots: //! Updates the states of the dialog's buttons. void updateButtonStates(); -protected slots: - void ShowContextMenu(const QPoint &pos); + protected slots: + void ShowContextMenu(const QPoint& pos); -private: - void changeEvent(QEvent * event) override; - QMenu * createPopupMenu() override; + private: + void changeEvent(QEvent* event) override; + QMenu* createPopupMenu() override; shared_qobject_ptr m_accounts; - Ui::AccountListPage *ui; + Ui::AccountListPage* ui; }; diff --git a/launcher/ui/pages/global/CustomCommandsPage.cpp b/launcher/ui/pages/global/CustomCommandsPage.cpp index df1420ca6..fad69050b 100644 --- a/launcher/ui/pages/global/CustomCommandsPage.cpp +++ b/launcher/ui/pages/global/CustomCommandsPage.cpp @@ -35,13 +35,12 @@ */ #include "CustomCommandsPage.h" -#include -#include #include +#include +#include -CustomCommandsPage::CustomCommandsPage(QWidget* parent): QWidget(parent) +CustomCommandsPage::CustomCommandsPage(QWidget* parent) : QWidget(parent) { - auto verticalLayout = new QVBoxLayout(this); verticalLayout->setObjectName(QStringLiteral("verticalLayout")); verticalLayout->setContentsMargins(0, 0, 0, 0); @@ -56,9 +55,7 @@ CustomCommandsPage::CustomCommandsPage(QWidget* parent): QWidget(parent) loadSettings(); } -CustomCommandsPage::~CustomCommandsPage() -{ -} +CustomCommandsPage::~CustomCommandsPage() {} bool CustomCommandsPage::apply() { @@ -77,13 +74,8 @@ void CustomCommandsPage::applySettings() void CustomCommandsPage::loadSettings() { auto s = APPLICATION->settings(); - commands->initialize( - false, - true, - s->get("PreLaunchCommand").toString(), - s->get("WrapperCommand").toString(), - s->get("PostExitCommand").toString() - ); + commands->initialize(false, true, s->get("PreLaunchCommand").toString(), s->get("WrapperCommand").toString(), + s->get("PostExitCommand").toString()); } void CustomCommandsPage::retranslate() diff --git a/launcher/ui/pages/global/CustomCommandsPage.h b/launcher/ui/pages/global/CustomCommandsPage.h index 865503ff7..c69b02e5a 100644 --- a/launcher/ui/pages/global/CustomCommandsPage.h +++ b/launcher/ui/pages/global/CustomCommandsPage.h @@ -35,42 +35,29 @@ #pragma once -#include #include +#include -#include "ui/pages/BasePage.h" #include +#include "ui/pages/BasePage.h" #include "ui/widgets/CustomCommands.h" -class CustomCommandsPage : public QWidget, public BasePage -{ +class CustomCommandsPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit CustomCommandsPage(QWidget *parent = 0); + public: + explicit CustomCommandsPage(QWidget* parent = 0); ~CustomCommandsPage(); - QString displayName() const override - { - return tr("Custom Commands"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("custom-commands"); - } - QString id() const override - { - return "custom-commands"; - } - QString helpPage() const override - { - return "Custom-commands"; - } + QString displayName() const override { return tr("Custom Commands"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("custom-commands"); } + QString id() const override { return "custom-commands"; } + QString helpPage() const override { return "Custom-commands"; } bool apply() override; void retranslate() override; -private: + private: void applySettings(); void loadSettings(); - CustomCommands * commands; + CustomCommands* commands; }; diff --git a/launcher/ui/pages/global/ExternalToolsPage.cpp b/launcher/ui/pages/global/ExternalToolsPage.cpp index 5ba0ebc28..abe157f09 100644 --- a/launcher/ui/pages/global/ExternalToolsPage.cpp +++ b/launcher/ui/pages/global/ExternalToolsPage.cpp @@ -36,20 +36,18 @@ #include "ExternalToolsPage.h" #include "ui_ExternalToolsPage.h" -#include #include +#include #include #include +#include +#include +#include "Application.h" #include "settings/SettingsObject.h" #include "tools/BaseProfiler.h" -#include -#include "Application.h" -#include -ExternalToolsPage::ExternalToolsPage(QWidget *parent) : - QWidget(parent), - ui(new Ui::ExternalToolsPage) +ExternalToolsPage::ExternalToolsPage(QWidget* parent) : QWidget(parent), ui(new Ui::ExternalToolsPage) { ui->setupUi(this); ui->tabWidget->tabBar()->hide(); @@ -87,12 +85,9 @@ void ExternalToolsPage::applySettings() // Editors QString jsonEditor = ui->jsonEditorTextBox->text(); - if (!jsonEditor.isEmpty() && - (!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable())) - { + if (!jsonEditor.isEmpty() && (!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable())) { QString found = QStandardPaths::findExecutable(jsonEditor); - if (!found.isEmpty()) - { + if (!found.isEmpty()) { jsonEditor = found; } } @@ -103,21 +98,16 @@ void ExternalToolsPage::on_jprofilerPathBtn_clicked() { QString raw_dir = ui->jprofilerPathEdit->text(); QString error; - do - { + do { raw_dir = QFileDialog::getExistingDirectory(this, tr("JProfiler Folder"), raw_dir); - if (raw_dir.isEmpty()) - { + if (raw_dir.isEmpty()) { break; } QString cooked_dir = FS::NormalizePath(raw_dir); - if (!APPLICATION->profilers()["jprofiler"]->check(cooked_dir, &error)) - { + if (!APPLICATION->profilers()["jprofiler"]->check(cooked_dir, &error)) { QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error)); continue; - } - else - { + } else { ui->jprofilerPathEdit->setText(cooked_dir); break; } @@ -126,12 +116,9 @@ void ExternalToolsPage::on_jprofilerPathBtn_clicked() void ExternalToolsPage::on_jprofilerCheckBtn_clicked() { QString error; - if (!APPLICATION->profilers()["jprofiler"]->check(ui->jprofilerPathEdit->text(), &error)) - { + if (!APPLICATION->profilers()["jprofiler"]->check(ui->jprofilerPathEdit->text(), &error)) { QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error)); - } - else - { + } else { QMessageBox::information(this, tr("OK"), tr("JProfiler setup seems to be OK")); } } @@ -140,21 +127,16 @@ void ExternalToolsPage::on_jvisualvmPathBtn_clicked() { QString raw_dir = ui->jvisualvmPathEdit->text(); QString error; - do - { + do { raw_dir = QFileDialog::getOpenFileName(this, tr("JVisualVM Executable"), raw_dir); - if (raw_dir.isEmpty()) - { + if (raw_dir.isEmpty()) { break; } QString cooked_dir = FS::NormalizePath(raw_dir); - if (!APPLICATION->profilers()["jvisualvm"]->check(cooked_dir, &error)) - { + if (!APPLICATION->profilers()["jvisualvm"]->check(cooked_dir, &error)) { QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error)); continue; - } - else - { + } else { ui->jvisualvmPathEdit->setText(cooked_dir); break; } @@ -163,12 +145,9 @@ void ExternalToolsPage::on_jvisualvmPathBtn_clicked() void ExternalToolsPage::on_jvisualvmCheckBtn_clicked() { QString error; - if (!APPLICATION->profilers()["jvisualvm"]->check(ui->jvisualvmPathEdit->text(), &error)) - { + if (!APPLICATION->profilers()["jvisualvm"]->check(ui->jvisualvmPathEdit->text(), &error)) { QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error)); - } - else - { + } else { QMessageBox::information(this, tr("OK"), tr("JVisualVM setup seems to be OK")); } } @@ -177,25 +156,20 @@ void ExternalToolsPage::on_mceditPathBtn_clicked() { QString raw_dir = ui->mceditPathEdit->text(); QString error; - do - { + do { #ifdef Q_OS_OSX raw_dir = QFileDialog::getOpenFileName(this, tr("MCEdit Application"), raw_dir); #else raw_dir = QFileDialog::getExistingDirectory(this, tr("MCEdit Folder"), raw_dir); #endif - if (raw_dir.isEmpty()) - { + if (raw_dir.isEmpty()) { break; } QString cooked_dir = FS::NormalizePath(raw_dir); - if (!APPLICATION->mcedit()->check(cooked_dir, error)) - { + if (!APPLICATION->mcedit()->check(cooked_dir, error)) { QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error)); continue; - } - else - { + } else { ui->mceditPathEdit->setText(cooked_dir); break; } @@ -204,43 +178,34 @@ void ExternalToolsPage::on_mceditPathBtn_clicked() void ExternalToolsPage::on_mceditCheckBtn_clicked() { QString error; - if (!APPLICATION->mcedit()->check(ui->mceditPathEdit->text(), error)) - { + if (!APPLICATION->mcedit()->check(ui->mceditPathEdit->text(), error)) { QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error)); - } - else - { + } else { QMessageBox::information(this, tr("OK"), tr("MCEdit setup seems to be OK")); } } void ExternalToolsPage::on_jsonEditorBrowseBtn_clicked() { - QString raw_file = QFileDialog::getOpenFileName( - this, tr("JSON Editor"), - ui->jsonEditorTextBox->text().isEmpty() + QString raw_file = QFileDialog::getOpenFileName(this, tr("JSON Editor"), + ui->jsonEditorTextBox->text().isEmpty() #if defined(Q_OS_LINUX) - ? QString("/usr/bin") + ? QString("/usr/bin") #else - ? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first() + ? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first() #endif - : ui->jsonEditorTextBox->text()); + : ui->jsonEditorTextBox->text()); - if (raw_file.isEmpty()) - { + if (raw_file.isEmpty()) { return; } QString cooked_file = FS::NormalizePath(raw_file); // it has to exist and be an executable - if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable()) - { + if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable()) { ui->jsonEditorTextBox->setText(cooked_file); - } - else - { - QMessageBox::warning(this, tr("Invalid"), - tr("The file chosen does not seem to be an executable")); + } else { + QMessageBox::warning(this, tr("Invalid"), tr("The file chosen does not seem to be an executable")); } } diff --git a/launcher/ui/pages/global/ExternalToolsPage.h b/launcher/ui/pages/global/ExternalToolsPage.h index 8bd38a196..0b38b80f9 100644 --- a/launcher/ui/pages/global/ExternalToolsPage.h +++ b/launcher/ui/pages/global/ExternalToolsPage.h @@ -37,54 +37,42 @@ #include -#include "ui/pages/BasePage.h" #include +#include "ui/pages/BasePage.h" namespace Ui { class ExternalToolsPage; } -class ExternalToolsPage : public QWidget, public BasePage -{ +class ExternalToolsPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit ExternalToolsPage(QWidget *parent = 0); + public: + explicit ExternalToolsPage(QWidget* parent = 0); ~ExternalToolsPage(); - QString displayName() const override - { - return tr("External Tools"); - } + QString displayName() const override { return tr("External Tools"); } QIcon icon() const override { auto icon = APPLICATION->getThemedIcon("externaltools"); - if(icon.isNull()) - { + if (icon.isNull()) { icon = APPLICATION->getThemedIcon("loadermods"); } return icon; } - QString id() const override - { - return "external-tools"; - } - QString helpPage() const override - { - return "Tools"; - } + QString id() const override { return "external-tools"; } + QString helpPage() const override { return "Tools"; } virtual bool apply() override; void retranslate() override; -private: + private: void loadSettings(); void applySettings(); -private: - Ui::ExternalToolsPage *ui; + private: + Ui::ExternalToolsPage* ui; -private -slots: + private slots: void on_jprofilerPathBtn_clicked(); void on_jprofilerCheckBtn_clicked(); void on_jvisualvmPathBtn_clicked(); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 1f4dcc8da..f28cbc5d9 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -38,22 +38,22 @@ #include "JavaCommon.h" #include "ui_JavaPage.h" +#include #include #include -#include #include #include "ui/dialogs/VersionSelectDialog.h" -#include "java/JavaUtils.h" #include "java/JavaInstallList.h" +#include "java/JavaUtils.h" -#include "settings/SettingsObject.h" #include -#include "Application.h" #include +#include "Application.h" +#include "settings/SettingsObject.h" -JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage) +JavaPage::JavaPage(QWidget* parent) : QWidget(parent), ui(new Ui::JavaPage) { ui->setupUi(this); ui->tabWidget->tabBar()->hide(); @@ -80,13 +80,10 @@ void JavaPage::applySettings() // Memory int min = ui->minMemSpinBox->value(); int max = ui->maxMemSpinBox->value(); - if(min < max) - { + if (min < max) { s->set("MinMemAlloc", min); s->set("MaxMemAlloc", max); - } - else - { + } else { s->set("MinMemAlloc", max); s->set("MaxMemAlloc", min); } @@ -105,13 +102,10 @@ void JavaPage::loadSettings() // Memory int min = s->get("MinMemAlloc").toInt(); int max = s->get("MaxMemAlloc").toInt(); - if(min < max) - { + if (min < max) { ui->minMemSpinBox->setValue(min); ui->maxMemSpinBox->setValue(max); - } - else - { + } else { ui->minMemSpinBox->setValue(max); ui->maxMemSpinBox->setValue(min); } @@ -137,8 +131,7 @@ void JavaPage::on_javaDetectBtn_clicked() vselect.setResizeOn(2); vselect.exec(); - if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) - { + if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) { java = std::dynamic_pointer_cast(vselect.selectedVersion()); ui->javaPathTextBox->setText(java->path); } @@ -149,15 +142,14 @@ void JavaPage::on_javaBrowseBtn_clicked() QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable")); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if(raw_path.isEmpty()) - { + if (raw_path.isEmpty()) { return; } QString cooked_path = FS::NormalizePath(raw_path); - QFileInfo javaInfo(cooked_path);; - if(!javaInfo.exists() || !javaInfo.isExecutable()) - { + QFileInfo javaInfo(cooked_path); + ; + if (!javaInfo.exists() || !javaInfo.isExecutable()) { return; } ui->javaPathTextBox->setText(cooked_path); @@ -165,13 +157,11 @@ void JavaPage::on_javaBrowseBtn_clicked() void JavaPage::on_javaTestBtn_clicked() { - if(checker) - { + if (checker) { return; } - checker.reset(new JavaCommon::TestCheck( - this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "), - ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value())); + checker.reset(new JavaCommon::TestCheck(this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "), + ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value())); connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished())); checker->run(); } diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index 2ef6d7493..64f2a296e 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -35,62 +35,47 @@ #pragma once -#include -#include -#include "ui/pages/BasePage.h" -#include "JavaCommon.h" #include #include +#include +#include +#include "JavaCommon.h" +#include "ui/pages/BasePage.h" class SettingsObject; -namespace Ui -{ +namespace Ui { class JavaPage; } -class JavaPage : public QWidget, public BasePage -{ +class JavaPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit JavaPage(QWidget *parent = 0); + public: + explicit JavaPage(QWidget* parent = 0); ~JavaPage(); - QString displayName() const override - { - return tr("Java"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("java"); - } - QString id() const override - { - return "java-settings"; - } - QString helpPage() const override - { - return "Java-settings"; - } + QString displayName() const override { return tr("Java"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("java"); } + QString id() const override { return "java-settings"; } + QString helpPage() const override { return "Java-settings"; } bool apply() override; void retranslate() override; void updateThresholds(); -private: + private: void applySettings(); void loadSettings(); -private -slots: + private slots: void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); void on_maxMemSpinBox_valueChanged(int i); void checkerFinished(); -private: - Ui::JavaPage *ui; + private: + Ui::JavaPage* ui; unique_qobject_ptr checker; }; diff --git a/launcher/ui/pages/global/LanguagePage.cpp b/launcher/ui/pages/global/LanguagePage.cpp index fcd174bdb..27af91d84 100644 --- a/launcher/ui/pages/global/LanguagePage.cpp +++ b/launcher/ui/pages/global/LanguagePage.cpp @@ -36,23 +36,20 @@ #include "LanguagePage.h" -#include "ui/widgets/LanguageSelectionWidget.h" #include +#include "ui/widgets/LanguageSelectionWidget.h" -LanguagePage::LanguagePage(QWidget* parent) : - QWidget(parent) +LanguagePage::LanguagePage(QWidget* parent) : QWidget(parent) { setObjectName(QStringLiteral("languagePage")); auto layout = new QVBoxLayout(this); mainWidget = new LanguageSelectionWidget(this); - layout->setContentsMargins(0,0,0,0); + layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(mainWidget); retranslate(); } -LanguagePage::~LanguagePage() -{ -} +LanguagePage::~LanguagePage() {} bool LanguagePage::apply() { diff --git a/launcher/ui/pages/global/LanguagePage.h b/launcher/ui/pages/global/LanguagePage.h index 2fd4ab0de..ea358851a 100644 --- a/launcher/ui/pages/global/LanguagePage.h +++ b/launcher/ui/pages/global/LanguagePage.h @@ -36,45 +36,32 @@ #pragma once -#include -#include "ui/pages/BasePage.h" #include #include +#include +#include "ui/pages/BasePage.h" class LanguageSelectionWidget; -class LanguagePage : public QWidget, public BasePage -{ +class LanguagePage : public QWidget, public BasePage { Q_OBJECT -public: - explicit LanguagePage(QWidget *parent = 0); + public: + explicit LanguagePage(QWidget* parent = 0); virtual ~LanguagePage(); - QString displayName() const override - { - return tr("Language"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("language"); - } - QString id() const override - { - return "language-settings"; - } - QString helpPage() const override - { - return "Language-settings"; - } + QString displayName() const override { return tr("Language"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("language"); } + QString id() const override { return "language-settings"; } + QString helpPage() const override { return "Language-settings"; } bool apply() override; void retranslate() override; -private: + private: void applySettings(); void loadSettings(); -private: - LanguageSelectionWidget *mainWidget; + private: + LanguageSelectionWidget* mainWidget; }; diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 2080b56f0..7f22fdb50 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -38,17 +38,17 @@ #include "LauncherPage.h" #include "ui_LauncherPage.h" -#include -#include #include -#include +#include #include +#include +#include -#include "settings/SettingsObject.h" #include #include "Application.h" #include "BuildConfig.h" #include "DesktopServices.h" +#include "settings/SettingsObject.h" #include "ui/themes/ITheme.h" #include "updater/ExternalUpdater.h" @@ -56,15 +56,14 @@ #include // FIXME: possibly move elsewhere -enum InstSortMode -{ +enum InstSortMode { // Sort alphabetically by name. Sort_Name, // Sort by which instance was launched most recently. Sort_LastLaunch }; -LauncherPage::LauncherPage(QWidget *parent) : QWidget(parent), ui(new Ui::LauncherPage) +LauncherPage::LauncherPage(QWidget* parent) : QWidget(parent), ui(new Ui::LauncherPage) { ui->setupUi(this); auto origForeground = ui->fontPreview->palette().color(ui->fontPreview->foregroundRole()); @@ -104,46 +103,39 @@ void LauncherPage::on_instDirBrowseBtn_clicked() QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"), ui->instDirTextBox->text()); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) - { + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { QString cooked_dir = FS::NormalizePath(raw_dir); - if (FS::checkProblemticPathJava(QDir(cooked_dir))) - { + if (FS::checkProblemticPathJava(QDir(cooked_dir))) { QMessageBox warning; - warning.setText(tr("You're trying to specify an instance folder which\'s path " - "contains at least one \'!\'. " - "Java is known to cause problems if that is the case, your " - "instances (probably) won't start!")); + warning.setText( + tr("You're trying to specify an instance folder which\'s path " + "contains at least one \'!\'. " + "Java is known to cause problems if that is the case, your " + "instances (probably) won't start!")); warning.setInformativeText( tr("Do you really want to use this path? " "Selecting \"No\" will close this and not alter your instance path.")); warning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); int result = warning.exec(); - if (result == QMessageBox::Ok) - { + if (result == QMessageBox::Ok) { ui->instDirTextBox->setText(cooked_dir); } - } - else if(DesktopServices::isFlatpak() && raw_dir.startsWith("/run/user")) - { + } else if (DesktopServices::isFlatpak() && raw_dir.startsWith("/run/user")) { QMessageBox warning; warning.setText(tr("You're trying to specify an instance folder " - "which was granted temporarily via Flatpak.\n" - "This is known to cause problems. " - "After a restart the launcher might break, " - "because it will no longer have access to that directory.\n\n" - "Granting %1 access to it via Flatseal is recommended.").arg(BuildConfig.LAUNCHER_DISPLAYNAME)); - warning.setInformativeText( - tr("Do you want to proceed anyway?")); + "which was granted temporarily via Flatpak.\n" + "This is known to cause problems. " + "After a restart the launcher might break, " + "because it will no longer have access to that directory.\n\n" + "Granting %1 access to it via Flatseal is recommended.") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME)); + warning.setInformativeText(tr("Do you want to proceed anyway?")); warning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); int result = warning.exec(); - if (result == QMessageBox::Ok) - { + if (result == QMessageBox::Ok) { ui->instDirTextBox->setText(cooked_dir); } - } - else - { + } else { ui->instDirTextBox->setText(cooked_dir); } } @@ -154,8 +146,7 @@ void LauncherPage::on_iconsDirBrowseBtn_clicked() QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"), ui->iconsDirTextBox->text()); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) - { + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { QString cooked_dir = FS::NormalizePath(raw_dir); ui->iconsDirTextBox->setText(cooked_dir); } @@ -166,8 +157,7 @@ void LauncherPage::on_modsDirBrowseBtn_clicked() QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"), ui->modsDirTextBox->text()); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) - { + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { QString cooked_dir = FS::NormalizePath(raw_dir); ui->modsDirTextBox->setText(cooked_dir); } @@ -177,8 +167,7 @@ void LauncherPage::on_downloadsDirBrowseBtn_clicked() { QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Downloads Folder"), ui->downloadsDirTextBox->text()); - if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) - { + if (!raw_dir.isEmpty() && QDir(raw_dir).exists()) { QString cooked_dir = FS::NormalizePath(raw_dir); ui->downloadsDirTextBox->setText(cooked_dir); } @@ -194,8 +183,7 @@ void LauncherPage::applySettings() auto s = APPLICATION->settings(); // Updates - if (APPLICATION->updater()) - { + if (APPLICATION->updater()) { APPLICATION->updater()->setAutomaticallyChecksForUpdates(ui->autoUpdateCheckBox->isChecked()); } @@ -220,15 +208,14 @@ void LauncherPage::applySettings() s->set("DownloadsDirWatchRecursive", ui->downloadsDirWatchRecursiveCheckBox->isChecked()); auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId(); - switch (sortMode) - { - case Sort_LastLaunch: - s->set("InstSortMode", "LastLaunch"); - break; - case Sort_Name: - default: - s->set("InstSortMode", "Name"); - break; + switch (sortMode) { + case Sort_LastLaunch: + s->set("InstSortMode", "LastLaunch"); + break; + case Sort_Name: + default: + s->set("InstSortMode", "Name"); + break; } // Mods @@ -238,12 +225,10 @@ void LauncherPage::loadSettings() { auto s = APPLICATION->settings(); // Updates - if (APPLICATION->updater()) - { + if (APPLICATION->updater()) { ui->autoUpdateCheckBox->setChecked(APPLICATION->updater()->getAutomaticallyChecksForUpdates()); } - // Toolbar/menu bar settings (not applicable if native menu bar is present) ui->toolsBox->setEnabled(!QMenuBar().isNativeMenuBar()); #ifdef Q_OS_MACOS @@ -261,8 +246,7 @@ void LauncherPage::loadSettings() bool conversionOk = true; int fontSize = APPLICATION->settings()->get("ConsoleFontSize").toInt(&conversionOk); - if(!conversionOk) - { + if (!conversionOk) { fontSize = 11; } ui->fontSizeBox->setValue(fontSize); @@ -279,12 +263,9 @@ void LauncherPage::loadSettings() QString sortMode = s->get("InstSortMode").toString(); - if (sortMode == "LastLaunch") - { + if (sortMode == "LastLaunch") { ui->sortLastLaunchedBtn->setChecked(true); - } - else - { + } else { ui->sortByNameBtn->setChecked(true); } diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h index e06d98971..238e31bb4 100644 --- a/launcher/ui/pages/global/LauncherPage.h +++ b/launcher/ui/pages/global/LauncherPage.h @@ -35,56 +35,41 @@ #pragma once -#include #include +#include -#include "java/JavaChecker.h" -#include "ui/pages/BasePage.h" #include -#include "ui/ColorCache.h" #include +#include "java/JavaChecker.h" +#include "ui/ColorCache.h" +#include "ui/pages/BasePage.h" class QTextCharFormat; class SettingsObject; -namespace Ui -{ +namespace Ui { class LauncherPage; } -class LauncherPage : public QWidget, public BasePage -{ +class LauncherPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit LauncherPage(QWidget *parent = 0); + public: + explicit LauncherPage(QWidget* parent = 0); ~LauncherPage(); - QString displayName() const override - { - return tr("Launcher"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("launcher"); - } - QString id() const override - { - return "launcher-settings"; - } - QString helpPage() const override - { - return "Launcher-settings"; - } + QString displayName() const override { return tr("Launcher"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("launcher"); } + QString id() const override { return "launcher-settings"; } + QString helpPage() const override { return "Launcher-settings"; } bool apply() override; void retranslate() override; -private: + private: void applySettings(); void loadSettings(); -private -slots: + private slots: void on_instDirBrowseBtn_clicked(); void on_modsDirBrowseBtn_clicked(); void on_iconsDirBrowseBtn_clicked(); @@ -96,8 +81,8 @@ slots: */ void refreshFontPreview(); -private: - Ui::LauncherPage *ui; + private: + Ui::LauncherPage* ui; /*! * Stores the currently selected update channel. @@ -105,7 +90,7 @@ private: QString m_currentUpdateChannel; // default format for the font preview... - QTextCharFormat *defaultFormat; + QTextCharFormat* defaultFormat; std::unique_ptr m_colors; diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp index 954823564..55ad12ac8 100644 --- a/launcher/ui/pages/global/MinecraftPage.cpp +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -37,14 +37,14 @@ #include "MinecraftPage.h" #include "ui_MinecraftPage.h" -#include #include +#include #include -#include "settings/SettingsObject.h" #include "Application.h" +#include "settings/SettingsObject.h" -MinecraftPage::MinecraftPage(QWidget *parent) : QWidget(parent), ui(new Ui::MinecraftPage) +MinecraftPage::MinecraftPage(QWidget* parent) : QWidget(parent), ui(new Ui::MinecraftPage) { ui->setupUi(this); loadSettings(); diff --git a/launcher/ui/pages/global/MinecraftPage.h b/launcher/ui/pages/global/MinecraftPage.h index cf5f95eb7..a9e2e8024 100644 --- a/launcher/ui/pages/global/MinecraftPage.h +++ b/launcher/ui/pages/global/MinecraftPage.h @@ -35,57 +35,41 @@ #pragma once -#include #include +#include +#include #include "java/JavaChecker.h" #include "ui/pages/BasePage.h" -#include class SettingsObject; -namespace Ui -{ +namespace Ui { class MinecraftPage; } -class MinecraftPage : public QWidget, public BasePage -{ +class MinecraftPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit MinecraftPage(QWidget *parent = 0); + public: + explicit MinecraftPage(QWidget* parent = 0); ~MinecraftPage(); - QString displayName() const override - { - return tr("Minecraft"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("minecraft"); - } - QString id() const override - { - return "minecraft-settings"; - } - QString helpPage() const override - { - return "Minecraft-settings"; - } + QString displayName() const override { return tr("Minecraft"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("minecraft"); } + QString id() const override { return "minecraft-settings"; } + QString helpPage() const override { return "Minecraft-settings"; } bool apply() override; void retranslate() override; -private: + private: void updateCheckboxStuff(); void applySettings(); void loadSettings(); -private -slots: + private slots: void on_maximizedCheckBox_clicked(bool checked); -private: - Ui::MinecraftPage *ui; - + private: + Ui::MinecraftPage* ui; }; diff --git a/launcher/ui/pages/global/ProxyPage.cpp b/launcher/ui/pages/global/ProxyPage.cpp index 5ccdb1528..0eae6e4b8 100644 --- a/launcher/ui/pages/global/ProxyPage.cpp +++ b/launcher/ui/pages/global/ProxyPage.cpp @@ -40,18 +40,17 @@ #include #include -#include "settings/SettingsObject.h" #include "Application.h" +#include "settings/SettingsObject.h" -ProxyPage::ProxyPage(QWidget *parent) : QWidget(parent), ui(new Ui::ProxyPage) +ProxyPage::ProxyPage(QWidget* parent) : QWidget(parent), ui(new Ui::ProxyPage) { ui->setupUi(this); ui->tabWidget->tabBar()->hide(); loadSettings(); updateCheckboxStuff(); - connect(ui->proxyGroup, QOverload::of(&QButtonGroup::buttonClicked), - this, &ProxyPage::proxyGroupChanged); + connect(ui->proxyGroup, QOverload::of(&QButtonGroup::buttonClicked), this, &ProxyPage::proxyGroupChanged); } ProxyPage::~ProxyPage() @@ -67,13 +66,12 @@ bool ProxyPage::apply() void ProxyPage::updateCheckboxStuff() { - bool enableEditing = ui->proxyHTTPBtn->isChecked() - || ui->proxySOCKS5Btn->isChecked(); + bool enableEditing = ui->proxyHTTPBtn->isChecked() || ui->proxySOCKS5Btn->isChecked(); ui->proxyAddrBox->setEnabled(enableEditing); ui->proxyAuthBox->setEnabled(enableEditing); } -void ProxyPage::proxyGroupChanged([[maybe_unused]] QAbstractButton *button) +void ProxyPage::proxyGroupChanged([[maybe_unused]] QAbstractButton* button) { updateCheckboxStuff(); } @@ -99,13 +97,8 @@ void ProxyPage::applySettings() s->set("ProxyUser", ui->proxyUserEdit->text()); s->set("ProxyPass", ui->proxyPassEdit->text()); - APPLICATION->updateProxySettings( - proxyType, - ui->proxyAddrEdit->text(), - ui->proxyPortEdit->value(), - ui->proxyUserEdit->text(), - ui->proxyPassEdit->text() - ); + APPLICATION->updateProxySettings(proxyType, ui->proxyAddrEdit->text(), ui->proxyPortEdit->value(), ui->proxyUserEdit->text(), + ui->proxyPassEdit->text()); } void ProxyPage::loadSettings() { diff --git a/launcher/ui/pages/global/ProxyPage.h b/launcher/ui/pages/global/ProxyPage.h index 279a90295..092a11d2f 100644 --- a/launcher/ui/pages/global/ProxyPage.h +++ b/launcher/ui/pages/global/ProxyPage.h @@ -36,53 +36,39 @@ #pragma once -#include #include #include +#include -#include "ui/pages/BasePage.h" #include +#include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class ProxyPage; } -class ProxyPage : public QWidget, public BasePage -{ +class ProxyPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit ProxyPage(QWidget *parent = 0); + public: + explicit ProxyPage(QWidget* parent = 0); ~ProxyPage(); - QString displayName() const override - { - return tr("Proxy"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("proxy"); - } - QString id() const override - { - return "proxy-settings"; - } - QString helpPage() const override - { - return "Proxy-settings"; - } + QString displayName() const override { return tr("Proxy"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("proxy"); } + QString id() const override { return "proxy-settings"; } + QString helpPage() const override { return "Proxy-settings"; } bool apply() override; void retranslate() override; -private slots: - void proxyGroupChanged(QAbstractButton *button); + private slots: + void proxyGroupChanged(QAbstractButton* button); -private: + private: void updateCheckboxStuff(); void applySettings(); void loadSettings(); -private: - Ui::ProxyPage *ui; + private: + Ui::ProxyPage* ui; }; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h index 97d922d88..d29be0fc3 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.h +++ b/launcher/ui/pages/instance/ExternalResourcesPage.h @@ -4,8 +4,8 @@ #include #include "Application.h" -#include "settings/Setting.h" #include "minecraft/MinecraftInstance.h" +#include "settings/Setting.h" #include "ui/pages/BasePage.h" class ResourceFolderModel; @@ -52,7 +52,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { virtual void addItem(); void removeItem(); - virtual void removeItems(const QItemSelection &selection); + virtual void removeItems(const QItemSelection& selection); virtual void enableItem(); virtual void disableItem(); diff --git a/launcher/ui/pages/instance/GameOptionsPage.cpp b/launcher/ui/pages/instance/GameOptionsPage.cpp index 63443166b..e90041709 100644 --- a/launcher/ui/pages/instance/GameOptionsPage.cpp +++ b/launcher/ui/pages/instance/GameOptionsPage.cpp @@ -34,23 +34,20 @@ */ #include "GameOptionsPage.h" -#include "ui_GameOptionsPage.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/gameoptions/GameOptions.h" +#include "ui_GameOptionsPage.h" -GameOptionsPage::GameOptionsPage(MinecraftInstance * inst, QWidget* parent) - : QWidget(parent), ui(new Ui::GameOptionsPage) +GameOptionsPage::GameOptionsPage(MinecraftInstance* inst, QWidget* parent) : QWidget(parent), ui(new Ui::GameOptionsPage) { ui->setupUi(this); ui->tabWidget->tabBar()->hide(); m_model = inst->gameOptionsModel(); ui->optionsView->setModel(m_model.get()); auto head = ui->optionsView->header(); - if(head->count()) - { + if (head->count()) { head->setSectionResizeMode(0, QHeaderView::ResizeToContents); - for(int i = 1; i < head->count(); i++) - { + for (int i = 1; i < head->count(); i++) { head->setSectionResizeMode(i, QHeaderView::Stretch); } } diff --git a/launcher/ui/pages/instance/GameOptionsPage.h b/launcher/ui/pages/instance/GameOptionsPage.h index de8c421e7..563bd10ae 100644 --- a/launcher/ui/pages/instance/GameOptionsPage.h +++ b/launcher/ui/pages/instance/GameOptionsPage.h @@ -35,50 +35,36 @@ #pragma once -#include #include +#include -#include "ui/pages/BasePage.h" #include +#include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class GameOptionsPage; } class GameOptions; class MinecraftInstance; -class GameOptionsPage : public QWidget, public BasePage -{ +class GameOptionsPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit GameOptionsPage(MinecraftInstance *inst, QWidget *parent = 0); + public: + explicit GameOptionsPage(MinecraftInstance* inst, QWidget* parent = 0); virtual ~GameOptionsPage(); void openedImpl() override; void closedImpl() override; - virtual QString displayName() const override - { - return tr("Game Options"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("settings"); - } - virtual QString id() const override - { - return "gameoptions"; - } - virtual QString helpPage() const override - { - return "Game-Options-management"; - } + virtual QString displayName() const override { return tr("Game Options"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("settings"); } + virtual QString id() const override { return "gameoptions"; } + virtual QString helpPage() const override { return "Game-Options-management"; } void retranslate() override; -private: // data - Ui::GameOptionsPage *ui = nullptr; + private: // data + Ui::GameOptionsPage* ui = nullptr; std::shared_ptr m_model; }; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 718c628c7..8ea24b78a 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -38,8 +38,8 @@ #include "InstanceSettingsPage.h" #include "ui_InstanceSettingsPage.h" -#include #include +#include #include #include @@ -47,15 +47,15 @@ #include "ui/dialogs/VersionSelectDialog.h" #include "ui/widgets/CustomCommands.h" -#include "JavaCommon.h" #include "Application.h" +#include "JavaCommon.h" #include "minecraft/auth/AccountList.h" #include "FileSystem.h" #include "java/JavaInstallList.h" #include "java/JavaUtils.h" -InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) +InstanceSettingsPage::InstanceSettingsPage(BaseInstance* inst, QWidget* parent) : QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst) { m_settings = inst->settings(); @@ -78,7 +78,7 @@ InstanceSettingsPage::~InstanceSettingsPage() void InstanceSettingsPage::globalSettingsButtonClicked(bool) { - switch(ui->settingsTabs->currentIndex()) { + switch (ui->settingsTabs->currentIndex()) { case 0: APPLICATION->ShowGlobalSettings(this, "java-settings"); return; @@ -104,13 +104,10 @@ void InstanceSettingsPage::applySettings() // Miscellaneous bool miscellaneous = ui->miscellaneousSettingsBox->isChecked(); m_settings->set("OverrideMiscellaneous", miscellaneous); - if (miscellaneous) - { + if (miscellaneous) { m_settings->set("CloseAfterLaunch", ui->closeAfterLaunchCheck->isChecked()); m_settings->set("QuitAfterGameStop", ui->quitAfterGameStopCheck->isChecked()); - } - else - { + } else { m_settings->reset("CloseAfterLaunch"); m_settings->reset("QuitAfterGameStop"); } @@ -118,14 +115,11 @@ void InstanceSettingsPage::applySettings() // Console bool console = ui->consoleSettingsBox->isChecked(); m_settings->set("OverrideConsole", console); - if (console) - { + if (console) { m_settings->set("ShowConsole", ui->showConsoleCheck->isChecked()); m_settings->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked()); m_settings->set("ShowConsoleOnError", ui->showConsoleErrorCheck->isChecked()); - } - else - { + } else { m_settings->reset("ShowConsole"); m_settings->reset("AutoCloseConsole"); m_settings->reset("ShowConsoleOnError"); @@ -134,14 +128,11 @@ void InstanceSettingsPage::applySettings() // Window Size bool window = ui->windowSizeGroupBox->isChecked(); m_settings->set("OverrideWindow", window); - if (window) - { + if (window) { m_settings->set("LaunchMaximized", ui->maximizedCheckBox->isChecked()); m_settings->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); m_settings->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); - } - else - { + } else { m_settings->reset("LaunchMaximized"); m_settings->reset("MinecraftWinWidth"); m_settings->reset("MinecraftWinHeight"); @@ -150,24 +141,18 @@ void InstanceSettingsPage::applySettings() // Memory bool memory = ui->memoryGroupBox->isChecked(); m_settings->set("OverrideMemory", memory); - if (memory) - { + if (memory) { int min = ui->minMemSpinBox->value(); int max = ui->maxMemSpinBox->value(); - if(min < max) - { + if (min < max) { m_settings->set("MinMemAlloc", min); m_settings->set("MaxMemAlloc", max); - } - else - { + } else { m_settings->set("MinMemAlloc", max); m_settings->set("MaxMemAlloc", min); } m_settings->set("PermGen", ui->permGenSpinBox->value()); - } - else - { + } else { m_settings->reset("MinMemAlloc"); m_settings->reset("MaxMemAlloc"); m_settings->reset("PermGen"); @@ -176,13 +161,10 @@ void InstanceSettingsPage::applySettings() // Java Install Settings bool javaInstall = ui->javaSettingsGroupBox->isChecked(); m_settings->set("OverrideJavaLocation", javaInstall); - if (javaInstall) - { + if (javaInstall) { m_settings->set("JavaPath", ui->javaPathTextBox->text()); m_settings->set("IgnoreJavaCompatibility", ui->skipCompatibilityCheckbox->isChecked()); - } - else - { + } else { m_settings->reset("JavaPath"); m_settings->reset("IgnoreJavaCompatibility"); } @@ -190,12 +172,9 @@ void InstanceSettingsPage::applySettings() // Java arguments bool javaArgs = ui->javaArgumentsGroupBox->isChecked(); m_settings->set("OverrideJavaArgs", javaArgs); - if(javaArgs) - { + if (javaArgs) { m_settings->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " ")); - } - else - { + } else { m_settings->reset("JvmArgs"); } @@ -205,14 +184,11 @@ void InstanceSettingsPage::applySettings() // Custom Commands bool custcmd = ui->customCommands->checked(); m_settings->set("OverrideCommands", custcmd); - if (custcmd) - { + if (custcmd) { m_settings->set("PreLaunchCommand", ui->customCommands->prelaunchCommand()); m_settings->set("WrapperCommand", ui->customCommands->wrapperCommand()); m_settings->set("PostExitCommand", ui->customCommands->postexitCommand()); - } - else - { + } else { m_settings->reset("PreLaunchCommand"); m_settings->reset("WrapperCommand"); m_settings->reset("PostExitCommand"); @@ -221,13 +197,10 @@ void InstanceSettingsPage::applySettings() // Workarounds bool workarounds = ui->nativeWorkaroundsGroupBox->isChecked(); m_settings->set("OverrideNativeWorkarounds", workarounds); - if(workarounds) - { + if (workarounds) { m_settings->set("UseNativeOpenAL", ui->useNativeOpenALCheck->isChecked()); m_settings->set("UseNativeGLFW", ui->useNativeGLFWCheck->isChecked()); - } - else - { + } else { m_settings->reset("UseNativeOpenAL"); m_settings->reset("UseNativeGLFW"); } @@ -235,14 +208,11 @@ void InstanceSettingsPage::applySettings() // Performance bool performance = ui->perfomanceGroupBox->isChecked(); m_settings->set("OverridePerformance", performance); - if(performance) - { + if (performance) { m_settings->set("EnableFeralGamemode", ui->enableFeralGamemodeCheck->isChecked()); m_settings->set("EnableMangoHud", ui->enableMangoHud->isChecked()); m_settings->set("UseDiscreteGpu", ui->useDiscreteGpuCheck->isChecked()); - } - else - { + } else { m_settings->reset("EnableFeralGamemode"); m_settings->reset("EnableMangoHud"); m_settings->reset("UseDiscreteGpu"); @@ -251,13 +221,10 @@ void InstanceSettingsPage::applySettings() // Game time bool gameTime = ui->gameTimeGroupBox->isChecked(); m_settings->set("OverrideGameTime", gameTime); - if (gameTime) - { + if (gameTime) { m_settings->set("ShowGameTime", ui->showGameTime->isChecked()); m_settings->set("RecordGameTime", ui->recordGameTime->isChecked()); - } - else - { + } else { m_settings->reset("ShowGameTime"); m_settings->reset("RecordGameTime"); } @@ -265,12 +232,9 @@ void InstanceSettingsPage::applySettings() // Join server on launch bool joinServerOnLaunch = ui->serverJoinGroupBox->isChecked(); m_settings->set("JoinServerOnLaunch", joinServerOnLaunch); - if (joinServerOnLaunch) - { + if (joinServerOnLaunch) { m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text()); - } - else - { + } else { m_settings->reset("JoinServerOnLaunchAddress"); } @@ -316,13 +280,10 @@ void InstanceSettingsPage::loadSettings() ui->memoryGroupBox->setChecked(m_settings->get("OverrideMemory").toBool()); int min = m_settings->get("MinMemAlloc").toInt(); int max = m_settings->get("MaxMemAlloc").toInt(); - if(min < max) - { + if (min < max) { ui->minMemSpinBox->setValue(min); ui->maxMemSpinBox->setValue(max); - } - else - { + } else { ui->minMemSpinBox->setValue(max); ui->maxMemSpinBox->setValue(min); } @@ -332,7 +293,6 @@ void InstanceSettingsPage::loadSettings() ui->labelPermGen->setVisible(permGenVisible); ui->labelPermgenNote->setVisible(permGenVisible); - // Java Settings bool overrideJava = m_settings->get("OverrideJava").toBool(); bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava; @@ -346,13 +306,8 @@ void InstanceSettingsPage::loadSettings() ui->jvmArgsTextBox->setPlainText(m_settings->get("JvmArgs").toString()); // Custom commands - ui->customCommands->initialize( - true, - m_settings->get("OverrideCommands").toBool(), - m_settings->get("PreLaunchCommand").toString(), - m_settings->get("WrapperCommand").toString(), - m_settings->get("PostExitCommand").toString() - ); + ui->customCommands->initialize(true, m_settings->get("OverrideCommands").toBool(), m_settings->get("PreLaunchCommand").toString(), + m_settings->get("WrapperCommand").toString(), m_settings->get("PostExitCommand").toString()); // Workarounds ui->nativeWorkaroundsGroupBox->setChecked(m_settings->get("OverrideNativeWorkarounds").toBool()); @@ -408,8 +363,7 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked() vselect.setResizeOn(2); vselect.exec(); - if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) - { + if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) { java = std::dynamic_pointer_cast(vselect.selectedVersion()); ui->javaPathTextBox->setText(java->path); bool visible = java->id.requiresPermGen() && m_settings->get("OverrideMemory").toBool(); @@ -425,15 +379,13 @@ void InstanceSettingsPage::on_javaBrowseBtn_clicked() QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable")); // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if(raw_path.isEmpty()) - { + if (raw_path.isEmpty()) { return; } QString cooked_path = FS::NormalizePath(raw_path); QFileInfo javaInfo(cooked_path); - if(!javaInfo.exists() || !javaInfo.isExecutable()) - { + if (!javaInfo.exists() || !javaInfo.isExecutable()) { return; } ui->javaPathTextBox->setText(cooked_path); @@ -447,13 +399,11 @@ void InstanceSettingsPage::on_javaBrowseBtn_clicked() void InstanceSettingsPage::on_javaTestBtn_clicked() { - if(checker) - { + if (checker) { return; } - checker.reset(new JavaCommon::TestCheck( - this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "), - ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value())); + checker.reset(new JavaCommon::TestCheck(this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "), + ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value())); connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished())); checker->run(); } @@ -470,7 +420,6 @@ void InstanceSettingsPage::updateAccountsMenu() if (i == accountIndex) ui->instanceAccountSelector->setCurrentIndex(i); } - } QIcon InstanceSettingsPage::getFaceForAccount(MinecraftAccountPtr account) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 036b41818..9f1355939 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -46,35 +46,21 @@ #include "ui/pages/BasePage.h" class JavaChecker; -namespace Ui -{ +namespace Ui { class InstanceSettingsPage; } -class InstanceSettingsPage : public QWidget, public BasePage -{ +class InstanceSettingsPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0); + public: + explicit InstanceSettingsPage(BaseInstance* inst, QWidget* parent = 0); virtual ~InstanceSettingsPage(); - virtual QString displayName() const override - { - return tr("Settings"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("instance-settings"); - } - virtual QString id() const override - { - return "settings"; - } + virtual QString displayName() const override { return tr("Settings"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("instance-settings"); } + virtual QString id() const override { return "settings"; } virtual bool apply() override; - virtual QString helpPage() const override - { - return "Instance-settings"; - } + virtual QString helpPage() const override { return "Instance-settings"; } void retranslate() override; void updateThresholds(); @@ -96,9 +82,9 @@ public: QIcon getFaceForAccount(MinecraftAccountPtr account); void changeInstanceAccount(int index); -private: - Ui::InstanceSettingsPage *ui; - BaseInstance *m_instance; + private: + Ui::InstanceSettingsPage* ui; + BaseInstance* m_instance; SettingsObjectPtr m_settings; unique_qobject_ptr checker; }; diff --git a/launcher/ui/pages/instance/LogPage.cpp b/launcher/ui/pages/instance/LogPage.cpp index 639cd7118..8e1e53762 100644 --- a/launcher/ui/pages/instance/LogPage.cpp +++ b/launcher/ui/pages/instance/LogPage.cpp @@ -47,56 +47,42 @@ #include "launch/LaunchTask.h" #include "settings/Setting.h" -#include "ui/GuiUtil.h" #include "ui/ColorCache.h" +#include "ui/GuiUtil.h" #include -class LogFormatProxyModel : public QIdentityProxyModel -{ -public: - LogFormatProxyModel(QObject* parent = nullptr) : QIdentityProxyModel(parent) +class LogFormatProxyModel : public QIdentityProxyModel { + public: + LogFormatProxyModel(QObject* parent = nullptr) : QIdentityProxyModel(parent) {} + QVariant data(const QModelIndex& index, int role) const override { - } - QVariant data(const QModelIndex &index, int role) const override - { - switch(role) - { + switch (role) { case Qt::FontRole: return m_font; - case Qt::ForegroundRole: - { - MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); + case Qt::ForegroundRole: { + MessageLevel::Enum level = (MessageLevel::Enum)QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); return m_colors->getFront(level); } - case Qt::BackgroundRole: - { - MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); + case Qt::BackgroundRole: { + MessageLevel::Enum level = (MessageLevel::Enum)QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); return m_colors->getBack(level); } default: return QIdentityProxyModel::data(index, role); - } + } } - void setFont(QFont font) - { - m_font = font; - } + void setFont(QFont font) { m_font = font; } - void setColors(LogColorCache* colors) - { - m_colors.reset(colors); - } + void setColors(LogColorCache* colors) { m_colors.reset(colors); } - QModelIndex find(const QModelIndex &start, const QString &value, bool reverse) const + QModelIndex find(const QModelIndex& start, const QString& value, bool reverse) const { QModelIndex parentIndex = parent(start); - auto compare = [&](int r) -> QModelIndex - { + auto compare = [&](int r) -> QModelIndex { QModelIndex idx = index(r, start.column(), parentIndex); - if (!idx.isValid() || idx == start) - { + if (!idx.isValid() || idx == start) { return QModelIndex(); } QVariant v = data(idx, Qt::DisplayRole); @@ -105,35 +91,28 @@ public: return idx; return QModelIndex(); }; - if(reverse) - { + if (reverse) { int from = start.row(); int to = 0; - for (int i = 0; i < 2; ++i) - { - for (int r = from; (r >= to); --r) - { + for (int i = 0; i < 2; ++i) { + for (int r = from; (r >= to); --r) { auto idx = compare(r); - if(idx.isValid()) + if (idx.isValid()) return idx; } // prepare for the next iteration from = rowCount() - 1; to = start.row(); } - } - else - { + } else { int from = start.row(); int to = rowCount(parentIndex); - for (int i = 0; i < 2; ++i) - { - for (int r = from; (r < to); ++r) - { + for (int i = 0; i < 2; ++i) { + for (int r = from; (r < to); ++r) { auto idx = compare(r); - if(idx.isValid()) + if (idx.isValid()) return idx; } // prepare for the next iteration @@ -143,13 +122,13 @@ public: } return QModelIndex(); } -private: + + private: QFont m_font; std::unique_ptr m_colors; }; -LogPage::LogPage(InstancePtr instance, QWidget *parent) - : QWidget(parent), ui(new Ui::LogPage), m_instance(instance) +LogPage::LogPage(InstancePtr instance, QWidget* parent) : QWidget(parent), ui(new Ui::LogPage), m_instance(instance) { ui->setupUi(this); ui->tabWidget->tabBar()->hide(); @@ -167,8 +146,7 @@ LogPage::LogPage(InstancePtr instance, QWidget *parent) QString fontFamily = APPLICATION->settings()->get("ConsoleFont").toString(); bool conversionOk = false; int fontSize = APPLICATION->settings()->get("ConsoleFontSize").toInt(&conversionOk); - if(!conversionOk) - { + if (!conversionOk) { fontSize = 11; } m_proxy->setFont(QFont(fontFamily, fontSize)); @@ -179,8 +157,7 @@ LogPage::LogPage(InstancePtr instance, QWidget *parent) // set up instance and launch process recognition { auto launchTask = m_instance->getLaunchTask(); - if(launchTask) - { + if (launchTask) { setInstanceLaunchTaskChanged(launchTask, true); } connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &LogPage::onInstanceLaunchTaskChanged); @@ -202,30 +179,23 @@ LogPage::~LogPage() void LogPage::modelStateToUI() { - if(m_model->wrapLines()) - { + if (m_model->wrapLines()) { ui->text->setWordWrap(true); ui->wrapCheckbox->setCheckState(Qt::Checked); - } - else - { + } else { ui->text->setWordWrap(false); ui->wrapCheckbox->setCheckState(Qt::Unchecked); } - if(m_model->suspended()) - { + if (m_model->suspended()) { ui->trackLogCheckbox->setCheckState(Qt::Unchecked); - } - else - { + } else { ui->trackLogCheckbox->setCheckState(Qt::Checked); } } void LogPage::UIToModelState() { - if(!m_model) - { + if (!m_model) { return; } m_model->setLineWrap(ui->wrapCheckbox->checkState() == Qt::Checked); @@ -235,21 +205,15 @@ void LogPage::UIToModelState() void LogPage::setInstanceLaunchTaskChanged(shared_qobject_ptr proc, bool initial) { m_process = proc; - if(m_process) - { + if (m_process) { m_model = proc->getLogModel(); m_proxy->setSourceModel(m_model.get()); - if(initial) - { + if (initial) { modelStateToUI(); - } - else - { + } else { UIToModelState(); } - } - else - { + } else { m_proxy->setSourceModel(nullptr); m_model.reset(); } @@ -272,34 +236,25 @@ bool LogPage::shouldDisplay() const void LogPage::on_btnPaste_clicked() { - if(!m_model) + if (!m_model) return; - //FIXME: turn this into a proper task and move the upload logic out of GuiUtil! - m_model->append( - MessageLevel::Launcher, - QString("Log upload triggered at: %1").arg( - QDateTime::currentDateTime().toString(Qt::RFC2822Date) - ) - ); + // FIXME: turn this into a proper task and move the upload logic out of GuiUtil! + m_model->append(MessageLevel::Launcher, + QString("Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); auto url = GuiUtil::uploadPaste(tr("Minecraft Log"), m_model->toPlainText(), this); - if(!url.has_value()) - { + if (!url.has_value()) { m_model->append(MessageLevel::Error, QString("Log upload canceled")); - } - else if (url->isNull()) - { + } else if (url->isNull()) { m_model->append(MessageLevel::Error, QString("Log upload failed!")); - } - else - { + } else { m_model->append(MessageLevel::Launcher, QString("Log uploaded to: %1").arg(url.value())); } } void LogPage::on_btnCopy_clicked() { - if(!m_model) + if (!m_model) return; m_model->append(MessageLevel::Launcher, QString("Clipboard copy at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); GuiUtil::setClipboardText(m_model->toPlainText()); @@ -307,7 +262,7 @@ void LogPage::on_btnCopy_clicked() void LogPage::on_btnClear_clicked() { - if(!m_model) + if (!m_model) return; m_model->clear(); m_container->refreshContainer(); @@ -320,7 +275,7 @@ void LogPage::on_btnBottom_clicked() void LogPage::on_trackLogCheckbox_clicked(bool checked) { - if(!m_model) + if (!m_model) return; m_model->suspend(!checked); } @@ -328,7 +283,7 @@ void LogPage::on_trackLogCheckbox_clicked(bool checked) void LogPage::on_wrapCheckbox_clicked(bool checked) { ui->text->setWordWrap(checked); - if(!m_model) + if (!m_model) return; m_model->setLineWrap(checked); } @@ -353,8 +308,7 @@ void LogPage::findPreviousActivated() void LogPage::findActivated() { // focus the search bar if it doesn't have focus - if (!ui->searchBar->hasFocus()) - { + if (!ui->searchBar->hasFocus()) { ui->searchBar->setFocus(); ui->searchBar->selectAll(); } diff --git a/launcher/ui/pages/instance/LogPage.h b/launcher/ui/pages/instance/LogPage.h index f6fe87c41..33b6cc39f 100644 --- a/launcher/ui/pages/instance/LogPage.h +++ b/launcher/ui/pages/instance/LogPage.h @@ -37,46 +37,32 @@ #include +#include #include "BaseInstance.h" #include "launch/LaunchTask.h" #include "ui/pages/BasePage.h" -#include -namespace Ui -{ +namespace Ui { class LogPage; } class QTextCharFormat; class LogFormatProxyModel; -class LogPage : public QWidget, public BasePage -{ +class LogPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit LogPage(InstancePtr instance, QWidget *parent = 0); + public: + explicit LogPage(InstancePtr instance, QWidget* parent = 0); virtual ~LogPage(); - virtual QString displayName() const override - { - return tr("Minecraft Log"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("log"); - } - virtual QString id() const override - { - return "console"; - } + virtual QString displayName() const override { return tr("Minecraft Log"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("log"); } + virtual QString id() const override { return "console"; } virtual bool apply() override; - virtual QString helpPage() const override - { - return "Minecraft-Logs"; - } + virtual QString helpPage() const override { return "Minecraft-Logs"; } virtual bool shouldDisplay() const override; void retranslate() override; -private slots: + private slots: void on_btnPaste_clicked(); void on_btnCopy_clicked(); void on_btnClear_clicked(); @@ -92,16 +78,16 @@ private slots: void onInstanceLaunchTaskChanged(shared_qobject_ptr proc); -private: + private: void modelStateToUI(); void UIToModelState(); void setInstanceLaunchTaskChanged(shared_qobject_ptr proc, bool initial); -private: - Ui::LogPage *ui; + private: + Ui::LogPage* ui; InstancePtr m_instance; shared_qobject_ptr m_process; - LogFormatProxyModel * m_proxy; - shared_qobject_ptr m_model; + LogFormatProxyModel* m_proxy; + shared_qobject_ptr m_model; }; diff --git a/launcher/ui/pages/instance/NotesPage.cpp b/launcher/ui/pages/instance/NotesPage.cpp index 95a9fad22..887bad85a 100644 --- a/launcher/ui/pages/instance/NotesPage.cpp +++ b/launcher/ui/pages/instance/NotesPage.cpp @@ -34,11 +34,10 @@ */ #include "NotesPage.h" -#include "ui_NotesPage.h" #include +#include "ui_NotesPage.h" -NotesPage::NotesPage(BaseInstance *inst, QWidget *parent) - : QWidget(parent), ui(new Ui::NotesPage), m_inst(inst) +NotesPage::NotesPage(BaseInstance* inst, QWidget* parent) : QWidget(parent), ui(new Ui::NotesPage), m_inst(inst) { ui->setupUi(this); ui->noteEditor->setText(m_inst->notes()); diff --git a/launcher/ui/pages/instance/NotesPage.h b/launcher/ui/pages/instance/NotesPage.h index 80a7279bc..aa6083062 100644 --- a/launcher/ui/pages/instance/NotesPage.h +++ b/launcher/ui/pages/instance/NotesPage.h @@ -37,45 +37,34 @@ #include +#include #include "BaseInstance.h" #include "ui/pages/BasePage.h" -#include -namespace Ui -{ +namespace Ui { class NotesPage; } -class NotesPage : public QWidget, public BasePage -{ +class NotesPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit NotesPage(BaseInstance *inst, QWidget *parent = 0); + public: + explicit NotesPage(BaseInstance* inst, QWidget* parent = 0); virtual ~NotesPage(); - virtual QString displayName() const override - { - return tr("Notes"); - } + virtual QString displayName() const override { return tr("Notes"); } virtual QIcon icon() const override { auto icon = APPLICATION->getThemedIcon("notes"); - if(icon.isNull()) + if (icon.isNull()) icon = APPLICATION->getThemedIcon("news"); return icon; } - virtual QString id() const override - { - return "notes"; - } + virtual QString id() const override { return "notes"; } virtual bool apply() override; - virtual QString helpPage() const override - { - return "Notes"; - } + virtual QString helpPage() const override { return "Notes"; } void retranslate() override; -private: - Ui::NotesPage *ui; - BaseInstance *m_inst; + private: + Ui::NotesPage* ui; + BaseInstance* m_inst; }; diff --git a/launcher/ui/pages/instance/OtherLogsPage.cpp b/launcher/ui/pages/instance/OtherLogsPage.cpp index f2b13f321..ab5d98289 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.cpp +++ b/launcher/ui/pages/instance/OtherLogsPage.cpp @@ -41,14 +41,13 @@ #include "ui/GuiUtil.h" -#include "RecursiveFileSystemWatcher.h" -#include #include +#include #include +#include "RecursiveFileSystemWatcher.h" -OtherLogsPage::OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget *parent) - : QWidget(parent), ui(new Ui::OtherLogsPage), m_path(path), m_fileFilter(fileFilter), - m_watcher(new RecursiveFileSystemWatcher(this)) +OtherLogsPage::OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget* parent) + : QWidget(parent), ui(new Ui::OtherLogsPage), m_path(path), m_fileFilter(fileFilter), m_watcher(new RecursiveFileSystemWatcher(this)) { ui->setupUi(this); ui->tabWidget->tabBar()->hide(); @@ -94,21 +93,15 @@ void OtherLogsPage::populateSelectLogBox() { ui->selectLogBox->clear(); ui->selectLogBox->addItems(m_watcher->files()); - if (m_currentFile.isEmpty()) - { + if (m_currentFile.isEmpty()) { setControlsEnabled(false); ui->selectLogBox->setCurrentIndex(-1); - } - else - { + } else { const int index = ui->selectLogBox->findText(m_currentFile); - if (index != -1) - { + if (index != -1) { ui->selectLogBox->setCurrentIndex(index); setControlsEnabled(true); - } - else - { + } else { setControlsEnabled(false); } } @@ -117,19 +110,15 @@ void OtherLogsPage::populateSelectLogBox() void OtherLogsPage::on_selectLogBox_currentIndexChanged(const int index) { QString file; - if (index != -1) - { + if (index != -1) { file = ui->selectLogBox->itemText(index); } - if (file.isEmpty() || !QFile::exists(FS::PathCombine(m_path, file))) - { + if (file.isEmpty() || !QFile::exists(FS::PathCombine(m_path, file))) { m_currentFile = QString(); ui->text->clear(); setControlsEnabled(false); - } - else - { + } else { m_currentFile = file; on_btnReload_clicked(); setControlsEnabled(true); @@ -138,64 +127,49 @@ void OtherLogsPage::on_selectLogBox_currentIndexChanged(const int index) void OtherLogsPage::on_btnReload_clicked() { - if(m_currentFile.isEmpty()) - { + if (m_currentFile.isEmpty()) { setControlsEnabled(false); return; } QFile file(FS::PathCombine(m_path, m_currentFile)); - if (!file.open(QFile::ReadOnly)) - { + if (!file.open(QFile::ReadOnly)) { setControlsEnabled(false); - ui->btnReload->setEnabled(true); // allow reload + ui->btnReload->setEnabled(true); // allow reload m_currentFile = QString(); - QMessageBox::critical(this, tr("Error"), tr("Unable to open %1 for reading: %2") - .arg(m_currentFile, file.errorString())); - } - else - { - auto setPlainText = [&](const QString & text) - { + QMessageBox::critical(this, tr("Error"), tr("Unable to open %1 for reading: %2").arg(m_currentFile, file.errorString())); + } else { + auto setPlainText = [&](const QString& text) { QString fontFamily = APPLICATION->settings()->get("ConsoleFont").toString(); bool conversionOk = false; int fontSize = APPLICATION->settings()->get("ConsoleFontSize").toInt(&conversionOk); - if(!conversionOk) - { + if (!conversionOk) { fontSize = 11; } - QTextDocument *doc = ui->text->document(); + QTextDocument* doc = ui->text->document(); doc->setDefaultFont(QFont(fontFamily, fontSize)); ui->text->setPlainText(text); }; - auto showTooBig = [&]() - { - setPlainText( - tr("The file (%1) is too big. You may want to open it in a viewer optimized " - "for large files.").arg(file.fileName())); + auto showTooBig = [&]() { + setPlainText(tr("The file (%1) is too big. You may want to open it in a viewer optimized " + "for large files.") + .arg(file.fileName())); }; - if(file.size() > (1024ll * 1024ll * 12ll)) - { + if (file.size() > (1024ll * 1024ll * 12ll)) { showTooBig(); return; } QString content; - if(file.fileName().endsWith(".gz")) - { + if (file.fileName().endsWith(".gz")) { QByteArray temp; - if(!GZip::unzip(file.readAll(), temp)) - { - setPlainText( - tr("The file (%1) is not readable.").arg(file.fileName())); + if (!GZip::unzip(file.readAll(), temp)) { + setPlainText(tr("The file (%1) is not readable.").arg(file.fileName())); return; } content = QString::fromUtf8(temp); - } - else - { + } else { content = QString::fromUtf8(file.readAll()); } - if (content.size() >= 50000000ll) - { + if (content.size() >= 50000000ll) { showTooBig(); return; } @@ -215,8 +189,7 @@ void OtherLogsPage::on_btnCopy_clicked() void OtherLogsPage::on_btnDelete_clicked() { - if(m_currentFile.isEmpty()) - { + if (m_currentFile.isEmpty()) { setControlsEnabled(false); return; } @@ -230,36 +203,27 @@ void OtherLogsPage::on_btnDelete_clicked() } QFile file(FS::PathCombine(m_path, m_currentFile)); - if (FS::trash(file.fileName())) - { + if (FS::trash(file.fileName())) { return; } - if (!file.remove()) - { - QMessageBox::critical(this, tr("Error"), tr("Unable to delete %1: %2") - .arg(m_currentFile, file.errorString())); + if (!file.remove()) { + QMessageBox::critical(this, tr("Error"), tr("Unable to delete %1: %2").arg(m_currentFile, file.errorString())); } } - - void OtherLogsPage::on_btnClean_clicked() { auto toDelete = m_watcher->files(); - if(toDelete.isEmpty()) - { + if (toDelete.isEmpty()) { return; } - QMessageBox *messageBox = new QMessageBox(this); + QMessageBox* messageBox = new QMessageBox(this); messageBox->setWindowTitle(tr("Confirm Cleanup")); - if(toDelete.size() > 5) - { + if (toDelete.size() > 5) { messageBox->setText(tr("Are you sure you want to delete all log files?")); messageBox->setDetailedText(toDelete.join('\n')); - } - else - { + } else { messageBox->setText(tr("Are you sure you want to delete all these files?\n%1").arg(toDelete.join('\n'))); } messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); @@ -268,34 +232,26 @@ void OtherLogsPage::on_btnClean_clicked() messageBox->setIcon(QMessageBox::Question); messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction); - if (messageBox->exec() != QMessageBox::Ok) - { + if (messageBox->exec() != QMessageBox::Ok) { return; } QStringList failed; - for(auto item: toDelete) - { + for (auto item : toDelete) { QFile file(FS::PathCombine(m_path, item)); - if (FS::trash(file.fileName())) - { + if (FS::trash(file.fileName())) { continue; } - if (!file.remove()) - { + if (!file.remove()) { failed.push_back(item); } } - if(!failed.empty()) - { - QMessageBox *messageBoxFailure = new QMessageBox(this); + if (!failed.empty()) { + QMessageBox* messageBoxFailure = new QMessageBox(this); messageBoxFailure->setWindowTitle(tr("Error")); - if(failed.size() > 5) - { + if (failed.size() > 5) { messageBoxFailure->setText(tr("Couldn't delete some files!")); messageBoxFailure->setDetailedText(failed.join('\n')); - } - else - { + } else { messageBoxFailure->setText(tr("Couldn't delete some files:\n%1").arg(failed.join('\n'))); } messageBoxFailure->setStandardButtons(QMessageBox::Ok); @@ -307,7 +263,6 @@ void OtherLogsPage::on_btnClean_clicked() } } - void OtherLogsPage::setControlsEnabled(const bool enabled) { ui->btnReload->setEnabled(enabled); @@ -319,7 +274,7 @@ void OtherLogsPage::setControlsEnabled(const bool enabled) } // FIXME: HACK, use LogView instead? -static void findNext(QPlainTextEdit * _this, const QString& what, bool reverse) +static void findNext(QPlainTextEdit* _this, const QString& what, bool reverse) { _this->find(what, reverse ? QTextDocument::FindFlag::FindBackward : QTextDocument::FindFlag(0)); } @@ -344,8 +299,7 @@ void OtherLogsPage::findPreviousActivated() void OtherLogsPage::findActivated() { // focus the search bar if it doesn't have focus - if (!ui->searchBar->hasFocus()) - { + if (!ui->searchBar->hasFocus()) { ui->searchBar->setFocus(); ui->searchBar->selectAll(); } diff --git a/launcher/ui/pages/instance/OtherLogsPage.h b/launcher/ui/pages/instance/OtherLogsPage.h index 95591638b..ecb896fca 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.h +++ b/launcher/ui/pages/instance/OtherLogsPage.h @@ -37,47 +37,33 @@ #include -#include "ui/pages/BasePage.h" #include #include +#include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class OtherLogsPage; } class RecursiveFileSystemWatcher; -class OtherLogsPage : public QWidget, public BasePage -{ +class OtherLogsPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget *parent = 0); + public: + explicit OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget* parent = 0); ~OtherLogsPage(); - QString id() const override - { - return "logs"; - } - QString displayName() const override - { - return tr("Other logs"); - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("log"); - } - QString helpPage() const override - { - return "Minecraft-Logs"; - } + QString id() const override { return "logs"; } + QString displayName() const override { return tr("Other logs"); } + QIcon icon() const override { return APPLICATION->getThemedIcon("log"); } + QString helpPage() const override { return "Minecraft-Logs"; } void retranslate() override; void openedImpl() override; void closedImpl() override; -private slots: + private slots: void populateSelectLogBox(); void on_selectLogBox_currentIndexChanged(const int index); void on_btnReload_clicked(); @@ -91,13 +77,13 @@ private slots: void findNextActivated(); void findPreviousActivated(); -private: + private: void setControlsEnabled(const bool enabled); -private: - Ui::OtherLogsPage *ui; + private: + Ui::OtherLogsPage* ui; QString m_path; QString m_currentFile; IPathMatcher::Ptr m_fileFilter; - RecursiveFileSystemWatcher *m_watcher; + RecursiveFileSystemWatcher* m_watcher; }; diff --git a/launcher/ui/pages/instance/ResourcePackPage.h b/launcher/ui/pages/instance/ResourcePackPage.h index b04aa2e96..cb84ca96d 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.h +++ b/launcher/ui/pages/instance/ResourcePackPage.h @@ -42,11 +42,10 @@ #include "minecraft/mod/ResourcePackFolderModel.h" -class ResourcePackPage : public ExternalResourcesPage -{ +class ResourcePackPage : public ExternalResourcesPage { Q_OBJECT -public: - explicit ResourcePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = 0); + public: + explicit ResourcePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent = 0); QString displayName() const override { return tr("Resource packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); } @@ -55,12 +54,10 @@ public: virtual bool shouldDisplay() const override { - return !m_instance->traits().contains("no-texturepacks") && - !m_instance->traits().contains("texturepacks"); + return !m_instance->traits().contains("no-texturepacks") && !m_instance->traits().contains("texturepacks"); } public slots: bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; void downloadRPs(); }; - diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index bcce5f572..29c835fc1 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -39,52 +39,50 @@ #include "BuildConfig.h" #include "ui_ScreenshotsPage.h" -#include -#include -#include -#include +#include +#include #include #include -#include -#include -#include -#include -#include #include +#include +#include #include +#include +#include +#include #include +#include +#include #include -#include "ui/dialogs/ProgressDialog.h" #include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" #include "net/NetJob.h" -#include "screenshots/ImgurUpload.h" #include "screenshots/ImgurAlbumCreation.h" +#include "screenshots/ImgurUpload.h" #include "tasks/SequentialTask.h" -#include "RWStorage.h" -#include #include +#include +#include "RWStorage.h" typedef RWStorage SharedIconCache; typedef std::shared_ptr SharedIconCachePtr; -class ThumbnailingResult : public QObject -{ +class ThumbnailingResult : public QObject { Q_OBJECT -public slots: - inline void emitResultsReady(const QString &path) { emit resultsReady(path); } - inline void emitResultsFailed(const QString &path) { emit resultsFailed(path); } -signals: - void resultsReady(const QString &path); - void resultsFailed(const QString &path); + public slots: + inline void emitResultsReady(const QString& path) { emit resultsReady(path); } + inline void emitResultsFailed(const QString& path) { emit resultsFailed(path); } + signals: + void resultsReady(const QString& path); + void resultsFailed(const QString& path); }; -class ThumbnailRunnable : public QRunnable -{ -public: +class ThumbnailRunnable : public QRunnable { + public: ThumbnailRunnable(QString path, SharedIconCachePtr cache) { m_path = path; @@ -129,57 +127,50 @@ public: // this is about as elegant and well written as a bag of bricks with scribbles done by insane // asylum patients. -class FilterModel : public QIdentityProxyModel -{ +class FilterModel : public QIdentityProxyModel { Q_OBJECT -public: - explicit FilterModel(QObject *parent = 0) : QIdentityProxyModel(parent) + public: + explicit FilterModel(QObject* parent = 0) : QIdentityProxyModel(parent) { m_thumbnailingPool.setMaxThreadCount(4); m_thumbnailCache = std::make_shared(); m_thumbnailCache->add("placeholder", APPLICATION->getThemedIcon("screenshot-placeholder")); connect(&watcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString))); } - virtual ~FilterModel() { + virtual ~FilterModel() + { m_thumbnailingPool.clear(); if (!m_thumbnailingPool.waitForDone(500)) qDebug() << "Thumbnail pool took longer than 500ms to finish"; } - virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const + virtual QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const { auto model = sourceModel(); if (!model) return QVariant(); - if (role == Qt::DisplayRole || role == Qt::EditRole) - { + if (role == Qt::DisplayRole || role == Qt::EditRole) { QVariant result = sourceModel()->data(mapToSource(proxyIndex), role); return result.toString().remove(QRegularExpression("\\.png$")); } - if (role == Qt::DecorationRole) - { - QVariant result = - sourceModel()->data(mapToSource(proxyIndex), QFileSystemModel::FilePathRole); + if (role == Qt::DecorationRole) { + QVariant result = sourceModel()->data(mapToSource(proxyIndex), QFileSystemModel::FilePathRole); QString filePath = result.toString(); QIcon temp; - if (!watched.contains(filePath)) - { - ((QFileSystemWatcher &)watcher).addPath(filePath); - ((QSet &)watched).insert(filePath); + if (!watched.contains(filePath)) { + ((QFileSystemWatcher&)watcher).addPath(filePath); + ((QSet&)watched).insert(filePath); } - if (m_thumbnailCache->get(filePath, temp)) - { + if (m_thumbnailCache->get(filePath, temp)) { return temp; } - if (!m_failed.contains(filePath)) - { - ((FilterModel *)this)->thumbnailImage(filePath); + if (!m_failed.contains(filePath)) { + ((FilterModel*)this)->thumbnailImage(filePath); } return (m_thumbnailCache->get("placeholder")); } return sourceModel()->data(mapToSource(proxyIndex), role); } - virtual bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole) + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) { auto model = sourceModel(); if (!model) @@ -189,23 +180,21 @@ public: // FIXME: this is a workaround for a bug in QFileSystemModel, where it doesn't // sort after renames { - ((QFileSystemModel *)model)->setNameFilterDisables(true); - ((QFileSystemModel *)model)->setNameFilterDisables(false); + ((QFileSystemModel*)model)->setNameFilterDisables(true); + ((QFileSystemModel*)model)->setNameFilterDisables(false); } return model->setData(mapToSource(index), value.toString() + ".png", role); } -private: + private: void thumbnailImage(QString path) { auto runnable = new ThumbnailRunnable(path, m_thumbnailCache); - connect(&(runnable->m_resultEmitter), SIGNAL(resultsReady(QString)), - SLOT(thumbnailReady(QString))); - connect(&(runnable->m_resultEmitter), SIGNAL(resultsFailed(QString)), - SLOT(thumbnailFailed(QString))); - ((QThreadPool &)m_thumbnailingPool).start(runnable); + connect(&(runnable->m_resultEmitter), SIGNAL(resultsReady(QString)), SLOT(thumbnailReady(QString))); + connect(&(runnable->m_resultEmitter), SIGNAL(resultsFailed(QString)), SLOT(thumbnailFailed(QString))); + ((QThreadPool&)m_thumbnailingPool).start(runnable); } -private slots: + private slots: void thumbnailReady(QString path) { emit layoutChanged(); } void thumbnailFailed(QString path) { m_failed.insert(path); } void fileChanged(QString filepath) @@ -219,7 +208,7 @@ private slots: } } -private: + private: SharedIconCachePtr m_thumbnailCache; QThreadPool m_thumbnailingPool; QSet m_failed; @@ -227,18 +216,15 @@ private: QFileSystemWatcher watcher; }; -class CenteredEditingDelegate : public QStyledItemDelegate -{ -public: - explicit CenteredEditingDelegate(QObject *parent = 0) : QStyledItemDelegate(parent) {} +class CenteredEditingDelegate : public QStyledItemDelegate { + public: + explicit CenteredEditingDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) {} virtual ~CenteredEditingDelegate() {} - virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const + virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { auto widget = QStyledItemDelegate::createEditor(parent, option, index); - auto foo = dynamic_cast(widget); - if (foo) - { + auto foo = dynamic_cast(widget); + if (foo) { foo->setAlignment(Qt::AlignHCenter); foo->setFrame(true); foo->setMaximumWidth(192); @@ -247,15 +233,14 @@ public: } }; -ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent) - : QMainWindow(parent), ui(new Ui::ScreenshotsPage) +ScreenshotsPage::ScreenshotsPage(QString path, QWidget* parent) : QMainWindow(parent), ui(new Ui::ScreenshotsPage) { m_model.reset(new QFileSystemModel()); m_filterModel.reset(new FilterModel()); m_filterModel->setSourceModel(m_model.get()); m_model->setFilter(QDir::Files); m_model->setReadOnly(false); - m_model->setNameFilters({"*.png"}); + m_model->setNameFilters({ "*.png" }); m_model->setNameFilterDisables(false); m_folder = path; m_valid = FS::ensureFolderPathExists(m_folder); @@ -278,31 +263,29 @@ ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent) connect(ui->listView, SIGNAL(activated(QModelIndex)), SLOT(onItemActivated(QModelIndex))); } -bool ScreenshotsPage::eventFilter(QObject *obj, QEvent *evt) +bool ScreenshotsPage::eventFilter(QObject* obj, QEvent* evt) { if (obj != ui->listView) return QWidget::eventFilter(obj, evt); - if (evt->type() != QEvent::KeyPress) - { + if (evt->type() != QEvent::KeyPress) { return QWidget::eventFilter(obj, evt); } - QKeyEvent *keyEvent = static_cast(evt); + QKeyEvent* keyEvent = static_cast(evt); if (keyEvent->matches(QKeySequence::Copy)) { on_actionCopy_File_s_triggered(); return true; } - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_actionDelete_triggered(); - return true; - case Qt::Key_F2: - on_actionRename_triggered(); - return true; - default: - break; + switch (keyEvent->key()) { + case Qt::Key_Delete: + on_actionDelete_triggered(); + return true; + case Qt::Key_F2: + on_actionRename_triggered(); + return true; + default: + break; } return QWidget::eventFilter(obj, evt); } @@ -322,17 +305,17 @@ void ScreenshotsPage::ShowContextMenu(const QPoint& pos) auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); if (ui->listView->selectionModel()->selectedRows().size() > 1) { - menu->removeAction( ui->actionCopy_Image ); + menu->removeAction(ui->actionCopy_Image); } menu->exec(ui->listView->mapToGlobal(pos)); delete menu; } -QMenu * ScreenshotsPage::createPopupMenu() +QMenu* ScreenshotsPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); + filteredMenu->removeAction(ui->toolBar->toggleViewAction()); return filteredMenu; } @@ -345,13 +328,12 @@ void ScreenshotsPage::onItemActivated(QModelIndex index) DesktopServices::openFile(info.absoluteFilePath()); } -void ScreenshotsPage::onCurrentSelectionChanged(const QItemSelection &selected) +void ScreenshotsPage::onCurrentSelectionChanged(const QItemSelection& selected) { bool allReadable = !selected.isEmpty(); bool allWritable = !selected.isEmpty(); - for (auto index : selected.indexes()) - { + for (auto index : selected.indexes()) { if (!index.isValid()) break; auto info = m_model->fileInfo(index); @@ -401,8 +383,7 @@ void ScreenshotsPage::on_actionUpload_triggered() QList uploaded; auto job = NetJob::Ptr(new NetJob("Screenshot Upload", APPLICATION->network())); - if(selection.size() < 2) - { + if (selection.size() < 2) { auto item = selection.at(0); auto info = m_model->fileInfo(item); auto screenshot = std::make_shared(info); @@ -411,31 +392,24 @@ void ScreenshotsPage::on_actionUpload_triggered() m_uploadActive = true; ProgressDialog dialog(this); - if(dialog.execWithTask(job.get()) != QDialog::Accepted) - { - CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), - tr("Unknown error"), QMessageBox::Warning)->exec(); - } - else - { + if (dialog.execWithTask(job.get()) != QDialog::Accepted) { + CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), tr("Unknown error"), QMessageBox::Warning)->exec(); + } else { auto link = screenshot->m_url; - QClipboard *clipboard = QApplication::clipboard(); + QClipboard* clipboard = QApplication::clipboard(); clipboard->setText(link); CustomMessageBox::selectable( - this, - tr("Upload finished"), - tr("The link to the uploaded screenshot has been placed in your clipboard.") - .arg(link), - QMessageBox::Information - )->exec(); + this, tr("Upload finished"), + tr("The link to the uploaded screenshot has been placed in your clipboard.").arg(link), + QMessageBox::Information) + ->exec(); } m_uploadActive = false; return; } - for (auto item : selection) - { + for (auto item : selection) { auto info = m_model->fileInfo(item); auto screenshot = std::make_shared(info); uploaded.push_back(screenshot); @@ -449,26 +423,16 @@ void ScreenshotsPage::on_actionUpload_triggered() task.addTask(albumTask); m_uploadActive = true; ProgressDialog prog(this); - if (prog.execWithTask(&task) != QDialog::Accepted) - { - CustomMessageBox::selectable( - this, - tr("Failed to upload screenshots!"), - tr("Unknown error"), - QMessageBox::Warning - )->exec(); - } - else - { + if (prog.execWithTask(&task) != QDialog::Accepted) { + CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), tr("Unknown error"), QMessageBox::Warning)->exec(); + } else { auto link = QString("https://imgur.com/a/%1").arg(imgurAlbum->id()); - QClipboard *clipboard = QApplication::clipboard(); + QClipboard* clipboard = QApplication::clipboard(); clipboard->setText(link); - CustomMessageBox::selectable( - this, - tr("Upload finished"), - tr("The link to the uploaded album has been placed in your clipboard.") .arg(link), - QMessageBox::Information - )->exec(); + CustomMessageBox::selectable(this, tr("Upload finished"), + tr("The link to the uploaded album has been placed in your clipboard.").arg(link), + QMessageBox::Information) + ->exec(); } m_uploadActive = false; } @@ -476,8 +440,7 @@ void ScreenshotsPage::on_actionUpload_triggered() void ScreenshotsPage::on_actionCopy_Image_triggered() { auto selection = ui->listView->selectionModel()->selectedRows(); - if(selection.size() < 1) - { + if (selection.size() < 1) { return; } @@ -492,15 +455,13 @@ void ScreenshotsPage::on_actionCopy_Image_triggered() void ScreenshotsPage::on_actionCopy_File_s_triggered() { auto selection = ui->listView->selectionModel()->selectedRows(); - if(selection.size() < 1) - { + if (selection.size() < 1) { // Don't do anything so we don't empty the users clipboard return; } QString buf = ""; - for (auto item : selection) - { + for (auto item : selection) { auto info = m_model->fileInfo(item); buf += "file:///" + info.absoluteFilePath() + "\r\n"; } @@ -532,8 +493,7 @@ void ScreenshotsPage::on_actionDelete_triggered() if (response != QMessageBox::Yes) return; - for (auto item : selected) - { + for (auto item : selected) { if (FS::trash(m_model->filePath(item))) continue; @@ -552,23 +512,19 @@ void ScreenshotsPage::on_actionRename_triggered() void ScreenshotsPage::openedImpl() { - if(!m_valid) - { + if (!m_valid) { m_valid = FS::ensureFolderPathExists(m_folder); } - if (m_valid) - { + if (m_valid) { QString path = QDir(m_folder).absolutePath(); auto idx = m_model->setRootPath(path); - if(idx.isValid()) - { + if (idx.isValid()) { ui->listView->setModel(m_filterModel.get()); - connect(ui->listView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ScreenshotsPage::onCurrentSelectionChanged); - onCurrentSelectionChanged(ui->listView->selectionModel()->selection()); // set initial button enable states + connect(ui->listView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + &ScreenshotsPage::onCurrentSelectionChanged); + onCurrentSelectionChanged(ui->listView->selectionModel()->selection()); // set initial button enable states ui->listView->setRootIndex(m_filterModel->mapFromSource(idx)); - } - else - { + } else { ui->listView->setModel(nullptr); } } diff --git a/launcher/ui/pages/instance/ScreenshotsPage.h b/launcher/ui/pages/instance/ScreenshotsPage.h index 89611b6d1..0f824a056 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.h +++ b/launcher/ui/pages/instance/ScreenshotsPage.h @@ -37,16 +37,15 @@ #include -#include "ui/pages/BasePage.h" #include +#include "ui/pages/BasePage.h" #include "settings/Setting.h" class QFileSystemModel; class QIdentityProxyModel; class QItemSelection; -namespace Ui -{ +namespace Ui { class ScreenshotsPage; } @@ -54,49 +53,30 @@ struct ScreenShot; class ScreenshotList; class ImgurAlbumCreation; -class ScreenshotsPage : public QMainWindow, public BasePage -{ +class ScreenshotsPage : public QMainWindow, public BasePage { Q_OBJECT -public: - explicit ScreenshotsPage(QString path, QWidget *parent = 0); + public: + explicit ScreenshotsPage(QString path, QWidget* parent = 0); virtual ~ScreenshotsPage(); void openedImpl() override; void closedImpl() override; - enum - { - NothingDone = 0x42 - }; + enum { NothingDone = 0x42 }; - virtual bool eventFilter(QObject *, QEvent *) override; - virtual QString displayName() const override - { - return tr("Screenshots"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("screenshots"); - } - virtual QString id() const override - { - return "screenshots"; - } - virtual QString helpPage() const override - { - return "Screenshots-management"; - } - virtual bool apply() override - { - return !m_uploadActive; - } + virtual bool eventFilter(QObject*, QEvent*) override; + virtual QString displayName() const override { return tr("Screenshots"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("screenshots"); } + virtual QString id() const override { return "screenshots"; } + virtual QString helpPage() const override { return "Screenshots-management"; } + virtual bool apply() override { return !m_uploadActive; } void retranslate() override; -protected: - QMenu * createPopupMenu() override; + protected: + QMenu* createPopupMenu() override; -private slots: + private slots: void on_actionUpload_triggered(); void on_actionCopy_Image_triggered(); void on_actionCopy_File_s_triggered(); @@ -104,11 +84,11 @@ private slots: void on_actionRename_triggered(); void on_actionView_Folder_triggered(); void onItemActivated(QModelIndex); - void onCurrentSelectionChanged(const QItemSelection &selected); - void ShowContextMenu(const QPoint &pos); + void onCurrentSelectionChanged(const QItemSelection& selected); + void ShowContextMenu(const QPoint& pos); -private: - Ui::ScreenshotsPage *ui; + private: + Ui::ScreenshotsPage* ui; std::shared_ptr m_model; std::shared_ptr m_filterModel; QString m_folder; diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index 09ed9e407..da49f4a7d 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -40,36 +40,27 @@ #include "ui_ServersPage.h" #include -#include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include #include #include -static const int COLUMN_COUNT = 2; // 3 , TBD: latency and other nice things. +static const int COLUMN_COUNT = 2; // 3 , TBD: latency and other nice things. -struct Server -{ +struct Server { // Types - enum class AcceptsTextures : int - { - ASK = 0, - ALWAYS = 1, - NEVER = 2 - }; + enum class AcceptsTextures : int { ASK = 0, ALWAYS = 1, NEVER = 2 }; // Methods - Server() - { - m_name = QObject::tr("Minecraft Server"); - } - Server(const QString & name, const QString & address) + Server() { m_name = QObject::tr("Minecraft Server"); } + Server(const QString& name, const QString& address) { m_name = name; m_address = address; @@ -82,21 +73,16 @@ struct Server std::string nameStr(server["name"]); m_name = QString::fromUtf8(nameStr.c_str()); - if(server["icon"]) - { + if (server["icon"]) { std::string base64str(server["icon"]); m_icon = QByteArray::fromBase64(base64str.c_str()); } - if(server.has_key("acceptTextures", nbt::tag_type::Byte)) - { + if (server.has_key("acceptTextures", nbt::tag_type::Byte)) { bool value = server["acceptTextures"].as().get(); - if(value) - { + if (value) { m_acceptsTextures = AcceptsTextures::ALWAYS; - } - else - { + } else { m_acceptsTextures = AcceptsTextures::NEVER; } } @@ -106,12 +92,10 @@ struct Server { server.insert("name", m_name.trimmed().toUtf8().toStdString()); server.insert("ip", m_address.trimmed().toUtf8().toStdString()); - if(m_icon.size()) - { + if (m_icon.size()) { server.insert("icon", m_icon.toBase64().toStdString()); } - if(m_acceptsTextures != AcceptsTextures::ASK) - { + if (m_acceptsTextures != AcceptsTextures::ASK) { server.insert("acceptTextures", nbt::tag_byte(m_acceptsTextures == AcceptsTextures::ALWAYS)); } } @@ -127,64 +111,54 @@ struct Server // Data - temporary bool m_checked = false; bool m_up = false; - QString m_motd; // https://mctools.org/motd-creator + QString m_motd; // https://mctools.org/motd-creator int m_ping = 0; int m_currentPlayers = 0; int m_maxPlayers = 0; }; -static std::unique_ptr parseServersDat(const QString& filename) +static std::unique_ptr parseServersDat(const QString& filename) { - try - { + try { QByteArray input = FS::read(filename); std::istringstream foo(std::string(input.constData(), input.size())); auto pair = nbt::io::read_compound(foo); - if(pair.first != "") + if (pair.first != "") return nullptr; - if(pair.second == nullptr) + if (pair.second == nullptr) return nullptr; return std::move(pair.second); - } - catch (...) - { + } catch (...) { return nullptr; } } -static bool serializeServerDat(const QString& filename, nbt::tag_compound * levelInfo) +static bool serializeServerDat(const QString& filename, nbt::tag_compound* levelInfo) { - try - { - if(!FS::ensureFilePathExists(filename)) - { + try { + if (!FS::ensureFilePathExists(filename)) { return false; } std::ostringstream s; nbt::io::write_tag("", *levelInfo, s); - QByteArray val(s.str().data(), (int) s.str().size() ); + QByteArray val(s.str().data(), (int)s.str().size()); FS::write(filename, val); return true; - } - catch (...) - { + } catch (...) { return false; } } -class ServersModel: public QAbstractListModel -{ +class ServersModel : public QAbstractListModel { Q_OBJECT -public: - enum Roles - { + public: + enum Roles { ServerPtrRole = Qt::UserRole, }; - explicit ServersModel(const QString &path, QObject *parent = 0) - : QAbstractListModel(parent) + explicit ServersModel(const QString& path, QObject* parent = 0) : QAbstractListModel(parent) { m_path = path; m_watcher = new QFileSystemWatcher(this); @@ -194,18 +168,16 @@ public: m_saveTimer.setInterval(5000); connect(&m_saveTimer, &QTimer::timeout, this, &ServersModel::save_internal); } - virtual ~ServersModel() {}; + virtual ~ServersModel(){}; void observe() { - if(m_observed) - { + if (m_observed) { return; } m_observed = true; - if(!m_loaded) - { + if (!m_loaded) { load(); } @@ -214,8 +186,7 @@ public: void unobserve() { - if(!m_observed) - { + if (!m_observed) { return; } m_observed = false; @@ -225,8 +196,7 @@ public: void lock() { - if(m_locked) - { + if (m_locked) { return; } saveNow(); @@ -237,8 +207,7 @@ public: void unlock() { - if(!m_locked) - { + if (!m_locked) { return; } m_locked = false; @@ -248,12 +217,10 @@ public: int addEmptyRow(int position) { - if(m_locked) - { + if (m_locked) { return -1; } - if(position < 0 || position >= rowCount()) - { + if (position < 0 || position >= rowCount()) { position = rowCount(); } beginInsertRows(QModelIndex(), position, position); @@ -265,36 +232,32 @@ public: bool removeRow(int row) { - if(m_locked) - { + if (m_locked) { return false; } - if(row < 0 || row >= rowCount()) - { + if (row < 0 || row >= rowCount()) { return false; } beginRemoveRows(QModelIndex(), row, row); m_servers.removeAt(row); - endRemoveRows(); // does absolutely nothing, the selected server stays as the next line... + endRemoveRows(); // does absolutely nothing, the selected server stays as the next line... scheduleSave(); return true; } bool moveUp(int row) { - if(m_locked) - { + if (m_locked) { return false; } - if(row <= 0) - { + if (row <= 0) { return false; } beginMoveRows(QModelIndex(), row, row, QModelIndex(), row - 1); #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) - m_servers.swapItemsAt(row-1, row); + m_servers.swapItemsAt(row - 1, row); #else - m_servers.swap(row-1, row); + m_servers.swap(row - 1, row); #endif endMoveRows(); scheduleSave(); @@ -303,20 +266,18 @@ public: bool moveDown(int row) { - if(m_locked) - { + if (m_locked) { return false; } int count = rowCount(); - if(row + 1 >= count) - { + if (row + 1 >= count) { return false; } beginMoveRows(QModelIndex(), row, row, QModelIndex(), row + 2); #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) - m_servers.swapItemsAt(row+1, row); + m_servers.swapItemsAt(row + 1, row); #else - m_servers.swap(row+1, row); + m_servers.swap(row + 1, row); #endif endMoveRows(); scheduleSave(); @@ -328,10 +289,8 @@ public: if (section < 0 || section >= COLUMN_COUNT) return QVariant(); - if(role == Qt::DisplayRole) - { - switch(section) - { + if (role == Qt::DisplayRole) { + switch (section) { case 0: return tr("Name"); case 1: @@ -344,90 +303,81 @@ public: return QAbstractListModel::headerData(section, orientation, role); } - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override { if (!index.isValid()) return QVariant(); int row = index.row(); int column = index.column(); - if(column < 0 || column >= COLUMN_COUNT) + if (column < 0 || column >= COLUMN_COUNT) return QVariant(); if (row < 0 || row >= m_servers.size()) return QVariant(); - switch(column) - { + switch (column) { case 0: - switch (role) - { - case Qt::DecorationRole: - { - auto & bytes = m_servers[row].m_icon; - if(bytes.size()) - { - QPixmap px; - if(px.loadFromData(bytes)) - return QIcon(px); + switch (role) { + case Qt::DecorationRole: { + auto& bytes = m_servers[row].m_icon; + if (bytes.size()) { + QPixmap px; + if (px.loadFromData(bytes)) + return QIcon(px); + } + return APPLICATION->getThemedIcon("unknown_server"); } - return APPLICATION->getThemedIcon("unknown_server"); - } - case Qt::DisplayRole: - return m_servers[row].m_name; - case ServerPtrRole: - return QVariant::fromValue((void *)&m_servers[row]); - default: - return QVariant(); + case Qt::DisplayRole: + return m_servers[row].m_name; + case ServerPtrRole: + return QVariant::fromValue((void*)&m_servers[row]); + default: + return QVariant(); } case 1: - switch (role) - { - case Qt::DisplayRole: - return m_servers[row].m_address; - default: - return QVariant(); + switch (role) { + case Qt::DisplayRole: + return m_servers[row].m_address; + default: + return QVariant(); } case 2: - switch (role) - { - case Qt::DisplayRole: - return m_servers[row].m_ping; - default: - return QVariant(); + switch (role) { + case Qt::DisplayRole: + return m_servers[row].m_ping; + default: + return QVariant(); } default: return QVariant(); } } - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override { return parent.isValid() ? 0 : m_servers.size(); } - int columnCount(const QModelIndex & parent) const override + int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : COLUMN_COUNT; } - Server * at(int index) + Server* at(int index) { - if(index < 0 || index >= rowCount()) - { + if (index < 0 || index >= rowCount()) { return nullptr; } return &m_servers[index]; } - void setName(int row, const QString & name) + void setName(int row, const QString& name) { - if(m_locked) - { + if (m_locked) { return; } auto server = at(row); - if(!server || server->m_name == name) - { + if (!server || server->m_name == name) { return; } server->m_name = name; @@ -435,15 +385,13 @@ public: scheduleSave(); } - void setAddress(int row, const QString & address) + void setAddress(int row, const QString& address) { - if(m_locked) - { + if (m_locked) { return; } auto server = at(row); - if(!server || server->m_address == address) - { + if (!server || server->m_address == address) { return; } server->m_address = address; @@ -453,13 +401,11 @@ public: void setAcceptsTextures(int row, Server::AcceptsTextures textures) { - if(m_locked) - { + if (m_locked) { return; } auto server = at(row); - if(!server || server->m_acceptsTextures == textures) - { + if (!server || server->m_acceptsTextures == textures) { return; } server->m_acceptsTextures = textures; @@ -473,12 +419,10 @@ public: beginResetModel(); QList servers; auto serversDat = parseServersDat(serversPath()); - if(serversDat) - { - auto &serversList = serversDat->at("servers").as(); - for(auto iter = serversList.begin(); iter != serversList.end(); iter++) - { - auto & serverTag = (*iter).as(); + if (serversDat) { + auto& serversList = serversDat->at("servers").as(); + for (auto iter = serversList.begin(); iter != serversList.end(); iter++) { + auto& serverTag = (*iter).as(); Server s(serverTag); servers.append(s); } @@ -490,14 +434,12 @@ public: void saveNow() { - if(saveIsScheduled()) - { + if (saveIsScheduled()) { save_internal(); } } - -public slots: + public slots: void dirChanged(const QString& path) { qDebug() << "Changed:" << path; @@ -508,7 +450,7 @@ public slots: qDebug() << "Changed:" << path; } -private slots: + private slots: void save_internal() { cancelSave(); @@ -517,31 +459,27 @@ private slots: nbt::tag_compound out; nbt::tag_list list; - for(auto & server: m_servers) - { + for (auto& server : m_servers) { nbt::tag_compound serverNbt; server.serialize(serverNbt); list.push_back(std::move(serverNbt)); } out.insert("servers", nbt::value(std::move(list))); - if(!serializeServerDat(path, &out)) - { + if (!serializeServerDat(path, &out)) { qDebug() << "Failed to save server list:" << path << "Will try again."; scheduleSave(); } } -private: + private: void scheduleSave() { - if(!m_loaded) - { + if (!m_loaded) { qDebug() << "Server list should never save if it didn't successfully load, path:" << m_path; return; } - if(!m_dirty) - { + if (!m_dirty) { m_dirty = true; qDebug() << "Server list save is scheduled for" << m_path; } @@ -562,24 +500,17 @@ private: void updateFSObserver() { bool observingFS = m_watcher->directories().contains(m_path); - if(m_observed && m_locked) - { - if(!observingFS) - { + if (m_observed && m_locked) { + if (!observingFS) { qWarning() << "Will watch" << m_path; - if(!m_watcher->addPath(m_path)) - { + if (!m_watcher->addPath(m_path)) { qWarning() << "Failed to start watching" << m_path; } } - } - else - { - if(observingFS) - { + } else { + if (observingFS) { qWarning() << "Will stop watching" << m_path; - if(!m_watcher->removePath(m_path)) - { + if (!m_watcher->removePath(m_path)) { qWarning() << "Failed to stop watching" << m_path; } } @@ -592,34 +523,31 @@ private: return foo.filePath(); } -private: + private: bool m_loaded = false; bool m_locked = false; bool m_observed = false; bool m_dirty = false; QString m_path; QList m_servers; - QFileSystemWatcher *m_watcher = nullptr; + QFileSystemWatcher* m_watcher = nullptr; QTimer m_saveTimer; }; -ServersPage::ServersPage(InstancePtr inst, QWidget* parent) - : QMainWindow(parent), ui(new Ui::ServersPage) +ServersPage::ServersPage(InstancePtr inst, QWidget* parent) : QMainWindow(parent), ui(new Ui::ServersPage) { ui->setupUi(this); m_inst = inst; m_model = new ServersModel(inst->gameRoot(), this); - ui->serversView->setIconSize(QSize(64,64)); + ui->serversView->setIconSize(QSize(64, 64)); ui->serversView->setModel(m_model); ui->serversView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->serversView, &QTreeView::customContextMenuRequested, this, &ServersPage::ShowContextMenu); auto head = ui->serversView->header(); - if(head->count()) - { + if (head->count()) { head->setSectionResizeMode(0, QHeaderView::Stretch); - for(int i = 1; i < head->count(); i++) - { + for (int i = 1; i < head->count(); i++) { head->setSectionResizeMode(i, QHeaderView::ResizeToContents); } } @@ -633,8 +561,7 @@ ServersPage::ServersPage(InstancePtr inst, QWidget* parent) connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ServersPage::rowsRemoved); m_locked = m_inst->isRunning(); - if(m_locked) - { + if (m_locked) { m_model->lock(); } @@ -659,40 +586,33 @@ void ServersPage::ShowContextMenu(const QPoint& pos) delete menu; } -QMenu * ServersPage::createPopupMenu() +QMenu* ServersPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); + filteredMenu->removeAction(ui->toolBar->toggleViewAction()); return filteredMenu; } void ServersPage::runningStateChanged(bool running) { - if(m_locked == running) - { + if (m_locked == running) { return; } m_locked = running; - if(m_locked) - { + if (m_locked) { m_model->lock(); - } - else - { + } else { m_model->unlock(); } updateState(); } -void ServersPage::currentChanged(const QModelIndex ¤t, [[maybe_unused]] const QModelIndex &previous) +void ServersPage::currentChanged(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous) { int nextServer = -1; - if (!current.isValid()) - { + if (!current.isValid()) { nextServer = -1; - } - else - { + } else { nextServer = current.row(); } currentServer = nextServer; @@ -702,18 +622,13 @@ void ServersPage::currentChanged(const QModelIndex ¤t, [[maybe_unused]] co // WARNING: this is here because currentChanged is not accurate when removing rows. the current item needs to be fixed up after removal. void ServersPage::rowsRemoved([[maybe_unused]] const QModelIndex& parent, int first, int last) { - if(currentServer < first) - { + if (currentServer < first) { // current was before the removal return; - } - else if(currentServer >= first && currentServer <= last) - { + } else if (currentServer >= first && currentServer <= last) { // current got removed... return; - } - else - { + } else { // current was past the removal int count = last - first + 1; currentServer -= count; @@ -749,14 +664,11 @@ void ServersPage::updateState() ui->actionRemove->setEnabled(serverEditEnabled); ui->actionJoin->setEnabled(serverEditEnabled); - if(server) - { + if (server) { ui->addressLine->setText(server->m_address); ui->nameLine->setText(server->m_name); ui->resourceComboBox->setCurrentIndex(int(server->m_acceptsTextures)); - } - else - { + } else { ui->addressLine->setText(QString()); ui->nameLine->setText(QString()); ui->resourceComboBox->setCurrentIndex(0); @@ -788,27 +700,25 @@ void ServersPage::closedImpl() void ServersPage::on_actionAdd_triggered() { int position = m_model->addEmptyRow(currentServer + 1); - if(position < 0) - { + if (position < 0) { return; } // select the new row ui->serversView->selectionModel()->setCurrentIndex( - m_model->index(position), - QItemSelectionModel::SelectCurrent | QItemSelectionModel::Clear | QItemSelectionModel::Rows - ); + m_model->index(position), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Clear | QItemSelectionModel::Rows); currentServer = position; } void ServersPage::on_actionRemove_triggered() { - auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), - tr("You are about to remove \"%1\".\n" - "This is permanent and the server will be gone from your list forever (A LONG TIME).\n\n" - "Are you sure?") - .arg(m_model->at(currentServer)->m_name), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) - ->exec(); + auto response = + CustomMessageBox::selectable(this, tr("Confirm Removal"), + tr("You are about to remove \"%1\".\n" + "This is permanent and the server will be gone from your list forever (A LONG TIME).\n\n" + "Are you sure?") + .arg(m_model->at(currentServer)->m_name), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); if (response != QMessageBox::Yes) return; @@ -818,23 +728,21 @@ void ServersPage::on_actionRemove_triggered() void ServersPage::on_actionMove_Up_triggered() { - if(m_model->moveUp(currentServer)) - { - currentServer --; + if (m_model->moveUp(currentServer)) { + currentServer--; } } void ServersPage::on_actionMove_Down_triggered() { - if(m_model->moveDown(currentServer)) - { - currentServer ++; + if (m_model->moveDown(currentServer)) { + currentServer++; } } void ServersPage::on_actionJoin_triggered() { - const auto &address = m_model->at(currentServer)->m_address; + const auto& address = m_model->at(currentServer)->m_address; APPLICATION->launch(m_inst, true, false, nullptr, std::make_shared(MinecraftServerTarget::parse(address))); } diff --git a/launcher/ui/pages/instance/ServersPage.h b/launcher/ui/pages/instance/ServersPage.h index 476e7d70d..96a8dd7d4 100644 --- a/launcher/ui/pages/instance/ServersPage.h +++ b/launcher/ui/pages/instance/ServersPage.h @@ -39,13 +39,12 @@ #include #include -#include "ui/pages/BasePage.h" #include +#include "ui/pages/BasePage.h" #include "settings/Setting.h" -namespace Ui -{ +namespace Ui { class ServersPage; } @@ -53,46 +52,33 @@ struct Server; class ServersModel; class MinecraftInstance; -class ServersPage : public QMainWindow, public BasePage -{ +class ServersPage : public QMainWindow, public BasePage { Q_OBJECT -public: - explicit ServersPage(InstancePtr inst, QWidget *parent = 0); + public: + explicit ServersPage(InstancePtr inst, QWidget* parent = 0); virtual ~ServersPage(); void openedImpl() override; void closedImpl() override; - virtual QString displayName() const override - { - return tr("Servers"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("server"); - } - virtual QString id() const override - { - return "servers"; - } - virtual QString helpPage() const override - { - return "Servers-management"; - } + virtual QString displayName() const override { return tr("Servers"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("server"); } + virtual QString id() const override { return "servers"; } + virtual QString helpPage() const override { return "Servers-management"; } void retranslate() override; -protected: - QMenu * createPopupMenu() override; + protected: + QMenu* createPopupMenu() override; -private: + private: void updateState(); void scheduleSave(); bool saveIsScheduled() const; -private slots: - void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - void rowsRemoved(const QModelIndex &parent, int first, int last); + private slots: + void currentChanged(const QModelIndex& current, const QModelIndex& previous); + void rowsRemoved(const QModelIndex& parent, int first, int last); void on_actionAdd_triggered(); void on_actionRemove_triggered(); @@ -102,19 +88,18 @@ private slots: void runningStateChanged(bool running); - void nameEdited(const QString & name); - void addressEdited(const QString & address); - void resourceIndexChanged(int index);\ + void nameEdited(const QString& name); + void addressEdited(const QString& address); + void resourceIndexChanged(int index); - void ShowContextMenu(const QPoint &pos); + void ShowContextMenu(const QPoint& pos); -private: // data + private: // data int currentServer = -1; bool m_locked = true; - Ui::ServersPage *ui = nullptr; - ServersModel * m_model = nullptr; + Ui::ServersPage* ui = nullptr; + ServersModel* m_model = nullptr; InstancePtr m_inst = nullptr; std::shared_ptr m_wide_bar_setting = nullptr; }; - diff --git a/launcher/ui/pages/instance/ShaderPackPage.h b/launcher/ui/pages/instance/ShaderPackPage.h index a779fd8cc..7c43a3756 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.h +++ b/launcher/ui/pages/instance/ShaderPackPage.h @@ -39,11 +39,10 @@ #include "ExternalResourcesPage.h" -class ShaderPackPage : public ExternalResourcesPage -{ +class ShaderPackPage : public ExternalResourcesPage { Q_OBJECT -public: - explicit ShaderPackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget *parent = nullptr); + public: + explicit ShaderPackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); ~ShaderPackPage() override = default; QString displayName() const override { return tr("Shader packs"); } diff --git a/launcher/ui/pages/instance/TexturePackPage.h b/launcher/ui/pages/instance/TexturePackPage.h index 47a8fa60d..9c4f24b70 100644 --- a/launcher/ui/pages/instance/TexturePackPage.h +++ b/launcher/ui/pages/instance/TexturePackPage.h @@ -42,21 +42,17 @@ #include "minecraft/mod/TexturePackFolderModel.h" -class TexturePackPage : public ExternalResourcesPage -{ +class TexturePackPage : public ExternalResourcesPage { Q_OBJECT -public: - explicit TexturePackPage(MinecraftInstance *instance, std::shared_ptr model, QWidget* parent = nullptr); + public: + explicit TexturePackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent = nullptr); QString displayName() const override { return tr("Texture packs"); } QIcon icon() const override { return APPLICATION->getThemedIcon("resourcepacks"); } QString id() const override { return "texturepacks"; } QString helpPage() const override { return "Texture-packs"; } - virtual bool shouldDisplay() const override - { - return m_instance->traits().contains("texturepacks"); - } + virtual bool shouldDisplay() const override { return m_instance->traits().contains("texturepacks"); } public slots: bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 1cc036ac5..ef029d1d9 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -189,7 +189,6 @@ void VersionPage::showContextMenu(const QPoint& pos) delete menu; } - void VersionPage::packageCurrent(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous) { if (!current.isValid()) { diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 8eb681d27..587bb6ce6 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -36,45 +36,42 @@ */ #include "WorldListPage.h" +#include "minecraft/WorldList.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui_WorldListPage.h" -#include "minecraft/WorldList.h" -#include -#include -#include #include +#include +#include +#include +#include #include #include #include -#include #include -#include "tools/MCEditTool.h" #include "FileSystem.h" +#include "tools/MCEditTool.h" -#include "ui/GuiUtil.h" #include "DesktopServices.h" +#include "ui/GuiUtil.h" #include "Application.h" - -class WorldListProxyModel : public QSortFilterProxyModel -{ +class WorldListProxyModel : public QSortFilterProxyModel { Q_OBJECT -public: - WorldListProxyModel(QObject *parent) : QSortFilterProxyModel(parent) {} + public: + WorldListProxyModel(QObject* parent) : QSortFilterProxyModel(parent) {} - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const { QModelIndex sourceIndex = mapToSource(index); - if (index.column() == 0 && role == Qt::DecorationRole) - { - WorldList *worlds = qobject_cast(sourceModel()); + if (index.column() == 0 && role == Qt::DecorationRole) { + WorldList* worlds = qobject_cast(sourceModel()); auto iconFile = worlds->data(sourceIndex, WorldList::IconFileRole).toString(); - if(iconFile.isNull()) { + if (iconFile.isNull()) { // NOTE: Minecraft uses the same placeholder for servers AND worlds return APPLICATION->getThemedIcon("unknown_server"); } @@ -85,15 +82,14 @@ public: } }; - -WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr worlds, QWidget *parent) +WorldListPage::WorldListPage(BaseInstance* inst, std::shared_ptr worlds, QWidget* parent) : QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds) { ui->setupUi(this); ui->toolBar->insertSpacer(ui->actionRefresh); - WorldListProxyModel * proxy = new WorldListProxyModel(this); + WorldListProxyModel* proxy = new WorldListProxyModel(this); proxy->setSortCaseSensitivity(Qt::CaseInsensitive); proxy->setSourceModel(m_worlds.get()); proxy->setSortRole(Qt::UserRole); @@ -101,7 +97,7 @@ WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr worl ui->worldTreeView->setModel(proxy); ui->worldTreeView->installEventFilter(this); ui->worldTreeView->setContextMenuPolicy(Qt::CustomContextMenu); - ui->worldTreeView->setIconSize(QSize(64,64)); + ui->worldTreeView->setIconSize(QSize(64, 64)); connect(ui->worldTreeView, &QTreeView::customContextMenuRequested, this, &WorldListPage::ShowContextMenu); auto head = ui->worldTreeView->header(); @@ -146,10 +142,10 @@ void WorldListPage::ShowContextMenu(const QPoint& pos) delete menu; } -QMenu * WorldListPage::createPopupMenu() +QMenu* WorldListPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); + filteredMenu->removeAction(ui->toolBar->toggleViewAction()); return filteredMenu; } @@ -163,26 +159,24 @@ void WorldListPage::retranslate() ui->retranslateUi(this); } -bool WorldListPage::worldListFilter(QKeyEvent *keyEvent) +bool WorldListPage::worldListFilter(QKeyEvent* keyEvent) { - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_actionRemove_triggered(); - return true; - default: - break; + switch (keyEvent->key()) { + case Qt::Key_Delete: + on_actionRemove_triggered(); + return true; + default: + break; } return QWidget::eventFilter(ui->worldTreeView, keyEvent); } -bool WorldListPage::eventFilter(QObject *obj, QEvent *ev) +bool WorldListPage::eventFilter(QObject* obj, QEvent* ev) { - if (ev->type() != QEvent::KeyPress) - { + if (ev->type() != QEvent::KeyPress) { return QWidget::eventFilter(obj, ev); } - QKeyEvent *keyEvent = static_cast(ev); + QKeyEvent* keyEvent = static_cast(ev); if (obj == ui->worldTreeView) return worldListFilter(keyEvent); return QWidget::eventFilter(obj, ev); @@ -192,7 +186,7 @@ void WorldListPage::on_actionRemove_triggered() { auto proxiedIndex = getSelectedWorld(); - if(!proxiedIndex.isValid()) + if (!proxiedIndex.isValid()) return; auto result = CustomMessageBox::selectable(this, tr("Confirm Deletion"), @@ -203,8 +197,7 @@ void WorldListPage::on_actionRemove_triggered() QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); - if(result != QMessageBox::Yes) - { + if (result != QMessageBox::Yes) { return; } m_worlds->stopWatching(); @@ -221,12 +214,11 @@ void WorldListPage::on_actionDatapacks_triggered() { QModelIndex index = getSelectedWorld(); - if (!index.isValid()) - { + if (!index.isValid()) { return; } - if(!worldSafetyNagQuestion(tr("Open World Datapacks Folder"))) + if (!worldSafetyNagQuestion(tr("Open World Datapacks Folder"))) return; auto fullPath = m_worlds->data(index, WorldList::FolderRole).toString(); @@ -234,25 +226,23 @@ void WorldListPage::on_actionDatapacks_triggered() DesktopServices::openDirectory(FS::PathCombine(fullPath, "datapacks"), true); } - void WorldListPage::on_actionReset_Icon_triggered() { auto proxiedIndex = getSelectedWorld(); - if(!proxiedIndex.isValid()) + if (!proxiedIndex.isValid()) return; - if(m_worlds->resetIcon(proxiedIndex.row())) { + if (m_worlds->resetIcon(proxiedIndex.row())) { ui->actionReset_Icon->setEnabled(false); } } - QModelIndex WorldListPage::getSelectedWorld() { auto index = ui->worldTreeView->selectionModel()->currentIndex(); - auto proxy = (QSortFilterProxyModel *) ui->worldTreeView->model(); + auto proxy = (QSortFilterProxyModel*)ui->worldTreeView->model(); return proxy->mapToSource(index); } @@ -260,8 +250,7 @@ void WorldListPage::on_actionCopy_Seed_triggered() { QModelIndex index = getSelectedWorld(); - if (!index.isValid()) - { + if (!index.isValid()) { return; } int64_t seed = m_worlds->data(index, WorldList::SeedRole).toLongLong(); @@ -270,7 +259,7 @@ void WorldListPage::on_actionCopy_Seed_triggered() void WorldListPage::on_actionMCEdit_triggered() { - if(m_mceditStarting) + if (m_mceditStarting) return; auto mcedit = APPLICATION->mcedit(); @@ -279,81 +268,66 @@ void WorldListPage::on_actionMCEdit_triggered() QModelIndex index = getSelectedWorld(); - if (!index.isValid()) - { + if (!index.isValid()) { return; } - if(!worldSafetyNagQuestion(tr("Open World in MCEdit"))) + if (!worldSafetyNagQuestion(tr("Open World in MCEdit"))) return; auto fullPath = m_worlds->data(index, WorldList::FolderRole).toString(); auto program = mcedit->getProgramPath(); - if(program.size()) - { + if (program.size()) { #ifdef Q_OS_WIN32 - if(!QProcess::startDetached(program, {fullPath}, mceditPath)) - { + if (!QProcess::startDetached(program, { fullPath }, mceditPath)) { mceditError(); } #else m_mceditProcess.reset(new LoggedProcess()); m_mceditProcess->setDetachable(true); connect(m_mceditProcess.get(), &LoggedProcess::stateChanged, this, &WorldListPage::mceditState); - m_mceditProcess->start(program, {fullPath}); + m_mceditProcess->start(program, { fullPath }); m_mceditProcess->setWorkingDirectory(mceditPath); m_mceditStarting = true; #endif - } - else - { - QMessageBox::warning( - this->parentWidget(), - tr("No MCEdit found or set up!"), - tr("You do not have MCEdit set up or it was moved.\nYou can set it up in the global settings.") - ); + } else { + QMessageBox::warning(this->parentWidget(), tr("No MCEdit found or set up!"), + tr("You do not have MCEdit set up or it was moved.\nYou can set it up in the global settings.")); } } void WorldListPage::mceditError() { - QMessageBox::warning( - this->parentWidget(), - tr("MCEdit failed to start!"), - tr("MCEdit failed to start.\nIt may be necessary to reinstall it.") - ); + QMessageBox::warning(this->parentWidget(), tr("MCEdit failed to start!"), + tr("MCEdit failed to start.\nIt may be necessary to reinstall it.")); } void WorldListPage::mceditState(LoggedProcess::State state) { bool failed = false; - switch(state) - { + switch (state) { case LoggedProcess::NotRunning: case LoggedProcess::Starting: return; case LoggedProcess::FailedToStart: case LoggedProcess::Crashed: - case LoggedProcess::Aborted: - { + case LoggedProcess::Aborted: { failed = true; } /* fallthrough */ case LoggedProcess::Running: - case LoggedProcess::Finished: - { + case LoggedProcess::Finished: { m_mceditStarting = false; break; } } - if(failed) - { + if (failed) { mceditError(); } } -void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex ¤t, [[maybe_unused]] const QModelIndex &previous) +void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous) { QModelIndex index = getSelectedWorld(); bool enable = index.isValid(); @@ -369,15 +343,11 @@ void WorldListPage::worldChanged([[maybe_unused]] const QModelIndex ¤t, [[ void WorldListPage::on_actionAdd_triggered() { - auto list = GuiUtil::BrowseForFiles( - displayName(), - tr("Select a Minecraft world zip"), - tr("Minecraft World Zip File (*.zip)"), QString(), this->parentWidget()); - if (!list.empty()) - { + auto list = GuiUtil::BrowseForFiles(displayName(), tr("Select a Minecraft world zip"), tr("Minecraft World Zip File (*.zip)"), + QString(), this->parentWidget()); + if (!list.empty()) { m_worlds->stopWatching(); - for (auto filename : list) - { + for (auto filename : list) { m_worlds->installWorld(QFileInfo(filename)); } m_worlds->startWatching(); @@ -389,38 +359,35 @@ bool WorldListPage::isWorldSafe(QModelIndex) return !m_inst->isRunning(); } -bool WorldListPage::worldSafetyNagQuestion(const QString &actionType) +bool WorldListPage::worldSafetyNagQuestion(const QString& actionType) { - if(!isWorldSafe(getSelectedWorld())) - { - auto result = QMessageBox::question(this, actionType, tr("Changing a world while Minecraft is running is potentially unsafe.\nDo you wish to proceed?")); - if(result == QMessageBox::No) - { + if (!isWorldSafe(getSelectedWorld())) { + auto result = QMessageBox::question( + this, actionType, tr("Changing a world while Minecraft is running is potentially unsafe.\nDo you wish to proceed?")); + if (result == QMessageBox::No) { return false; } } return true; } - void WorldListPage::on_actionCopy_triggered() { QModelIndex index = getSelectedWorld(); - if (!index.isValid()) - { + if (!index.isValid()) { return; } - if(!worldSafetyNagQuestion(tr("Copy World"))) + if (!worldSafetyNagQuestion(tr("Copy World"))) return; auto worldVariant = m_worlds->data(index, WorldList::ObjectRole); - auto world = (World *) worldVariant.value(); + auto world = (World*)worldVariant.value(); bool ok = false; - QString name = QInputDialog::getText(this, tr("World name"), tr("Enter a new name for the copy."), QLineEdit::Normal, world->name(), &ok); + QString name = + QInputDialog::getText(this, tr("World name"), tr("Enter a new name for the copy."), QLineEdit::Normal, world->name(), &ok); - if (ok && name.length() > 0) - { + if (ok && name.length() > 0) { world->install(m_worlds->dir().absolutePath(), name); } } @@ -428,22 +395,20 @@ void WorldListPage::on_actionCopy_triggered() void WorldListPage::on_actionRename_triggered() { QModelIndex index = getSelectedWorld(); - if (!index.isValid()) - { + if (!index.isValid()) { return; } - if(!worldSafetyNagQuestion(tr("Rename World"))) + if (!worldSafetyNagQuestion(tr("Rename World"))) return; auto worldVariant = m_worlds->data(index, WorldList::ObjectRole); - auto world = (World *) worldVariant.value(); + auto world = (World*)worldVariant.value(); bool ok = false; QString name = QInputDialog::getText(this, tr("World name"), tr("Enter a new world name."), QLineEdit::Normal, world->name(), &ok); - if (ok && name.length() > 0) - { + if (ok && name.length() > 0) { world->rename(name); } } diff --git a/launcher/ui/pages/instance/WorldListPage.h b/launcher/ui/pages/instance/WorldListPage.h index 925521bec..df8b512ff 100644 --- a/launcher/ui/pages/instance/WorldListPage.h +++ b/launcher/ui/pages/instance/WorldListPage.h @@ -37,76 +37,58 @@ #include -#include "minecraft/MinecraftInstance.h" -#include "ui/pages/BasePage.h" #include #include +#include "minecraft/MinecraftInstance.h" +#include "ui/pages/BasePage.h" #include "settings/Setting.h" class WorldList; -namespace Ui -{ +namespace Ui { class WorldListPage; } -class WorldListPage : public QMainWindow, public BasePage -{ +class WorldListPage : public QMainWindow, public BasePage { Q_OBJECT -public: - explicit WorldListPage( - BaseInstance *inst, - std::shared_ptr worlds, - QWidget *parent = 0 - ); + public: + explicit WorldListPage(BaseInstance* inst, std::shared_ptr worlds, QWidget* parent = 0); virtual ~WorldListPage(); - virtual QString displayName() const override - { - return tr("Worlds"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("worlds"); - } - virtual QString id() const override - { - return "worlds"; - } - virtual QString helpPage() const override - { - return "Worlds"; - } + virtual QString displayName() const override { return tr("Worlds"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("worlds"); } + virtual QString id() const override { return "worlds"; } + virtual QString helpPage() const override { return "Worlds"; } virtual bool shouldDisplay() const override; void retranslate() override; virtual void openedImpl() override; virtual void closedImpl() override; -protected: - bool eventFilter(QObject *obj, QEvent *ev) override; - bool worldListFilter(QKeyEvent *ev); - QMenu * createPopupMenu() override; + protected: + bool eventFilter(QObject* obj, QEvent* ev) override; + bool worldListFilter(QKeyEvent* ev); + QMenu* createPopupMenu() override; -protected: - BaseInstance *m_inst; + protected: + BaseInstance* m_inst; -private: + private: QModelIndex getSelectedWorld(); bool isWorldSafe(QModelIndex index); - bool worldSafetyNagQuestion(const QString &actionType); + bool worldSafetyNagQuestion(const QString& actionType); void mceditError(); -private: - Ui::WorldListPage *ui; + private: + Ui::WorldListPage* ui; std::shared_ptr m_worlds; unique_qobject_ptr m_mceditProcess; bool m_mceditStarting = false; std::shared_ptr m_wide_bar_setting = nullptr; -private slots: + private slots: void on_actionCopy_Seed_triggered(); void on_actionMCEdit_triggered(); void on_actionRemove_triggered(); @@ -117,8 +99,8 @@ private slots: void on_actionView_Folder_triggered(); void on_actionDatapacks_triggered(); void on_actionReset_Icon_triggered(); - void worldChanged(const QModelIndex ¤t, const QModelIndex &previous); + void worldChanged(const QModelIndex& current, const QModelIndex& previous); void mceditState(LoggedProcess::State state); - void ShowContextMenu(const QPoint &pos); + void ShowContextMenu(const QPoint& pos); }; diff --git a/launcher/ui/pages/modplatform/CustomPage.cpp b/launcher/ui/pages/modplatform/CustomPage.cpp index e164171a4..ae5cae30f 100644 --- a/launcher/ui/pages/modplatform/CustomPage.cpp +++ b/launcher/ui/pages/modplatform/CustomPage.cpp @@ -46,8 +46,7 @@ #include "minecraft/VanillaInstanceCreationTask.h" #include "ui/dialogs/NewInstanceDialog.h" -CustomPage::CustomPage(NewInstanceDialog *dialog, QWidget *parent) - : QWidget(parent), dialog(dialog), ui(new Ui::CustomPage) +CustomPage::CustomPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog(dialog), ui(new Ui::CustomPage) { ui->setupUi(this); ui->tabWidget->tabBar()->hide(); @@ -68,19 +67,15 @@ CustomPage::CustomPage(NewInstanceDialog *dialog, QWidget *parent) connect(ui->quiltFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged); connect(ui->liteLoaderFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged); connect(ui->loaderRefreshBtn, &QPushButton::clicked, this, &CustomPage::loaderRefresh); - } void CustomPage::openedImpl() { - if(!initialized) - { + if (!initialized) { auto vlist = APPLICATION->metadataIndex()->get("net.minecraft"); ui->versionList->initialize(vlist.get()); initialized = true; - } - else - { + } else { suggestCurrent(); } } @@ -92,7 +87,7 @@ void CustomPage::refresh() void CustomPage::loaderRefresh() { - if(ui->noneFilter->isChecked()) + if (ui->noneFilter->isChecked()) return; ui->loaderVersionList->loadList(); } @@ -100,17 +95,17 @@ void CustomPage::loaderRefresh() void CustomPage::filterChanged() { QStringList out; - if(ui->alphaFilter->isChecked()) + if (ui->alphaFilter->isChecked()) out << "(old_alpha)"; - if(ui->betaFilter->isChecked()) + if (ui->betaFilter->isChecked()) out << "(old_beta)"; - if(ui->snapshotFilter->isChecked()) + if (ui->snapshotFilter->isChecked()) out << "(snapshot)"; - if(ui->oldSnapshotFilter->isChecked()) + if (ui->oldSnapshotFilter->isChecked()) out << "(old_snapshot)"; - if(ui->releaseFilter->isChecked()) + if (ui->releaseFilter->isChecked()) out << "(release)"; - if(ui->experimentsFilter->isChecked()) + if (ui->experimentsFilter->isChecked()) out << "(experiment)"; auto regexp = out.join('|'); ui->versionList->setFilter(BaseVersionList::TypeRole, new RegexpFilter(regexp, false)); @@ -119,49 +114,37 @@ void CustomPage::filterChanged() void CustomPage::loaderFilterChanged() { QString minecraftVersion; - if (m_selectedVersion) - { + if (m_selectedVersion) { minecraftVersion = m_selectedVersion->descriptor(); - } - else - { - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list + } else { + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list ui->loaderVersionList->setEmptyString(tr("No Minecraft version is selected.")); ui->loaderVersionList->setEmptyMode(VersionListView::String); return; } - if(ui->noneFilter->isChecked()) - { - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list + if (ui->noneFilter->isChecked()) { + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list ui->loaderVersionList->setEmptyString(tr("No mod loader is selected.")); ui->loaderVersionList->setEmptyMode(VersionListView::String); return; - } - else if(ui->forgeFilter->isChecked()) - { + } else if (ui->forgeFilter->isChecked()) { ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); m_selectedLoader = "net.minecraftforge"; - } - else if(ui->fabricFilter->isChecked()) - { + } else if (ui->fabricFilter->isChecked()) { // FIXME: dirty hack because the launcher is unaware of Fabric's dependencies - if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported + if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, ""); - else // Fabric/Quilt unsupported - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list + else // Fabric/Quilt unsupported + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list m_selectedLoader = "net.fabricmc.fabric-loader"; - } - else if(ui->quiltFilter->isChecked()) - { + } else if (ui->quiltFilter->isChecked()) { // FIXME: dirty hack because the launcher is unaware of Quilt's dependencies (same as Fabric) - if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported + if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, ""); - else // Fabric/Quilt unsupported - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list + else // Fabric/Quilt unsupported + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list m_selectedLoader = "org.quiltmc.quilt-loader"; - } - else if(ui->liteLoaderFilter->isChecked()) - { + } else if (ui->liteLoaderFilter->isChecked()) { ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); m_selectedLoader = "com.mumfrey.liteloader"; } @@ -204,25 +187,21 @@ QString CustomPage::selectedLoader() const void CustomPage::suggestCurrent() { - if (!isOpened) - { + if (!isOpened) { return; } - - if(!m_selectedVersion) - { + + if (!m_selectedVersion) { dialog->setSuggestedPack(); return; } // There isn't a selected version if the version list is empty - if(ui->loaderVersionList->selectedVersion() == nullptr) + if (ui->loaderVersionList->selectedVersion() == nullptr) dialog->setSuggestedPack(m_selectedVersion->descriptor(), new VanillaCreationTask(m_selectedVersion)); - else - { + else { dialog->setSuggestedPack(m_selectedVersion->descriptor(), - new VanillaCreationTask(m_selectedVersion, m_selectedLoader, - m_selectedLoaderVersion)); + new VanillaCreationTask(m_selectedVersion, m_selectedLoader, m_selectedLoaderVersion)); } dialog->setSuggestedIcon("default"); } diff --git a/launcher/ui/pages/modplatform/CustomPage.h b/launcher/ui/pages/modplatform/CustomPage.h index 8b5a5011c..273a60790 100644 --- a/launcher/ui/pages/modplatform/CustomPage.h +++ b/launcher/ui/pages/modplatform/CustomPage.h @@ -37,40 +37,26 @@ #include -#include "ui/pages/BasePage.h" #include #include "tasks/Task.h" +#include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class CustomPage; } class NewInstanceDialog; -class CustomPage : public QWidget, public BasePage -{ +class CustomPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit CustomPage(NewInstanceDialog *dialog, QWidget *parent = 0); + public: + explicit CustomPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~CustomPage(); - virtual QString displayName() const override - { - return tr("Custom"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("minecraft"); - } - virtual QString id() const override - { - return "vanilla"; - } - virtual QString helpPage() const override - { - return "Vanilla-platform"; - } + virtual QString displayName() const override { return tr("Custom"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("minecraft"); } + virtual QString id() const override { return "vanilla"; } + virtual QString helpPage() const override { return "Vanilla-platform"; } virtual bool shouldDisplay() const override; void retranslate() override; @@ -80,23 +66,23 @@ public: BaseVersion::Ptr selectedLoaderVersion() const; QString selectedLoader() const; -public slots: + public slots: void setSelectedVersion(BaseVersion::Ptr version); void setSelectedLoaderVersion(BaseVersion::Ptr version); -private slots: + private slots: void filterChanged(); void loaderFilterChanged(); -private: + private: void refresh(); void loaderRefresh(); void suggestCurrent(); -private: + private: bool initialized = false; - NewInstanceDialog *dialog = nullptr; - Ui::CustomPage *ui = nullptr; + NewInstanceDialog* dialog = nullptr; + Ui::CustomPage* ui = nullptr; bool m_versionSetByUser = false; BaseVersion::Ptr m_selectedVersion; BaseVersion::Ptr m_selectedLoaderVersion; diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 8f30781e1..79f295997 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -44,32 +44,24 @@ #include "InstanceImportTask.h" - -class UrlValidator : public QValidator -{ -public: +class UrlValidator : public QValidator { + public: using QValidator::QValidator; - State validate(QString &in, [[maybe_unused]] int &pos) const + State validate(QString& in, [[maybe_unused]] int& pos) const { const QUrl url(in); - if (url.isValid() && !url.isRelative() && !url.isEmpty()) - { + if (url.isValid() && !url.isRelative() && !url.isEmpty()) { return Acceptable; - } - else if (QFile::exists(in)) - { + } else if (QFile::exists(in)) { return Acceptable; - } - else - { + } else { return Intermediate; } } }; -ImportPage::ImportPage(NewInstanceDialog* dialog, QWidget *parent) - : QWidget(parent), ui(new Ui::ImportPage), dialog(dialog) +ImportPage::ImportPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::ImportPage), dialog(dialog) { ui->setupUi(this); ui->modpackEdit->setValidator(new UrlValidator(ui->modpackEdit)); @@ -98,16 +90,13 @@ void ImportPage::openedImpl() void ImportPage::updateState() { - if(!isOpened) - { + if (!isOpened) { return; } - if(ui->modpackEdit->hasAcceptableInput()) - { + if (ui->modpackEdit->hasAcceptableInput()) { QString input = ui->modpackEdit->text(); auto url = QUrl::fromUserInput(input); - if(url.isLocalFile()) - { + if (url.isLocalFile()) { // FIXME: actually do some validation of what's inside here... this is fake AF QFileInfo fi(input); @@ -116,28 +105,23 @@ void ImportPage::updateState() // mrpack is a modrinth pack bool isMRPack = fi.suffix() == "mrpack"; - if(fi.exists() && (isZip || isMRPack)) - { + if (fi.exists() && (isZip || isMRPack)) { QFileInfo file_info(url.fileName()); - dialog->setSuggestedPack(file_info.completeBaseName(), new InstanceImportTask(url,this)); + dialog->setSuggestedPack(file_info.completeBaseName(), new InstanceImportTask(url, this)); dialog->setSuggestedIcon("default"); } - } - else - { - if(input.endsWith("?client=y")) { + } else { + if (input.endsWith("?client=y")) { input.chop(9); input.append("/file"); url = QUrl::fromUserInput(input); } // hook, line and sinker. QFileInfo fi(url.fileName()); - dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url,this)); + dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this)); dialog->setSuggestedIcon("default"); } - } - else - { + } else { dialog->setSuggestedPack(); } } @@ -154,29 +138,21 @@ void ImportPage::on_modpackBtn_clicked() //: Option for filtering for *.mrpack files when importing filter += ";;" + tr("Modrinth pack") + " (*.mrpack)"; const QUrl url = QFileDialog::getOpenFileUrl(this, tr("Choose modpack"), modpackUrl(), filter); - if (url.isValid()) - { - if (url.isLocalFile()) - { + if (url.isValid()) { + if (url.isLocalFile()) { ui->modpackEdit->setText(url.toLocalFile()); - } - else - { + } else { ui->modpackEdit->setText(url.toString()); } } } - QUrl ImportPage::modpackUrl() const { const QUrl url(ui->modpackEdit->text()); - if (url.isValid() && !url.isRelative() && !url.host().isEmpty()) - { + if (url.isValid() && !url.isRelative() && !url.host().isEmpty()) { return url; - } - else - { + } else { return QUrl::fromLocalFile(ui->modpackEdit->text()); } } diff --git a/launcher/ui/pages/modplatform/ImportPage.h b/launcher/ui/pages/modplatform/ImportPage.h index c2acb92da..66c452b9f 100644 --- a/launcher/ui/pages/modplatform/ImportPage.h +++ b/launcher/ui/pages/modplatform/ImportPage.h @@ -37,55 +37,40 @@ #include -#include "ui/pages/BasePage.h" #include #include "tasks/Task.h" +#include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class ImportPage; } class NewInstanceDialog; -class ImportPage : public QWidget, public BasePage -{ +class ImportPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit ImportPage(NewInstanceDialog* dialog, QWidget *parent = 0); + public: + explicit ImportPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~ImportPage(); - virtual QString displayName() const override - { - return tr("Import"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("viewfolder"); - } - virtual QString id() const override - { - return "import"; - } - virtual QString helpPage() const override - { - return "Zip-import"; - } + virtual QString displayName() const override { return tr("Import"); } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("viewfolder"); } + virtual QString id() const override { return "import"; } + virtual QString helpPage() const override { return "Zip-import"; } virtual bool shouldDisplay() const override; void retranslate() override; - void setUrl(const QString & url); + void setUrl(const QString& url); void openedImpl() override; -private slots: + private slots: void on_modpackBtn_clicked(); void updateState(); -private: + private: QUrl modpackUrl() const; -private: - Ui::ImportPage *ui = nullptr; + private: + Ui::ImportPage* ui = nullptr; NewInstanceDialog* dialog = nullptr; }; - diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.cpp b/launcher/ui/pages/modplatform/ResourcePackPage.cpp index 52fb4802c..2a4d02815 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackPage.cpp @@ -13,8 +13,7 @@ namespace ResourceDownload { -ResourcePackResourcePage::ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance) - : ResourcePage(dialog, instance) +ResourcePackResourcePage::ResourcePackResourcePage(ResourceDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) { connect(m_ui->searchButton, &QPushButton::clicked, this, &ResourcePackResourcePage::triggerSearch); connect(m_ui->packView, &QListView::doubleClicked, this, &ResourcePackResourcePage::onResourceSelected); @@ -38,7 +37,8 @@ QMap ResourcePackResourcePage::urlHandlers() const { QMap map; map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/resourcepack\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/texture-packs\\/([^\\/]+)\\/?"), "curseforge"); + map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/texture-packs\\/([^\\/]+)\\/?"), + "curseforge"); map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); return map; } diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h index 8c5cf08b7..6015aec0b 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.h +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -4,8 +4,8 @@ #pragma once -#include "ui/pages/modplatform/ResourcePage.h" #include "ui/pages/modplatform/ResourcePackModel.h" +#include "ui/pages/modplatform/ResourcePage.h" namespace Ui { class ResourcePage; diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 3e8bb7d8a..7bec0a375 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -97,7 +97,8 @@ class ResourcePage : public QWidget, public BasePage { virtual void openUrl(const QUrl&); /** Whether the version is opted out or not. Currently only makes sense in CF. */ - virtual bool optedOut(ModPlatform::IndexedVersion& ver) const { + virtual bool optedOut(ModPlatform::IndexedVersion& ver) const + { Q_UNUSED(ver); return false; }; diff --git a/launcher/ui/pages/modplatform/TexturePackPage.h b/launcher/ui/pages/modplatform/TexturePackPage.h index 0bdce2f90..948e5286b 100644 --- a/launcher/ui/pages/modplatform/TexturePackPage.h +++ b/launcher/ui/pages/modplatform/TexturePackPage.h @@ -4,10 +4,10 @@ #pragma once -#include "ui_ResourcePage.h" #include "ui/dialogs/ResourceDownloadDialog.h" #include "ui/pages/modplatform/ResourcePackPage.h" #include "ui/pages/modplatform/TexturePackModel.h" +#include "ui_ResourcePage.h" namespace Ui { class ResourcePage; @@ -39,8 +39,7 @@ class TexturePackResourcePage : public ResourcePackResourcePage { [[nodiscard]] inline QString resourceString() const override { return tr("texture pack"); } protected: - TexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance) - : ResourcePackResourcePage(dialog, instance) + TexturePackResourcePage(TexturePackDownloadDialog* dialog, BaseInstance& instance) : ResourcePackResourcePage(dialog, instance) { connect(m_ui->searchButton, &QPushButton::clicked, this, &TexturePackResourcePage::triggerSearch); connect(m_ui->packView, &QListView::doubleClicked, this, &TexturePackResourcePage::onResourceSelected); diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp index 0887ebeef..9cd5eed53 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp @@ -18,14 +18,14 @@ #include -#include #include +#include #include "StringUtils.h" namespace Atl { -FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent) +FilterModel::FilterModel(QObject* parent) : QSortFilterProxyModel(parent) { currentSorting = Sorting::ByPopularity; sortings.insert(tr("Sort by Popularity"), Sorting::ByPopularity); @@ -62,7 +62,7 @@ void FilterModel::setSearchTerm(const QString term) invalidate(); } -bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { if (searchTerm.isEmpty()) { return true; @@ -73,20 +73,18 @@ bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParen return pack.name.contains(searchTerm, Qt::CaseInsensitive); } -bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { ATLauncher::IndexedPack leftPack = sourceModel()->data(left, Qt::UserRole).value(); ATLauncher::IndexedPack rightPack = sourceModel()->data(right, Qt::UserRole).value(); if (currentSorting == ByPopularity) { return leftPack.position > rightPack.position; - } - else if (currentSorting == ByGameVersion) { + } else if (currentSorting == ByGameVersion) { Version lv(leftPack.versions.at(0).minecraft); Version rv(rightPack.versions.at(0).minecraft); return lv < rv; - } - else if (currentSorting == ByName) { + } else if (currentSorting == ByName) { return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0; } @@ -95,4 +93,4 @@ bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) co return true; } -} +} // namespace Atl diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h index 5235ccdbf..0ab46ed2d 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.h @@ -20,10 +20,9 @@ namespace Atl { -class FilterModel : public QSortFilterProxyModel -{ +class FilterModel : public QSortFilterProxyModel { Q_OBJECT -public: + public: FilterModel(QObject* parent = Q_NULLPTR); enum Sorting { ByPopularity, @@ -36,15 +35,14 @@ public: Sorting getCurrentSorting(); void setSearchTerm(QString term); -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; -private: + private: QMap sortings; Sorting currentSorting; QString searchTerm; - }; -} +} // namespace Atl diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp index d9f3274dc..868d98138 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -38,17 +38,15 @@ #include #include +#include "Application.h" #include "BuildConfig.h" #include "Json.h" #include "modplatform/atlauncher/ATLShareCode.h" -#include "Application.h" #include "net/ApiDownload.h" AtlOptionalModListModel::AtlOptionalModListModel(QWidget* parent, ATLauncher::PackVersion version, QVector mods) - : QAbstractListModel(parent) - , m_version(version) - , m_mods(mods) + : QAbstractListModel(parent), m_version(version), m_mods(mods) { // fill mod index for (int i = 0; i < m_mods.size(); i++) { @@ -64,7 +62,8 @@ AtlOptionalModListModel::AtlOptionalModListModel(QWidget* parent, ATLauncher::Pa } } -QVector AtlOptionalModListModel::getResult() { +QVector AtlOptionalModListModel::getResult() +{ QVector result; for (const auto& mod : m_mods) { @@ -76,16 +75,19 @@ QVector AtlOptionalModListModel::getResult() { return result; } -int AtlOptionalModListModel::rowCount(const QModelIndex &parent) const { +int AtlOptionalModListModel::rowCount(const QModelIndex& parent) const +{ return parent.isValid() ? 0 : m_mods.size(); } -int AtlOptionalModListModel::columnCount(const QModelIndex &parent) const { +int AtlOptionalModListModel::columnCount(const QModelIndex& parent) const +{ // Enabled, Name, Description return parent.isValid() ? 0 : 3; } -QVariant AtlOptionalModListModel::data(const QModelIndex &index, int role) const { +QVariant AtlOptionalModListModel::data(const QModelIndex& index, int role) const +{ auto row = index.row(); auto mod = m_mods.at(row); @@ -96,18 +98,15 @@ QVariant AtlOptionalModListModel::data(const QModelIndex &index, int role) const if (index.column() == DescriptionColumn) { return mod.description; } - } - else if (role == Qt::ToolTipRole) { + } else if (role == Qt::ToolTipRole) { if (index.column() == DescriptionColumn) { return mod.description; } - } - else if (role == Qt::ForegroundRole) { + } else if (role == Qt::ForegroundRole) { if (!mod.colour.isEmpty() && m_version.colours.contains(mod.colour)) { return QColor(QString("#%1").arg(m_version.colours[mod.colour])); } - } - else if (role == Qt::CheckStateRole) { + } else if (role == Qt::CheckStateRole) { if (index.column() == EnabledColumn) { return m_selection[mod.name] ? Qt::Checked : Qt::Unchecked; } @@ -116,7 +115,8 @@ QVariant AtlOptionalModListModel::data(const QModelIndex &index, int role) const return {}; } -bool AtlOptionalModListModel::setData(const QModelIndex &index, [[maybe_unused]] const QVariant &value, int role) { +bool AtlOptionalModListModel::setData(const QModelIndex& index, [[maybe_unused]] const QVariant& value, int role) +{ if (role == Qt::CheckStateRole) { auto row = index.row(); auto mod = m_mods.at(row); @@ -128,7 +128,8 @@ bool AtlOptionalModListModel::setData(const QModelIndex &index, [[maybe_unused]] return false; } -QVariant AtlOptionalModListModel::headerData(int section, Qt::Orientation orientation, int role) const { +QVariant AtlOptionalModListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { switch (section) { case EnabledColumn: @@ -143,7 +144,8 @@ QVariant AtlOptionalModListModel::headerData(int section, Qt::Orientation orient return {}; } -Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const { +Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex& index) const +{ auto flags = QAbstractListModel::flags(index); if (index.isValid() && index.column() == EnabledColumn) { flags |= Qt::ItemIsUserCheckable; @@ -151,23 +153,23 @@ Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const { return flags; } -void AtlOptionalModListModel::useShareCode(const QString& code) { +void AtlOptionalModListModel::useShareCode(const QString& code) +{ m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network())); auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code); m_jobPtr->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), m_response)); - connect(m_jobPtr.get(), &NetJob::succeeded, - this, &AtlOptionalModListModel::shareCodeSuccess); - connect(m_jobPtr.get(), &NetJob::failed, - this, &AtlOptionalModListModel::shareCodeFailure); + connect(m_jobPtr.get(), &NetJob::succeeded, this, &AtlOptionalModListModel::shareCodeSuccess); + connect(m_jobPtr.get(), &NetJob::failed, this, &AtlOptionalModListModel::shareCodeFailure); m_jobPtr->start(); } -void AtlOptionalModListModel::shareCodeSuccess() { +void AtlOptionalModListModel::shareCodeSuccess() +{ m_jobPtr.reset(); - QJsonParseError parse_error {}; + QJsonParseError parse_error{}; auto doc = QJsonDocument::fromJson(*m_response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString(); @@ -179,8 +181,7 @@ void AtlOptionalModListModel::shareCodeSuccess() { ATLauncher::ShareCodeResponse response; try { ATLauncher::loadShareCodeResponse(response, obj); - } - catch (const JSONValidationError& e) { + } catch (const JSONValidationError& e) { qDebug() << QString::fromUtf8(*m_response); qWarning() << "Error while reading response from ATLauncher: " << e.cause(); return; @@ -204,44 +205,44 @@ void AtlOptionalModListModel::shareCodeSuccess() { m_selection[mod.name] = mod.selected; } - emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), - AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); + emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); } -void AtlOptionalModListModel::shareCodeFailure([[maybe_unused]] const QString& reason) { +void AtlOptionalModListModel::shareCodeFailure([[maybe_unused]] const QString& reason) +{ m_jobPtr.reset(); // fixme: plumb in an error message } -void AtlOptionalModListModel::selectRecommended() { +void AtlOptionalModListModel::selectRecommended() +{ for (const auto& mod : m_mods) { m_selection[mod.name] = mod.recommended; } - emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), - AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); + emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); } -void AtlOptionalModListModel::clearAll() { +void AtlOptionalModListModel::clearAll() +{ for (const auto& mod : m_mods) { m_selection[mod.name] = false; } - emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), - AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); + emit dataChanged(AtlOptionalModListModel::index(0, EnabledColumn), AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); } -void AtlOptionalModListModel::toggleMod(ATLauncher::VersionMod mod, int index) { +void AtlOptionalModListModel::toggleMod(ATLauncher::VersionMod mod, int index) +{ auto enable = !m_selection[mod.name]; // If there is a warning for the mod, display that first (if we would be enabling the mod) if (enable && !mod.warning.isEmpty() && m_version.warnings.contains(mod.warning)) { - auto message = QString("%1

%2") - .arg(m_version.warnings[mod.warning], tr("Are you sure that you want to enable this mod?")); + auto message = QString("%1

%2").arg(m_version.warnings[mod.warning], tr("Are you sure that you want to enable this mod?")); // fixme: avoid casting here - auto result = QMessageBox::warning((QWidget*) this->parent(), tr("Warning"), message, QMessageBox::Yes | QMessageBox::No); + auto result = QMessageBox::warning((QWidget*)this->parent(), tr("Warning"), message, QMessageBox::Yes | QMessageBox::No); if (result != QMessageBox::Yes) { return; } @@ -250,15 +251,18 @@ void AtlOptionalModListModel::toggleMod(ATLauncher::VersionMod mod, int index) { setMod(mod, index, enable); } -void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit) { - if (m_selection[mod.name] == enable) return; +void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit) +{ + if (m_selection[mod.name] == enable) + return; m_selection[mod.name] = enable; // disable other mods in the group, if applicable if (enable && !mod.group.isEmpty()) { for (int i = 0; i < m_mods.size(); i++) { - if (index == i) continue; + if (index == i) + continue; auto other = m_mods.at(i); if (mod.group == other.group) { @@ -283,8 +287,7 @@ void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool if (enable) { dependents.append(mod.name); - } - else { + } else { dependents.removeAll(mod.name); // if there are no longer any dependents, let's disable the mod @@ -306,14 +309,12 @@ void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool } if (shouldEmit) { - emit dataChanged(AtlOptionalModListModel::index(index, EnabledColumn), - AtlOptionalModListModel::index(index, EnabledColumn)); + emit dataChanged(AtlOptionalModListModel::index(index, EnabledColumn), AtlOptionalModListModel::index(index, EnabledColumn)); } } AtlOptionalModDialog::AtlOptionalModDialog(QWidget* parent, ATLauncher::PackVersion version, QVector mods) - : QDialog(parent) - , ui(new Ui::AtlOptionalModDialog) + : QDialog(parent), ui(new Ui::AtlOptionalModDialog) { ui->setupUi(this); @@ -321,35 +322,24 @@ AtlOptionalModDialog::AtlOptionalModDialog(QWidget* parent, ATLauncher::PackVers ui->treeView->setModel(listModel); ui->treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - ui->treeView->header()->setSectionResizeMode( - AtlOptionalModListModel::NameColumn, QHeaderView::ResizeToContents); - ui->treeView->header()->setSectionResizeMode( - AtlOptionalModListModel::DescriptionColumn, QHeaderView::Stretch); + ui->treeView->header()->setSectionResizeMode(AtlOptionalModListModel::NameColumn, QHeaderView::ResizeToContents); + ui->treeView->header()->setSectionResizeMode(AtlOptionalModListModel::DescriptionColumn, QHeaderView::Stretch); - connect(ui->shareCodeButton, &QPushButton::clicked, - this, &AtlOptionalModDialog::useShareCode); - connect(ui->selectRecommendedButton, &QPushButton::clicked, - listModel, &AtlOptionalModListModel::selectRecommended); - connect(ui->clearAllButton, &QPushButton::clicked, - listModel, &AtlOptionalModListModel::clearAll); - connect(ui->installButton, &QPushButton::clicked, - this, &QDialog::accept); + connect(ui->shareCodeButton, &QPushButton::clicked, this, &AtlOptionalModDialog::useShareCode); + connect(ui->selectRecommendedButton, &QPushButton::clicked, listModel, &AtlOptionalModListModel::selectRecommended); + connect(ui->clearAllButton, &QPushButton::clicked, listModel, &AtlOptionalModListModel::clearAll); + connect(ui->installButton, &QPushButton::clicked, this, &QDialog::accept); } -AtlOptionalModDialog::~AtlOptionalModDialog() { +AtlOptionalModDialog::~AtlOptionalModDialog() +{ delete ui; } -void AtlOptionalModDialog::useShareCode() { +void AtlOptionalModDialog::useShareCode() +{ bool ok; - auto shareCode = QInputDialog::getText( - this, - tr("Select a share code"), - tr("Share code:"), - QLineEdit::Normal, - "", - &ok - ); + auto shareCode = QInputDialog::getText(this, tr("Select a share code"), tr("Share code:"), QLineEdit::Normal, "", &ok); if (!ok) { // If the user cancels the dialog, we don't need to show any error dialogs. diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h index fe24d821d..1adfdf036 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h @@ -35,8 +35,8 @@ #pragma once -#include #include +#include #include "modplatform/atlauncher/ATLPackIndex.h" #include "net/NetJob.h" @@ -48,37 +48,36 @@ class AtlOptionalModDialog; class AtlOptionalModListModel : public QAbstractListModel { Q_OBJECT -public: - enum Columns - { + public: + enum Columns { EnabledColumn = 0, NameColumn, DescriptionColumn, }; - AtlOptionalModListModel(QWidget *parent, ATLauncher::PackVersion version, QVector mods); + AtlOptionalModListModel(QWidget* parent, ATLauncher::PackVersion version, QVector mods); QVector getResult(); - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; + int rowCount(const QModelIndex& parent) const override; + int columnCount(const QModelIndex& parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - bool setData(const QModelIndex &index, const QVariant &value, int role) override; + QVariant data(const QModelIndex& index, int role) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; void useShareCode(const QString& code); -public slots: + public slots: void shareCodeSuccess(); void shareCodeFailure(const QString& reason); void selectRecommended(); void clearAll(); -private: + private: void toggleMod(ATLauncher::VersionMod mod, int index); void setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit = true); @@ -97,18 +96,16 @@ private: class AtlOptionalModDialog : public QDialog { Q_OBJECT -public: - AtlOptionalModDialog(QWidget *parent, ATLauncher::PackVersion version, QVector mods); + public: + AtlOptionalModDialog(QWidget* parent, ATLauncher::PackVersion version, QVector mods); ~AtlOptionalModDialog() override; - QVector getResult() { - return listModel->getResult(); - } + QVector getResult() { return listModel->getResult(); } void useShareCode(); -private: - Ui::AtlOptionalModDialog *ui; + private: + Ui::AtlOptionalModDialog* ui; - AtlOptionalModListModel *listModel; + AtlOptionalModListModel* listModel; }; diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp index 7c80ed2de..1e96a75df 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp @@ -46,10 +46,7 @@ #include -AtlPage::AtlPage(NewInstanceDialog* dialog, QWidget* parent) - : QWidget(parent) - , ui(new Ui::AtlPage) - , dialog(dialog) +AtlPage::AtlPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::AtlPage), dialog(dialog) { ui->setupUi(this); @@ -65,8 +62,7 @@ AtlPage::AtlPage(NewInstanceDialog* dialog, QWidget* parent) ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); - for(int i = 0; i < filterModel->getAvailableSortings().size(); i++) - { + for (int i = 0; i < filterModel->getAvailableSortings().size(); i++) { ui->sortByBox->addItem(filterModel->getAvailableSortings().keys().at(i)); } ui->sortByBox->setCurrentText(filterModel->translateCurrentSorting()); @@ -94,8 +90,7 @@ void AtlPage::retranslate() void AtlPage::openedImpl() { - if(!initialized) - { + if (!initialized) { listModel->request(); initialized = true; } @@ -105,13 +100,11 @@ void AtlPage::openedImpl() void AtlPage::suggestCurrent() { - if(!isOpened) - { + if (!isOpened) { return; } - if (selectedVersion.isEmpty()) - { + if (selectedVersion.isEmpty()) { dialog->setSuggestedPack(); return; } @@ -121,10 +114,8 @@ void AtlPage::suggestCurrent() auto editedLogoName = selected.safeName; auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(selected.safeName.toLower()); - listModel->getLogo(selected.safeName, url, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); + listModel->getLogo(selected.safeName, url, + [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } void AtlPage::triggerSearch() @@ -142,10 +133,8 @@ void AtlPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelIndex { ui->versionSelectionBox->clear(); - if(!first.isValid()) - { - if(isOpened) - { + if (!first.isValid()) { + if (isOpened) { dialog->setSuggestedPack(); } return; @@ -155,7 +144,7 @@ void AtlPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelIndex ui->packDescription->setHtml(selected.description.replace("\n", "
")); - for(const auto& version : selected.versions) { + for (const auto& version : selected.versions) { ui->versionSelectionBox->addItem(version.version); } @@ -164,8 +153,7 @@ void AtlPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelIndex void AtlPage::onVersionSelectionChanged(QString version) { - if(version.isNull() || version.isEmpty()) - { + if (version.isNull() || version.isEmpty()) { selectedVersion = ""; return; } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h index 1b3b15c1a..ac336ec10 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h @@ -38,52 +38,38 @@ #include "AtlFilterModel.h" #include "AtlListModel.h" -#include #include +#include #include "Application.h" -#include "ui/pages/BasePage.h" #include "tasks/Task.h" +#include "ui/pages/BasePage.h" -namespace Ui -{ - class AtlPage; +namespace Ui { +class AtlPage; } class NewInstanceDialog; -class AtlPage : public QWidget, public BasePage -{ -Q_OBJECT +class AtlPage : public QWidget, public BasePage { + Q_OBJECT -public: - explicit AtlPage(NewInstanceDialog* dialog, QWidget *parent = 0); + public: + explicit AtlPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~AtlPage(); - virtual QString displayName() const override - { - return "ATLauncher"; - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("atlauncher"); - } - virtual QString id() const override - { - return "atl"; - } - virtual QString helpPage() const override - { - return "ATL-platform"; - } + virtual QString displayName() const override { return "ATLauncher"; } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("atlauncher"); } + virtual QString id() const override { return "atl"; } + virtual QString helpPage() const override { return "ATL-platform"; } virtual bool shouldDisplay() const override; void retranslate() override; void openedImpl() override; -private: + private: void suggestCurrent(); -private slots: + private slots: void triggerSearch(); void onSortingSelectionChanged(QString data); @@ -91,8 +77,8 @@ private slots: void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); -private: - Ui::AtlPage *ui = nullptr; + private: + Ui::AtlPage* ui = nullptr; NewInstanceDialog* dialog = nullptr; Atl::ListModel* listModel = nullptr; Atl::FilterModel* filterModel = nullptr; diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp index 3d2d568a1..9ed75bccf 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp @@ -33,17 +33,16 @@ * limitations under the License. */ -#include #include "AtlUserInteractionSupportImpl.h" +#include #include "AtlOptionalModDialog.h" #include "ui/dialogs/VersionSelectDialog.h" -AtlUserInteractionSupportImpl::AtlUserInteractionSupportImpl(QWidget *parent) : m_parent(parent) -{ -} +AtlUserInteractionSupportImpl::AtlUserInteractionSupportImpl(QWidget* parent) : m_parent(parent) {} -std::optional> AtlUserInteractionSupportImpl::chooseOptionalMods(ATLauncher::PackVersion version, QVector mods) +std::optional> AtlUserInteractionSupportImpl::chooseOptionalMods(ATLauncher::PackVersion version, + QVector mods) { AtlOptionalModDialog optionalModDialog(m_parent, version, mods); auto result = optionalModDialog.exec(); @@ -59,8 +58,7 @@ QString AtlUserInteractionSupportImpl::chooseVersion(Meta::VersionList::Ptr vlis if (minecraftVersion != nullptr) { vselect.setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); vselect.setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); - } - else { + } else { vselect.setEmptyString(tr("No versions are currently available")); } vselect.setEmptyErrorString(tr("Couldn't load or download the version lists!")); @@ -72,9 +70,7 @@ QString AtlUserInteractionSupportImpl::chooseVersion(Meta::VersionList::Ptr vlis // filter by minecraft version, if the loader depends on a certain version. if (minecraftVersion != nullptr) { - auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Meta::Require& req) { - return req.uid == "net.minecraft"; - }); + auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Meta::Require& req) { return req.uid == "net.minecraft"; }); if (iter == reqs.end()) continue; if (iter->equalsVersion != minecraftVersion) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index ead79c6c7..28af22e30 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -134,7 +134,8 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network()); auto response = std::make_shared(); int addonId = current.addonId; - netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); + netJob->addNetAction( + Net::ApiDownload::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); QObject::connect(netJob, &NetJob::succeeded, this, [this, response, addonId, curr] { if (addonId != current.addonId) { diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index 8bdca38e8..ad54c13a8 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -37,45 +37,31 @@ #include -#include "ui/pages/BasePage.h" #include -#include "tasks/Task.h" #include +#include "tasks/Task.h" +#include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class FlamePage; } class NewInstanceDialog; namespace Flame { - class ListModel; +class ListModel; } -class FlamePage : public QWidget, public BasePage -{ +class FlamePage : public QWidget, public BasePage { Q_OBJECT -public: - explicit FlamePage(NewInstanceDialog* dialog, QWidget *parent = 0); + public: + explicit FlamePage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~FlamePage(); - virtual QString displayName() const override - { - return "CurseForge"; - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("flame"); - } - virtual QString id() const override - { - return "flame"; - } - virtual QString helpPage() const override - { - return "Flame-platform"; - } + virtual QString displayName() const override { return "CurseForge"; } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("flame"); } + virtual QString id() const override { return "flame"; } + virtual QString helpPage() const override { return "Flame-platform"; } virtual bool shouldDisplay() const override; void retranslate() override; @@ -83,18 +69,18 @@ public: void openedImpl() override; - bool eventFilter(QObject * watched, QEvent * event) override; + bool eventFilter(QObject* watched, QEvent* event) override; -private: + private: void suggestCurrent(); -private slots: + private slots: void triggerSearch(); void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); -private: - Ui::FlamePage *ui = nullptr; + private: + Ui::FlamePage* ui = nullptr; NewInstanceDialog* dialog = nullptr; Flame::ListModel* listModel = nullptr; Flame::IndexedPack current; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index f93e27e64..dc17e705a 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -49,8 +49,7 @@ static bool isOptedOut(ModPlatform::IndexedVersion const& ver) return ver.downloadUrl.isEmpty(); } -FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) - : ModPage(dialog, instance) +FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) { m_model = new FlameModModel(instance); m_ui->packView->setModel(m_model); @@ -67,7 +66,9 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) m_ui->packDescription->setMetaEntry(metaEntryBase()); } -auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders) const -> bool +auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, + QString mineVer, + std::optional loaders) const -> bool { Q_UNUSED(loaders); return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty(); @@ -86,7 +87,7 @@ void FlameModPage::openUrl(const QUrl& url) if (query.startsWith("remoteUrl=")) { // attempt to resolve url from warning page query.remove(0, 10); - ModPage::openUrl({QUrl::fromPercentEncoding(query.toUtf8())}); // double decoding is necessary + ModPage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary return; } } @@ -125,7 +126,7 @@ void FlameResourcePackPage::openUrl(const QUrl& url) if (query.startsWith("remoteUrl=")) { // attempt to resolve url from warning page query.remove(0, 10); - ResourcePackResourcePage::openUrl({QUrl::fromPercentEncoding(query.toUtf8())}); // double decoding is necessary + ResourcePackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary return; } } @@ -164,7 +165,7 @@ void FlameTexturePackPage::openUrl(const QUrl& url) if (query.startsWith("remoteUrl=")) { // attempt to resolve url from warning page query.remove(0, 10); - ResourcePackResourcePage::openUrl({QUrl::fromPercentEncoding(query.toUtf8())}); // double decoding is necessary + ResourcePackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary return; } } @@ -175,8 +176,17 @@ void FlameTexturePackPage::openUrl(const QUrl& url) // I don't know why, but doing this on the parent class makes it so that // other mod providers start loading before being selected, at least with // my Qt, so we need to implement this in every derived class... -auto FlameModPage::shouldDisplay() const -> bool { return true; } -auto FlameResourcePackPage::shouldDisplay() const -> bool { return true; } -auto FlameTexturePackPage::shouldDisplay() const -> bool { return true; } +auto FlameModPage::shouldDisplay() const -> bool +{ + return true; +} +auto FlameResourcePackPage::shouldDisplay() const -> bool +{ + return true; +} +auto FlameTexturePackPage::shouldDisplay() const -> bool +{ + return true; +} } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index 103a6bb92..c6ebc1eac 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -49,12 +49,27 @@ namespace ResourceDownload { namespace Flame { -static inline QString displayName() { return "CurseForge"; } -static inline QIcon icon() { return APPLICATION->getThemedIcon("flame"); } -static inline QString id() { return "curseforge"; } -static inline QString debugName() { return "Flame"; } -static inline QString metaEntryBase() { return "FlameMods"; } +static inline QString displayName() +{ + return "CurseForge"; } +static inline QIcon icon() +{ + return APPLICATION->getThemedIcon("flame"); +} +static inline QString id() +{ + return "curseforge"; +} +static inline QString debugName() +{ + return "Flame"; +} +static inline QString metaEntryBase() +{ + return "FlameMods"; +} +} // namespace Flame class FlameModPage : public ModPage { Q_OBJECT @@ -78,7 +93,9 @@ class FlameModPage : public ModPage { [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } - bool validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const override; + bool validateVersion(ModPlatform::IndexedVersion& ver, + QString mineVer, + std::optional loaders = {}) const override; bool optedOut(ModPlatform::IndexedVersion& ver) const override; void openUrl(const QUrl& url) override; diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 29b17ab78..f4ddf3312 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -35,9 +35,9 @@ #include "ListModel.h" #include "Application.h" +#include "net/ApiDownload.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" -#include "net/ApiDownload.h" #include #include "StringUtils.h" diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h index c55df0009..51a58d991 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h @@ -1,13 +1,13 @@ #pragma once -#include #include +#include #include -#include -#include #include +#include #include +#include #include @@ -16,34 +16,28 @@ namespace LegacyFTB { typedef QMap FTBLogoMap; typedef std::function LogoCallback; -class FilterModel : public QSortFilterProxyModel -{ +class FilterModel : public QSortFilterProxyModel { Q_OBJECT -public: + public: FilterModel(QObject* parent = Q_NULLPTR); - enum Sorting { - ByName, - ByGameVersion - }; + enum Sorting { ByName, ByGameVersion }; const QMap getAvailableSortings(); QString translateCurrentSorting(); void setSorting(Sorting sorting); Sorting getCurrentSorting(); -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; -private: + private: QMap sortings; Sorting currentSorting; - }; -class ListModel : public QAbstractListModel -{ +class ListModel : public QAbstractListModel { Q_OBJECT -private: + private: ModpackList modpacks; QStringList m_failedLogos; QStringList m_loadingLogos; @@ -53,18 +47,17 @@ private: void requestLogo(QString file); QString translatePackType(PackType type) const; - -private slots: + private slots: void logoFailed(QString logo); void logoLoaded(QString logo, QIcon out); -public: - ListModel(QObject *parent); + public: + ListModel(QObject* parent); ~ListModel(); - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; + int rowCount(const QModelIndex& parent) const override; + int columnCount(const QModelIndex& parent) const override; + QVariant data(const QModelIndex& index, int role) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; void fill(ModpackList modpacks); void addPack(Modpack modpack); @@ -72,7 +65,7 @@ public: void remove(int row); Modpack at(int row); - void getLogo(const QString &logo, LogoCallback callback); + void getLogo(const QString& logo, LogoCallback callback); }; -} +} // namespace LegacyFTB diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index d4174ff1c..d3983696f 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -44,15 +44,14 @@ #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/NewInstanceDialog.h" +#include "ListModel.h" #include "modplatform/legacy_ftb/PackFetchTask.h" #include "modplatform/legacy_ftb/PackInstallTask.h" #include "modplatform/legacy_ftb/PrivatePackManager.h" -#include "ListModel.h" namespace LegacyFTB { -Page::Page(NewInstanceDialog* dialog, QWidget *parent) - : QWidget(parent), dialog(dialog), ui(new Ui::Page) +Page::Page(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog(dialog), ui(new Ui::Page) { ftbFetchTask.reset(new PackFetchTask(APPLICATION->network())); ftbPrivatePacks.reset(new PrivatePackManager()); @@ -70,8 +69,7 @@ Page::Page(NewInstanceDialog* dialog, QWidget *parent) ui->publicPackList->setIndentation(0); ui->publicPackList->setIconSize(QSize(42, 42)); - for(int i = 0; i < publicFilterModel->getAvailableSortings().size(); i++) - { + for (int i = 0; i < publicFilterModel->getAvailableSortings().size(); i++) { ui->sortByBox->addItem(publicFilterModel->getAvailableSortings().keys().at(i)); } @@ -142,8 +140,7 @@ bool Page::shouldDisplay() const void Page::openedImpl() { - if(!initialized) - { + if (!initialized) { connect(ftbFetchTask.get(), &PackFetchTask::finished, this, &Page::ftbPackDataDownloadSuccessfully); connect(ftbFetchTask.get(), &PackFetchTask::failed, this, &Page::ftbPackDataDownloadFailed); connect(ftbFetchTask.get(), &PackFetchTask::aborted, this, &Page::ftbPackDataDownloadAborted); @@ -166,50 +163,34 @@ void Page::retranslate() void Page::suggestCurrent() { - if(!isOpened) - { + if (!isOpened) { return; } - if(selected.broken || selectedVersion.isEmpty()) - { + if (selected.broken || selectedVersion.isEmpty()) { dialog->setSuggestedPack(); return; } dialog->setSuggestedPack(selected.name, selectedVersion, new PackInstallTask(APPLICATION->network(), selected, selectedVersion)); QString editedLogoName; - if(selected.logo.toLower().startsWith("ftb")) - { + if (selected.logo.toLower().startsWith("ftb")) { editedLogoName = selected.logo; - } - else - { + } else { editedLogoName = "ftb_" + selected.logo; } editedLogoName = editedLogoName.left(editedLogoName.lastIndexOf(".png")); - if(selected.type == PackType::Public) - { - publicListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); - } - else if (selected.type == PackType::ThirdParty) - { - thirdPartyModel->getLogo(selected.logo, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); - } - else if (selected.type == PackType::Private) - { - privateListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) - { - dialog->setSuggestedIconFromFile(logo, editedLogoName); - }); + if (selected.type == PackType::Public) { + publicListModel->getLogo(selected.logo, + [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); + } else if (selected.type == PackType::ThirdParty) { + thirdPartyModel->getLogo(selected.logo, + [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); + } else if (selected.type == PackType::Private) { + privateListModel->getLogo(selected.logo, + [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } } @@ -236,21 +217,16 @@ void Page::ftbPrivatePackDataDownloadSuccessfully(Modpack pack) void Page::ftbPrivatePackDataDownloadFailed([[maybe_unused]] QString reason, QString packCode) { - auto reply = QMessageBox::question( - this, - tr("FTB private packs"), - tr("Failed to download pack information for code %1.\nShould it be removed now?").arg(packCode) - ); - if(reply == QMessageBox::Yes) - { + auto reply = QMessageBox::question(this, tr("FTB private packs"), + tr("Failed to download pack information for code %1.\nShould it be removed now?").arg(packCode)); + if (reply == QMessageBox::Yes) { ftbPrivatePacks->remove(packCode); } } void Page::onPublicPackSelectionChanged(QModelIndex now, [[maybe_unused]] QModelIndex prev) { - if(!now.isValid()) - { + if (!now.isValid()) { onPackSelectionChanged(); return; } @@ -260,8 +236,7 @@ void Page::onPublicPackSelectionChanged(QModelIndex now, [[maybe_unused]] QModel void Page::onThirdPartyPackSelectionChanged(QModelIndex now, [[maybe_unused]] QModelIndex prev) { - if(!now.isValid()) - { + if (!now.isValid()) { onPackSelectionChanged(); return; } @@ -271,8 +246,7 @@ void Page::onThirdPartyPackSelectionChanged(QModelIndex now, [[maybe_unused]] QM void Page::onPrivatePackSelectionChanged(QModelIndex now, [[maybe_unused]] QModelIndex prev) { - if(!now.isValid()) - { + if (!now.isValid()) { onPackSelectionChanged(); return; } @@ -283,34 +257,26 @@ void Page::onPrivatePackSelectionChanged(QModelIndex now, [[maybe_unused]] QMode void Page::onPackSelectionChanged(Modpack* pack) { ui->versionSelectionBox->clear(); - if(pack) - { - currentModpackInfo->setHtml("Pack by " + pack->author + "" + - "
Minecraft " + pack->mcVersion + "
" + "
" + pack->description + "
  • " + pack->mods.replace(";", "
  • ") - + "
"); + if (pack) { + currentModpackInfo->setHtml("Pack by " + pack->author + "" + "
Minecraft " + pack->mcVersion + "
" + "
" + + pack->description + "
  • " + pack->mods.replace(";", "
  • ") + "
"); bool currentAdded = false; - for(int i = 0; i < pack->oldVersions.size(); i++) - { - if(pack->currentVersion == pack->oldVersions.at(i)) - { + for (int i = 0; i < pack->oldVersions.size(); i++) { + if (pack->currentVersion == pack->oldVersions.at(i)) { currentAdded = true; } ui->versionSelectionBox->addItem(pack->oldVersions.at(i)); } - if(!currentAdded) - { + if (!currentAdded) { ui->versionSelectionBox->addItem(pack->currentVersion); } selected = *pack; - } - else - { + } else { currentModpackInfo->setHtml(""); ui->versionSelectionBox->clear(); - if(isOpened) - { + if (isOpened) { dialog->setSuggestedPack(); } return; @@ -320,8 +286,7 @@ void Page::onPackSelectionChanged(Modpack* pack) void Page::onVersionSelectionItemChanged(QString version) { - if(version.isNull() || version.isEmpty()) - { + if (version.isNull() || version.isEmpty()) { selectedVersion = ""; return; } @@ -340,20 +305,15 @@ void Page::onSortingSelectionChanged(QString sort) void Page::onTabChanged(int tab) { - if(tab == 1) - { + if (tab == 1) { currentModel = thirdPartyFilterModel; currentList = ui->thirdPartyPackList; currentModpackInfo = ui->thirdPartyPackDescription; - } - else if(tab == 2) - { + } else if (tab == 2) { currentModel = privateFilterModel; currentList = ui->privatePackList; currentModpackInfo = ui->privatePackDescription; - } - else - { + } else { currentModel = publicFilterModel; currentList = ui->publicPackList; currentModpackInfo = ui->publicPackDescription; @@ -361,13 +321,10 @@ void Page::onTabChanged(int tab) currentList->selectionModel()->reset(); QModelIndex idx = currentList->currentIndex(); - if(idx.isValid()) - { + if (idx.isValid()) { auto pack = currentModel->data(idx, Qt::UserRole).value(); onPackSelectionChanged(&pack); - } - else - { + } else { onPackSelectionChanged(); } } @@ -375,38 +332,24 @@ void Page::onTabChanged(int tab) void Page::onAddPackClicked() { bool ok; - QString text = QInputDialog::getText( - this, - tr("Add FTB pack"), - tr("Enter pack code:"), - QLineEdit::Normal, - QString(), - &ok - ); - if(ok && !text.isEmpty()) - { + QString text = QInputDialog::getText(this, tr("Add FTB pack"), tr("Enter pack code:"), QLineEdit::Normal, QString(), &ok); + if (ok && !text.isEmpty()) { ftbPrivatePacks->add(text); - ftbFetchTask->fetchPrivate({text}); + ftbFetchTask->fetchPrivate({ text }); } } void Page::onRemovePackClicked() { auto index = ui->privatePackList->currentIndex(); - if(!index.isValid()) - { + if (!index.isValid()) { return; } auto row = index.row(); Modpack pack = privateListModel->at(row); - auto answer = QMessageBox::question( - this, - tr("Remove pack"), - tr("Are you sure you want to remove pack %1?").arg(pack.name), - QMessageBox::Yes | QMessageBox::No - ); - if(answer != QMessageBox::Yes) - { + auto answer = QMessageBox::question(this, tr("Remove pack"), tr("Are you sure you want to remove pack %1?").arg(pack.name), + QMessageBox::Yes | QMessageBox::No); + if (answer != QMessageBox::Yes) { return; } @@ -415,4 +358,4 @@ void Page::onRemovePackClicked() onPackSelectionChanged(); } -} +} // namespace LegacyFTB diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.h b/launcher/ui/pages/modplatform/legacy_ftb/Page.h index 1de8b40ab..32b4a8146 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.h @@ -35,23 +35,22 @@ #pragma once -#include -#include #include +#include +#include -#include "ui/pages/BasePage.h" #include -#include "tasks/Task.h" -#include "modplatform/legacy_ftb/PackHelpers.h" -#include "modplatform/legacy_ftb/PackFetchTask.h" #include "QObjectPtr.h" +#include "modplatform/legacy_ftb/PackFetchTask.h" +#include "modplatform/legacy_ftb/PackHelpers.h" +#include "tasks/Task.h" +#include "ui/pages/BasePage.h" class NewInstanceDialog; namespace LegacyFTB { -namespace Ui -{ +namespace Ui { class Page; } @@ -61,38 +60,25 @@ class PrivatePackListModel; class PrivatePackFilterModel; class PrivatePackManager; -class Page : public QWidget, public BasePage -{ +class Page : public QWidget, public BasePage { Q_OBJECT -public: - explicit Page(NewInstanceDialog * dialog, QWidget *parent = 0); + public: + explicit Page(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~Page(); - QString displayName() const override - { - return "FTB Legacy"; - } - QIcon icon() const override - { - return APPLICATION->getThemedIcon("ftb_logo"); - } - QString id() const override - { - return "legacy_ftb"; - } - QString helpPage() const override - { - return "FTB-platform"; - } + QString displayName() const override { return "FTB Legacy"; } + QIcon icon() const override { return APPLICATION->getThemedIcon("ftb_logo"); } + QString id() const override { return "legacy_ftb"; } + QString helpPage() const override { return "FTB-platform"; } bool shouldDisplay() const override; void openedImpl() override; void retranslate() override; -private: + private: void suggestCurrent(); - void onPackSelectionChanged(Modpack *pack = nullptr); + void onPackSelectionChanged(Modpack* pack = nullptr); -private slots: + private slots: void ftbPackDataDownloadSuccessfully(ModpackList publicPacks, ModpackList thirdPartyPacks); void ftbPackDataDownloadFailed(QString reason); void ftbPackDataDownloadAborted(); @@ -112,7 +98,7 @@ private slots: void onAddPackClicked(); void onRemovePackClicked(); -private: + private: FilterModel* currentModel = nullptr; QTreeView* currentList = nullptr; QTextBrowser* currentModpackInfo = nullptr; @@ -124,18 +110,18 @@ private: ListModel* publicListModel = nullptr; FilterModel* publicFilterModel = nullptr; - ListModel *thirdPartyModel = nullptr; - FilterModel *thirdPartyFilterModel = nullptr; + ListModel* thirdPartyModel = nullptr; + FilterModel* thirdPartyFilterModel = nullptr; - ListModel *privateListModel = nullptr; - FilterModel *privateFilterModel = nullptr; + ListModel* privateListModel = nullptr; + FilterModel* privateFilterModel = nullptr; unique_qobject_ptr ftbFetchTask; std::unique_ptr ftbPrivatePacks; NewInstanceDialog* dialog = nullptr; - Ui::Page *ui = nullptr; + Ui::Page* ui = nullptr; }; -} +} // namespace LegacyFTB diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 823439d3c..7427c0473 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -117,7 +117,7 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian return {}; } -bool ModpackListModel::setData(const QModelIndex &index, const QVariant &value, [[maybe_unused]] int role) +bool ModpackListModel::setData(const QModelIndex& index, const QVariant& value, [[maybe_unused]] int role) { int pos = index.row(); if (pos >= modpacks.size() || pos < 0 || !index.isValid()) @@ -183,24 +183,24 @@ void ModpackListModel::refresh() static auto sortFromIndex(int index) -> QString { - switch(index){ - default: - case 0: - return "relevance"; - case 1: - return "downloads"; - case 2: - return "follows"; - case 3: - return "newest"; - case 4: - return "updated"; + switch (index) { + default: + case 0: + return "relevance"; + case 1: + return "downloads"; + case 2: + return "follows"; + case 3: + return "newest"; + case 4: + return "updated"; } } void ModpackListModel::searchWithTerm(const QString& term, const int sort) { - if(sort > 5 || sort < 0) + if (sort > 5 || sort < 0) return; auto sort_str = sortFromIndex(sort); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index b9e9c3da5..47c2d55b4 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -47,7 +47,7 @@ class Version; namespace Modrinth { using LogoMap = QMap; -using LogoCallback = std::function; +using LogoCallback = std::function; class ModpackListModel : public QAbstractListModel { Q_OBJECT @@ -64,7 +64,7 @@ class ModpackListModel : public QAbstractListModel { /* Retrieve information from the model at a given index with the given role */ auto data(const QModelIndex& index, int role) const -> QVariant override; - bool setData(const QModelIndex &index, const QVariant &value, int role) override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; inline void setActiveJob(NetJob::Ptr ptr) { jobPtr = ptr; } @@ -75,7 +75,10 @@ class ModpackListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); - inline auto canFetchMore(const QModelIndex& parent) const -> bool override { return parent.isValid() ? false : searchState == CanPossiblyFetchMore; }; + inline auto canFetchMore(const QModelIndex& parent) const -> bool override + { + return parent.isValid() ? false : searchState == CanPossiblyFetchMore; + }; public slots: void searchRequestFinished(QJsonDocument& doc_all); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index dd143700c..ff809c7bb 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -46,8 +46,7 @@ namespace ResourceDownload { -ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instance) - : ModPage(dialog, instance) +ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) { m_model = new ModrinthModModel(instance); m_ui->packView->setModel(m_model); @@ -64,14 +63,15 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan m_ui->packDescription->setMetaEntry(metaEntryBase()); } -auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders) const -> bool +auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver, + QString mineVer, + std::optional loaders) const -> bool { auto loaderCompatible = !loaders.has_value(); if (!loaderCompatible) { auto loaderStrings = ModrinthAPI::getModLoaderStrings(loaders.value()); - for (auto remoteLoader : ver.loaders) - { + for (auto remoteLoader : ver.loaders) { if (loaderStrings.contains(remoteLoader)) { loaderCompatible = true; break; @@ -139,9 +139,21 @@ ModrinthShaderPackPage::ModrinthShaderPackPage(ShaderPackDownloadDialog* dialog, // I don't know why, but doing this on the parent class makes it so that // other mod providers start loading before being selected, at least with // my Qt, so we need to implement this in every derived class... -auto ModrinthModPage::shouldDisplay() const -> bool { return true; } -auto ModrinthResourcePackPage::shouldDisplay() const -> bool { return true; } -auto ModrinthTexturePackPage::shouldDisplay() const -> bool { return true; } -auto ModrinthShaderPackPage::shouldDisplay() const -> bool { return true; } +auto ModrinthModPage::shouldDisplay() const -> bool +{ + return true; +} +auto ModrinthResourcePackPage::shouldDisplay() const -> bool +{ + return true; +} +auto ModrinthTexturePackPage::shouldDisplay() const -> bool +{ + return true; +} +auto ModrinthShaderPackPage::shouldDisplay() const -> bool +{ + return true; +} } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index f4eb5ce09..26037f0cd 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -43,18 +43,33 @@ #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" -#include "ui/pages/modplatform/TexturePackPage.h" #include "ui/pages/modplatform/ShaderPackPage.h" +#include "ui/pages/modplatform/TexturePackPage.h" namespace ResourceDownload { namespace Modrinth { -static inline QString displayName() { return "Modrinth"; } -static inline QIcon icon() { return APPLICATION->getThemedIcon("modrinth"); } -static inline QString id() { return "modrinth"; } -static inline QString debugName() { return "Modrinth"; } -static inline QString metaEntryBase() { return "ModrinthPacks"; } +static inline QString displayName() +{ + return "Modrinth"; } +static inline QIcon icon() +{ + return APPLICATION->getThemedIcon("modrinth"); +} +static inline QString id() +{ + return "modrinth"; +} +static inline QString debugName() +{ + return "Modrinth"; +} +static inline QString metaEntryBase() +{ + return "ModrinthPacks"; +} +} // namespace Modrinth class ModrinthModPage : public ModPage { Q_OBJECT @@ -78,7 +93,8 @@ class ModrinthModPage : public ModPage { [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } - auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const -> bool override; + auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const + -> bool override; }; class ModrinthResourcePackPage : public ResourcePackResourcePage { diff --git a/launcher/ui/pages/modplatform/technic/TechnicData.h b/launcher/ui/pages/modplatform/technic/TechnicData.h index cd2ea8e14..81488811a 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicData.h +++ b/launcher/ui/pages/modplatform/technic/TechnicData.h @@ -63,6 +63,6 @@ struct Modpack { QString recommended; QVector versions; }; -} +} // namespace Technic Q_DECLARE_METATYPE(Technic::Modpack) diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 933904541..e87164711 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -41,18 +41,17 @@ #include "ui/dialogs/NewInstanceDialog.h" #include "BuildConfig.h" +#include "Json.h" #include "TechnicModel.h" #include "modplatform/technic/SingleZipPackInstallTask.h" #include "modplatform/technic/SolderPackInstallTask.h" -#include "Json.h" #include "Application.h" #include "modplatform/technic/SolderPackManifest.h" #include "net/ApiDownload.h" -TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget *parent) - : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog) +TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog) { ui->setupUi(this); connect(ui->searchButton, &QPushButton::clicked, this, &TechnicPage::triggerSearch); @@ -98,7 +97,8 @@ void TechnicPage::openedImpl() triggerSearch(); } -void TechnicPage::triggerSearch() { +void TechnicPage::triggerSearch() +{ model->searchWithTerm(ui->searchEdit->text()); } @@ -106,10 +106,8 @@ void TechnicPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelI { ui->versionSelectionBox->clear(); - if(!first.isValid()) - { - if(isOpened) - { + if (!first.isValid()) { + if (isOpened) { dialog->setSuggestedPack(); } return; @@ -121,12 +119,10 @@ void TechnicPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelI void TechnicPage::suggestCurrent() { - if (!isOpened) - { + if (!isOpened) { return; } - if (current.broken) - { + if (current.broken) { dialog->setSuggestedPack(); return; } @@ -142,50 +138,41 @@ void TechnicPage::suggestCurrent() auto netJob = makeShared(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network()); QString slug = current.slug; - netJob->addNetAction(Net::ApiDownload::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), response)); - QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug] - { + netJob->addNetAction(Net::ApiDownload::makeByteArray( + QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), response)); + QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug] { jobPtr.reset(); - if (current.slug != slug) - { + if (current.slug != slug) { return; } - QJsonParseError parse_error {}; + QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); QJsonObject obj = doc.object(); - if(parse_error.error != QJsonParseError::NoError) - { - qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset << " reason: " << parse_error.errorString(); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset + << " reason: " << parse_error.errorString(); qWarning() << *response; return; } - if (!obj.contains("url")) - { + if (!obj.contains("url")) { qWarning() << "Json doesn't contain an url key"; return; } QJsonValueRef url = obj["url"]; - if (url.isString()) - { + if (url.isString()) { current.url = url.toString(); - } - else - { - if (!obj.contains("solder")) - { + } else { + if (!obj.contains("solder")) { qWarning() << "Json doesn't contain a valid url or solder key"; return; } QJsonValueRef solderUrl = obj["solder"]; - if (solderUrl.isString()) - { + if (solderUrl.isString()) { current.url = solderUrl.toString(); current.isSolder = true; - } - else - { + } else { qWarning() << "Json doesn't contain a valid url or solder key"; return; } @@ -226,22 +213,21 @@ void TechnicPage::metadataLoaded() // Strip trailing forward-slashes from Solder URL's if (current.isSolder) { - while (current.url.endsWith('/')) current.url.chop(1); + while (current.url.endsWith('/')) + current.url.chop(1); } // Display versions from Solder if (!current.isSolder) { // If the pack isn't a Solder pack, it only has the single version ui->versionSelectionBox->addItem(current.currentVersion); - } - else if (current.versionsLoaded) { + } else if (current.versionsLoaded) { // reverse foreach, so that the newest versions are first for (auto i = current.versions.size(); i--;) { ui->versionSelectionBox->addItem(current.versions.at(i)); } ui->versionSelectionBox->setCurrentText(current.recommended); - } - else { + } else { // For now, until the versions are pulled from the Solder instance, display the current // version so we can display something quicker ui->versionSelectionBox->addItem(current.currentVersion); @@ -259,7 +245,8 @@ void TechnicPage::metadataLoaded() selectVersion(); } -void TechnicPage::selectVersion() { +void TechnicPage::selectVersion() +{ if (!isOpened) { return; } @@ -268,17 +255,18 @@ void TechnicPage::selectVersion() { return; } - if (!current.isSolder) - { - dialog->setSuggestedPack(current.name, selectedVersion, new Technic::SingleZipPackInstallTask(current.url, current.minecraftVersion)); - } - else - { - dialog->setSuggestedPack(current.name, selectedVersion, new Technic::SolderPackInstallTask(APPLICATION->network(), current.url, current.slug, selectedVersion, current.minecraftVersion)); + if (!current.isSolder) { + dialog->setSuggestedPack(current.name, selectedVersion, + new Technic::SingleZipPackInstallTask(current.url, current.minecraftVersion)); + } else { + dialog->setSuggestedPack(current.name, selectedVersion, + new Technic::SolderPackInstallTask(APPLICATION->network(), current.url, current.slug, selectedVersion, + current.minecraftVersion)); } } -void TechnicPage::onSolderLoaded() { +void TechnicPage::onSolderLoaded() +{ jobPtr.reset(); auto fallback = [this]() { @@ -318,7 +306,8 @@ void TechnicPage::onSolderLoaded() { metadataLoaded(); } -void TechnicPage::onVersionSelectionChanged(QString version) { +void TechnicPage::onVersionSelectionChanged(QString version) +{ if (version.isNull() || version.isEmpty()) { selectedVersion = ""; return; diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index 753261b30..d33656ebb 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -37,46 +37,32 @@ #include -#include "ui/pages/BasePage.h" #include +#include "TechnicData.h" #include "net/NetJob.h" #include "tasks/Task.h" -#include "TechnicData.h" +#include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class TechnicPage; } class NewInstanceDialog; namespace Technic { - class ListModel; +class ListModel; } -class TechnicPage : public QWidget, public BasePage -{ +class TechnicPage : public QWidget, public BasePage { Q_OBJECT -public: - explicit TechnicPage(NewInstanceDialog* dialog, QWidget *parent = 0); + public: + explicit TechnicPage(NewInstanceDialog* dialog, QWidget* parent = 0); virtual ~TechnicPage(); - virtual QString displayName() const override - { - return "Technic"; - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("technic"); - } - virtual QString id() const override - { - return "technic"; - } - virtual QString helpPage() const override - { - return "Technic-platform"; - } + virtual QString displayName() const override { return "Technic"; } + virtual QIcon icon() const override { return APPLICATION->getThemedIcon("technic"); } + virtual QString id() const override { return "technic"; } + virtual QString helpPage() const override { return "Technic-platform"; } virtual bool shouldDisplay() const override; void retranslate() override; @@ -84,19 +70,19 @@ public: bool eventFilter(QObject* watched, QEvent* event) override; -private: + private: void suggestCurrent(); void metadataLoaded(); void selectVersion(); -private slots: + private slots: void triggerSearch(); void onSelectionChanged(QModelIndex first, QModelIndex second); void onSolderLoaded(); void onVersionSelectionChanged(QString data); -private: - Ui::TechnicPage *ui = nullptr; + private: + Ui::TechnicPage* ui = nullptr; NewInstanceDialog* dialog = nullptr; Technic::ListModel* model = nullptr; diff --git a/launcher/ui/setupwizard/BaseWizardPage.h b/launcher/ui/setupwizard/BaseWizardPage.h index 72dbecfd5..80cc64969 100644 --- a/launcher/ui/setupwizard/BaseWizardPage.h +++ b/launcher/ui/setupwizard/BaseWizardPage.h @@ -1,31 +1,21 @@ #pragma once -#include #include +#include -class BaseWizardPage : public QWizardPage -{ -public: - explicit BaseWizardPage(QWidget *parent = Q_NULLPTR) - : QWizardPage(parent) - { - } - virtual ~BaseWizardPage() {}; +class BaseWizardPage : public QWizardPage { + public: + explicit BaseWizardPage(QWidget* parent = Q_NULLPTR) : QWizardPage(parent) {} + virtual ~BaseWizardPage(){}; - virtual bool wantsRefreshButton() - { - return false; - } - virtual void refresh() - { - } + virtual bool wantsRefreshButton() { return false; } + virtual void refresh() {} -protected: + protected: virtual void retranslate() = 0; - void changeEvent(QEvent * event) override + void changeEvent(QEvent* event) override { - if (event->type() == QEvent::LanguageChange) - { + if (event->type() == QEvent::LanguageChange) { retranslate(); } QWizardPage::changeEvent(event); diff --git a/launcher/ui/setupwizard/JavaWizardPage.cpp b/launcher/ui/setupwizard/JavaWizardPage.cpp index 2b70c47c3..e2c444373 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.cpp +++ b/launcher/ui/setupwizard/JavaWizardPage.cpp @@ -1,29 +1,27 @@ #include "JavaWizardPage.h" #include "Application.h" -#include +#include #include -#include #include #include #include +#include #include -#include +#include #include #include "FileSystem.h" +#include "JavaCommon.h" #include "java/JavaInstall.h" #include "java/JavaUtils.h" -#include "JavaCommon.h" -#include "ui/widgets/VersionSelectWidget.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/widgets/JavaSettingsWidget.h" +#include "ui/widgets/VersionSelectWidget.h" - -JavaWizardPage::JavaWizardPage(QWidget *parent) - :BaseWizardPage(parent) +JavaWizardPage::JavaWizardPage(QWidget* parent) : BaseWizardPage(parent) { setupUi(); } @@ -31,7 +29,7 @@ JavaWizardPage::JavaWizardPage(QWidget *parent) void JavaWizardPage::setupUi() { setObjectName(QStringLiteral("javaPage")); - QVBoxLayout * layout = new QVBoxLayout(this); + QVBoxLayout* layout = new QVBoxLayout(this); m_java_widget = new JavaSettingsWidget(this); layout->addWidget(m_java_widget); @@ -59,30 +57,23 @@ bool JavaWizardPage::validatePage() { auto settings = APPLICATION->settings(); auto result = m_java_widget->validate(); - switch(result) - { + switch (result) { default: - case JavaSettingsWidget::ValidationStatus::Bad: - { + case JavaSettingsWidget::ValidationStatus::Bad: { return false; } - case JavaSettingsWidget::ValidationStatus::AllOK: - { + case JavaSettingsWidget::ValidationStatus::AllOK: { settings->set("JavaPath", m_java_widget->javaPath()); return true; } - case JavaSettingsWidget::ValidationStatus::JavaBad: - { + case JavaSettingsWidget::ValidationStatus::JavaBad: { // Memory auto s = APPLICATION->settings(); s->set("MinMemAlloc", m_java_widget->minHeapSize()); s->set("MaxMemAlloc", m_java_widget->maxHeapSize()); - if (m_java_widget->permGenEnabled()) - { + if (m_java_widget->permGenEnabled()) { s->set("PermGen", m_java_widget->permGenSize()); - } - else - { + } else { s->reset("PermGen"); } return true; @@ -93,7 +84,8 @@ bool JavaWizardPage::validatePage() void JavaWizardPage::retranslate() { setTitle(tr("Java")); - setSubTitle(tr("You do not have a working Java set up yet or it went missing.\n" - "Please select one of the following or browse for a Java executable.")); + setSubTitle( + tr("You do not have a working Java set up yet or it went missing.\n" + "Please select one of the following or browse for a Java executable.")); m_java_widget->retranslate(); } diff --git a/launcher/ui/setupwizard/JavaWizardPage.h b/launcher/ui/setupwizard/JavaWizardPage.h index 0d749039c..6c083dc96 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.h +++ b/launcher/ui/setupwizard/JavaWizardPage.h @@ -4,26 +4,22 @@ class JavaSettingsWidget; -class JavaWizardPage : public BaseWizardPage -{ +class JavaWizardPage : public BaseWizardPage { Q_OBJECT -public: - explicit JavaWizardPage(QWidget *parent = Q_NULLPTR); + public: + explicit JavaWizardPage(QWidget* parent = Q_NULLPTR); - virtual ~JavaWizardPage() - { - }; + virtual ~JavaWizardPage(){}; bool wantsRefreshButton() override; void refresh() override; void initializePage() override; bool validatePage() override; -protected: /* methods */ + protected: /* methods */ void setupUi(); void retranslate() override; -private: /* data */ - JavaSettingsWidget *m_java_widget = nullptr; + private: /* data */ + JavaSettingsWidget* m_java_widget = nullptr; }; - diff --git a/launcher/ui/setupwizard/LanguageWizardPage.cpp b/launcher/ui/setupwizard/LanguageWizardPage.cpp index 6bd19b6ff..09cdb807e 100644 --- a/launcher/ui/setupwizard/LanguageWizardPage.cpp +++ b/launcher/ui/setupwizard/LanguageWizardPage.cpp @@ -2,25 +2,22 @@ #include #include -#include "ui/widgets/LanguageSelectionWidget.h" -#include #include +#include +#include "ui/widgets/LanguageSelectionWidget.h" -LanguageWizardPage::LanguageWizardPage(QWidget *parent) - : BaseWizardPage(parent) +LanguageWizardPage::LanguageWizardPage(QWidget* parent) : BaseWizardPage(parent) { setObjectName(QStringLiteral("languagePage")); auto layout = new QVBoxLayout(this); mainWidget = new LanguageSelectionWidget(this); - layout->setContentsMargins(0,0,0,0); + layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(mainWidget); retranslate(); } -LanguageWizardPage::~LanguageWizardPage() -{ -} +LanguageWizardPage::~LanguageWizardPage() {} bool LanguageWizardPage::wantsRefreshButton() { diff --git a/launcher/ui/setupwizard/LanguageWizardPage.h b/launcher/ui/setupwizard/LanguageWizardPage.h index 45a0e5c04..44a062399 100644 --- a/launcher/ui/setupwizard/LanguageWizardPage.h +++ b/launcher/ui/setupwizard/LanguageWizardPage.h @@ -4,11 +4,10 @@ class LanguageSelectionWidget; -class LanguageWizardPage : public BaseWizardPage -{ +class LanguageWizardPage : public BaseWizardPage { Q_OBJECT -public: - explicit LanguageWizardPage(QWidget *parent = Q_NULLPTR); + public: + explicit LanguageWizardPage(QWidget* parent = Q_NULLPTR); virtual ~LanguageWizardPage(); @@ -18,9 +17,9 @@ public: bool validatePage() override; -protected: + protected: void retranslate() override; -private: - LanguageSelectionWidget *mainWidget = nullptr; + private: + LanguageSelectionWidget* mainWidget = nullptr; }; diff --git a/launcher/ui/setupwizard/PasteWizardPage.cpp b/launcher/ui/setupwizard/PasteWizardPage.cpp index 0f47da4b1..777fd3a44 100644 --- a/launcher/ui/setupwizard/PasteWizardPage.cpp +++ b/launcher/ui/setupwizard/PasteWizardPage.cpp @@ -4,9 +4,7 @@ #include "Application.h" #include "net/PasteUpload.h" -PasteWizardPage::PasteWizardPage(QWidget *parent) : - BaseWizardPage(parent), - ui(new Ui::PasteWizardPage) +PasteWizardPage::PasteWizardPage(QWidget* parent) : BaseWizardPage(parent), ui(new Ui::PasteWizardPage) { ui->setupUi(this); } @@ -16,17 +14,14 @@ PasteWizardPage::~PasteWizardPage() delete ui; } -void PasteWizardPage::initializePage() -{ -} +void PasteWizardPage::initializePage() {} bool PasteWizardPage::validatePage() { auto s = APPLICATION->settings(); QString prevPasteURL = s->get("PastebinURL").toString(); s->reset("PastebinURL"); - if (ui->previousSettingsRadioButton->isChecked()) - { + if (ui->previousSettingsRadioButton->isChecked()) { bool usingDefaultBase = prevPasteURL == PasteUpload::PasteTypes.at(PasteUpload::PasteType::NullPointer).defaultBase; s->set("PastebinType", PasteUpload::PasteType::NullPointer); if (!usingDefaultBase) diff --git a/launcher/ui/setupwizard/PasteWizardPage.h b/launcher/ui/setupwizard/PasteWizardPage.h index 513a14cb5..dece81c42 100644 --- a/launcher/ui/setupwizard/PasteWizardPage.h +++ b/launcher/ui/setupwizard/PasteWizardPage.h @@ -8,20 +8,19 @@ namespace Ui { class PasteWizardPage; } -class PasteWizardPage : public BaseWizardPage -{ +class PasteWizardPage : public BaseWizardPage { Q_OBJECT -public: - explicit PasteWizardPage(QWidget *parent = nullptr); + public: + explicit PasteWizardPage(QWidget* parent = nullptr); ~PasteWizardPage(); void initializePage() override; bool validatePage() override; void retranslate() override; -private: - Ui::PasteWizardPage *ui; + private: + Ui::PasteWizardPage* ui; }; -#endif // PASTEDEFAULTSCONFIRMATIONWIZARD_H +#endif // PASTEDEFAULTSCONFIRMATIONWIZARD_H diff --git a/launcher/ui/setupwizard/SetupWizard.cpp b/launcher/ui/setupwizard/SetupWizard.cpp index 0a47334fc..4e5bd1dca 100644 --- a/launcher/ui/setupwizard/SetupWizard.cpp +++ b/launcher/ui/setupwizard/SetupWizard.cpp @@ -1,16 +1,16 @@ #include "SetupWizard.h" -#include "LanguageWizardPage.h" #include "JavaWizardPage.h" +#include "LanguageWizardPage.h" -#include "translations/TranslationsModel.h" #include #include +#include "translations/TranslationsModel.h" -#include #include +#include -SetupWizard::SetupWizard(QWidget *parent) : QWizard(parent) +SetupWizard::SetupWizard(QWidget* parent) : QWizard(parent) { setObjectName(QStringLiteral("SetupWizard")); resize(620, 660); @@ -33,17 +33,17 @@ void SetupWizard::retranslate() setWindowTitle(tr("%1 Quick Setup").arg(BuildConfig.LAUNCHER_DISPLAYNAME)); } -BaseWizardPage * SetupWizard::getBasePage(int id) +BaseWizardPage* SetupWizard::getBasePage(int id) { - if(id == -1) + if (id == -1) return nullptr; auto pagePtr = page(id); - if(!pagePtr) + if (!pagePtr) return nullptr; - return dynamic_cast(pagePtr); + return dynamic_cast(pagePtr); } -BaseWizardPage * SetupWizard::getCurrentBasePage() +BaseWizardPage* SetupWizard::getCurrentBasePage() { return getBasePage(currentId()); } @@ -51,38 +51,29 @@ BaseWizardPage * SetupWizard::getCurrentBasePage() void SetupWizard::pageChanged(int id) { auto basePagePtr = getBasePage(id); - if(!basePagePtr) - { + if (!basePagePtr) { return; } - if(basePagePtr->wantsRefreshButton()) - { - setButtonLayout({QWizard::CustomButton1, QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton}); + if (basePagePtr->wantsRefreshButton()) { + setButtonLayout({ QWizard::CustomButton1, QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton }); auto customButton = button(QWizard::CustomButton1); - connect(customButton, &QAbstractButton::clicked, [&](){ + connect(customButton, &QAbstractButton::clicked, [&]() { auto basePagePtr = getCurrentBasePage(); - if(basePagePtr) - { + if (basePagePtr) { basePagePtr->refresh(); } }); - } - else - { - setButtonLayout({QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton}); + } else { + setButtonLayout({ QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton }); } } - -void SetupWizard::changeEvent(QEvent *event) +void SetupWizard::changeEvent(QEvent* event) { - if (event->type() == QEvent::LanguageChange) - { + if (event->type() == QEvent::LanguageChange) { retranslate(); } QWizard::changeEvent(event); } -SetupWizard::~SetupWizard() -{ -} +SetupWizard::~SetupWizard() {} diff --git a/launcher/ui/setupwizard/SetupWizard.h b/launcher/ui/setupwizard/SetupWizard.h index 9b8adb4df..c26c59fdb 100644 --- a/launcher/ui/setupwizard/SetupWizard.h +++ b/launcher/ui/setupwizard/SetupWizard.h @@ -17,29 +17,26 @@ #include -namespace Ui -{ +namespace Ui { class SetupWizard; } class BaseWizardPage; -class SetupWizard : public QWizard -{ +class SetupWizard : public QWizard { Q_OBJECT -public: /* con/destructors */ - explicit SetupWizard(QWidget *parent = 0); + public: /* con/destructors */ + explicit SetupWizard(QWidget* parent = 0); virtual ~SetupWizard(); - void changeEvent(QEvent * event) override; - BaseWizardPage *getBasePage(int id); - BaseWizardPage *getCurrentBasePage(); + void changeEvent(QEvent* event) override; + BaseWizardPage* getBasePage(int id); + BaseWizardPage* getCurrentBasePage(); -private slots: + private slots: void pageChanged(int id); -private: /* methods */ + private: /* methods */ void retranslate(); }; - diff --git a/launcher/ui/themes/BrightTheme.cpp b/launcher/ui/themes/BrightTheme.cpp index 696ffdfb4..ffccdaab1 100644 --- a/launcher/ui/themes/BrightTheme.cpp +++ b/launcher/ui/themes/BrightTheme.cpp @@ -20,18 +20,18 @@ bool BrightTheme::hasColorScheme() QPalette BrightTheme::colorScheme() { QPalette brightPalette; - brightPalette.setColor(QPalette::Window, QColor(255,255,255)); - brightPalette.setColor(QPalette::WindowText, QColor(17,17,17)); - brightPalette.setColor(QPalette::Base, QColor(250,250,250)); - brightPalette.setColor(QPalette::AlternateBase, QColor(240,240,240)); - brightPalette.setColor(QPalette::ToolTipBase, QColor(17,17,17)); - brightPalette.setColor(QPalette::ToolTipText, QColor(255,255,255)); - brightPalette.setColor(QPalette::Text, Qt::black); - brightPalette.setColor(QPalette::Button, QColor(249,249,249)); + brightPalette.setColor(QPalette::Window, QColor(255, 255, 255)); + brightPalette.setColor(QPalette::WindowText, QColor(17, 17, 17)); + brightPalette.setColor(QPalette::Base, QColor(250, 250, 250)); + brightPalette.setColor(QPalette::AlternateBase, QColor(240, 240, 240)); + brightPalette.setColor(QPalette::ToolTipBase, QColor(17, 17, 17)); + brightPalette.setColor(QPalette::ToolTipText, QColor(255, 255, 255)); + brightPalette.setColor(QPalette::Text, Qt::black); + brightPalette.setColor(QPalette::Button, QColor(249, 249, 249)); brightPalette.setColor(QPalette::ButtonText, Qt::black); brightPalette.setColor(QPalette::BrightText, Qt::red); - brightPalette.setColor(QPalette::Link, QColor(37,137,164)); - brightPalette.setColor(QPalette::Highlight, QColor(137,207,84)); + brightPalette.setColor(QPalette::Link, QColor(37, 137, 164)); + brightPalette.setColor(QPalette::Highlight, QColor(137, 207, 84)); brightPalette.setColor(QPalette::HighlightedText, Qt::black); return fadeInactive(brightPalette, fadeAmount(), fadeColor()); } @@ -43,7 +43,7 @@ double BrightTheme::fadeAmount() QColor BrightTheme::fadeColor() { - return QColor(255,255,255); + return QColor(255, 255, 255); } bool BrightTheme::hasStyleSheet() @@ -55,4 +55,3 @@ QString BrightTheme::appStyleSheet() { return QString(); } - diff --git a/launcher/ui/themes/BrightTheme.h b/launcher/ui/themes/BrightTheme.h index c61f52d58..44a767492 100644 --- a/launcher/ui/themes/BrightTheme.h +++ b/launcher/ui/themes/BrightTheme.h @@ -2,9 +2,8 @@ #include "FusionTheme.h" -class BrightTheme: public FusionTheme -{ -public: +class BrightTheme : public FusionTheme { + public: virtual ~BrightTheme() {} QString id() override; @@ -16,4 +15,3 @@ public: double fadeAmount() override; QColor fadeColor() override; }; - diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 8e28ba4fc..29ecf6254 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -183,7 +183,8 @@ CustomTheme::CustomTheme(ITheme* baseTheme, QFileInfo& fileInfo, bool isManifest return; } - // FIXME: This is kinda jank, it only actually checks if the qss file path is not present. It should actually check for any relevant missing data (e.g. name, colors) + // FIXME: This is kinda jank, it only actually checks if the qss file path is not present. It should actually check for any relevant + // missing data (e.g. name, colors) if (jsonDataIncomplete) { writeThemeJson(fileInfo.absoluteFilePath(), m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets, m_qssFilePath); } diff --git a/launcher/ui/themes/DarkTheme.cpp b/launcher/ui/themes/DarkTheme.cpp index 48231b53e..c3a68a2d4 100644 --- a/launcher/ui/themes/DarkTheme.cpp +++ b/launcher/ui/themes/DarkTheme.cpp @@ -20,21 +20,21 @@ bool DarkTheme::hasColorScheme() QPalette DarkTheme::colorScheme() { QPalette darkPalette; - darkPalette.setColor(QPalette::Window, QColor(49,49,49)); + darkPalette.setColor(QPalette::Window, QColor(49, 49, 49)); darkPalette.setColor(QPalette::WindowText, Qt::white); - darkPalette.setColor(QPalette::Base, QColor(34,34,34)); - darkPalette.setColor(QPalette::AlternateBase, QColor(42,42,42)); + darkPalette.setColor(QPalette::Base, QColor(34, 34, 34)); + darkPalette.setColor(QPalette::AlternateBase, QColor(42, 42, 42)); darkPalette.setColor(QPalette::ToolTipBase, Qt::white); darkPalette.setColor(QPalette::ToolTipText, Qt::white); darkPalette.setColor(QPalette::Text, Qt::white); - darkPalette.setColor(QPalette::Button, QColor(48,48,48)); + darkPalette.setColor(QPalette::Button, QColor(48, 48, 48)); darkPalette.setColor(QPalette::ButtonText, Qt::white); darkPalette.setColor(QPalette::BrightText, Qt::red); - darkPalette.setColor(QPalette::Link, QColor(47,163,198)); - darkPalette.setColor(QPalette::Highlight, QColor(150,219,89)); + darkPalette.setColor(QPalette::Link, QColor(47, 163, 198)); + darkPalette.setColor(QPalette::Highlight, QColor(150, 219, 89)); darkPalette.setColor(QPalette::HighlightedText, Qt::black); darkPalette.setColor(QPalette::PlaceholderText, Qt::darkGray); - return fadeInactive(darkPalette, fadeAmount(), fadeColor()); + return fadeInactive(darkPalette, fadeAmount(), fadeColor()); } double DarkTheme::fadeAmount() @@ -44,7 +44,7 @@ double DarkTheme::fadeAmount() QColor DarkTheme::fadeColor() { - return QColor(49,49,49); + return QColor(49, 49, 49); } bool DarkTheme::hasStyleSheet() diff --git a/launcher/ui/themes/DarkTheme.h b/launcher/ui/themes/DarkTheme.h index 9bd2f3439..431e9a735 100644 --- a/launcher/ui/themes/DarkTheme.h +++ b/launcher/ui/themes/DarkTheme.h @@ -2,9 +2,8 @@ #include "FusionTheme.h" -class DarkTheme: public FusionTheme -{ -public: +class DarkTheme : public FusionTheme { + public: virtual ~DarkTheme() {} QString id() override; diff --git a/launcher/ui/themes/FusionTheme.h b/launcher/ui/themes/FusionTheme.h index ee34245ac..826fae1db 100644 --- a/launcher/ui/themes/FusionTheme.h +++ b/launcher/ui/themes/FusionTheme.h @@ -2,9 +2,8 @@ #include "ITheme.h" -class FusionTheme: public ITheme -{ -public: +class FusionTheme : public ITheme { + public: virtual ~FusionTheme() {} QString qtTheme() override; diff --git a/launcher/ui/themes/ITheme.cpp b/launcher/ui/themes/ITheme.cpp index 42d63b113..316b0f2ed 100644 --- a/launcher/ui/themes/ITheme.cpp +++ b/launcher/ui/themes/ITheme.cpp @@ -33,10 +33,10 @@ * limitations under the License. */ #include "ITheme.h" -#include "rainbow.h" -#include #include +#include #include "Application.h" +#include "rainbow.h" void ITheme::apply(bool) { @@ -51,8 +51,7 @@ void ITheme::apply(bool) QPalette ITheme::fadeInactive(QPalette in, qreal bias, QColor color) { - auto blend = [&in, bias, color](QPalette::ColorRole role) - { + auto blend = [&in, bias, color](QPalette::ColorRole role) { QColor from = in.color(QPalette::Active, role); QColor blended = Rainbow::mix(from, color, bias); in.setColor(QPalette::Disabled, role, blended); diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index 3b8cb24a4..7ad144c7a 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -65,7 +65,7 @@ void SystemTheme::apply(bool initial) // See https://github.com/MultiMC/Launcher/issues/1790 // or https://github.com/PrismLauncher/PrismLauncher/issues/490 if (initial) - return; + return; ITheme::apply(initial); } diff --git a/launcher/ui/widgets/CustomCommands.cpp b/launcher/ui/widgets/CustomCommands.cpp index 5ab903950..98a1b7e86 100644 --- a/launcher/ui/widgets/CustomCommands.cpp +++ b/launcher/ui/widgets/CustomCommands.cpp @@ -41,9 +41,7 @@ CustomCommands::~CustomCommands() delete ui; } -CustomCommands::CustomCommands(QWidget* parent): - QWidget(parent), - ui(new Ui::CustomCommands) +CustomCommands::CustomCommands(QWidget* parent) : QWidget(parent), ui(new Ui::CustomCommands) { ui->setupUi(this); } @@ -51,8 +49,7 @@ CustomCommands::CustomCommands(QWidget* parent): void CustomCommands::initialize(bool checkable, bool checked, const QString& prelaunch, const QString& wrapper, const QString& postexit) { ui->customCommandsGroupBox->setCheckable(checkable); - if(checkable) - { + if (checkable) { ui->customCommandsGroupBox->setChecked(checked); } ui->preLaunchCmdTextBox->setText(prelaunch); @@ -60,14 +57,14 @@ void CustomCommands::initialize(bool checkable, bool checked, const QString& pre ui->postExitCmdTextBox->setText(postexit); } - -void CustomCommands::retranslate() { +void CustomCommands::retranslate() +{ ui->retranslateUi(this); } bool CustomCommands::checked() const { - if(!ui->customCommandsGroupBox->isCheckable()) + if (!ui->customCommandsGroupBox->isCheckable()) return true; return ui->customCommandsGroupBox->isChecked(); } diff --git a/launcher/ui/widgets/CustomCommands.h b/launcher/ui/widgets/CustomCommands.h index ed10ba956..96a3fa627 100644 --- a/launcher/ui/widgets/CustomCommands.h +++ b/launcher/ui/widgets/CustomCommands.h @@ -37,19 +37,17 @@ #include -namespace Ui -{ +namespace Ui { class CustomCommands; } -class CustomCommands : public QWidget -{ +class CustomCommands : public QWidget { Q_OBJECT -public: - explicit CustomCommands(QWidget *parent = 0); + public: + explicit CustomCommands(QWidget* parent = 0); virtual ~CustomCommands(); - void initialize(bool checkable, bool checked, const QString & prelaunch, const QString & wrapper, const QString & postexit); + void initialize(bool checkable, bool checked, const QString& prelaunch, const QString& wrapper, const QString& postexit); void retranslate(); bool checked() const; @@ -57,8 +55,6 @@ public: QString wrapperCommand() const; QString postexitCommand() const; -private: - Ui::CustomCommands *ui; + private: + Ui::CustomCommands* ui; }; - - diff --git a/launcher/ui/widgets/DropLabel.cpp b/launcher/ui/widgets/DropLabel.cpp index a900e57cf..b1473b358 100644 --- a/launcher/ui/widgets/DropLabel.cpp +++ b/launcher/ui/widgets/DropLabel.cpp @@ -1,34 +1,33 @@ #include "DropLabel.h" -#include #include +#include -DropLabel::DropLabel(QWidget *parent) : QLabel(parent) +DropLabel::DropLabel(QWidget* parent) : QLabel(parent) { setAcceptDrops(true); } -void DropLabel::dragEnterEvent(QDragEnterEvent *event) +void DropLabel::dragEnterEvent(QDragEnterEvent* event) { event->acceptProposedAction(); } -void DropLabel::dragMoveEvent(QDragMoveEvent *event) +void DropLabel::dragMoveEvent(QDragMoveEvent* event) { event->acceptProposedAction(); } -void DropLabel::dragLeaveEvent(QDragLeaveEvent *event) +void DropLabel::dragLeaveEvent(QDragLeaveEvent* event) { event->accept(); } -void DropLabel::dropEvent(QDropEvent *event) +void DropLabel::dropEvent(QDropEvent* event) { - const QMimeData *mimeData = event->mimeData(); + const QMimeData* mimeData = event->mimeData(); - if (!mimeData) - { + if (!mimeData) { return; } diff --git a/launcher/ui/widgets/DropLabel.h b/launcher/ui/widgets/DropLabel.h index c5ca0bcca..0027f48b1 100644 --- a/launcher/ui/widgets/DropLabel.h +++ b/launcher/ui/widgets/DropLabel.h @@ -2,19 +2,18 @@ #include -class DropLabel : public QLabel -{ +class DropLabel : public QLabel { Q_OBJECT -public: - explicit DropLabel(QWidget *parent = nullptr); + public: + explicit DropLabel(QWidget* parent = nullptr); -signals: + signals: void droppedURLs(QList urls); -protected: - void dropEvent(QDropEvent *event) override; - void dragEnterEvent(QDragEnterEvent *event) override; - void dragMoveEvent(QDragMoveEvent *event) override; - void dragLeaveEvent(QDragLeaveEvent *event) override; + protected: + void dropEvent(QDropEvent* event) override; + void dragEnterEvent(QDragEnterEvent* event) override; + void dragMoveEvent(QDragMoveEvent* event) override; + void dragLeaveEvent(QDragLeaveEvent* event) override; }; diff --git a/launcher/ui/widgets/ErrorFrame.cpp b/launcher/ui/widgets/ErrorFrame.cpp index b3e410361..213c26b76 100644 --- a/launcher/ui/widgets/ErrorFrame.cpp +++ b/launcher/ui/widgets/ErrorFrame.cpp @@ -27,9 +27,7 @@ void ErrorFrame::clear() setDescription(QString()); } -ErrorFrame::ErrorFrame(QWidget *parent) : - QFrame(parent), - ui(new Ui::ErrorFrame) +ErrorFrame::ErrorFrame(QWidget* parent) : QFrame(parent), ui(new Ui::ErrorFrame) { ui->setupUi(this); ui->label_Description->setHidden(true); @@ -44,24 +42,18 @@ ErrorFrame::~ErrorFrame() void ErrorFrame::updateHiddenState() { - if(ui->label_Description->isHidden() && ui->label_Title->isHidden()) - { + if (ui->label_Description->isHidden() && ui->label_Title->isHidden()) { setHidden(true); - } - else - { + } else { setHidden(false); } } void ErrorFrame::setTitle(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->label_Title->setHidden(true); - } - else - { + } else { ui->label_Title->setText(text); ui->label_Title->setHidden(false); } @@ -70,14 +62,11 @@ void ErrorFrame::setTitle(QString text) void ErrorFrame::setDescription(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->label_Description->setHidden(true); updateHiddenState(); return; - } - else - { + } else { ui->label_Description->setHidden(false); updateHiddenState(); } @@ -87,9 +76,8 @@ void ErrorFrame::setDescription(QString text) QChar rem('\n'); QString finaltext; finaltext.reserve(intermediatetext.size()); - foreach(const QChar& c, intermediatetext) - { - if(c == rem && prev){ + foreach (const QChar& c, intermediatetext) { + if (c == rem && prev) { continue; } prev = c == rem; @@ -97,33 +85,27 @@ void ErrorFrame::setDescription(QString text) } QString labeltext; labeltext.reserve(300); - if(finaltext.length() > 290) - { + if (finaltext.length() > 290) { ui->label_Description->setOpenExternalLinks(false); ui->label_Description->setTextFormat(Qt::TextFormat::RichText); desc = text; // This allows injecting HTML here. labeltext.append("" + finaltext.left(287) + "..."); QObject::connect(ui->label_Description, &QLabel::linkActivated, this, &ErrorFrame::ellipsisHandler); - } - else - { + } else { ui->label_Description->setTextFormat(Qt::TextFormat::PlainText); labeltext.append(finaltext); } ui->label_Description->setText(labeltext); } -void ErrorFrame::ellipsisHandler(const QString &link) +void ErrorFrame::ellipsisHandler(const QString& link) { - if(!currentBox) - { + if (!currentBox) { currentBox = CustomMessageBox::selectable(this, QString(), desc); connect(currentBox, &QMessageBox::finished, this, &ErrorFrame::boxClosed); currentBox->show(); - } - else - { + } else { currentBox->setText(desc); } } diff --git a/launcher/ui/widgets/ErrorFrame.h b/launcher/ui/widgets/ErrorFrame.h index d5069a14b..1aea6a1d8 100644 --- a/launcher/ui/widgets/ErrorFrame.h +++ b/launcher/ui/widgets/ErrorFrame.h @@ -17,17 +17,15 @@ #include -namespace Ui -{ +namespace Ui { class ErrorFrame; } -class ErrorFrame : public QFrame -{ +class ErrorFrame : public QFrame { Q_OBJECT -public: - explicit ErrorFrame(QWidget *parent = 0); + public: + explicit ErrorFrame(QWidget* parent = 0); ~ErrorFrame(); void setTitle(QString text); @@ -35,15 +33,15 @@ public: void clear(); -public slots: - void ellipsisHandler(const QString& link ); + public slots: + void ellipsisHandler(const QString& link); void boxClosed(int result); -private: + private: void updateHiddenState(); -private: - Ui::ErrorFrame *ui; + private: + Ui::ErrorFrame* ui; QString desc; - class QMessageBox * currentBox = nullptr; + class QMessageBox* currentBox = nullptr; }; diff --git a/launcher/ui/widgets/FocusLineEdit.cpp b/launcher/ui/widgets/FocusLineEdit.cpp index b272100c0..6570227bb 100644 --- a/launcher/ui/widgets/FocusLineEdit.cpp +++ b/launcher/ui/widgets/FocusLineEdit.cpp @@ -1,23 +1,22 @@ #include "FocusLineEdit.h" #include -FocusLineEdit::FocusLineEdit(QWidget *parent) : QLineEdit(parent) +FocusLineEdit::FocusLineEdit(QWidget* parent) : QLineEdit(parent) { _selectOnMousePress = false; } -void FocusLineEdit::focusInEvent(QFocusEvent *e) +void FocusLineEdit::focusInEvent(QFocusEvent* e) { QLineEdit::focusInEvent(e); selectAll(); _selectOnMousePress = true; } -void FocusLineEdit::mousePressEvent(QMouseEvent *me) +void FocusLineEdit::mousePressEvent(QMouseEvent* me) { QLineEdit::mousePressEvent(me); - if (_selectOnMousePress) - { + if (_selectOnMousePress) { selectAll(); _selectOnMousePress = false; } diff --git a/launcher/ui/widgets/FocusLineEdit.h b/launcher/ui/widgets/FocusLineEdit.h index 71b4f140a..f5ea6602e 100644 --- a/launcher/ui/widgets/FocusLineEdit.h +++ b/launcher/ui/widgets/FocusLineEdit.h @@ -1,17 +1,14 @@ #include -class FocusLineEdit : public QLineEdit -{ +class FocusLineEdit : public QLineEdit { Q_OBJECT -public: - FocusLineEdit(QWidget *parent); - virtual ~FocusLineEdit() - { - } + public: + FocusLineEdit(QWidget* parent); + virtual ~FocusLineEdit() {} -protected: - void focusInEvent(QFocusEvent *e); - void mousePressEvent(QMouseEvent *me); + protected: + void focusInEvent(QFocusEvent* e); + void mousePressEvent(QMouseEvent* me); bool _selectOnMousePress; }; diff --git a/launcher/ui/widgets/IconLabel.cpp b/launcher/ui/widgets/IconLabel.cpp index bf1c23584..28776686b 100644 --- a/launcher/ui/widgets/IconLabel.cpp +++ b/launcher/ui/widgets/IconLabel.cpp @@ -1,13 +1,12 @@ #include "IconLabel.h" -#include -#include #include #include #include +#include +#include -IconLabel::IconLabel(QWidget *parent, QIcon icon, QSize size) - : QWidget(parent), m_size(size), m_icon(icon) +IconLabel::IconLabel(QWidget* parent, QIcon icon, QSize size) : QWidget(parent), m_size(size), m_icon(icon) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); } @@ -23,19 +22,16 @@ void IconLabel::setIcon(QIcon icon) update(); } -void IconLabel::paintEvent(QPaintEvent *) +void IconLabel::paintEvent(QPaintEvent*) { QPainter p(this); QRect rect = contentsRect(); int width = rect.width(); int height = rect.height(); - if(width < height) - { + if (width < height) { rect.setHeight(width); rect.translate(0, (height - width) / 2); - } - else if (width > height) - { + } else if (width > height) { rect.setWidth(height); rect.translate((width - height) / 2, 0); } diff --git a/launcher/ui/widgets/IconLabel.h b/launcher/ui/widgets/IconLabel.h index 6d212c4ca..41d97f694 100644 --- a/launcher/ui/widgets/IconLabel.h +++ b/launcher/ui/widgets/IconLabel.h @@ -1,26 +1,25 @@ #pragma once -#include #include +#include class QStyleOption; /** * This is a trivial widget that paints a QIcon of the specified size. */ -class IconLabel : public QWidget -{ +class IconLabel : public QWidget { Q_OBJECT -public: + public: /// Create a line separator. orientation is the orientation of the line. - explicit IconLabel(QWidget *parent, QIcon icon, QSize size); + explicit IconLabel(QWidget* parent, QIcon icon, QSize size); virtual QSize sizeHint() const; - virtual void paintEvent(QPaintEvent *); + virtual void paintEvent(QPaintEvent*); void setIcon(QIcon icon); -private: + private: QSize m_size; QIcon m_icon; }; diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index d77e0fa00..42279a663 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -1,20 +1,20 @@ #include "JavaSettingsWidget.h" -#include +#include #include -#include #include #include #include +#include #include -#include +#include #include +#include "FileSystem.h" #include "JavaCommon.h" #include "java/JavaInstall.h" #include "java/JavaUtils.h" -#include "FileSystem.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/widgets/VersionSelectWidget.h" @@ -150,40 +150,30 @@ void JavaSettingsWidget::refresh() JavaSettingsWidget::ValidationStatus JavaSettingsWidget::validate() { - switch(javaStatus) - { + switch (javaStatus) { default: case JavaStatus::NotSet: case JavaStatus::DoesNotExist: case JavaStatus::DoesNotStart: - case JavaStatus::ReturnedInvalidData: - { - int button = CustomMessageBox::selectable( - this, - tr("No Java version selected"), - tr("You didn't select a Java version or selected something that doesn't work.\n" - "%1 will not be able to start Minecraft.\n" - "Do you wish to proceed without any Java?" - "\n\n" - "You can change the Java version in the settings later.\n" - ).arg(BuildConfig.LAUNCHER_DISPLAYNAME), - QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::No, - QMessageBox::NoButton - )->exec(); - if(button == QMessageBox::No) - { + case JavaStatus::ReturnedInvalidData: { + int button = CustomMessageBox::selectable(this, tr("No Java version selected"), + tr("You didn't select a Java version or selected something that doesn't work.\n" + "%1 will not be able to start Minecraft.\n" + "Do you wish to proceed without any Java?" + "\n\n" + "You can change the Java version in the settings later.\n") + .arg(BuildConfig.LAUNCHER_DISPLAYNAME), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton) + ->exec(); + if (button == QMessageBox::No) { return ValidationStatus::Bad; } return ValidationStatus::JavaBad; - } - break; - case JavaStatus::Pending: - { + } break; + case JavaStatus::Pending: { return ValidationStatus::Bad; } - case JavaStatus::Good: - { + case JavaStatus::Good: { return ValidationStatus::AllOK; } } @@ -220,34 +210,26 @@ void JavaSettingsWidget::memoryValueChanged(int) unsigned int min = m_minMemSpinBox->value(); unsigned int max = m_maxMemSpinBox->value(); unsigned int permgen = m_permGenSpinBox->value(); - QObject *obj = sender(); - if (obj == m_minMemSpinBox && min != observedMinMemory) - { + QObject* obj = sender(); + if (obj == m_minMemSpinBox && min != observedMinMemory) { observedMinMemory = min; actuallyChanged = true; - if (min > max) - { + if (min > max) { observedMaxMemory = min; m_maxMemSpinBox->setValue(min); } - } - else if (obj == m_maxMemSpinBox && max != observedMaxMemory) - { + } else if (obj == m_maxMemSpinBox && max != observedMaxMemory) { observedMaxMemory = max; actuallyChanged = true; - if (min > max) - { + if (min > max) { observedMinMemory = max; m_minMemSpinBox->setValue(max); } - } - else if (obj == m_permGenSpinBox && permgen != observedPermGenMemory) - { + } else if (obj == m_permGenSpinBox && permgen != observedPermGenMemory) { observedPermGenMemory = permgen; actuallyChanged = true; } - if(actuallyChanged) - { + if (actuallyChanged) { checkJavaPathOnEdit(m_javaPathTextBox->text()); updateThresholds(); } @@ -256,8 +238,7 @@ void JavaSettingsWidget::memoryValueChanged(int) void JavaSettingsWidget::javaVersionSelected(BaseVersion::Ptr version) { auto java = std::dynamic_pointer_cast(version); - if(!java) - { + if (!java) { return; } auto visible = java->id.requiresPermGen(); @@ -276,8 +257,7 @@ void JavaSettingsWidget::on_javaBrowseBtn_clicked() filter = "Java (java)"; #endif QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"), QString(), filter); - if(raw_path.isEmpty()) - { + if (raw_path.isEmpty()) { return; } QString cooked_path = FS::NormalizePath(raw_path); @@ -289,8 +269,7 @@ void JavaSettingsWidget::on_javaStatusBtn_clicked() { QString text; bool failed = false; - switch(javaStatus) - { + switch (javaStatus) { case JavaStatus::NotSet: checkJavaPath(m_javaPathTextBox->text()); return; @@ -298,24 +277,20 @@ void JavaSettingsWidget::on_javaStatusBtn_clicked() text += QObject::tr("The specified file either doesn't exist or is not a proper executable."); failed = true; break; - case JavaStatus::DoesNotStart: - { + case JavaStatus::DoesNotStart: { text += QObject::tr("The specified Java binary didn't start properly.
"); auto htmlError = m_result.errorLog; - if(!htmlError.isEmpty()) - { + if (!htmlError.isEmpty()) { htmlError.replace('\n', "
"); text += QString("%1").arg(htmlError); } failed = true; break; } - case JavaStatus::ReturnedInvalidData: - { + case JavaStatus::ReturnedInvalidData: { text += QObject::tr("The specified Java binary returned unexpected results:
"); auto htmlOut = m_result.outLog; - if(!htmlOut.isEmpty()) - { + if (!htmlOut.isEmpty()) { htmlOut.replace('\n', "
"); text += QString("%1").arg(htmlOut); } @@ -323,26 +298,24 @@ void JavaSettingsWidget::on_javaStatusBtn_clicked() break; } case JavaStatus::Good: - text += QObject::tr("Java test succeeded!
Platform reported: %1
Java version " - "reported: %2
").arg(m_result.realPlatform, m_result.javaVersion.toString()); + text += QObject::tr( + "Java test succeeded!
Platform reported: %1
Java version " + "reported: %2
") + .arg(m_result.realPlatform, m_result.javaVersion.toString()); break; case JavaStatus::Pending: // TODO: abort here? return; } - CustomMessageBox::selectable( - this, - failed ? QObject::tr("Java test failure") : QObject::tr("Java test success"), - text, - failed ? QMessageBox::Critical : QMessageBox::Information - )->show(); + CustomMessageBox::selectable(this, failed ? QObject::tr("Java test failure") : QObject::tr("Java test success"), text, + failed ? QMessageBox::Critical : QMessageBox::Information) + ->show(); } void JavaSettingsWidget::setJavaStatus(JavaSettingsWidget::JavaStatus status) { javaStatus = status; - switch(javaStatus) - { + switch (javaStatus) { case JavaStatus::Good: m_javaStatusBtn->setIcon(goodIcon); break; @@ -365,29 +338,23 @@ void JavaSettingsWidget::checkJavaPathOnEdit(const QString& path) { auto realPath = FS::ResolveExecutable(path); QFileInfo pathInfo(realPath); - if (pathInfo.baseName().toLower().contains("java")) - { + if (pathInfo.baseName().toLower().contains("java")) { checkJavaPath(path); - } - else - { - if(!m_checker) - { + } else { + if (!m_checker) { setJavaStatus(JavaStatus::NotSet); } } } -void JavaSettingsWidget::checkJavaPath(const QString &path) +void JavaSettingsWidget::checkJavaPath(const QString& path) { - if(m_checker) - { + if (m_checker) { queuedCheck = path; return; } auto realPath = FS::ResolveExecutable(path); - if(realPath.isNull()) - { + if (realPath.isNull()) { setJavaStatus(JavaStatus::DoesNotExist); return; } @@ -396,8 +363,7 @@ void JavaSettingsWidget::checkJavaPath(const QString &path) m_checker->m_path = path; m_checker->m_minMem = m_minMemSpinBox->value(); m_checker->m_maxMem = m_maxMemSpinBox->value(); - if(m_permGenSpinBox->isVisible()) - { + if (m_permGenSpinBox->isVisible()) { m_checker->m_permGen = m_permGenSpinBox->value(); } connect(m_checker.get(), &JavaChecker::checkFinished, this, &JavaSettingsWidget::checkFinished); @@ -407,27 +373,22 @@ void JavaSettingsWidget::checkJavaPath(const QString &path) void JavaSettingsWidget::checkFinished(JavaCheckResult result) { m_result = result; - switch(result.validity) - { - case JavaCheckResult::Validity::Valid: - { + switch (result.validity) { + case JavaCheckResult::Validity::Valid: { setJavaStatus(JavaStatus::Good); break; } - case JavaCheckResult::Validity::ReturnedInvalidData: - { + case JavaCheckResult::Validity::ReturnedInvalidData: { setJavaStatus(JavaStatus::ReturnedInvalidData); break; } - case JavaCheckResult::Validity::Errored: - { + case JavaCheckResult::Validity::Errored: { setJavaStatus(JavaStatus::DoesNotStart); break; } } m_checker.reset(); - if(!queuedCheck.isNull()) - { + if (!queuedCheck.isNull()) { checkJavaPath(queuedCheck); queuedCheck.clear(); } diff --git a/launcher/ui/widgets/JavaSettingsWidget.h b/launcher/ui/widgets/JavaSettingsWidget.h index e4b7c7129..6ea73da60 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.h +++ b/launcher/ui/widgets/JavaSettingsWidget.h @@ -1,9 +1,9 @@ #pragma once #include -#include #include #include +#include #include class QLineEdit; @@ -20,30 +20,16 @@ class QToolButton; /** * This is a widget for all the Java settings dialogs and pages. */ -class JavaSettingsWidget : public QWidget -{ +class JavaSettingsWidget : public QWidget { Q_OBJECT -public: - explicit JavaSettingsWidget(QWidget *parent); - virtual ~JavaSettingsWidget() {}; + public: + explicit JavaSettingsWidget(QWidget* parent); + virtual ~JavaSettingsWidget(){}; - enum class JavaStatus - { - NotSet, - Pending, - Good, - DoesNotExist, - DoesNotStart, - ReturnedInvalidData - } javaStatus = JavaStatus::NotSet; + enum class JavaStatus { NotSet, Pending, Good, DoesNotExist, DoesNotStart, ReturnedInvalidData } javaStatus = JavaStatus::NotSet; - enum class ValidationStatus - { - Bad, - JavaBad, - AllOK - }; + enum class ValidationStatus { Bad, JavaBad, AllOK }; void refresh(); void initialize(); @@ -58,39 +44,38 @@ public: void updateThresholds(); - -protected slots: + protected slots: void memoryValueChanged(int); - void javaPathEdited(const QString &path); + void javaPathEdited(const QString& path); void javaVersionSelected(BaseVersion::Ptr version); void on_javaBrowseBtn_clicked(); void on_javaStatusBtn_clicked(); void checkFinished(JavaCheckResult result); -protected: /* methods */ - void checkJavaPathOnEdit(const QString &path); - void checkJavaPath(const QString &path); + protected: /* methods */ + void checkJavaPathOnEdit(const QString& path); + void checkJavaPath(const QString& path); void setJavaStatus(JavaStatus status); void setupUi(); -private: /* data */ - VersionSelectWidget *m_versionWidget = nullptr; - QVBoxLayout *m_verticalLayout = nullptr; + private: /* data */ + VersionSelectWidget* m_versionWidget = nullptr; + QVBoxLayout* m_verticalLayout = nullptr; - QLineEdit * m_javaPathTextBox = nullptr; - QPushButton * m_javaBrowseBtn = nullptr; - QToolButton * m_javaStatusBtn = nullptr; - QHBoxLayout *m_horizontalLayout = nullptr; + QLineEdit* m_javaPathTextBox = nullptr; + QPushButton* m_javaBrowseBtn = nullptr; + QToolButton* m_javaStatusBtn = nullptr; + QHBoxLayout* m_horizontalLayout = nullptr; - QGroupBox *m_memoryGroupBox = nullptr; - QGridLayout *m_gridLayout_2 = nullptr; - QSpinBox *m_maxMemSpinBox = nullptr; - QLabel *m_labelMinMem = nullptr; - QLabel *m_labelMaxMem = nullptr; - QLabel *m_labelMaxMemIcon = nullptr; - QSpinBox *m_minMemSpinBox = nullptr; - QLabel *m_labelPermGen = nullptr; - QSpinBox *m_permGenSpinBox = nullptr; + QGroupBox* m_memoryGroupBox = nullptr; + QGridLayout* m_gridLayout_2 = nullptr; + QSpinBox* m_maxMemSpinBox = nullptr; + QLabel* m_labelMinMem = nullptr; + QLabel* m_labelMaxMem = nullptr; + QLabel* m_labelMaxMemIcon = nullptr; + QSpinBox* m_minMemSpinBox = nullptr; + QLabel* m_labelPermGen = nullptr; + QSpinBox* m_permGenSpinBox = nullptr; QIcon goodIcon; QIcon yellowIcon; QIcon badIcon; diff --git a/launcher/ui/widgets/LabeledToolButton.cpp b/launcher/ui/widgets/LabeledToolButton.cpp index f52e49c98..7af48b0c9 100644 --- a/launcher/ui/widgets/LabeledToolButton.cpp +++ b/launcher/ui/widgets/LabeledToolButton.cpp @@ -33,31 +33,29 @@ * limitations under the License. */ -#include -#include -#include -#include #include "LabeledToolButton.h" #include #include +#include +#include +#include +#include /* - * + * * Tool Button with a label on it, instead of the normal text rendering - * + * */ -LabeledToolButton::LabeledToolButton(QWidget * parent) - : QToolButton(parent) - , m_label(new QLabel(this)) +LabeledToolButton::LabeledToolButton(QWidget* parent) : QToolButton(parent), m_label(new QLabel(this)) { - //QToolButton::setText(" "); + // QToolButton::setText(" "); m_label->setWordWrap(true); m_label->setMouseTracking(false); m_label->setAlignment(Qt::AlignCenter); m_label->setTextInteractionFlags(Qt::NoTextInteraction); // somehow, this makes word wrap work in the QLabel. yay. - //m_label->setMinimumWidth(100); + // m_label->setMinimumWidth(100); } QString LabeledToolButton::text() const @@ -65,7 +63,7 @@ QString LabeledToolButton::text() const return m_label->text(); } -void LabeledToolButton::setText(const QString & text) +void LabeledToolButton::setText(const QString& text) { m_label->setText(text); } @@ -76,7 +74,6 @@ void LabeledToolButton::setIcon(QIcon icon) resetIcon(); } - /*! \reimp */ @@ -92,24 +89,21 @@ QSize LabeledToolButton::sizeHint() const int w = 0, h = 0; QStyleOptionToolButton opt; initStyleOption(&opt); - QSize sz =m_label->sizeHint(); + QSize sz = m_label->sizeHint(); w = sz.width(); h = sz.height(); - opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height + opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height if (popupMode() == MenuButtonPopup) w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this); - + return style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this); } - - -void LabeledToolButton::resizeEvent(QResizeEvent * event) +void LabeledToolButton::resizeEvent(QResizeEvent* event) { - m_label->setGeometry(QRect(4, 4, width()-8, height()-8)); - if(!m_icon.isNull()) - { + m_label->setGeometry(QRect(4, 4, width() - 8, height() - 8)); + if (!m_icon.isNull()) { resetIcon(); } QWidget::resizeEvent(event); @@ -120,14 +114,14 @@ void LabeledToolButton::resetIcon() auto iconSz = m_icon.actualSize(QSize(160, 80)); float w = iconSz.width(); float h = iconSz.height(); - float ar = w/h; + float ar = w / h; // FIXME: hardcoded max size of 160x80 int newW = 80 * ar; - if(newW > 160) + if (newW > 160) newW = 160; - QSize newSz (newW, 80); + QSize newSz(newW, 80); auto pixmap = m_icon.pixmap(newSz); m_label->setPixmap(pixmap); m_label->setMinimumHeight(80); - m_label->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred ); + m_label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); } diff --git a/launcher/ui/widgets/LabeledToolButton.h b/launcher/ui/widgets/LabeledToolButton.h index 51f99e9ba..0bb5e28de 100644 --- a/launcher/ui/widgets/LabeledToolButton.h +++ b/launcher/ui/widgets/LabeledToolButton.h @@ -20,21 +20,21 @@ class QLabel; -class LabeledToolButton : public QToolButton -{ +class LabeledToolButton : public QToolButton { Q_OBJECT - QLabel * m_label; + QLabel* m_label; QIcon m_icon; -public: - LabeledToolButton(QWidget * parent = 0); + public: + LabeledToolButton(QWidget* parent = 0); QString text() const; - void setText(const QString & text); + void setText(const QString& text); void setIcon(QIcon icon); virtual QSize sizeHint() const; -protected: - void resizeEvent(QResizeEvent * event); + + protected: + void resizeEvent(QResizeEvent* event); void resetIcon(); }; diff --git a/launcher/ui/widgets/LineSeparator.cpp b/launcher/ui/widgets/LineSeparator.cpp index d03e67623..2d6239a2f 100644 --- a/launcher/ui/widgets/LineSeparator.cpp +++ b/launcher/ui/widgets/LineSeparator.cpp @@ -1,11 +1,11 @@ #include "LineSeparator.h" -#include -#include #include #include +#include +#include -void LineSeparator::initStyleOption(QStyleOption *option) const +void LineSeparator::initStyleOption(QStyleOption* option) const { option->initFrom(this); // in a horizontal layout, the line is vertical (and vice versa) @@ -13,8 +13,7 @@ void LineSeparator::initStyleOption(QStyleOption *option) const option->state |= QStyle::State_Horizontal; } -LineSeparator::LineSeparator(QWidget *parent, Qt::Orientation orientation) - : QWidget(parent), m_orientation(orientation) +LineSeparator::LineSeparator(QWidget* parent, Qt::Orientation orientation) : QWidget(parent), m_orientation(orientation) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); } @@ -23,12 +22,11 @@ QSize LineSeparator::sizeHint() const { QStyleOption opt; initStyleOption(&opt); - const int extent = - style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, &opt, parentWidget()); + const int extent = style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, &opt, parentWidget()); return QSize(extent, extent); } -void LineSeparator::paintEvent(QPaintEvent *) +void LineSeparator::paintEvent(QPaintEvent*) { QPainter p(this); QStyleOption opt; diff --git a/launcher/ui/widgets/LineSeparator.h b/launcher/ui/widgets/LineSeparator.h index 22927b68d..719facb99 100644 --- a/launcher/ui/widgets/LineSeparator.h +++ b/launcher/ui/widgets/LineSeparator.h @@ -3,16 +3,16 @@ class QStyleOption; -class LineSeparator : public QWidget -{ +class LineSeparator : public QWidget { Q_OBJECT -public: + public: /// Create a line separator. orientation is the orientation of the line. - explicit LineSeparator(QWidget *parent, Qt::Orientation orientation = Qt::Horizontal); + explicit LineSeparator(QWidget* parent, Qt::Orientation orientation = Qt::Horizontal); QSize sizeHint() const; - void paintEvent(QPaintEvent *); - void initStyleOption(QStyleOption *option) const; -private: + void paintEvent(QPaintEvent*); + void initStyleOption(QStyleOption* option) const; + + private: Qt::Orientation m_orientation = Qt::Horizontal; }; diff --git a/launcher/ui/widgets/LogView.cpp b/launcher/ui/widgets/LogView.cpp index 9c46438d6..8c960ebb1 100644 --- a/launcher/ui/widgets/LogView.cpp +++ b/launcher/ui/widgets/LogView.cpp @@ -34,8 +34,8 @@ */ #include "LogView.h" -#include #include +#include LogView::LogView(QWidget* parent) : QPlainTextEdit(parent) { @@ -50,13 +50,10 @@ LogView::~LogView() void LogView::setWordWrap(bool wrapping) { - if(wrapping) - { + if (wrapping) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setLineWrapMode(QPlainTextEdit::WidgetWidth); - } - else - { + } else { setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setLineWrapMode(QPlainTextEdit::NoWrap); } @@ -64,16 +61,14 @@ void LogView::setWordWrap(bool wrapping) void LogView::setModel(QAbstractItemModel* model) { - if(m_model) - { + if (m_model) { disconnect(m_model, &QAbstractItemModel::modelReset, this, &LogView::repopulate); disconnect(m_model, &QAbstractItemModel::rowsInserted, this, &LogView::rowsInserted); disconnect(m_model, &QAbstractItemModel::rowsAboutToBeInserted, this, &LogView::rowsAboutToBeInserted); disconnect(m_model, &QAbstractItemModel::rowsRemoved, this, &LogView::rowsRemoved); } m_model = model; - if(m_model) - { + if (m_model) { connect(m_model, &QAbstractItemModel::modelReset, this, &LogView::repopulate); connect(m_model, &QAbstractItemModel::rowsInserted, this, &LogView::rowsInserted); connect(m_model, &QAbstractItemModel::rowsAboutToBeInserted, this, &LogView::rowsAboutToBeInserted); @@ -83,15 +78,14 @@ void LogView::setModel(QAbstractItemModel* model) repopulate(); } -QAbstractItemModel * LogView::model() const +QAbstractItemModel* LogView::model() const { return m_model; } void LogView::modelDestroyed(QObject* model) { - if(m_model == model) - { + if (m_model == model) { setModel(nullptr); } } @@ -100,8 +94,7 @@ void LogView::repopulate() { auto doc = document(); doc->clear(); - if(!m_model) - { + if (!m_model) { return; } rowsInserted(QModelIndex(), 0, m_model->rowCount() - 1); @@ -112,39 +105,32 @@ void LogView::rowsAboutToBeInserted(const QModelIndex& parent, int first, int la Q_UNUSED(parent) Q_UNUSED(first) Q_UNUSED(last) - QScrollBar *bar = verticalScrollBar(); + QScrollBar* bar = verticalScrollBar(); int max_bar = bar->maximum(); int val_bar = bar->value(); - if (m_scroll) - { + if (m_scroll) { m_scroll = (max_bar - val_bar) <= 1; - } - else - { + } else { m_scroll = val_bar == max_bar; } } void LogView::rowsInserted(const QModelIndex& parent, int first, int last) { - for(int i = first; i <= last; i++) - { + for (int i = first; i <= last; i++) { auto idx = m_model->index(i, 0, parent); auto text = m_model->data(idx, Qt::DisplayRole).toString(); QTextCharFormat format(*m_defaultFormat); auto font = m_model->data(idx, Qt::FontRole); - if(font.isValid()) - { + if (font.isValid()) { format.setFont(font.value()); } auto fg = m_model->data(idx, Qt::ForegroundRole); - if(fg.isValid()) - { + if (fg.isValid()) { format.setForeground(fg.value()); } auto bg = m_model->data(idx, Qt::BackgroundRole); - if(bg.isValid()) - { + if (bg.isValid()) { format.setBackground(bg.value()); } auto workCursor = textCursor(); @@ -152,10 +138,9 @@ void LogView::rowsInserted(const QModelIndex& parent, int first, int last) workCursor.insertText(text, format); workCursor.insertBlock(); } - if(m_scroll && !m_scrolling) - { + if (m_scroll && !m_scrolling) { m_scrolling = true; - QMetaObject::invokeMethod( this, "scrollToBottom", Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "scrollToBottom", Qt::QueuedConnection); } } diff --git a/launcher/ui/widgets/LogView.h b/launcher/ui/widgets/LogView.h index 3143360aa..dde5f8f76 100644 --- a/launcher/ui/widgets/LogView.h +++ b/launcher/ui/widgets/LogView.h @@ -1,36 +1,35 @@ #pragma once -#include #include +#include class QAbstractItemModel; -class LogView: public QPlainTextEdit -{ +class LogView : public QPlainTextEdit { Q_OBJECT -public: - explicit LogView(QWidget *parent = nullptr); + public: + explicit LogView(QWidget* parent = nullptr); virtual ~LogView(); - virtual void setModel(QAbstractItemModel *model); - QAbstractItemModel *model() const; + virtual void setModel(QAbstractItemModel* model); + QAbstractItemModel* model() const; -public slots: + public slots: void setWordWrap(bool wrapping); - void findNext(const QString & what, bool reverse); + void findNext(const QString& what, bool reverse); void scrollToBottom(); -protected slots: + protected slots: void repopulate(); // note: this supports only appending - void rowsInserted(const QModelIndex &parent, int first, int last); - void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last); + void rowsInserted(const QModelIndex& parent, int first, int last); + void rowsAboutToBeInserted(const QModelIndex& parent, int first, int last); // note: this supports only removing from front - void rowsRemoved(const QModelIndex &parent, int first, int last); - void modelDestroyed(QObject * model); + void rowsRemoved(const QModelIndex& parent, int first, int last); + void modelDestroyed(QObject* model); -protected: - QAbstractItemModel *m_model = nullptr; - QTextCharFormat *m_defaultFormat = nullptr; + protected: + QAbstractItemModel* m_model = nullptr; + QTextCharFormat* m_defaultFormat = nullptr; bool m_scroll = false; bool m_scrolling = false; }; diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index ea052c41a..c2c099eeb 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -18,9 +18,8 @@ unique_qobject_ptr ModFilterWidget::create(Version default_vers auto task = filter_widget->versionList()->getLoadTask(); - connect(task.get(), &Task::failed, [filter_widget]{ - filter_widget->disableVersionButton(VersionButtonID::Major, tr("failed to get version index")); - }); + connect(task.get(), &Task::failed, + [filter_widget] { filter_widget->disableVersionButton(VersionButtonID::Major, tr("failed to get version index")); }); connect(task.get(), &Task::finished, &load_version_list_loop, &QEventLoop::quit); if (!task->isRunning()) @@ -34,16 +33,15 @@ unique_qobject_ptr ModFilterWidget::create(Version default_vers return unique_qobject_ptr(filter_widget); } -ModFilterWidget::ModFilterWidget(Version def, QWidget* parent) - : QTabWidget(parent), m_filter(new Filter()), ui(new Ui::ModFilterWidget) +ModFilterWidget::ModFilterWidget(Version def, QWidget* parent) : QTabWidget(parent), m_filter(new Filter()), ui(new Ui::ModFilterWidget) { ui->setupUi(this); - m_mcVersion_buttons.addButton(ui->strictVersionButton, VersionButtonID::Strict); + m_mcVersion_buttons.addButton(ui->strictVersionButton, VersionButtonID::Strict); ui->strictVersionButton->click(); - m_mcVersion_buttons.addButton(ui->majorVersionButton, VersionButtonID::Major); - m_mcVersion_buttons.addButton(ui->allVersionsButton, VersionButtonID::All); - //m_mcVersion_buttons.addButton(ui->betweenVersionsButton, VersionButtonID::Between); + m_mcVersion_buttons.addButton(ui->majorVersionButton, VersionButtonID::Major); + m_mcVersion_buttons.addButton(ui->allVersionsButton, VersionButtonID::All); + // m_mcVersion_buttons.addButton(ui->betweenVersionsButton, VersionButtonID::Between); connect(&m_mcVersion_buttons, SIGNAL(idClicked(int)), this, SLOT(onVersionFilterChanged(int))); @@ -57,25 +55,19 @@ void ModFilterWidget::setInstance(MinecraftInstance* instance) { m_instance = instance; - ui->strictVersionButton->setText( - tr("Strict match (= %1)").arg(mcVersionStr())); + ui->strictVersionButton->setText(tr("Strict match (= %1)").arg(mcVersionStr())); // we can't do this for snapshots sadly - if(mcVersionStr().contains('.')) - { + if (mcVersionStr().contains('.')) { auto mcVersionSplit = mcVersionStr().split("."); - ui->majorVersionButton->setText( - tr("Major version match (= %1.%2.x)").arg(mcVersionSplit[0], mcVersionSplit[1])); - } - else - { + ui->majorVersionButton->setText(tr("Major version match (= %1.%2.x)").arg(mcVersionSplit[0], mcVersionSplit[1])); + } else { ui->majorVersionButton->setText(tr("Major version match (unsupported)")); disableVersionButton(Major); } - ui->allVersionsButton->setText( - tr("Any version")); - //ui->betweenVersionsButton->setText( - // tr("Between two versions")); + ui->allVersionsButton->setText(tr("Any version")); + // ui->betweenVersionsButton->setText( + // tr("Between two versions")); } auto ModFilterWidget::getFilter() -> std::shared_ptr @@ -89,19 +81,19 @@ void ModFilterWidget::disableVersionButton(VersionButtonID id, QString reason) { QAbstractButton* btn = nullptr; - switch(id){ - case(VersionButtonID::Strict): - btn = ui->strictVersionButton; - break; - case(VersionButtonID::Major): - btn = ui->majorVersionButton; - break; - case(VersionButtonID::All): - btn = ui->allVersionsButton; - break; - case(VersionButtonID::Between): - default: - break; + switch (id) { + case (VersionButtonID::Strict): + btn = ui->strictVersionButton; + break; + case (VersionButtonID::Major): + btn = ui->majorVersionButton; + break; + case (VersionButtonID::All): + btn = ui->allVersionsButton; + break; + case (VersionButtonID::Between): + default: + break; } if (btn) { @@ -113,12 +105,12 @@ void ModFilterWidget::disableVersionButton(VersionButtonID id, QString reason) void ModFilterWidget::onVersionFilterChanged(int id) { - //ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between); - //ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between); + // ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between); + // ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between); int index = 1; - auto cast_id = (VersionButtonID) id; + auto cast_id = (VersionButtonID)id; if (cast_id != m_version_id) { m_version_id = cast_id; } else { @@ -127,32 +119,32 @@ void ModFilterWidget::onVersionFilterChanged(int id) m_filter->versions.clear(); - switch(cast_id){ - case(VersionButtonID::Strict): - m_filter->versions.push_front(mcVersion()); - break; - case(VersionButtonID::Major): { - auto versionSplit = mcVersionStr().split("."); + switch (cast_id) { + case (VersionButtonID::Strict): + m_filter->versions.push_front(mcVersion()); + break; + case (VersionButtonID::Major): { + auto versionSplit = mcVersionStr().split("."); - auto major_version = QString("%1.%2").arg(versionSplit[0], versionSplit[1]); - QString version_str = major_version; + auto major_version = QString("%1.%2").arg(versionSplit[0], versionSplit[1]); + QString version_str = major_version; - while (m_version_list->hasVersion(version_str)) { - m_filter->versions.emplace_back(version_str); - version_str = QString("%1.%2").arg(major_version, QString::number(index++)); + while (m_version_list->hasVersion(version_str)) { + m_filter->versions.emplace_back(version_str); + version_str = QString("%1.%2").arg(major_version, QString::number(index++)); + } + + break; } - - break; - } - case(VersionButtonID::All): - // Empty list to avoid enumerating all versions :P - break; - case(VersionButtonID::Between): - // TODO - break; + case (VersionButtonID::All): + // Empty list to avoid enumerating all versions :P + break; + case (VersionButtonID::Between): + // TODO + break; } - if(changed()) + if (changed()) emit filterChanged(); else emit filterUnchanged(); diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index 706ffd21a..ed6cd0ea7 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "Version.h" @@ -17,16 +17,10 @@ namespace Ui { class ModFilterWidget; } -class ModFilterWidget : public QTabWidget -{ +class ModFilterWidget : public QTabWidget { Q_OBJECT -public: - enum VersionButtonID { - Strict = 0, - Major = 1, - All = 2, - Between = 3 - }; + public: + enum VersionButtonID { Strict = 0, Major = 1, All = 2, Between = 3 }; struct Filter { std::list versions; @@ -37,7 +31,7 @@ public: std::shared_ptr m_filter; -public: + public: static unique_qobject_ptr create(Version default_version, QWidget* parent = nullptr); ~ModFilterWidget(); @@ -51,26 +45,29 @@ public: Meta::VersionList::Ptr versionList() { return m_version_list; } -private: + private: ModFilterWidget(Version def, QWidget* parent = nullptr); - inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; } + inline auto mcVersionStr() const -> QString + { + return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; + } inline auto mcVersion() const -> Version { return { mcVersionStr() }; } -private slots: + private slots: void onVersionFilterChanged(int id); -public: signals: + public: + signals: void filterChanged(); void filterUnchanged(); -private: + private: Ui::ModFilterWidget* ui; MinecraftInstance* m_instance = nullptr; - -/* Version stuff */ + /* Version stuff */ QButtonGroup m_mcVersion_buttons; Meta::VersionList::Ptr m_version_list; diff --git a/launcher/ui/widgets/ModListView.cpp b/launcher/ui/widgets/ModListView.cpp index 80a918b64..c72d4c522 100644 --- a/launcher/ui/widgets/ModListView.cpp +++ b/launcher/ui/widgets/ModListView.cpp @@ -14,61 +14,55 @@ */ #include "ModListView.h" +#include #include #include #include -#include #include -ModListView::ModListView ( QWidget* parent ) - :QTreeView ( parent ) +ModListView::ModListView(QWidget* parent) : QTreeView(parent) { - setAllColumnsShowFocus ( true ); - setExpandsOnDoubleClick ( false ); - setRootIsDecorated ( false ); - setSortingEnabled ( true ); - setAlternatingRowColors ( true ); - setSelectionMode ( QAbstractItemView::ExtendedSelection ); - setHeaderHidden ( false ); + setAllColumnsShowFocus(true); + setExpandsOnDoubleClick(false); + setRootIsDecorated(false); + setSortingEnabled(true); + setAlternatingRowColors(true); + setSelectionMode(QAbstractItemView::ExtendedSelection); + setHeaderHidden(false); setSelectionBehavior(QAbstractItemView::SelectRows); - setHorizontalScrollBarPolicy ( Qt::ScrollBarAsNeeded ); + setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setDropIndicatorShown(true); setDragEnabled(true); setDragDropMode(QAbstractItemView::DropOnly); viewport()->setAcceptDrops(true); } -void ModListView::setModel ( QAbstractItemModel* model ) +void ModListView::setModel(QAbstractItemModel* model) { - QTreeView::setModel ( model ); + QTreeView::setModel(model); auto head = header(); head->setStretchLastSection(false); // HACK: this is true for the checkbox column of mod lists - auto string = model->headerData(0,head->orientation()).toString(); - if(head->count() < 1) - { + auto string = model->headerData(0, head->orientation()).toString(); + if (head->count() < 1) { return; } - if(!string.size()) - { + if (!string.size()) { head->setSectionResizeMode(0, QHeaderView::ResizeToContents); head->setSectionResizeMode(1, QHeaderView::Stretch); - for(int i = 2; i < head->count(); i++) + for (int i = 2; i < head->count(); i++) head->setSectionResizeMode(i, QHeaderView::ResizeToContents); - } - else - { + } else { head->setSectionResizeMode(0, QHeaderView::Stretch); - for(int i = 1; i < head->count(); i++) + for (int i = 1; i < head->count(); i++) head->setSectionResizeMode(i, QHeaderView::ResizeToContents); } } -void ModListView::setResizeModes(const QList &modes) +void ModListView::setResizeModes(const QList& modes) { auto head = header(); - for(int i = 0; i < modes.count(); i++) { + for (int i = 0; i < modes.count(); i++) { head->setSectionResizeMode(i, modes[i]); } } - diff --git a/launcher/ui/widgets/ModListView.h b/launcher/ui/widgets/ModListView.h index 3f0b3b0e1..86316459f 100644 --- a/launcher/ui/widgets/ModListView.h +++ b/launcher/ui/widgets/ModListView.h @@ -17,11 +17,10 @@ #include #include -class ModListView: public QTreeView -{ +class ModListView : public QTreeView { Q_OBJECT -public: - explicit ModListView ( QWidget* parent = 0 ); - virtual void setModel ( QAbstractItemModel* model ); - virtual void setResizeModes (const QList& modes); + public: + explicit ModListView(QWidget* parent = 0); + virtual void setModel(QAbstractItemModel* model); + virtual void setResizeModes(const QList& modes); }; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index dbbed36a7..514e1d25c 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -39,36 +39,33 @@ #include "BuildConfig.h" #include "PageContainer_p.h" -#include -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include "settings/SettingsObject.h" #include "ui/widgets/IconLabel.h" -#include "DesktopServices.h" #include "Application.h" +#include "DesktopServices.h" -class PageEntryFilterModel : public QSortFilterProxyModel -{ -public: - explicit PageEntryFilterModel(QObject *parent = 0) : QSortFilterProxyModel(parent) - { - } +class PageEntryFilterModel : public QSortFilterProxyModel { + public: + explicit PageEntryFilterModel(QObject* parent = 0) : QSortFilterProxyModel(parent) {} -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { const QString pattern = filterRegularExpression().pattern(); - const auto model = static_cast(sourceModel()); + const auto model = static_cast(sourceModel()); const auto page = model->pages().at(sourceRow); if (!page->shouldDisplay()) return false; @@ -77,18 +74,15 @@ protected: } }; -PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId, - QWidget *parent) - : QWidget(parent) +PageContainer::PageContainer(BasePageProvider* pageProvider, QString defaultId, QWidget* parent) : QWidget(parent) { createUI(); m_model = new PageModel(this); m_proxyModel = new PageEntryFilterModel(this); int counter = 0; auto pages = pageProvider->getPages(); - for (auto page : pages) - { - auto widget = dynamic_cast(page); + for (auto page : pages) { + auto widget = dynamic_cast(page); widget->setParent(this); page->stackIndex = m_pageStack->addWidget(widget); page->listIndex = counter; @@ -109,8 +103,7 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId, m_pageList->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_pageList->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); m_pageList->setModel(m_proxyModel); - connect(m_pageList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), - this, SLOT(currentChanged(QModelIndex))); + connect(m_pageList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex))); m_pageStack->setStackingMode(QStackedLayout::StackOne); m_pageList->setFocus(); selectPage(defaultId); @@ -121,16 +114,13 @@ bool PageContainer::selectPage(QString pageId) // now find what we want to have selected... auto page = m_model->findPageEntryById(pageId); QModelIndex index; - if (page) - { + if (page) { index = m_proxyModel->mapFromSource(m_model->index(page->listIndex)); } - if(!index.isValid()) - { + if (!index.isValid()) { index = m_proxyModel->index(0, 0); } - if (index.isValid()) - { + if (index.isValid()) { m_pageList->setCurrentIndex(index); return true; } @@ -155,15 +145,11 @@ const QList& PageContainer::getPages() const void PageContainer::refreshContainer() { m_proxyModel->invalidate(); - if(!m_currentPage->shouldDisplay()) - { + if (!m_currentPage->shouldDisplay()) { auto index = m_proxyModel->index(0, 0); - if(index.isValid()) - { + if (index.isValid()) { m_pageList->setCurrentIndex(index); - } - else - { + } else { // FIXME: unhandled corner case: what to do when there's no page to select? } } @@ -183,7 +169,7 @@ void PageContainer::createUI() headerLabelFont.setPointSize(pointSize + 2); m_header->setFont(headerLabelFont); - QHBoxLayout *headerHLayout = new QHBoxLayout; + QHBoxLayout* headerHLayout = new QHBoxLayout; const int leftMargin = APPLICATION->style()->pixelMetric(QStyle::PM_LayoutLeftMargin); headerHLayout->addSpacerItem(new QSpacerItem(leftMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored)); headerHLayout->addWidget(m_header); @@ -201,7 +187,7 @@ void PageContainer::createUI() m_layout->addWidget(m_pageList, 0, 0, 2, 1); m_layout->addLayout(m_pageStack, 1, 1, 1, 1); m_layout->setColumnStretch(1, 4); - m_layout->setContentsMargins(0,0,0,6); + m_layout->setContentsMargins(0, 0, 0, 6); setLayout(m_layout); } @@ -214,39 +200,32 @@ void PageContainer::retranslate() page->retranslate(); } -void PageContainer::addButtons(QWidget *buttons) +void PageContainer::addButtons(QWidget* buttons) { m_layout->addWidget(buttons, 2, 0, 1, 2); } -void PageContainer::addButtons(QLayout *buttons) +void PageContainer::addButtons(QLayout* buttons) { m_layout->addLayout(buttons, 2, 0, 1, 2); } void PageContainer::showPage(int row) { - if (m_currentPage) - { + if (m_currentPage) { m_currentPage->closed(); } - if (row != -1) - { + if (row != -1) { m_currentPage = m_model->pages().at(row); - } - else - { + } else { m_currentPage = nullptr; } - if (m_currentPage) - { + if (m_currentPage) { m_pageStack->setCurrentIndex(m_currentPage->stackIndex); m_header->setText(m_currentPage->displayName()); m_iconHeader->setIcon(m_currentPage->icon()); m_currentPage->opened(); - } - else - { + } else { m_pageStack->setCurrentIndex(0); m_header->setText(QString()); m_iconHeader->setIcon(APPLICATION->getThemedIcon("bug")); @@ -255,8 +234,7 @@ void PageContainer::showPage(int row) void PageContainer::help() { - if (m_currentPage) - { + if (m_currentPage) { QString pageId = m_currentPage->helpPage(); if (pageId.isEmpty()) return; @@ -264,7 +242,7 @@ void PageContainer::help() } } -void PageContainer::currentChanged(const QModelIndex ¤t) +void PageContainer::currentChanged(const QModelIndex& current) { int selected_index = current.isValid() ? m_proxyModel->mapToSource(current).row() : -1; @@ -278,12 +256,10 @@ void PageContainer::currentChanged(const QModelIndex ¤t) bool PageContainer::prepareToClose() { - if(!saveAll()) - { + if (!saveAll()) { return false; } - if (m_currentPage) - { + if (m_currentPage) { m_currentPage->closed(); } return true; @@ -291,8 +267,7 @@ bool PageContainer::prepareToClose() bool PageContainer::saveAll() { - for (auto page : m_model->pages()) - { + for (auto page : m_model->pages()) { if (!page->apply()) return false; } diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index eac597232..05be1c3a5 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -36,11 +36,11 @@ #pragma once -#include #include +#include -#include "ui/pages/BasePageProvider.h" #include "ui/pages/BasePageContainer.h" +#include "ui/pages/BasePageProvider.h" class QLayout; class IconLabel; @@ -52,16 +52,14 @@ class QLineEdit; class QStackedLayout; class QGridLayout; -class PageContainer : public QWidget, public BasePageContainer -{ +class PageContainer : public QWidget, public BasePageContainer { Q_OBJECT -public: - explicit PageContainer(BasePageProvider *pageProvider, QString defaultId = QString(), - QWidget *parent = 0); + public: + explicit PageContainer(BasePageProvider* pageProvider, QString defaultId = QString(), QWidget* parent = 0); virtual ~PageContainer() {} - void addButtons(QWidget * buttons); - void addButtons(QLayout * buttons); + void addButtons(QWidget* buttons); + void addButtons(QLayout* buttons); /* * Save any unsaved state and prepare to be closed. * @return true if everything can be saved, false if there is something that requires attention @@ -72,8 +70,7 @@ public: /* request close - used by individual pages */ bool requestClose() override { - if(m_container) - { + if (m_container) { return m_container->requestClose(); } return false; @@ -85,36 +82,33 @@ public: const QList& getPages() const; void refreshContainer() override; - virtual void setParentContainer(BasePageContainer * container) - { - m_container = container; - }; + virtual void setParentContainer(BasePageContainer* container) { m_container = container; }; void changeEvent(QEvent*) override; -private: + private: void createUI(); void retranslate(); -public slots: + public slots: void help(); -signals: + signals: /** Emitted when the currently selected page is changed */ void selectedPageChanged(BasePage* previous, BasePage* selected); -private slots: - void currentChanged(const QModelIndex ¤t); + private slots: + void currentChanged(const QModelIndex& current); void showPage(int row); -private: - BasePageContainer * m_container = nullptr; - BasePage * m_currentPage = 0; - QSortFilterProxyModel *m_proxyModel; - PageModel *m_model; - QStackedLayout *m_pageStack; - QListView *m_pageList; - QLabel *m_header; - IconLabel *m_iconHeader; - QGridLayout *m_layout; + private: + BasePageContainer* m_container = nullptr; + BasePage* m_currentPage = 0; + QSortFilterProxyModel* m_proxyModel; + PageModel* m_model; + QStackedLayout* m_pageStack; + QListView* m_pageList; + QLabel* m_header; + IconLabel* m_iconHeader; + QGridLayout* m_layout; }; diff --git a/launcher/ui/widgets/PageContainer_p.h b/launcher/ui/widgets/PageContainer_p.h index 8bf26618f..e61f6e154 100644 --- a/launcher/ui/widgets/PageContainer_p.h +++ b/launcher/ui/widgets/PageContainer_p.h @@ -15,21 +15,18 @@ #pragma once -#include -#include #include +#include #include +#include class BasePage; const int pageIconSize = 24; -class PageViewDelegate : public QStyledItemDelegate -{ -public: - PageViewDelegate(QObject *parent) : QStyledItemDelegate(parent) - { - } - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +class PageViewDelegate : public QStyledItemDelegate { + public: + PageViewDelegate(QObject* parent) : QStyledItemDelegate(parent) {} + QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { QSize size = QStyledItemDelegate::sizeHint(option, index); size.setHeight(qMax(size.height(), 32)); @@ -37,10 +34,9 @@ public: } }; -class PageModel : public QAbstractListModel -{ -public: - PageModel(QObject *parent = 0) : QAbstractListModel(parent) +class PageModel : public QAbstractListModel { + public: + PageModel(QObject* parent = 0) : QAbstractListModel(parent) { QPixmap empty(pageIconSize, pageIconSize); empty.fill(Qt::transparent); @@ -48,57 +44,47 @@ public: } virtual ~PageModel() {} - int rowCount(const QModelIndex &parent = QModelIndex()) const + int rowCount(const QModelIndex& parent = QModelIndex()) const { return parent.isValid() ? 0 : m_pages.size(); } + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const { - return parent.isValid() ? 0 : m_pages.size(); - } - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const - { - switch (role) - { - case Qt::DisplayRole: - return m_pages.at(index.row())->displayName(); - case Qt::DecorationRole: - { - QIcon icon = m_pages.at(index.row())->icon(); - if (icon.isNull()) - icon = m_emptyIcon; - // HACK: fixes icon stretching on windows. TODO: report Qt bug for this - return QIcon(icon.pixmap(QSize(48,48))); - } + switch (role) { + case Qt::DisplayRole: + return m_pages.at(index.row())->displayName(); + case Qt::DecorationRole: { + QIcon icon = m_pages.at(index.row())->icon(); + if (icon.isNull()) + icon = m_emptyIcon; + // HACK: fixes icon stretching on windows. TODO: report Qt bug for this + return QIcon(icon.pixmap(QSize(48, 48))); + } } return QVariant(); } - void setPages(const QList &pages) + void setPages(const QList& pages) { beginResetModel(); m_pages = pages; endResetModel(); } - const QList &pages() const - { - return m_pages; - } + const QList& pages() const { return m_pages; } - BasePage * findPageEntryById(QString id) + BasePage* findPageEntryById(QString id) { - for(auto page: m_pages) - { + for (auto page : m_pages) { if (page->id() == id) return page; } return nullptr; } - QList m_pages; + QList m_pages; QIcon m_emptyIcon; }; -class PageView : public QListView -{ -public: - PageView(QWidget *parent = 0) : QListView(parent) +class PageView : public QListView { + public: + PageView(QWidget* parent = 0) : QListView(parent) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); setItemDelegate(new PageViewDelegate(this)); @@ -115,10 +101,9 @@ public: return QSize(width, 100); } - virtual bool eventFilter(QObject *obj, QEvent *event) + virtual bool eventFilter(QObject* obj, QEvent* event) { - if (obj == verticalScrollBar() && - (event->type() == QEvent::Show || event->type() == QEvent::Hide)) + if (obj == verticalScrollBar() && (event->type() == QEvent::Show || event->type() == QEvent::Hide)) updateGeometry(); return QListView::eventFilter(obj, event); } diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index 0085d6b2b..1481c1b6b 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -116,7 +116,6 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o } int description_x = rect.x(); - // Have the y-value be set based on the number of lines in the description, to centralize the // description text with the space between the base and the title. @@ -127,8 +126,8 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o description_y -= opt.fontMetrics.height(); // On the bottom, aligned to the left after the icon, and featuring at most two lines of text (with some margin space to spare) - painter->drawText(description_x, description_y, remaining_width, - cut_text.size() * opt.fontMetrics.height(), Qt::TextWordWrap, description); + painter->drawText(description_x, description_y, remaining_width, cut_text.size() * opt.fontMetrics.height(), Qt::TextWordWrap, + description); } painter->restore(); diff --git a/launcher/ui/widgets/ProjectItem.h b/launcher/ui/widgets/ProjectItem.h index 196055ea4..c3d0dce70 100644 --- a/launcher/ui/widgets/ProjectItem.h +++ b/launcher/ui/widgets/ProjectItem.h @@ -18,9 +18,8 @@ enum UserDataTypes { class ProjectItemDelegate final : public QStyledItemDelegate { Q_OBJECT - public: - ProjectItemDelegate(QWidget* parent); - - void paint(QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const override; + public: + ProjectItemDelegate(QWidget* parent); + void paint(QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const override; }; diff --git a/launcher/ui/widgets/SubTaskProgressBar.cpp b/launcher/ui/widgets/SubTaskProgressBar.cpp index 96f4fe245..b0e62e0f5 100644 --- a/launcher/ui/widgets/SubTaskProgressBar.cpp +++ b/launcher/ui/widgets/SubTaskProgressBar.cpp @@ -26,12 +26,11 @@ unique_qobject_ptr SubTaskProgressBar::create(QWidget* paren return unique_qobject_ptr(progress_bar); } -SubTaskProgressBar::SubTaskProgressBar(QWidget* parent) - : QWidget(parent), ui(new Ui::SubTaskProgressBar) +SubTaskProgressBar::SubTaskProgressBar(QWidget* parent) : QWidget(parent), ui(new Ui::SubTaskProgressBar) { ui->setupUi(this); } -SubTaskProgressBar::~SubTaskProgressBar() +SubTaskProgressBar::~SubTaskProgressBar() { delete ui; } @@ -55,4 +54,3 @@ void SubTaskProgressBar::setDetails(QString details) { ui->statusDetailsLabel->setText(details); } - diff --git a/launcher/ui/widgets/SubTaskProgressBar.h b/launcher/ui/widgets/SubTaskProgressBar.h index 8f8aeea2a..cd08809f1 100644 --- a/launcher/ui/widgets/SubTaskProgressBar.h +++ b/launcher/ui/widgets/SubTaskProgressBar.h @@ -25,11 +25,10 @@ namespace Ui { class SubTaskProgressBar; } -class SubTaskProgressBar : public QWidget -{ +class SubTaskProgressBar : public QWidget { Q_OBJECT -public: + public: static unique_qobject_ptr create(QWidget* parent = nullptr); SubTaskProgressBar(QWidget* parent = nullptr); @@ -40,9 +39,6 @@ public: void setStatus(QString status); void setDetails(QString details); - - -private: + private: Ui::SubTaskProgressBar* ui; - }; diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp index 291f8ed9e..d26906bd3 100644 --- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp +++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp @@ -22,13 +22,14 @@ #include "ui/themes/ITheme.h" #include "ui/themes/ThemeManager.h" -ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ThemeCustomizationWidget) +ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget* parent) : QWidget(parent), ui(new Ui::ThemeCustomizationWidget) { ui->setupUi(this); loadSettings(); connect(ui->iconsComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyIconTheme); - connect(ui->widgetStyleComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyWidgetTheme); + connect(ui->widgetStyleComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ThemeCustomizationWidget::applyWidgetTheme); connect(ui->backgroundCatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyCatTheme); } @@ -40,7 +41,7 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget() /// /// The layout was not quite right, so currently this just disables the UI elements, which should be hidden instead /// TODO FIXME -/// +/// /// Original Method One: /// ui->iconsComboBox->setVisible(features& ThemeFields::ICONS); /// ui->iconsLabel->setVisible(features& ThemeFields::ICONS); @@ -48,7 +49,7 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget() /// ui->widgetThemeLabel->setVisible(features& ThemeFields::WIDGETS); /// ui->backgroundCatComboBox->setVisible(features& ThemeFields::CAT); /// ui->backgroundCatLabel->setVisible(features& ThemeFields::CAT); -/// +/// /// original Method Two: /// if (!(features & ThemeFields::ICONS)) { /// ui->formLayout->setRowVisible(0, false); @@ -61,7 +62,8 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget() /// } /// /// -void ThemeCustomizationWidget::showFeatures(ThemeFields features) { +void ThemeCustomizationWidget::showFeatures(ThemeFields features) +{ ui->iconsComboBox->setEnabled(features & ThemeFields::ICONS); ui->iconsLabel->setEnabled(features & ThemeFields::ICONS); ui->widgetStyleComboBox->setEnabled(features & ThemeFields::WIDGETS); @@ -70,7 +72,8 @@ void ThemeCustomizationWidget::showFeatures(ThemeFields features) { ui->backgroundCatLabel->setEnabled(features & ThemeFields::CAT); } -void ThemeCustomizationWidget::applyIconTheme(int index) { +void ThemeCustomizationWidget::applyIconTheme(int index) +{ auto settings = APPLICATION->settings(); auto originalIconTheme = settings->get("IconTheme").toString(); auto& newIconTheme = m_iconThemeOptions[index].first; @@ -83,7 +86,8 @@ void ThemeCustomizationWidget::applyIconTheme(int index) { emit currentIconThemeChanged(index); } -void ThemeCustomizationWidget::applyWidgetTheme(int index) { +void ThemeCustomizationWidget::applyWidgetTheme(int index) +{ auto settings = APPLICATION->settings(); auto originalAppTheme = settings->get("ApplicationTheme").toString(); auto newAppTheme = ui->widgetStyleComboBox->currentData().toString(); diff --git a/launcher/ui/widgets/VariableSizedImageObject.cpp b/launcher/ui/widgets/VariableSizedImageObject.cpp index 3aa3343d0..c72df5a9c 100644 --- a/launcher/ui/widgets/VariableSizedImageObject.cpp +++ b/launcher/ui/widgets/VariableSizedImageObject.cpp @@ -25,8 +25,8 @@ #include "Application.h" -#include "net/NetJob.h" #include "net/ApiDownload.h" +#include "net/NetJob.h" enum FormatProperties { ImageData = QTextFormat::UserProperty + 1 }; diff --git a/launcher/ui/widgets/VersionListView.cpp b/launcher/ui/widgets/VersionListView.cpp index 06e58d221..7701d1271 100644 --- a/launcher/ui/widgets/VersionListView.cpp +++ b/launcher/ui/widgets/VersionListView.cpp @@ -34,35 +34,33 @@ * limitations under the License. */ -#include -#include -#include -#include -#include #include "VersionListView.h" +#include +#include +#include +#include +#include -VersionListView::VersionListView(QWidget *parent) - :QTreeView ( parent ) +VersionListView::VersionListView(QWidget* parent) : QTreeView(parent) { m_emptyString = tr("No versions are currently available."); } -void VersionListView::rowsInserted(const QModelIndex &parent, int start, int end) +void VersionListView::rowsInserted(const QModelIndex& parent, int start, int end) { - m_itemCount += end-start+1; + m_itemCount += end - start + 1; updateEmptyViewPort(); QTreeView::rowsInserted(parent, start, end); } - -void VersionListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void VersionListView::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) { - m_itemCount -= end-start+1; + m_itemCount -= end - start + 1; updateEmptyViewPort(); QTreeView::rowsInserted(parent, start, end); } -void VersionListView::setModel(QAbstractItemModel *model) +void VersionListView::setModel(QAbstractItemModel* model) { m_itemCount = model->rowCount(); updateEmptyViewPort(); @@ -71,11 +69,9 @@ void VersionListView::setModel(QAbstractItemModel *model) void VersionListView::reset() { - if(model()) - { + if (model()) { m_itemCount = model()->rowCount(); - } - else { + } else { m_itemCount = 0; } updateEmptyViewPort(); @@ -106,28 +102,23 @@ void VersionListView::updateEmptyViewPort() setAccessibleDescription(currentEmptyString()); #endif /* !QT_NO_ACCESSIBILITY */ - if(!m_itemCount) - { + if (!m_itemCount) { viewport()->update(); } } -void VersionListView::paintEvent(QPaintEvent *event) +void VersionListView::paintEvent(QPaintEvent* event) { - if(m_itemCount) - { + if (m_itemCount) { QTreeView::paintEvent(event); - } - else - { + } else { paintInfoLabel(event); } } QString VersionListView::currentEmptyString() const { - switch(m_emptyMode) - { + switch (m_emptyMode) { default: case VersionListView::String: return m_emptyString; @@ -136,12 +127,11 @@ QString VersionListView::currentEmptyString() const } } - -void VersionListView::paintInfoLabel(QPaintEvent *event) const +void VersionListView::paintInfoLabel(QPaintEvent* event) const { QString emptyString = currentEmptyString(); - //calculate the rect for the overlay + // calculate the rect for the overlay QPainter painter(viewport()); painter.setRenderHint(QPainter::Antialiasing, true); QFont font("sans", 20); @@ -163,7 +153,7 @@ void VersionListView::paintInfoLabel(QPaintEvent *event) const auto wrapRect = textRect; wrapRect.adjust(-10, -10, 10, 10); - //check if we are allowed to draw in our area + // check if we are allowed to draw in our area if (!event->rect().intersects(wrapRect)) { return; } diff --git a/launcher/ui/widgets/VersionListView.h b/launcher/ui/widgets/VersionListView.h index 4153b314a..07792db52 100644 --- a/launcher/ui/widgets/VersionListView.h +++ b/launcher/ui/widgets/VersionListView.h @@ -16,39 +16,32 @@ #pragma once #include -class VersionListView : public QTreeView -{ +class VersionListView : public QTreeView { Q_OBJECT -public: - - explicit VersionListView(QWidget *parent = 0); - virtual void paintEvent(QPaintEvent *event) override; + public: + explicit VersionListView(QWidget* parent = 0); + virtual void paintEvent(QPaintEvent* event) override; virtual void setModel(QAbstractItemModel* model) override; - enum EmptyMode - { - Empty, - String, - ErrorString - }; + enum EmptyMode { Empty, String, ErrorString }; void setEmptyString(QString emptyString); void setEmptyErrorString(QString emptyErrorString); void setEmptyMode(EmptyMode mode); -public slots: + public slots: virtual void reset() override; -protected slots: - virtual void rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end) override; - virtual void rowsInserted(const QModelIndex &parent, int start, int end) override; + protected slots: + virtual void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override; + virtual void rowsInserted(const QModelIndex& parent, int start, int end) override; -private: /* methods */ - void paintInfoLabel(QPaintEvent *event) const; + private: /* methods */ + void paintInfoLabel(QPaintEvent* event) const; void updateEmptyViewPort(); QString currentEmptyString() const; -private: /* variables */ + private: /* variables */ int m_itemCount = 0; QString m_emptyString; QString m_emptyErrorString; diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 2b22a4a92..a24630b31 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -11,8 +11,7 @@ #include "ui/dialogs/CustomMessageBox.h" -VersionSelectWidget::VersionSelectWidget(QWidget* parent) - : QWidget(parent) +VersionSelectWidget::VersionSelectWidget(QWidget* parent) : QWidget(parent) { setObjectName(QStringLiteral("VersionSelectWidget")); verticalLayout = new QVBoxLayout(this); @@ -79,9 +78,7 @@ void VersionSelectWidget::setEmptyMode(VersionListView::EmptyMode mode) listView->setEmptyMode(mode); } -VersionSelectWidget::~VersionSelectWidget() -{ -} +VersionSelectWidget::~VersionSelectWidget() {} void VersionSelectWidget::setResizeOn(int column) { @@ -90,7 +87,8 @@ void VersionSelectWidget::setResizeOn(int column) listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); } -bool VersionSelectWidget::eventFilter(QObject *watched, QEvent *event) { +bool VersionSelectWidget::eventFilter(QObject* watched, QEvent* event) +{ if (watched == search && event->type() == QEvent::KeyPress) { const QKeyEvent* keyEvent = (QKeyEvent*)event; const bool up = keyEvent->key() == Qt::Key_Up; @@ -107,28 +105,24 @@ bool VersionSelectWidget::eventFilter(QObject *watched, QEvent *event) { return QObject::eventFilter(watched, event); } -void VersionSelectWidget::initialize(BaseVersionList *vlist) +void VersionSelectWidget::initialize(BaseVersionList* vlist) { m_vlist = vlist; m_proxyModel->setSourceModel(vlist); listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); - if (!m_vlist->isLoaded()) - { + if (!m_vlist->isLoaded()) { loadList(); - } - else - { - if (m_proxyModel->rowCount() == 0) - { + } else { + if (m_proxyModel->rowCount() == 0) { listView->setEmptyMode(VersionListView::String); } preselect(); } } -void VersionSelectWidget::closeEvent(QCloseEvent * event) +void VersionSelectWidget::closeEvent(QCloseEvent* event) { QWidget::closeEvent(event); } @@ -136,16 +130,14 @@ void VersionSelectWidget::closeEvent(QCloseEvent * event) void VersionSelectWidget::loadList() { auto newTask = m_vlist->getLoadTask(); - if (!newTask) - { + if (!newTask) { return; } loadTask = newTask.get(); connect(loadTask, &Task::succeeded, this, &VersionSelectWidget::onTaskSucceeded); connect(loadTask, &Task::failed, this, &VersionSelectWidget::onTaskFailed); connect(loadTask, &Task::progress, this, &VersionSelectWidget::changeProgress); - if(!loadTask->isRunning()) - { + if (!loadTask->isRunning()) { loadTask->start(); } sneakyProgressBar->setHidden(false); @@ -153,8 +145,7 @@ void VersionSelectWidget::loadList() void VersionSelectWidget::onTaskSucceeded() { - if (m_proxyModel->rowCount() == 0) - { + if (m_proxyModel->rowCount() == 0) { listView->setEmptyMode(VersionListView::String); } sneakyProgressBar->setHidden(true); @@ -182,25 +173,23 @@ void VersionSelectWidget::currentRowChanged(const QModelIndex& current, const QM void VersionSelectWidget::preselect() { - if(preselectedAlready) + if (preselectedAlready) return; selectCurrent(); - if(preselectedAlready) + if (preselectedAlready) return; selectRecommended(); } void VersionSelectWidget::selectCurrent() { - if(m_currentVersion.isEmpty()) - { + if (m_currentVersion.isEmpty()) { return; } auto idx = m_proxyModel->getVersion(m_currentVersion); - if(idx.isValid()) - { + if (idx.isValid()) { preselectedAlready = true; - listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + listView->selectionModel()->setCurrentIndex(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); listView->scrollTo(idx, QAbstractItemView::PositionAtCenter); } } @@ -218,10 +207,9 @@ VersionListView* VersionSelectWidget::view() void VersionSelectWidget::selectRecommended() { auto idx = m_proxyModel->getRecommended(); - if(idx.isValid()) - { + if (idx.isValid()) { preselectedAlready = true; - listView->selectionModel()->setCurrentIndex(idx,QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + listView->selectionModel()->setCurrentIndex(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); listView->scrollTo(idx, QAbstractItemView::PositionAtCenter); } } @@ -253,7 +241,7 @@ void VersionSelectWidget::setExactIfPresentFilter(BaseVersionList::ModelRoles ro m_proxyModel->setFilter(role, new ExactIfPresentFilter(filter)); } -void VersionSelectWidget::setFilter(BaseVersionList::ModelRoles role, Filter *filter) +void VersionSelectWidget::setFilter(BaseVersionList::ModelRoles role, Filter* filter) { m_proxyModel->setFilter(role, filter); } diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index 598e10591..99729fbdf 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -35,9 +35,9 @@ #pragma once -#include -#include #include +#include +#include #include "BaseVersionList.h" #include "VersionListView.h" @@ -47,15 +47,14 @@ class QVBoxLayout; class QProgressBar; class Filter; -class VersionSelectWidget: public QWidget -{ +class VersionSelectWidget : public QWidget { Q_OBJECT -public: - explicit VersionSelectWidget(QWidget *parent); + public: + explicit VersionSelectWidget(QWidget* parent); ~VersionSelectWidget(); //! loads the list if needed. - void initialize(BaseVersionList *vlist); + void initialize(BaseVersionList* vlist); //! Starts a task that loads the list. void loadList(); @@ -67,11 +66,11 @@ public: void selectSearch(); VersionListView* view(); - void setCurrentVersion(const QString & version); + void setCurrentVersion(const QString& version); void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter); void setExactFilter(BaseVersionList::ModelRoles role, QString filter); void setExactIfPresentFilter(BaseVersionList::ModelRoles role, QString filter); - void setFilter(BaseVersionList::ModelRoles role, Filter *filter); + void setFilter(BaseVersionList::ModelRoles role, Filter* filter); void setEmptyString(QString emptyString); void setEmptyErrorString(QString emptyErrorString); void setEmptyMode(VersionListView::EmptyMode mode); @@ -79,31 +78,31 @@ public: bool eventFilter(QObject* watched, QEvent* event) override; -signals: + signals: void selectedVersionChanged(BaseVersion::Ptr version); -protected: - virtual void closeEvent ( QCloseEvent* ); + protected: + virtual void closeEvent(QCloseEvent*); -private slots: + private slots: void onTaskSucceeded(); - void onTaskFailed(const QString &reason); + void onTaskFailed(const QString& reason); void changeProgress(qint64 current, qint64 total); - void currentRowChanged(const QModelIndex ¤t, const QModelIndex &); + void currentRowChanged(const QModelIndex& current, const QModelIndex&); -private: + private: void preselect(); -private: + private: QString m_currentVersion; - BaseVersionList *m_vlist = nullptr; - VersionProxyModel *m_proxyModel = nullptr; + BaseVersionList* m_vlist = nullptr; + VersionProxyModel* m_proxyModel = nullptr; int resizeOnColumn = 0; - Task * loadTask; + Task* loadTask; bool preselectedAlready = false; - QVBoxLayout *verticalLayout = nullptr; - VersionListView *listView = nullptr; - QLineEdit *search; - QProgressBar *sneakyProgressBar = nullptr; + QVBoxLayout* verticalLayout = nullptr; + VersionListView* listView = nullptr; + QLineEdit* search; + QProgressBar* sneakyProgressBar = nullptr; }; diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index 3b57ee894..46caaaef2 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -7,8 +7,8 @@ class ActionButton : public QToolButton { Q_OBJECT public: - ActionButton(QAction* action, QWidget* parent = nullptr, bool use_default_action = false) : QToolButton(parent), - m_action(action), m_use_default_action(use_default_action) + ActionButton(QAction* action, QWidget* parent = nullptr, bool use_default_action = false) + : QToolButton(parent), m_action(action), m_use_default_action(use_default_action) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -229,7 +229,7 @@ void WideBar::showVisibilityMenu(QPoint const& position) act->setCheckable(true); act->setChecked(entry.bar_action->isVisible()); - connect(act, &QAction::toggled, entry.bar_action, [this, &entry](bool toggled){ + connect(act, &QAction::toggled, entry.bar_action, [this, &entry](bool toggled) { entry.bar_action->setVisible(toggled); // NOTE: This is needed so that disabled actions get reflected on the button when it is made visible. @@ -245,7 +245,8 @@ void WideBar::showVisibilityMenu(QPoint const& position) m_bar_menu->popup(mapToGlobal(position)); } -void WideBar::addContextMenuAction(QAction* action) { +void WideBar::addContextMenuAction(QAction* action) +{ m_context_menu_actions.append(action); } @@ -308,5 +309,4 @@ bool WideBar::checkHash(QByteArray const& old_hash) const return old_hash == getHash(); } - #include "WideBar.moc" diff --git a/launcher/updater/ExternalUpdater.h b/launcher/updater/ExternalUpdater.h index a053e081f..6c0803a7e 100644 --- a/launcher/updater/ExternalUpdater.h +++ b/launcher/updater/ExternalUpdater.h @@ -31,11 +31,10 @@ * The initializer of the new class should have the side effect of starting the automatic updater. That is, * once the class is initialized, the program should automatically check for updates if necessary. */ -class ExternalUpdater : public QObject -{ +class ExternalUpdater : public QObject { Q_OBJECT -public: + public: /*! * Check for updates manually, showing the user a progress bar and an alert if no updates are found. */ @@ -71,7 +70,7 @@ public: */ virtual void setBetaAllowed(bool allowed) = 0; -signals: + signals: /*! * Emits whenever the user's ability to check for updates changes. * @@ -84,4 +83,4 @@ signals: void canCheckForUpdatesChanged(bool canCheck); }; -#endif //LAUNCHER_EXTERNALUPDATER_H +#endif // LAUNCHER_EXTERNALUPDATER_H diff --git a/launcher/updater/MacSparkleUpdater.h b/launcher/updater/MacSparkleUpdater.h index cee19f7c7..3f6b5f4ad 100644 --- a/launcher/updater/MacSparkleUpdater.h +++ b/launcher/updater/MacSparkleUpdater.h @@ -26,11 +26,10 @@ /*! * An implementation for the updater on macOS that uses the Sparkle framework. */ -class MacSparkleUpdater : public ExternalUpdater -{ +class MacSparkleUpdater : public ExternalUpdater { Q_OBJECT -public: + public: /*! * Start the Sparkle updater, which automatically checks for updates if necessary. */ @@ -115,10 +114,10 @@ public: */ void setBetaAllowed(bool allowed) override; -private: + private: class Private; - Private *priv; + Private* priv; }; -#endif //LAUNCHER_MACSPARKLEUPDATER_H +#endif // LAUNCHER_MACSPARKLEUPDATER_H diff --git a/launcher/updater/MacSparkleUpdater.mm b/launcher/updater/MacSparkleUpdater.mm index 07337176d..1c1f5cd27 100644 --- a/launcher/updater/MacSparkleUpdater.mm +++ b/launcher/updater/MacSparkleUpdater.mm @@ -28,7 +28,7 @@ @property(nonatomic, readonly) SPUUpdater* updater; /// A callback to run when the state of `canCheckForUpdates` for the `updater` changes. -@property(nonatomic, copy) void (^callback) (bool); +@property(nonatomic, copy) void (^callback)(bool); - (id)initWithUpdater:(SPUUpdater*)updater; @@ -36,8 +36,7 @@ @implementation UpdaterObserver -- (id)initWithUpdater:(SPUUpdater*)updater -{ +- (id)initWithUpdater:(SPUUpdater*)updater { self = [super init]; _updater = updater; [self addObserver:self forKeyPath:@"updater.canCheckForUpdates" options:NSKeyValueObservingOptionNew context:nil]; @@ -45,13 +44,11 @@ return self; } -- (void)observeValueForKeyPath:(NSString *)keyPath +- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context -{ - if ([keyPath isEqualToString:@"updater.canCheckForUpdates"]) - { + change:(NSDictionary*)change + context:(void*)context { + if ([keyPath isEqualToString:@"updater.canCheckForUpdates"]) { bool canCheck = [change[NSKeyValueChangeNewKey] boolValue]; self.callback(canCheck); } @@ -59,34 +56,29 @@ @end - @interface UpdaterDelegate : NSObject -@property(nonatomic, copy) NSSet *allowedChannels; +@property(nonatomic, copy) NSSet* allowedChannels; @end @implementation UpdaterDelegate -- (NSSet *)allowedChannelsForUpdater:(SPUUpdater *)updater -{ +- (NSSet*)allowedChannelsForUpdater:(SPUUpdater*)updater { return _allowedChannels; } @end - -class MacSparkleUpdater::Private -{ -public: - SPUStandardUpdaterController *updaterController; - UpdaterObserver *updaterObserver; - UpdaterDelegate *updaterDelegate; - NSAutoreleasePool *autoReleasePool; +class MacSparkleUpdater::Private { + public: + SPUStandardUpdaterController* updaterController; + UpdaterObserver* updaterObserver; + UpdaterDelegate* updaterDelegate; + NSAutoreleasePool* autoReleasePool; }; -MacSparkleUpdater::MacSparkleUpdater() -{ +MacSparkleUpdater::MacSparkleUpdater() { priv = new MacSparkleUpdater::Private(); // Enable Cocoa's memory management. @@ -98,18 +90,17 @@ MacSparkleUpdater::MacSparkleUpdater() // Controller is the interface for actually doing the updates. priv->updaterController = [[SPUStandardUpdaterController alloc] initWithStartingUpdater:true - updaterDelegate:priv->updaterDelegate - userDriverDelegate:nil]; + updaterDelegate:priv->updaterDelegate + userDriverDelegate:nil]; priv->updaterObserver = [[UpdaterObserver alloc] initWithUpdater:priv->updaterController.updater]; // Use KVO to run a callback that emits a Qt signal when `canCheckForUpdates` changes, so the UI can respond accordingly. priv->updaterObserver.callback = ^(bool canCheck) { - emit canCheckForUpdatesChanged(canCheck); + emit canCheckForUpdatesChanged(canCheck); }; } -MacSparkleUpdater::~MacSparkleUpdater() -{ +MacSparkleUpdater::~MacSparkleUpdater() { [priv->updaterObserver removeObserver:priv->updaterObserver forKeyPath:@"updater.canCheckForUpdates"]; [priv->updaterController release]; @@ -119,77 +110,63 @@ MacSparkleUpdater::~MacSparkleUpdater() delete priv; } -void MacSparkleUpdater::checkForUpdates() -{ +void MacSparkleUpdater::checkForUpdates() { [priv->updaterController checkForUpdates:nil]; } -bool MacSparkleUpdater::getAutomaticallyChecksForUpdates() -{ +bool MacSparkleUpdater::getAutomaticallyChecksForUpdates() { return priv->updaterController.updater.automaticallyChecksForUpdates; } -double MacSparkleUpdater::getUpdateCheckInterval() -{ +double MacSparkleUpdater::getUpdateCheckInterval() { return priv->updaterController.updater.updateCheckInterval; } -QSet MacSparkleUpdater::getAllowedChannels() -{ +QSet MacSparkleUpdater::getAllowedChannels() { // Convert NSSet -> QSet __block QSet channels; - [priv->updaterDelegate.allowedChannels enumerateObjectsUsingBlock:^(NSString *channel, BOOL *stop) - { - channels.insert(QString::fromNSString(channel)); + [priv->updaterDelegate.allowedChannels enumerateObjectsUsingBlock:^(NSString* channel, BOOL* stop) { + channels.insert(QString::fromNSString(channel)); }]; return channels; } -bool MacSparkleUpdater::getBetaAllowed() -{ +bool MacSparkleUpdater::getBetaAllowed() { return getAllowedChannels().contains("beta"); } -void MacSparkleUpdater::setAutomaticallyChecksForUpdates(bool check) -{ - priv->updaterController.updater.automaticallyChecksForUpdates = check ? YES : NO; // make clang-tidy happy +void MacSparkleUpdater::setAutomaticallyChecksForUpdates(bool check) { + priv->updaterController.updater.automaticallyChecksForUpdates = check ? YES : NO; // make clang-tidy happy } -void MacSparkleUpdater::setUpdateCheckInterval(double seconds) -{ +void MacSparkleUpdater::setUpdateCheckInterval(double seconds) { priv->updaterController.updater.updateCheckInterval = seconds; } -void MacSparkleUpdater::clearAllowedChannels() -{ +void MacSparkleUpdater::clearAllowedChannels() { priv->updaterDelegate.allowedChannels = [NSSet set]; } -void MacSparkleUpdater::setAllowedChannel(const QString &channel) -{ - if (channel.isEmpty()) - { +void MacSparkleUpdater::setAllowedChannel(const QString& channel) { + if (channel.isEmpty()) { clearAllowedChannels(); return; } - NSSet *nsChannels = [NSSet setWithObject:channel.toNSString()]; + NSSet* nsChannels = [NSSet setWithObject:channel.toNSString()]; priv->updaterDelegate.allowedChannels = nsChannels; } -void MacSparkleUpdater::setAllowedChannels(const QSet &channels) -{ - if (channels.isEmpty()) - { +void MacSparkleUpdater::setAllowedChannels(const QSet& channels) { + if (channels.isEmpty()) { clearAllowedChannels(); return; } QString channelsConfig = ""; // Convert QSet -> NSSet - NSMutableSet *nsChannels = [NSMutableSet setWithCapacity:channels.count()]; - foreach (const QString channel, channels) - { + NSMutableSet* nsChannels = [NSMutableSet setWithCapacity:channels.count()]; + foreach (const QString channel, channels) { [nsChannels addObject:channel.toNSString()]; channelsConfig += channel + " "; } @@ -197,14 +174,10 @@ void MacSparkleUpdater::setAllowedChannels(const QSet &channels) priv->updaterDelegate.allowedChannels = nsChannels; } -void MacSparkleUpdater::setBetaAllowed(bool allowed) -{ - if (allowed) - { +void MacSparkleUpdater::setBetaAllowed(bool allowed) { + if (allowed) { setAllowedChannel("beta"); - } - else - { + } else { clearAllowedChannels(); } } diff --git a/libraries/LocalPeer/include/LocalPeer.h b/libraries/LocalPeer/include/LocalPeer.h index 3619ed5d1..c370102fd 100644 --- a/libraries/LocalPeer/include/LocalPeer.h +++ b/libraries/LocalPeer/include/LocalPeer.h @@ -43,56 +43,46 @@ #include #include - class QLocalServer; class LockedFile; -class ApplicationId -{ -public: /* methods */ +class ApplicationId { + public: /* methods */ // traditional app = installed system wide and used in a multi-user environment static ApplicationId fromTraditionalApp(); // ID based on a path with all the application data (no two instances with the same data path should run) - static ApplicationId fromPathAndVersion(const QString & dataPath, const QString & version); + static ApplicationId fromPathAndVersion(const QString& dataPath, const QString& version); // custom ID - static ApplicationId fromCustomId(const QString & id); + static ApplicationId fromCustomId(const QString& id); // custom ID, based on a raw string previously acquired from 'toString' - static ApplicationId fromRawString(const QString & id); + static ApplicationId fromRawString(const QString& id); + QString toString() { return m_id; } - QString toString() - { - return m_id; - } + private: /* methods */ + ApplicationId(const QString& value) { m_id = value; } -private: /* methods */ - ApplicationId(const QString & value) - { - m_id = value; - } - -private: /* data */ + private: /* data */ QString m_id; }; -class LocalPeer : public QObject -{ +class LocalPeer : public QObject { Q_OBJECT -public: - LocalPeer(QObject *parent, const ApplicationId &appId); + public: + LocalPeer(QObject* parent, const ApplicationId& appId); ~LocalPeer(); bool isClient(); - bool sendMessage(const QByteArray &message, int timeout); + bool sendMessage(const QByteArray& message, int timeout); ApplicationId applicationId() const; -Q_SIGNALS: - void messageReceived(const QByteArray &message); + Q_SIGNALS: + void messageReceived(const QByteArray& message); -protected Q_SLOTS: + protected Q_SLOTS: void receiveConnection(); -protected: + protected: ApplicationId id; QString socketName; std::unique_ptr server; diff --git a/libraries/LocalPeer/src/LocalPeer.cpp b/libraries/LocalPeer/src/LocalPeer.cpp index b7149c408..ab528c2a1 100644 --- a/libraries/LocalPeer/src/LocalPeer.cpp +++ b/libraries/LocalPeer/src/LocalPeer.cpp @@ -38,21 +38,20 @@ ** ****************************************************************************/ - #include "LocalPeer.h" #include #include -#include +#include #include #include -#include #include +#include #include "LockedFile.h" #if defined(Q_OS_WIN) -#include #include -typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); +#include +typedef BOOL(WINAPI* PProcessIdToSessionId)(DWORD, DWORD*); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) @@ -60,9 +59,9 @@ static PProcessIdToSessionId pProcessIdToSessionId = 0; #include #endif +#include #include #include -#include static const char* ack = "ack"; @@ -79,13 +78,11 @@ ApplicationId ApplicationId::fromTraditionalApp() quint16 idNum = qChecksum(idc.constData(), idc.size()); auto socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) - if (!pProcessIdToSessionId) - { + if (!pProcessIdToSessionId) { QLibrary lib("kernel32"); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } - if (pProcessIdToSessionId) - { + if (pProcessIdToSessionId) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); socketName += QLatin1Char('-') + QString::number(sessionId, 16); @@ -114,8 +111,7 @@ ApplicationId ApplicationId::fromRawString(const QString& id) return ApplicationId(id); } -LocalPeer::LocalPeer(QObject * parent, const ApplicationId &appId) - : QObject(parent), id(appId) +LocalPeer::LocalPeer(QObject* parent, const ApplicationId& appId) : QObject(parent), id(appId) { socketName = id.toString(); server.reset(new QLocalServer()); @@ -124,9 +120,7 @@ LocalPeer::LocalPeer(QObject * parent, const ApplicationId &appId) lockFile->open(QIODevice::ReadWrite); } -LocalPeer::~LocalPeer() -{ -} +LocalPeer::~LocalPeer() {} ApplicationId LocalPeer::applicationId() const { @@ -145,7 +139,7 @@ bool LocalPeer::isClient() #if defined(Q_OS_UNIX) // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); + QFile::remove(QDir::cleanPath(QDir::tempPath()) + QLatin1Char('/') + socketName); res = server->listen(socketName); } #endif @@ -155,8 +149,7 @@ bool LocalPeer::isClient() return false; } - -bool LocalPeer::sendMessage(const QByteArray &message, int timeout) +bool LocalPeer::sendMessage(const QByteArray& message, int timeout) { if (!isClient()) return false; @@ -164,17 +157,15 @@ bool LocalPeer::sendMessage(const QByteArray &message, int timeout) QLocalSocket socket; bool connOk = false; int tries = 2; - for(int i = 0; i < tries; i++) { + for (int i = 0; i < tries; i++) { // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); - connOk = socket.waitForConnected(timeout/2); - if (!connOk && i < (tries - 1)) - { + connOk = socket.waitForConnected(timeout / 2); + if (!connOk && i < (tries - 1)) { std::this_thread::sleep_for(std::chrono::milliseconds(250)); } } - if (!connOk) - { + if (!connOk) { return false; } @@ -182,36 +173,30 @@ bool LocalPeer::sendMessage(const QByteArray &message, int timeout) QDataStream ds(&socket); ds.writeBytes(uMsg.constData(), uMsg.size()); - if(!socket.waitForBytesWritten(timeout)) - { + if (!socket.waitForBytesWritten(timeout)) { return false; } // wait for 'ack' - if(!socket.waitForReadyRead(timeout)) - { + if (!socket.waitForReadyRead(timeout)) { return false; } // make sure we got 'ack' - if(!(socket.read(qstrlen(ack)) == ack)) - { + if (!(socket.read(qstrlen(ack)) == ack)) { return false; } return true; } - void LocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); - if (!socket) - { + if (!socket) { return; } - while (socket->bytesAvailable() < static_cast(sizeof(quint32))) - { + while (socket->bytesAvailable() < static_cast(sizeof(quint32))) { socket->waitForReadyRead(); } QDataStream ds(socket); @@ -221,21 +206,19 @@ void LocalPeer::receiveConnection() uMsg.resize(remaining); int got = 0; char* uMsgBuf = uMsg.data(); - do - { + do { got = ds.readRawData(uMsgBuf, remaining); remaining -= got; uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); - if (got < 0) - { + if (got < 0) { qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); - socket->waitForDisconnected(1000); // make sure client reads ack + socket->waitForDisconnected(1000); // make sure client reads ack delete socket; - emit messageReceived(uMsg); //### (might take a long time to return) + emit messageReceived(uMsg); //### (might take a long time to return) } diff --git a/libraries/LocalPeer/src/LockedFile.cpp b/libraries/LocalPeer/src/LockedFile.cpp index 73294a16e..e93eabc96 100644 --- a/libraries/LocalPeer/src/LockedFile.cpp +++ b/libraries/LocalPeer/src/LockedFile.cpp @@ -80,8 +80,7 @@ \sa QFile::QFile() */ -LockedFile::LockedFile() - : QFile() +LockedFile::LockedFile() : QFile() { #ifdef Q_OS_WIN wmutex = 0; @@ -97,8 +96,7 @@ LockedFile::LockedFile() \sa QFile::QFile() */ -LockedFile::LockedFile(const QString &name) - : QFile(name) +LockedFile::LockedFile(const QString& name) : QFile(name) { #ifdef Q_OS_WIN wmutex = 0; diff --git a/libraries/LocalPeer/src/LockedFile.h b/libraries/LocalPeer/src/LockedFile.h index 2f29ee201..e8023251c 100644 --- a/libraries/LocalPeer/src/LockedFile.h +++ b/libraries/LocalPeer/src/LockedFile.h @@ -45,13 +45,12 @@ #include #endif -class LockedFile : public QFile -{ -public: +class LockedFile : public QFile { + public: enum LockMode { NoLock = 0, ReadLock, WriteLock }; LockedFile(); - LockedFile(const QString &name); + LockedFile(const QString& name); ~LockedFile(); bool open(OpenMode mode); @@ -61,8 +60,7 @@ public: bool isLocked() const; LockMode lockMode() const; - private: - + private: #ifdef Q_OS_WIN Qt::HANDLE wmutex; Qt::HANDLE rmutex; diff --git a/libraries/LocalPeer/src/LockedFile_unix.cpp b/libraries/LocalPeer/src/LockedFile_unix.cpp index 6becc89e2..d17e625e4 100644 --- a/libraries/LocalPeer/src/LockedFile_unix.cpp +++ b/libraries/LocalPeer/src/LockedFile_unix.cpp @@ -38,10 +38,10 @@ ** ****************************************************************************/ -#include #include -#include #include +#include +#include #include "LockedFile.h" @@ -75,12 +75,10 @@ bool LockedFile::lock(LockMode mode, bool block) return false; } - m_lock_mode = mode; return true; } - bool LockedFile::unlock() { if (!isOpen()) { diff --git a/libraries/LocalPeer/src/LockedFile_win.cpp b/libraries/LocalPeer/src/LockedFile_win.cpp index 93d2c73b3..a8dbead36 100644 --- a/libraries/LocalPeer/src/LockedFile_win.cpp +++ b/libraries/LocalPeer/src/LockedFile_win.cpp @@ -38,9 +38,9 @@ ** ****************************************************************************/ -#include "LockedFile.h" #include #include +#include "LockedFile.h" #define MUTEX_PREFIX "QtLockedFile mutex " // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS @@ -50,8 +50,7 @@ Qt::HANDLE LockedFile::getMutexHandle(int idx, bool doCreate) { if (mutexname.isEmpty()) { QFileInfo fi(*this); - mutexname = QString::fromLatin1(MUTEX_PREFIX) - + fi.absoluteFilePath().toLower(); + mutexname = QString::fromLatin1(MUTEX_PREFIX) + fi.absoluteFilePath().toLower(); } QString mname(mutexname); if (idx >= 0) @@ -64,8 +63,7 @@ Qt::HANDLE LockedFile::getMutexHandle(int idx, bool doCreate) qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); return 0; } - } - else { + } else { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (LPCWSTR)mname.utf16()); if (!mutex) { if (GetLastError() != ERROR_FILE_NOT_FOUND) @@ -81,20 +79,18 @@ bool LockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) Q_ASSERT(mutex); DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); switch (res) { - case WAIT_OBJECT_0: - case WAIT_ABANDONED: - return true; - break; - case WAIT_TIMEOUT: - break; - default: - qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return true; + break; + case WAIT_TIMEOUT: + break; + default: + qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); } return false; } - - bool LockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { @@ -130,8 +126,7 @@ bool LockedFile::lock(LockMode mode, bool block) qWarning("QtLockedFile::lock(): too many readers"); rmutex = 0; ok = false; - } - else if (!rmutex) { + } else if (!rmutex) { rmutex = getMutexHandle(idx, true); if (!rmutex || !waitMutex(rmutex, false)) ok = false; @@ -143,8 +138,7 @@ bool LockedFile::lock(LockMode mode, bool block) ReleaseMutex(wmutex); if (!ok) return false; - } - else { + } else { Q_ASSERT(rmutexes.isEmpty()); for (int i = 0; i < MAX_READERS; i++) { Qt::HANDLE mutex = getMutexHandle(i, false); @@ -152,8 +146,7 @@ bool LockedFile::lock(LockMode mode, bool block) rmutexes.append(mutex); } if (rmutexes.size()) { - DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), - TRUE, block ? INFINITE : 0); + DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), TRUE, block ? INFINITE : 0); if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { if (res != WAIT_TIMEOUT) qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); @@ -182,9 +175,8 @@ bool LockedFile::unlock() ReleaseMutex(rmutex); CloseHandle(rmutex); rmutex = 0; - } - else { - foreach(Qt::HANDLE mutex, rmutexes) { + } else { + foreach (Qt::HANDLE mutex, rmutexes) { ReleaseMutex(mutex); CloseHandle(mutex); } diff --git a/libraries/gamemode/include/gamemode_client.h b/libraries/gamemode/include/gamemode_client.h index b6f7afd4c..b186cd489 100644 --- a/libraries/gamemode/include/gamemode_client.h +++ b/libraries/gamemode/include/gamemode_client.h @@ -94,7 +94,7 @@ static volatile int internal_libgamemode_loaded = 1; /* Typedefs for the functions to load */ typedef int (*api_call_return_int)(void); -typedef const char *(*api_call_return_cstring)(void); +typedef const char* (*api_call_return_cstring)(void); typedef int (*api_call_pid_return_int)(pid_t); /* Storage for functors */ @@ -111,26 +111,26 @@ static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL; * * Returns 0 on success and -1 on failure */ -__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol( - void *handle, const char *name, void **out_func, size_t func_size, bool required) +__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(void* handle, + const char* name, + void** out_func, + size_t func_size, + bool required) { - void *symbol_lookup = NULL; - char *dl_error = NULL; + void* symbol_lookup = NULL; + char* dl_error = NULL; - /* Safely look up the symbol */ - symbol_lookup = dlsym(handle, name); - dl_error = dlerror(); - if (required && (dl_error || !symbol_lookup)) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "dlsym failed - %s", - dl_error); - return -1; - } + /* Safely look up the symbol */ + symbol_lookup = dlsym(handle, name); + dl_error = dlerror(); + if (required && (dl_error || !symbol_lookup)) { + snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), "dlsym failed - %s", dl_error); + return -1; + } - /* Have the symbol correctly, copy it to make it usable */ - memcpy(out_func, &symbol_lookup, func_size); - return 0; + /* Have the symbol correctly, copy it to make it usable */ + memcpy(out_func, &symbol_lookup, func_size); + return 0; } /** @@ -140,98 +140,74 @@ __attribute__((always_inline)) static inline int internal_bind_libgamemode_symbo */ __attribute__((always_inline)) static inline int internal_load_libgamemode(void) { - /* We start at 1, 0 is a success and -1 is a fail */ - if (internal_libgamemode_loaded != 1) { - return internal_libgamemode_loaded; - } + /* We start at 1, 0 is a success and -1 is a fail */ + if (internal_libgamemode_loaded != 1) { + return internal_libgamemode_loaded; + } - /* Anonymous struct type to define our bindings */ - struct binding { - const char *name; - void **functor; - size_t func_size; - bool required; - } bindings[] = { - { "real_gamemode_request_start", - (void **)&REAL_internal_gamemode_request_start, - sizeof(REAL_internal_gamemode_request_start), - true }, - { "real_gamemode_request_end", - (void **)&REAL_internal_gamemode_request_end, - sizeof(REAL_internal_gamemode_request_end), - true }, - { "real_gamemode_query_status", - (void **)&REAL_internal_gamemode_query_status, - sizeof(REAL_internal_gamemode_query_status), - false }, - { "real_gamemode_error_string", - (void **)&REAL_internal_gamemode_error_string, - sizeof(REAL_internal_gamemode_error_string), - true }, - { "real_gamemode_request_start_for", - (void **)&REAL_internal_gamemode_request_start_for, - sizeof(REAL_internal_gamemode_request_start_for), - false }, - { "real_gamemode_request_end_for", - (void **)&REAL_internal_gamemode_request_end_for, - sizeof(REAL_internal_gamemode_request_end_for), - false }, - { "real_gamemode_query_status_for", - (void **)&REAL_internal_gamemode_query_status_for, - sizeof(REAL_internal_gamemode_query_status_for), - false }, - }; + /* Anonymous struct type to define our bindings */ + struct binding { + const char* name; + void** functor; + size_t func_size; + bool required; + } bindings[] = { + { "real_gamemode_request_start", (void**)&REAL_internal_gamemode_request_start, sizeof(REAL_internal_gamemode_request_start), + true }, + { "real_gamemode_request_end", (void**)&REAL_internal_gamemode_request_end, sizeof(REAL_internal_gamemode_request_end), true }, + { "real_gamemode_query_status", (void**)&REAL_internal_gamemode_query_status, sizeof(REAL_internal_gamemode_query_status), false }, + { "real_gamemode_error_string", (void**)&REAL_internal_gamemode_error_string, sizeof(REAL_internal_gamemode_error_string), true }, + { "real_gamemode_request_start_for", (void**)&REAL_internal_gamemode_request_start_for, + sizeof(REAL_internal_gamemode_request_start_for), false }, + { "real_gamemode_request_end_for", (void**)&REAL_internal_gamemode_request_end_for, sizeof(REAL_internal_gamemode_request_end_for), + false }, + { "real_gamemode_query_status_for", (void**)&REAL_internal_gamemode_query_status_for, + sizeof(REAL_internal_gamemode_query_status_for), false }, + }; - void *libgamemode = NULL; + void* libgamemode = NULL; - /* Try and load libgamemode */ - libgamemode = dlopen("libgamemode.so.0", RTLD_NOW); - if (!libgamemode) { - /* Attempt to load unversioned library for compatibility with older - * versions (as of writing, there are no ABI changes between the two - - * this may need to change if ever ABI-breaking changes are made) */ - libgamemode = dlopen("libgamemode.so", RTLD_NOW); - if (!libgamemode) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "dlopen failed - %s", - dlerror()); - internal_libgamemode_loaded = -1; - return -1; - } - } + /* Try and load libgamemode */ + libgamemode = dlopen("libgamemode.so.0", RTLD_NOW); + if (!libgamemode) { + /* Attempt to load unversioned library for compatibility with older + * versions (as of writing, there are no ABI changes between the two - + * this may need to change if ever ABI-breaking changes are made) */ + libgamemode = dlopen("libgamemode.so", RTLD_NOW); + if (!libgamemode) { + snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), "dlopen failed - %s", dlerror()); + internal_libgamemode_loaded = -1; + return -1; + } + } - /* Attempt to bind all symbols */ - for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) { - struct binding *binder = &bindings[i]; + /* Attempt to bind all symbols */ + for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) { + struct binding* binder = &bindings[i]; - if (internal_bind_libgamemode_symbol(libgamemode, - binder->name, - binder->functor, - binder->func_size, - binder->required)) { - internal_libgamemode_loaded = -1; - return -1; - }; - } + if (internal_bind_libgamemode_symbol(libgamemode, binder->name, binder->functor, binder->func_size, binder->required)) { + internal_libgamemode_loaded = -1; + return -1; + }; + } - /* Success */ - internal_libgamemode_loaded = 0; - return 0; + /* Success */ + internal_libgamemode_loaded = 0; + return 0; } /** * Redirect to the real libgamemode */ -__attribute__((always_inline)) static inline const char *gamemode_error_string(void) +__attribute__((always_inline)) static inline const char* gamemode_error_string(void) { - /* If we fail to load the system gamemode, or we have an error string already, return our error - * string instead of diverting to the system version */ - if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') { - return internal_gamemode_client_error_string; - } + /* If we fail to load the system gamemode, or we have an error string already, return our error + * string instead of diverting to the system version */ + if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') { + return internal_gamemode_client_error_string; + } - return REAL_internal_gamemode_error_string(); + return REAL_internal_gamemode_error_string(); } /** @@ -246,22 +222,22 @@ __attribute__((always_inline)) static inline #endif int gamemode_request_start(void) { - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { #ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); #endif - return -1; - } + return -1; + } - if (REAL_internal_gamemode_request_start() < 0) { + if (REAL_internal_gamemode_request_start() < 0) { #ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); #endif - return -1; - } + return -1; + } - return 0; + return 0; } /* Redirect to the real libgamemode */ @@ -272,94 +248,90 @@ __attribute__((always_inline)) static inline #endif int gamemode_request_end(void) { - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { #ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); #endif - return -1; - } + return -1; + } - if (REAL_internal_gamemode_request_end() < 0) { + if (REAL_internal_gamemode_request_end() < 0) { #ifdef GAMEMODE_AUTO - fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); #endif - return -1; - } + return -1; + } - return 0; + return 0; } /* Redirect to the real libgamemode */ __attribute__((always_inline)) static inline int gamemode_query_status(void) { - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } - if (REAL_internal_gamemode_query_status == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_query_status missing (older host?)"); - return -1; - } + if (REAL_internal_gamemode_query_status == NULL) { + snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), + "gamemode_query_status missing (older host?)"); + return -1; + } - return REAL_internal_gamemode_query_status(); + return REAL_internal_gamemode_query_status(); } /* Redirect to the real libgamemode */ __attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid) { - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } - if (REAL_internal_gamemode_request_start_for == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_request_start_for missing (older host?)"); - return -1; - } + if (REAL_internal_gamemode_request_start_for == NULL) { + snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), + "gamemode_request_start_for missing (older host?)"); + return -1; + } - return REAL_internal_gamemode_request_start_for(pid); + return REAL_internal_gamemode_request_start_for(pid); } /* Redirect to the real libgamemode */ __attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid) { - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } - if (REAL_internal_gamemode_request_end_for == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_request_end_for missing (older host?)"); - return -1; - } + if (REAL_internal_gamemode_request_end_for == NULL) { + snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), + "gamemode_request_end_for missing (older host?)"); + return -1; + } - return REAL_internal_gamemode_request_end_for(pid); + return REAL_internal_gamemode_request_end_for(pid); } /* Redirect to the real libgamemode */ __attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid) { - /* Need to load gamemode */ - if (internal_load_libgamemode() < 0) { - return -1; - } + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } - if (REAL_internal_gamemode_query_status_for == NULL) { - snprintf(internal_gamemode_client_error_string, - sizeof(internal_gamemode_client_error_string), - "gamemode_query_status_for missing (older host?)"); - return -1; - } + if (REAL_internal_gamemode_query_status_for == NULL) { + snprintf(internal_gamemode_client_error_string, sizeof(internal_gamemode_client_error_string), + "gamemode_query_status_for missing (older host?)"); + return -1; + } - return REAL_internal_gamemode_query_status_for(pid); + return REAL_internal_gamemode_query_status_for(pid); } -#endif // CLIENT_GAMEMODE_H +#endif // CLIENT_GAMEMODE_H diff --git a/libraries/javacheck/JavaCheck.java b/libraries/javacheck/JavaCheck.java index 4bf43a544..7cde86cf2 100644 --- a/libraries/javacheck/JavaCheck.java +++ b/libraries/javacheck/JavaCheck.java @@ -1,10 +1,5 @@ public final class JavaCheck { - - private static final String[] CHECKED_PROPERTIES = new String[] { - "os.arch", - "java.version", - "java.vendor" - }; + private static final String[] CHECKED_PROPERTIES = new String[] {"os.arch", "java.version", "java.vendor"}; public static void main(String[] args) { int returnCode = 0; @@ -21,5 +16,4 @@ public final class JavaCheck { System.exit(returnCode); } - } diff --git a/libraries/katabasis/include/katabasis/Bits.h b/libraries/katabasis/include/katabasis/Bits.h index f11f25d25..15da2a5a8 100644 --- a/libraries/katabasis/include/katabasis/Bits.h +++ b/libraries/katabasis/include/katabasis/Bits.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include #include namespace Katabasis { @@ -11,17 +11,13 @@ enum class Activity { LoggingIn, LoggingOut, Refreshing, - FailedSoft, //!< soft failure. this generally means the user auth details haven't been invalidated - FailedHard, //!< hard failure. auth is invalid - FailedGone, //!< hard failure. auth is invalid, and the account no longer exists + FailedSoft, //!< soft failure. this generally means the user auth details haven't been invalidated + FailedHard, //!< hard failure. auth is invalid + FailedGone, //!< hard failure. auth is invalid, and the account no longer exists Succeeded }; -enum class Validity { - None, - Assumed, - Certain -}; +enum class Validity { None, Assumed, Certain }; struct Token { QDateTime issueInstant; @@ -34,4 +30,4 @@ struct Token { bool persistent = true; }; -} +} // namespace Katabasis diff --git a/libraries/katabasis/include/katabasis/DeviceFlow.h b/libraries/katabasis/include/katabasis/DeviceFlow.h index 0401df3c0..98724d81b 100644 --- a/libraries/katabasis/include/katabasis/DeviceFlow.h +++ b/libraries/katabasis/include/katabasis/DeviceFlow.h @@ -2,13 +2,13 @@ #include #include -#include #include +#include #include +#include "Bits.h" #include "Reply.h" #include "RequestParameter.h" -#include "Bits.h" namespace Katabasis { @@ -16,14 +16,12 @@ class ReplyServer; class PollServer; /// Simple OAuth2 Device Flow authenticator. -class DeviceFlow: public QObject -{ +class DeviceFlow : public QObject { Q_OBJECT -public: + public: Q_ENUMS(GrantFlow) -public: - + public: struct Options { QString userAgent = QStringLiteral("Katabasis/1.0"); QString responseType = QStringLiteral("code"); @@ -34,7 +32,7 @@ public: QUrl accessTokenUrl; }; -public: + public: /// Are we authenticated? bool linked(); @@ -44,21 +42,21 @@ public: /// Provider-specific extra tokens, available after a successful authentication QVariantMap extraTokens(); -public: + public: // TODO: put in `Options` /// User-defined extra parameters to append to request URL QVariantMap extraRequestParams(); - void setExtraRequestParams(const QVariantMap &value); + void setExtraRequestParams(const QVariantMap& value); // TODO: split up the class into multiple, each implementing one OAuth2 flow /// Grant type (if non-standard) QString grantType(); - void setGrantType(const QString &value); + void setGrantType(const QString& value); -public: + public: /// Constructor. /// @param parent Parent object. - explicit DeviceFlow(Options & opts, Token & token, QObject *parent = 0, QNetworkAccessManager *manager = 0); + explicit DeviceFlow(Options& opts, Token& token, QObject* parent = 0, QNetworkAccessManager* manager = 0); /// Get refresh token. QString refreshToken(); @@ -66,7 +64,7 @@ public: /// Get token expiration time QDateTime expires(); -public slots: + public slots: /// Authenticate. void login(); @@ -79,24 +77,24 @@ public slots: /// Handle situation where reply server has opted to close its connection void serverHasClosed(bool paramsfound = false); -signals: + signals: /// Emitted when client needs to open a web browser window, with the given URL. - void openBrowser(const QUrl &url); + void openBrowser(const QUrl& url); /// Emitted when client can close the browser window. void closeBrowser(); /// Emitted when client needs to show a verification uri and user code - void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn); + void showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn); /// Emitted when the internal state changes void activityChanged(Activity activity); -public slots: + public slots: /// Handle verification response. void onVerificationReceived(QMap); -protected slots: + protected slots: /// Handle completion of a Device Authorization Request void onDeviceAuthReplyFinished(); @@ -104,20 +102,20 @@ protected slots: void onRefreshFinished(); /// Handle failure of a refresh request. - void onRefreshError(QNetworkReply::NetworkError error, QNetworkReply *reply); + void onRefreshError(QNetworkReply::NetworkError error, QNetworkReply* reply); -protected: + protected: /// Set refresh token. - void setRefreshToken(const QString &v); + void setRefreshToken(const QString& v); /// Set token expiration time. void setExpires(QDateTime v); /// Start polling authorization server - void startPollServer(const QVariantMap ¶ms, int expiresIn); + void startPollServer(const QVariantMap& params, int expiresIn); /// Set authentication token. - void setToken(const QString &v); + void setToken(const QString& v); /// Set the linked state void setLinked(bool v); @@ -126,26 +124,26 @@ protected: void setExtraTokens(QVariantMap extraTokens); /// Set local poll server - void setPollServer(PollServer *server); + void setPollServer(PollServer* server); - PollServer * pollServer() const; + PollServer* pollServer() const; void updateActivity(Activity activity); -protected: + protected: Options options_; QVariantMap extraReqParams_; - QNetworkAccessManager *manager_ = nullptr; + QNetworkAccessManager* manager_ = nullptr; ReplyList timedReplies_; QString grantType_; -protected: - Token &token_; + protected: + Token& token_; -private: - PollServer *pollServer_ = nullptr; + private: + PollServer* pollServer_ = nullptr; Activity activity_ = Activity::Idle; }; -} +} // namespace Katabasis diff --git a/libraries/katabasis/include/katabasis/Globals.h b/libraries/katabasis/include/katabasis/Globals.h index 512745d3c..02fe1cf45 100644 --- a/libraries/katabasis/include/katabasis/Globals.h +++ b/libraries/katabasis/include/katabasis/Globals.h @@ -45,7 +45,7 @@ const char OAUTH2_EXPIRES_IN[] = "expires_in"; const char OAUTH2_DEVICE_CODE[] = "device_code"; const char OAUTH2_USER_CODE[] = "user_code"; const char OAUTH2_VERIFICATION_URI[] = "verification_uri"; -const char OAUTH2_VERIFICATION_URL[] = "verification_url"; // Google sign-in +const char OAUTH2_VERIFICATION_URL[] = "verification_url"; // Google sign-in const char OAUTH2_VERIFICATION_URI_COMPLETE[] = "verification_uri_complete"; const char OAUTH2_INTERVAL[] = "interval"; @@ -56,4 +56,4 @@ const char AUTHORIZATION_CODE[] = "authorization_code"; const char HTTP_HTTP_HEADER[] = "HTTP"; const char HTTP_AUTHORIZATION_HEADER[] = "Authorization"; -} +} // namespace Katabasis diff --git a/libraries/katabasis/include/katabasis/PollServer.h b/libraries/katabasis/include/katabasis/PollServer.h index 77103867c..fd6a5351c 100644 --- a/libraries/katabasis/include/katabasis/PollServer.h +++ b/libraries/katabasis/include/katabasis/PollServer.h @@ -12,32 +12,35 @@ class QNetworkAccessManager; namespace Katabasis { /// Poll an authorization server for token -class PollServer : public QObject -{ +class PollServer : public QObject { Q_OBJECT -public: - explicit PollServer(QNetworkAccessManager * manager, const QNetworkRequest &request, const QByteArray & payload, int expiresIn, QObject *parent = 0); + public: + explicit PollServer(QNetworkAccessManager* manager, + const QNetworkRequest& request, + const QByteArray& payload, + int expiresIn, + QObject* parent = 0); /// Seconds to wait between polling requests Q_PROPERTY(int interval READ interval WRITE setInterval) int interval() const; void setInterval(int interval); -signals: + signals: void verificationReceived(QMap); - void serverClosed(bool); // whether it has found parameters + void serverClosed(bool); // whether it has found parameters -public slots: + public slots: void startPolling(); -protected slots: + protected slots: void onPollTimeout(); void onExpiration(); void onReplyFinished(); -protected: - QNetworkAccessManager *manager_; + protected: + QNetworkAccessManager* manager_; const QNetworkRequest request_; const QByteArray payload_; const int expiresIn_; @@ -45,4 +48,4 @@ protected: QTimer pollTimer; }; -} +} // namespace Katabasis diff --git a/libraries/katabasis/include/katabasis/Reply.h b/libraries/katabasis/include/katabasis/Reply.h index 415cf4ec8..89ee90e98 100644 --- a/libraries/katabasis/include/katabasis/Reply.h +++ b/libraries/katabasis/include/katabasis/Reply.h @@ -1,38 +1,38 @@ #pragma once -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include namespace Katabasis { constexpr int defaultTimeout = 30 * 1000; /// A network request/reply pair that can time out. -class Reply: public QTimer { +class Reply : public QTimer { Q_OBJECT -public: - Reply(QNetworkReply *reply, int timeOut = defaultTimeout, QObject *parent = 0); + public: + Reply(QNetworkReply* reply, int timeOut = defaultTimeout, QObject* parent = 0); -signals: + signals: void error(QNetworkReply::NetworkError); -public slots: + public slots: /// When time out occurs, the QNetworkReply's error() signal is triggered. void onTimeOut(); -public: - QNetworkReply *reply; + public: + QNetworkReply* reply; bool timedOut = false; }; /// List of O2Replies. class ReplyList { -public: + public: ReplyList() { ignoreSslErrors_ = false; } /// Destructor. @@ -40,24 +40,24 @@ public: virtual ~ReplyList(); /// Create a new O2Reply from a QNetworkReply, and add it to this list. - void add(QNetworkReply *reply, int timeOut = defaultTimeout); + void add(QNetworkReply* reply, int timeOut = defaultTimeout); /// Add an O2Reply to the list, while taking ownership of it. - void add(Reply *reply); + void add(Reply* reply); /// Remove item from the list that corresponds to a QNetworkReply. - void remove(QNetworkReply *reply); + void remove(QNetworkReply* reply); /// Find an O2Reply in the list, corresponding to a QNetworkReply. /// @return Matching O2Reply or NULL. - Reply *find(QNetworkReply *reply); + Reply* find(QNetworkReply* reply); bool ignoreSslErrors(); void setIgnoreSslErrors(bool ignoreSslErrors); -protected: - QList replies_; + protected: + QList replies_; bool ignoreSslErrors_; }; -} +} // namespace Katabasis diff --git a/libraries/katabasis/include/katabasis/RequestParameter.h b/libraries/katabasis/include/katabasis/RequestParameter.h index ca36934a3..1d23cf0e1 100644 --- a/libraries/katabasis/include/katabasis/RequestParameter.h +++ b/libraries/katabasis/include/katabasis/RequestParameter.h @@ -4,12 +4,10 @@ namespace Katabasis { /// Request parameter (name-value pair) participating in authentication. struct RequestParameter { - RequestParameter(const QByteArray &n, const QByteArray &v): name(n), value(v) {} - bool operator <(const RequestParameter &other) const { - return (name == other.name)? (value < other.value): (name < other.name); - } + RequestParameter(const QByteArray& n, const QByteArray& v) : name(n), value(v) {} + bool operator<(const RequestParameter& other) const { return (name == other.name) ? (value < other.value) : (name < other.name); } QByteArray name; QByteArray value; }; -} +} // namespace Katabasis diff --git a/libraries/katabasis/src/DeviceFlow.cpp b/libraries/katabasis/src/DeviceFlow.cpp index f49fcb7d7..3b9d9c53f 100644 --- a/libraries/katabasis/src/DeviceFlow.cpp +++ b/libraries/katabasis/src/DeviceFlow.cpp @@ -1,26 +1,26 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include "katabasis/DeviceFlow.h" -#include "katabasis/PollServer.h" #include "katabasis/Globals.h" +#include "katabasis/PollServer.h" -#include "KatabasisLogging.h" #include "JsonResponse.h" +#include "KatabasisLogging.h" namespace { @@ -43,10 +43,11 @@ bool hasMandatoryDeviceAuthParams(const QVariantMap& params) return true; } -QByteArray createQueryParameters(const QList ¶meters) { +QByteArray createQueryParameters(const QList& parameters) +{ QByteArray ret; bool first = true; - for( auto & h: parameters) { + for (auto& h : parameters) { if (first) { first = false; } else { @@ -56,32 +57,35 @@ QByteArray createQueryParameters(const QList ¶m } return ret; } -} +} // namespace namespace Katabasis { -DeviceFlow::DeviceFlow(Options & opts, Token & token, QObject *parent, QNetworkAccessManager *manager) : QObject(parent), token_(token) { +DeviceFlow::DeviceFlow(Options& opts, Token& token, QObject* parent, QNetworkAccessManager* manager) : QObject(parent), token_(token) +{ manager_ = manager ? manager : new QNetworkAccessManager(this); qRegisterMetaType("QNetworkReply::NetworkError"); options_ = opts; } -bool DeviceFlow::linked() { +bool DeviceFlow::linked() +{ return token_.validity != Validity::None; } -void DeviceFlow::setLinked(bool v) { - qDebug() << "DeviceFlow::setLinked:" << (v? "true": "false"); +void DeviceFlow::setLinked(bool v) +{ + qDebug() << "DeviceFlow::setLinked:" << (v ? "true" : "false"); token_.validity = v ? Validity::Certain : Validity::None; } void DeviceFlow::updateActivity(Activity activity) { - if(activity_ == activity) { + if (activity_ == activity) { return; } activity_ = activity; - switch(activity) { + switch (activity) { case Katabasis::Activity::Idle: case Katabasis::Activity::LoggingIn: case Katabasis::Activity::LoggingOut: @@ -103,22 +107,26 @@ void DeviceFlow::updateActivity(Activity activity) emit activityChanged(activity_); } -QString DeviceFlow::token() { +QString DeviceFlow::token() +{ return token_.token; } -void DeviceFlow::setToken(const QString &v) { +void DeviceFlow::setToken(const QString& v) +{ token_.token = v; } -QVariantMap DeviceFlow::extraTokens() { +QVariantMap DeviceFlow::extraTokens() +{ return token_.extra; } -void DeviceFlow::setExtraTokens(QVariantMap extraTokens) { +void DeviceFlow::setExtraTokens(QVariantMap extraTokens) +{ token_.extra = extraTokens; } -void DeviceFlow::setPollServer(PollServer *server) +void DeviceFlow::setPollServer(PollServer* server) { if (pollServer_) pollServer_->deleteLater(); @@ -126,7 +134,7 @@ void DeviceFlow::setPollServer(PollServer *server) pollServer_ = server; } -PollServer *DeviceFlow::pollServer() const +PollServer* DeviceFlow::pollServer() const { return pollServer_; } @@ -136,7 +144,7 @@ QVariantMap DeviceFlow::extraRequestParams() return extraReqParams_; } -void DeviceFlow::setExtraRequestParams(const QVariantMap &value) +void DeviceFlow::setExtraRequestParams(const QVariantMap& value) { extraReqParams_ = value; } @@ -149,13 +157,14 @@ QString DeviceFlow::grantType() return OAUTH2_GRANT_TYPE_DEVICE; } -void DeviceFlow::setGrantType(const QString &value) +void DeviceFlow::setGrantType(const QString& value) { grantType_ = value; } // First get the URL and token to display to the user -void DeviceFlow::login() { +void DeviceFlow::login() +{ qDebug() << "DeviceFlow::link"; updateActivity(Activity::LoggingIn); @@ -173,7 +182,7 @@ void DeviceFlow::login() { QUrl url(options_.authorizationUrl); QNetworkRequest deviceRequest(url); deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); - QNetworkReply *tokenReply = manager_->post(deviceRequest, payload); + QNetworkReply* tokenReply = manager_->post(deviceRequest, payload); connect(tokenReply, &QNetworkReply::finished, this, &DeviceFlow::onDeviceAuthReplyFinished, Qt::QueuedConnection); } @@ -182,19 +191,18 @@ void DeviceFlow::login() { void DeviceFlow::onDeviceAuthReplyFinished() { qDebug() << "DeviceFlow::onDeviceAuthReplyFinished"; - QNetworkReply *tokenReply = qobject_cast(sender()); - if (!tokenReply) - { - qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: reply is null"; - return; + QNetworkReply* tokenReply = qobject_cast(sender()); + if (!tokenReply) { + qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: reply is null"; + return; } if (tokenReply->error() == QNetworkReply::NoError) { QByteArray replyData = tokenReply->readAll(); // Dump replyData // SENSITIVE DATA in RelWithDebInfo or Debug builds - //qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: replyData\n"; - //qDebug() << QString( replyData ); + // qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: replyData\n"; + // qDebug() << QString( replyData ); QVariantMap params = parseJsonResponse(replyData); @@ -202,7 +210,7 @@ void DeviceFlow::onDeviceAuthReplyFinished() qDebug() << "DeviceFlow::onDeviceAuthReplyFinished: Tokens returned:\n"; foreach (QString key, params.keys()) { // SENSITIVE DATA in RelWithDebInfo or Debug builds, so it is truncated first - qDebug() << key << ": "<< params.value( key ).toString(); + qDebug() << key << ": " << params.value(key).toString(); } // Check for mandatory parameters @@ -237,7 +245,7 @@ void DeviceFlow::onDeviceAuthReplyFinished() } // Spin up polling for the user completing the login flow out of band -void DeviceFlow::startPollServer(const QVariantMap ¶ms, int expiresIn) +void DeviceFlow::startPollServer(const QVariantMap& params, int expiresIn) { qDebug() << "DeviceFlow::startPollServer: device_ and user_code expires in" << expiresIn << "seconds"; @@ -250,14 +258,14 @@ void DeviceFlow::startPollServer(const QVariantMap ¶ms, int expiresIn) QList parameters; parameters.append(RequestParameter(OAUTH2_CLIENT_ID, options_.clientIdentifier.toUtf8())); - if ( !options_.clientSecret.isEmpty() ) { + if (!options_.clientSecret.isEmpty()) { parameters.append(RequestParameter(OAUTH2_CLIENT_SECRET, options_.clientSecret.toUtf8())); } parameters.append(RequestParameter(OAUTH2_CODE, deviceCode.toUtf8())); parameters.append(RequestParameter(OAUTH2_GRANT_TYPE, grantType.toUtf8())); QByteArray payload = createQueryParameters(parameters); - PollServer * pollServer = new PollServer(manager_, authRequest, payload, expiresIn, this); + PollServer* pollServer = new PollServer(manager_, authRequest, payload, expiresIn, this); if (params.contains(OAUTH2_INTERVAL)) { bool ok = false; int interval = params[OAUTH2_INTERVAL].toInt(&ok); @@ -272,7 +280,8 @@ void DeviceFlow::startPollServer(const QVariantMap ¶ms, int expiresIn) } // Once the user completes the flow, update the internal state and report it to observers -void DeviceFlow::onVerificationReceived(const QMap response) { +void DeviceFlow::onVerificationReceived(const QMap response) +{ qDebug() << "DeviceFlow::onVerificationReceived: Emitting closeBrowser()"; emit closeBrowser(); @@ -307,7 +316,7 @@ void DeviceFlow::onVerificationReceived(const QMap response) { // Or if the flow fails or the polling times out, update the internal state with error and report it to observers void DeviceFlow::serverHasClosed(bool paramsfound) { - if ( !paramsfound ) { + if (!paramsfound) { // server has probably timed out after receiving first response updateActivity(Activity::FailedHard); } @@ -315,7 +324,8 @@ void DeviceFlow::serverHasClosed(bool paramsfound) setPollServer(NULL); } -void DeviceFlow::logout() { +void DeviceFlow::logout() +{ qDebug() << "DeviceFlow::unlink"; updateActivity(Activity::LoggingOut); // FIXME: implement logout flows... if they exist @@ -323,24 +333,29 @@ void DeviceFlow::logout() { updateActivity(Activity::FailedHard); } -QDateTime DeviceFlow::expires() { +QDateTime DeviceFlow::expires() +{ return token_.notAfter; } -void DeviceFlow::setExpires(QDateTime v) { +void DeviceFlow::setExpires(QDateTime v) +{ token_.notAfter = v; } -QString DeviceFlow::refreshToken() { +QString DeviceFlow::refreshToken() +{ return token_.refresh_token; } -void DeviceFlow::setRefreshToken(const QString &v) { +void DeviceFlow::setRefreshToken(const QString& v) +{ qCDebug(katabasisCredentials) << "new refresh token:" << v; token_.refresh_token = v; } namespace { -QByteArray buildRequestBody(const QMap ¶meters) { +QByteArray buildRequestBody(const QMap& parameters) +{ QByteArray body; bool first = true; foreach (QString key, parameters.keys()) { @@ -354,9 +369,10 @@ QByteArray buildRequestBody(const QMap ¶meters) { } return body; } -} +} // namespace -bool DeviceFlow::refresh() { +bool DeviceFlow::refresh() +{ qDebug() << "DeviceFlow::refresh: Token: ..." << refreshToken().right(7); updateActivity(Activity::Refreshing); @@ -376,21 +392,22 @@ bool DeviceFlow::refresh() { refreshRequest.setHeader(QNetworkRequest::ContentTypeHeader, MIME_TYPE_XFORM); QMap parameters; parameters.insert(OAUTH2_CLIENT_ID, options_.clientIdentifier); - if ( !options_.clientSecret.isEmpty() ) { + if (!options_.clientSecret.isEmpty()) { parameters.insert(OAUTH2_CLIENT_SECRET, options_.clientSecret); } parameters.insert(OAUTH2_REFRESH_TOKEN, refreshToken()); parameters.insert(OAUTH2_GRANT_TYPE, OAUTH2_REFRESH_TOKEN); QByteArray data = buildRequestBody(parameters); - QNetworkReply *refreshReply = manager_->post(refreshRequest, data); + QNetworkReply* refreshReply = manager_->post(refreshRequest, data); timedReplies_.add(refreshReply); connect(refreshReply, &QNetworkReply::finished, this, &DeviceFlow::onRefreshFinished, Qt::QueuedConnection); return true; } -void DeviceFlow::onRefreshFinished() { - QNetworkReply *refreshReply = qobject_cast(sender()); +void DeviceFlow::onRefreshFinished() +{ + QNetworkReply* refreshReply = qobject_cast(sender()); auto networkError = refreshReply->error(); if (networkError == QNetworkReply::NoError) { @@ -399,10 +416,9 @@ void DeviceFlow::onRefreshFinished() { setToken(tokens.value(OAUTH2_ACCESS_TOKEN).toString()); setExpires(QDateTime::currentDateTimeUtc().addSecs(tokens.value(OAUTH2_EXPIRES_IN).toInt())); QString refreshToken = tokens.value(OAUTH2_REFRESH_TOKEN).toString(); - if(!refreshToken.isEmpty()) { + if (!refreshToken.isEmpty()) { setRefreshToken(refreshToken); - } - else { + } else { qDebug() << "No new refresh token. Keep the old one."; } timedReplies_.remove(refreshReply); @@ -415,37 +431,37 @@ void DeviceFlow::onRefreshFinished() { } } -void DeviceFlow::onRefreshError(QNetworkReply::NetworkError error, QNetworkReply *refreshReply) { +void DeviceFlow::onRefreshError(QNetworkReply::NetworkError error, QNetworkReply* refreshReply) +{ QString errorString = "No Reply"; - if(refreshReply) { + if (refreshReply) { timedReplies_.remove(refreshReply); errorString = refreshReply->errorString(); } - switch (error) - { - // used for invalid credentials and similar errors. Fall through. - case QNetworkReply::AuthenticationRequiredError: - case QNetworkReply::ContentAccessDenied: - case QNetworkReply::ContentOperationNotPermittedError: - case QNetworkReply::ProtocolInvalidOperationError: - updateActivity(Activity::FailedHard); - break; - case QNetworkReply::ContentGoneError: { - updateActivity(Activity::FailedGone); - break; + switch (error) { + // used for invalid credentials and similar errors. Fall through. + case QNetworkReply::AuthenticationRequiredError: + case QNetworkReply::ContentAccessDenied: + case QNetworkReply::ContentOperationNotPermittedError: + case QNetworkReply::ProtocolInvalidOperationError: + updateActivity(Activity::FailedHard); + break; + case QNetworkReply::ContentGoneError: { + updateActivity(Activity::FailedGone); + break; + } + case QNetworkReply::TimeoutError: + case QNetworkReply::OperationCanceledError: + case QNetworkReply::SslHandshakeFailedError: + default: + updateActivity(Activity::FailedSoft); + return; } - case QNetworkReply::TimeoutError: - case QNetworkReply::OperationCanceledError: - case QNetworkReply::SslHandshakeFailedError: - default: - updateActivity(Activity::FailedSoft); - return; - } - if(refreshReply) { + if (refreshReply) { refreshReply->deleteLater(); } qDebug() << "DeviceFlow::onRefreshFinished: Error" << static_cast(error) << " - " << errorString; } -} +} // namespace Katabasis diff --git a/libraries/katabasis/src/JsonResponse.cpp b/libraries/katabasis/src/JsonResponse.cpp index 63384d121..6840627ac 100644 --- a/libraries/katabasis/src/JsonResponse.cpp +++ b/libraries/katabasis/src/JsonResponse.cpp @@ -7,7 +7,8 @@ namespace Katabasis { -QVariantMap parseJsonResponse(const QByteArray &data) { +QVariantMap parseJsonResponse(const QByteArray& data) +{ QJsonParseError err; QJsonDocument doc = QJsonDocument::fromJson(data, &err); if (err.error != QJsonParseError::NoError) { @@ -23,4 +24,4 @@ QVariantMap parseJsonResponse(const QByteArray &data) { return doc.object().toVariantMap(); } -} +} // namespace Katabasis diff --git a/libraries/katabasis/src/JsonResponse.h b/libraries/katabasis/src/JsonResponse.h index e7fe7e30d..ff3471752 100644 --- a/libraries/katabasis/src/JsonResponse.h +++ b/libraries/katabasis/src/JsonResponse.h @@ -6,7 +6,7 @@ class QByteArray; namespace Katabasis { - /// Parse JSON data into a QVariantMap -QVariantMap parseJsonResponse(const QByteArray &data); +/// Parse JSON data into a QVariantMap +QVariantMap parseJsonResponse(const QByteArray& data); -} +} // namespace Katabasis diff --git a/libraries/katabasis/src/PollServer.cpp b/libraries/katabasis/src/PollServer.cpp index 1083c5994..c1c316df9 100644 --- a/libraries/katabasis/src/PollServer.cpp +++ b/libraries/katabasis/src/PollServer.cpp @@ -1,30 +1,28 @@ #include #include -#include "katabasis/PollServer.h" #include "JsonResponse.h" +#include "katabasis/PollServer.h" namespace { -QMap toVerificationParams(const QVariantMap &map) +QMap toVerificationParams(const QVariantMap& map) { QMap params; - for (QVariantMap::const_iterator i = map.constBegin(); - i != map.constEnd(); ++i) - { + for (QVariantMap::const_iterator i = map.constBegin(); i != map.constEnd(); ++i) { params[i.key()] = i.value().toString(); } return params; } -} +} // namespace namespace Katabasis { -PollServer::PollServer(QNetworkAccessManager *manager, const QNetworkRequest &request, const QByteArray &payload, int expiresIn, QObject *parent) - : QObject(parent) - , manager_(manager) - , request_(request) - , payload_(payload) - , expiresIn_(expiresIn) +PollServer::PollServer(QNetworkAccessManager* manager, + const QNetworkRequest& request, + const QByteArray& payload, + int expiresIn, + QObject* parent) + : QObject(parent), manager_(manager), request_(request), payload_(payload), expiresIn_(expiresIn) { expirationTimer.setTimerType(Qt::VeryCoarseTimer); expirationTimer.setInterval(expiresIn * 1000); @@ -58,7 +56,7 @@ void PollServer::startPolling() void PollServer::onPollTimeout() { qDebug() << "PollServer::onPollTimeout: retrying"; - QNetworkReply * reply = manager_->post(request_, payload_); + QNetworkReply* reply = manager_->post(request_, payload_); connect(reply, SIGNAL(finished()), this, SLOT(onReplyFinished())); } @@ -70,7 +68,7 @@ void PollServer::onExpiration() void PollServer::onReplyFinished() { - QNetworkReply *reply = qobject_cast(sender()); + QNetworkReply* reply = qobject_cast(sender()); if (!reply) { qDebug() << "PollServer::onReplyFinished: reply is null"; @@ -93,8 +91,7 @@ void PollServer::onReplyFinished() // polling interval on each such connection timeout, is RECOMMENDED." setInterval(interval() * 2); pollTimer.start(); - } - else { + } else { QString error = params.value("error"); if (error == "slow_down") { // rfc8628#section-3.2 @@ -103,14 +100,12 @@ void PollServer::onReplyFinished() // be increased by 5 seconds for this and all subsequent requests." setInterval(interval() + 5); pollTimer.start(); - } - else if (error == "authorization_pending") { + } else if (error == "authorization_pending") { // keep trying - rfc8628#section-3.2 // "The authorization request is still pending as the end user hasn't // yet completed the user-interaction steps (Section 3.3)." pollTimer.start(); - } - else { + } else { expirationTimer.stop(); emit serverClosed(true); // let O2 handle the other cases @@ -120,4 +115,4 @@ void PollServer::onReplyFinished() reply->deleteLater(); } -} +} // namespace Katabasis diff --git a/libraries/katabasis/src/Reply.cpp b/libraries/katabasis/src/Reply.cpp index c26079005..4a5017e22 100644 --- a/libraries/katabasis/src/Reply.cpp +++ b/libraries/katabasis/src/Reply.cpp @@ -1,42 +1,48 @@ -#include #include +#include #include "katabasis/Reply.h" namespace Katabasis { -Reply::Reply(QNetworkReply *r, int timeOut, QObject *parent): QTimer(parent), reply(r) { +Reply::Reply(QNetworkReply* r, int timeOut, QObject* parent) : QTimer(parent), reply(r) +{ setSingleShot(true); connect(this, &Reply::timeout, this, &Reply::onTimeOut, Qt::QueuedConnection); start(timeOut); } -void Reply::onTimeOut() { +void Reply::onTimeOut() +{ timedOut = true; reply->abort(); } // ---------------------------- -ReplyList::~ReplyList() { - foreach (Reply *timedReply, replies_) { +ReplyList::~ReplyList() +{ + foreach (Reply* timedReply, replies_) { delete timedReply; } } -void ReplyList::add(QNetworkReply *reply, int timeOut) { +void ReplyList::add(QNetworkReply* reply, int timeOut) +{ if (reply && ignoreSslErrors()) { reply->ignoreSslErrors(); } add(new Reply(reply, timeOut)); } -void ReplyList::add(Reply *reply) { +void ReplyList::add(Reply* reply) +{ replies_.append(reply); } -void ReplyList::remove(QNetworkReply *reply) { - Reply *o2Reply = find(reply); +void ReplyList::remove(QNetworkReply* reply) +{ + Reply* o2Reply = find(reply); if (o2Reply) { o2Reply->stop(); (void)replies_.removeOne(o2Reply); @@ -45,8 +51,9 @@ void ReplyList::remove(QNetworkReply *reply) { } } -Reply *ReplyList::find(QNetworkReply *reply) { - foreach (Reply *timedReply, replies_) { +Reply* ReplyList::find(QNetworkReply* reply) +{ + foreach (Reply* timedReply, replies_) { if (timedReply->reply == reply) { return timedReply; } @@ -64,4 +71,4 @@ void ReplyList::setIgnoreSslErrors(bool ignoreSslErrors) ignoreSslErrors_ = ignoreSslErrors; } -} +} // namespace Katabasis diff --git a/libraries/launcher/net/minecraft/Launcher.java b/libraries/launcher/net/minecraft/Launcher.java index 646e2e3ea..10cfa2ac0 100644 --- a/libraries/launcher/net/minecraft/Launcher.java +++ b/libraries/launcher/net/minecraft/Launcher.java @@ -71,7 +71,6 @@ import java.util.Map; * recommended. */ public final class Launcher extends Applet implements AppletStub { - private static final long serialVersionUID = 1L; private final Map params = new HashMap<>(); @@ -207,12 +206,10 @@ public final class Launcher extends Applet implements AppletStub { } @Override - public void paint(Graphics graphics) { - } + public void paint(Graphics graphics) {} @Override - public void update(Graphics graphics) { - } + public void update(Graphics graphics) {} public void setParameter(String key, String value) { params.put(key, value); @@ -221,5 +218,4 @@ public final class Launcher extends Applet implements AppletStub { public void setParameter(String key, boolean value) { setParameter(key, value ? "true" : "false"); } - } diff --git a/libraries/launcher/org/prismlauncher/EntryPoint.java b/libraries/launcher/org/prismlauncher/EntryPoint.java index 78804b3e8..4b59c1da6 100644 --- a/libraries/launcher/org/prismlauncher/EntryPoint.java +++ b/libraries/launcher/org/prismlauncher/EntryPoint.java @@ -54,10 +54,6 @@ package org.prismlauncher; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; - import org.prismlauncher.exception.ParseException; import org.prismlauncher.launcher.Launcher; import org.prismlauncher.launcher.impl.StandardLauncher; @@ -65,8 +61,11 @@ import org.prismlauncher.launcher.impl.legacy.LegacyLauncher; import org.prismlauncher.utils.Parameters; import org.prismlauncher.utils.logging.Log; -public final class EntryPoint { +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +public final class EntryPoint { public static void main(String[] args) { ExitCode code = listen(); @@ -160,19 +159,18 @@ public final class EntryPoint { return PreLaunchAction.PROCEED; } - private enum PreLaunchAction { - PROCEED, LAUNCH, ABORT - } + private enum PreLaunchAction { PROCEED, LAUNCH, ABORT } private enum ExitCode { - NORMAL(0), ABORT(1), ERROR(2), ILLEGAL_ARGUMENT(65); + NORMAL(0), + ABORT(1), + ERROR(2), + ILLEGAL_ARGUMENT(65); private final int numeric; ExitCode(int numeric) { this.numeric = numeric; } - } - } diff --git a/libraries/launcher/org/prismlauncher/exception/ParameterNotFoundException.java b/libraries/launcher/org/prismlauncher/exception/ParameterNotFoundException.java index 524076ff7..e9abc5ee3 100644 --- a/libraries/launcher/org/prismlauncher/exception/ParameterNotFoundException.java +++ b/libraries/launcher/org/prismlauncher/exception/ParameterNotFoundException.java @@ -38,11 +38,9 @@ package org.prismlauncher.exception; public final class ParameterNotFoundException extends IllegalArgumentException { - private static final long serialVersionUID = 1L; public ParameterNotFoundException(String key) { super(String.format("Required parameter '%s' was not found", key)); } - } diff --git a/libraries/launcher/org/prismlauncher/exception/ParseException.java b/libraries/launcher/org/prismlauncher/exception/ParseException.java index 4608fdd17..ae0578958 100644 --- a/libraries/launcher/org/prismlauncher/exception/ParseException.java +++ b/libraries/launcher/org/prismlauncher/exception/ParseException.java @@ -38,11 +38,9 @@ package org.prismlauncher.exception; public final class ParseException extends IllegalArgumentException { - private static final long serialVersionUID = 1L; public ParseException(String input, String format) { super(String.format("For input '%s' - should match '%s'", input, format)); } - } diff --git a/libraries/launcher/org/prismlauncher/launcher/Launcher.java b/libraries/launcher/org/prismlauncher/launcher/Launcher.java index 049a83d84..5dc0bb10d 100644 --- a/libraries/launcher/org/prismlauncher/launcher/Launcher.java +++ b/libraries/launcher/org/prismlauncher/launcher/Launcher.java @@ -38,7 +38,5 @@ package org.prismlauncher.launcher; public interface Launcher { - void launch() throws Throwable; - } diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java index 0c2153a9d..761837041 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/AbstractLauncher.java @@ -54,15 +54,14 @@ package org.prismlauncher.launcher.impl; -import java.util.ArrayList; -import java.util.List; - import org.prismlauncher.exception.ParseException; import org.prismlauncher.launcher.Launcher; import org.prismlauncher.utils.Parameters; -public abstract class AbstractLauncher implements Launcher { +import java.util.ArrayList; +import java.util.List; +public abstract class AbstractLauncher implements Launcher { private static final int DEFAULT_WINDOW_WIDTH = 854, DEFAULT_WINDOW_HEIGHT = 480; // parameters, separated from ParamBucket @@ -106,5 +105,4 @@ public abstract class AbstractLauncher implements Launcher { throw new ParseException(windowParams, "[width]x[height]"); } } - } diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java index 9436ff15e..186909123 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/StandardLauncher.java @@ -54,13 +54,12 @@ package org.prismlauncher.launcher.impl; -import java.lang.invoke.MethodHandle; - import org.prismlauncher.utils.Parameters; import org.prismlauncher.utils.ReflectionUtils; -public final class StandardLauncher extends AbstractLauncher { +import java.lang.invoke.MethodHandle; +public final class StandardLauncher extends AbstractLauncher { public StandardLauncher(Parameters params) { super(params); } @@ -87,5 +86,4 @@ public final class StandardLauncher extends AbstractLauncher { MethodHandle method = ReflectionUtils.findMainMethod(mainClassName); method.invokeExact(gameArgs.toArray(new String[0])); } - } diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java index c215e7fe0..6cfe35d86 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java @@ -54,6 +54,8 @@ package org.prismlauncher.launcher.impl.legacy; +import org.prismlauncher.utils.logging.Log; + import java.applet.Applet; import java.awt.Dimension; import java.awt.event.WindowAdapter; @@ -70,12 +72,9 @@ import java.util.List; import javax.imageio.ImageIO; import javax.swing.JFrame; -import org.prismlauncher.utils.logging.Log; - import net.minecraft.Launcher; public final class LegacyFrame extends JFrame { - private static final long serialVersionUID = 1L; private final Launcher launcher; @@ -96,8 +95,8 @@ public final class LegacyFrame extends JFrame { addWindowListener(new ForceExitHandler()); } - public void start(String user, String session, int width, int height, boolean maximize, String serverAddress, - String serverPort, boolean demo) { + public void start( + String user, String session, int width, int height, boolean maximize, String serverAddress, String serverPort, boolean demo) { // Implements support for launching in to multiplayer on classic servers using a // mpticket file generated by an external program and stored in the instance's // root folder. @@ -157,7 +156,6 @@ public final class LegacyFrame extends JFrame { } private final class ForceExitHandler extends WindowAdapter { - @Override public void windowClosing(WindowEvent event) { // FIXME better solution @@ -184,7 +182,5 @@ public final class LegacyFrame extends JFrame { // old minecraft versions can hang without this >_< System.exit(0); } - } - } diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java index d349177b2..5c5f86d47 100644 --- a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java +++ b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java @@ -55,22 +55,21 @@ package org.prismlauncher.launcher.impl.legacy; +import org.prismlauncher.launcher.impl.AbstractLauncher; +import org.prismlauncher.utils.Parameters; +import org.prismlauncher.utils.ReflectionUtils; +import org.prismlauncher.utils.logging.Log; + import java.io.File; import java.lang.invoke.MethodHandle; import java.lang.reflect.Field; import java.util.Collections; import java.util.List; -import org.prismlauncher.launcher.impl.AbstractLauncher; -import org.prismlauncher.utils.Parameters; -import org.prismlauncher.utils.ReflectionUtils; -import org.prismlauncher.utils.logging.Log; - /** * Used to launch old versions that support applets. */ public final class LegacyLauncher extends AbstractLauncher { - private final String user, session; private final String title; private final String appletClass; @@ -109,8 +108,7 @@ public final class LegacyLauncher extends AbstractLauncher { try { LegacyFrame window = new LegacyFrame(title, ReflectionUtils.createAppletClass(appletClass)); - window.start(user, session, width, height, maximize, serverAddress, serverPort, - gameArgs.contains("--demo")); + window.start(user, session, width, height, maximize, serverAddress, serverPort, gameArgs.contains("--demo")); return; } catch (Throwable e) { Log.error("Running applet wrapper failed with exception; falling back to main class", e); @@ -122,5 +120,4 @@ public final class LegacyLauncher extends AbstractLauncher { MethodHandle method = ReflectionUtils.findMainMethod(main); method.invokeExact(gameArgs.toArray(new String[0])); } - } diff --git a/libraries/launcher/org/prismlauncher/utils/Parameters.java b/libraries/launcher/org/prismlauncher/utils/Parameters.java index 6365753e2..2b0aed22a 100644 --- a/libraries/launcher/org/prismlauncher/utils/Parameters.java +++ b/libraries/launcher/org/prismlauncher/utils/Parameters.java @@ -54,15 +54,14 @@ package org.prismlauncher.utils; +import org.prismlauncher.exception.ParameterNotFoundException; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.prismlauncher.exception.ParameterNotFoundException; - public final class Parameters { - private final Map> map = new HashMap<>(); public void add(String key, String value) { @@ -112,5 +111,4 @@ public final class Parameters { return params.get(0); } - } diff --git a/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java b/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java index dd212ef93..ad222bd2a 100644 --- a/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java +++ b/libraries/launcher/org/prismlauncher/utils/ReflectionUtils.java @@ -54,6 +54,8 @@ package org.prismlauncher.utils; +import org.prismlauncher.utils.logging.Log; + import java.applet.Applet; import java.io.File; import java.lang.invoke.MethodHandle; @@ -62,10 +64,7 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import org.prismlauncher.utils.logging.Log; - public final class ReflectionUtils { - private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private static final ClassLoader LOADER = ClassLoader.getSystemClassLoader(); @@ -146,9 +145,7 @@ public final class ReflectionUtils { * @throws NoSuchMethodException * @throws IllegalAccessException */ - public static MethodHandle findMainMethod(String clazz) - throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException { + public static MethodHandle findMainMethod(String clazz) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException { return findMainMethod(LOADER.loadClass(clazz)); } - } diff --git a/libraries/launcher/org/prismlauncher/utils/logging/Level.java b/libraries/launcher/org/prismlauncher/utils/logging/Level.java index 552b0b55e..7af9c34a0 100644 --- a/libraries/launcher/org/prismlauncher/utils/logging/Level.java +++ b/libraries/launcher/org/prismlauncher/utils/logging/Level.java @@ -55,5 +55,4 @@ public enum Level { this.name = name; this.stderr = stderr; } - } diff --git a/libraries/launcher/org/prismlauncher/utils/logging/Log.java b/libraries/launcher/org/prismlauncher/utils/logging/Log.java index e3aa538b2..992698e55 100644 --- a/libraries/launcher/org/prismlauncher/utils/logging/Log.java +++ b/libraries/launcher/org/prismlauncher/utils/logging/Log.java @@ -43,9 +43,8 @@ import java.io.PrintStream; * messages. */ public final class Log { - // original before possibly overridden by MC - private static final PrintStream OUT = new PrintStream(System.out), ERR = new PrintStream(System.err); + private static final PrintStream OUT = new PrintStream(System.out), ERR = new PrintStream(System.err); private static final boolean DEBUG = Boolean.getBoolean("org.prismlauncher.debug"); public static void launcher(String message) { @@ -100,5 +99,4 @@ public final class Log { else OUT.println(message); } - } diff --git a/libraries/murmur2/src/MurmurHash2.h b/libraries/murmur2/src/MurmurHash2.h index dc2c9681d..5d4f48713 100644 --- a/libraries/murmur2/src/MurmurHash2.h +++ b/libraries/murmur2/src/MurmurHash2.h @@ -16,11 +16,11 @@ //----------------------------------------------------------------------------- #define KiB 1024 -#define MiB 1024*KiB +#define MiB 1024 * KiB uint32_t MurmurHash2( std::ifstream&& file_stream, - std::size_t buffer_size = 4*MiB, + std::size_t buffer_size = 4 * MiB, std::function filter_out = [](char) { return false; }); struct IncrementalHashInfo { diff --git a/libraries/rainbow/include/rainbow.h b/libraries/rainbow/include/rainbow.h index 57be87f14..a75e53ee7 100644 --- a/libraries/rainbow/include/rainbow.h +++ b/libraries/rainbow/include/rainbow.h @@ -29,8 +29,7 @@ class QColor; /** * A set of methods used to work with colors. */ -namespace Rainbow -{ +namespace Rainbow { /** * Calculate the luma of a color. Luma is weighted sum of gamma-adjusted * R'G'B' components of a color. The result is similar to qGray. The range @@ -41,14 +40,13 @@ namespace Rainbow * * @see http://en.wikipedia.org/wiki/Luma_(video) */ -qreal luma(const QColor &); +qreal luma(const QColor&); /** * Calculate hue, chroma and luma of a color in one call. * @since 5.0 */ -void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma, - qreal *alpha = 0); +void getHcy(const QColor&, qreal* hue, qreal* chroma, qreal* luma, qreal* alpha = 0); /** * Calculate the contrast ratio between two colors, according to the @@ -62,7 +60,7 @@ void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma, * * @see Rainbow::luma */ -qreal contrastRatio(const QColor &, const QColor &); +qreal contrastRatio(const QColor&, const QColor&); /** * Adjust the luma of a color by changing its distance from white. @@ -79,8 +77,7 @@ qreal contrastRatio(const QColor &, const QColor &); * component of the color; 1.0 means no change, 0.0 maximizes chroma * @see Rainbow::shade */ -QColor -lighten(const QColor &, qreal amount = 0.5, qreal chromaInverseGain = 1.0); +QColor lighten(const QColor&, qreal amount = 0.5, qreal chromaInverseGain = 1.0); /** * Adjust the luma of a color by changing its distance from black. @@ -97,7 +94,7 @@ lighten(const QColor &, qreal amount = 0.5, qreal chromaInverseGain = 1.0); * component of the color; 1.0 means no change, 0.0 minimizes chroma * @see Rainbow::shade */ -QColor darken(const QColor &, qreal amount = 0.5, qreal chromaGain = 1.0); +QColor darken(const QColor&, qreal amount = 0.5, qreal chromaGain = 1.0); /** * Adjust the luma and chroma components of a color. The amount is added @@ -111,7 +108,7 @@ QColor darken(const QColor &, qreal amount = 0.5, qreal chromaGain = 1.0); * 1.0 maximizes chroma * @see Rainbow::luma */ -QColor shade(const QColor &, qreal lumaAmount, qreal chromaAmount = 0.0); +QColor shade(const QColor&, qreal lumaAmount, qreal chromaAmount = 0.0); /** * Create a new color by tinting one color with another. This function is @@ -125,7 +122,7 @@ QColor shade(const QColor &, qreal lumaAmount, qreal chromaAmount = 0.0); * @param amount how strongly to tint the base; 0.0 gives @p base, * 1.0 gives @p color */ -QColor tint(const QColor &base, const QColor &color, qreal amount = 0.3); +QColor tint(const QColor& base, const QColor& color, qreal amount = 0.3); /** * Blend two colors into a new color by linear combination. @@ -138,7 +135,7 @@ QColor tint(const QColor &base, const QColor &color, qreal amount = 0.3); * @p bias >= 1 gives @p c2. @p bias == 0.5 gives a 50% blend of @p c1 * and @p c2. */ -QColor mix(const QColor &c1, const QColor &c2, qreal bias = 0.5); +QColor mix(const QColor& c1, const QColor& c2, qreal bias = 0.5); /** * Blend two colors into a new color by painting the second color over the @@ -152,7 +149,5 @@ QColor mix(const QColor &c1, const QColor &c2, qreal bias = 0.5); * @param paint the color to be overlayed onto the base color. * @param comp the CompositionMode used to do the blending. */ -QColor -overlayColors(const QColor &base, const QColor &paint, - QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver); -} +QColor overlayColors(const QColor& base, const QColor& paint, QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver); +} // namespace Rainbow diff --git a/libraries/rainbow/src/rainbow.cpp b/libraries/rainbow/src/rainbow.cpp index 9054d71dd..5ef196520 100644 --- a/libraries/rainbow/src/rainbow.cpp +++ b/libraries/rainbow/src/rainbow.cpp @@ -25,11 +25,11 @@ #include #include -#include // qIsNaN +#include // qIsNaN #include -//BEGIN internal helper functions +// BEGIN internal helper functions static inline qreal wrap(qreal a, qreal d = 1.0) { @@ -44,23 +44,21 @@ static inline qreal normalize(qreal a) return (a < 1.0 ? (a > 0.0 ? a : 0.0) : 1.0); } - /////////////////////////////////////////////////////////////////////////////// // HCY color space -#define HCY_REC 709 // use 709 for now +#define HCY_REC 709 // use 709 for now #if HCY_REC == 601 -static const qreal yc[3] = {0.299, 0.587, 0.114}; +static const qreal yc[3] = { 0.299, 0.587, 0.114 }; #elif HCY_REC == 709 -static const qreal yc[3] = {0.2126, 0.7152, 0.0722}; -#else // use Qt values -static const qreal yc[3] = {0.34375, 0.5, 0.15625}; +static const qreal yc[3] = { 0.2126, 0.7152, 0.0722 }; +#else // use Qt values +static const qreal yc[3] = { 0.34375, 0.5, 0.15625 }; #endif -class KHCY -{ -public: - explicit KHCY(const QColor &color) +class KHCY { + public: + explicit KHCY(const QColor& color) { qreal r = gamma(color.redF()); qreal g = gamma(color.greenF()); @@ -74,30 +72,20 @@ public: qreal p = qMax(qMax(r, g), b); qreal n = qMin(qMin(r, g), b); qreal d = 6.0 * (p - n); - if (n == p) - { + if (n == p) { h = 0.0; - } - else if (r == p) - { + } else if (r == p) { h = ((g - b) / d); - } - else if (g == p) - { + } else if (g == p) { h = ((b - r) / d) + (1.0 / 3.0); - } - else - { + } else { h = ((r - g) / d) + (2.0 / 3.0); } // chroma component - if (r == g && g == b) - { + if (r == g && g == b) { c = 0.0; - } - else - { + } else { c = qMax((y - n) / y, (p - y) / (1 - y)); } } @@ -118,145 +106,103 @@ public: // calculate some needed variables qreal _hs = _h * 6.0, th, tm; - if (_hs < 1.0) - { + if (_hs < 1.0) { th = _hs; tm = yc[0] + yc[1] * th; - } - else if (_hs < 2.0) - { + } else if (_hs < 2.0) { th = 2.0 - _hs; tm = yc[1] + yc[0] * th; - } - else if (_hs < 3.0) - { + } else if (_hs < 3.0) { th = _hs - 2.0; tm = yc[1] + yc[2] * th; - } - else if (_hs < 4.0) - { + } else if (_hs < 4.0) { th = 4.0 - _hs; tm = yc[2] + yc[1] * th; - } - else if (_hs < 5.0) - { + } else if (_hs < 5.0) { th = _hs - 4.0; tm = yc[2] + yc[0] * th; - } - else - { + } else { th = 6.0 - _hs; tm = yc[0] + yc[2] * th; } // calculate RGB channels in sorted order qreal tn, to, tp; - if (tm >= _y) - { + if (tm >= _y) { tp = _y + _y * _c * (1.0 - tm) / tm; to = _y + _y * _c * (th - tm) / tm; tn = _y - (_y * _c); - } - else - { + } else { tp = _y + (1.0 - _y) * _c; to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm); tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm); } // return RGB channels in appropriate order - if (_hs < 1.0) - { + if (_hs < 1.0) { return QColor::fromRgbF(igamma(tp), igamma(to), igamma(tn), a); - } - else if (_hs < 2.0) - { + } else if (_hs < 2.0) { return QColor::fromRgbF(igamma(to), igamma(tp), igamma(tn), a); - } - else if (_hs < 3.0) - { + } else if (_hs < 3.0) { return QColor::fromRgbF(igamma(tn), igamma(tp), igamma(to), a); - } - else if (_hs < 4.0) - { + } else if (_hs < 4.0) { return QColor::fromRgbF(igamma(tn), igamma(to), igamma(tp), a); - } - else if (_hs < 5.0) - { + } else if (_hs < 5.0) { return QColor::fromRgbF(igamma(to), igamma(tn), igamma(tp), a); - } - else - { + } else { return QColor::fromRgbF(igamma(tp), igamma(tn), igamma(to), a); } } qreal h, c, y, a; - static qreal luma(const QColor &color) - { - return lumag(gamma(color.redF()), gamma(color.greenF()), gamma(color.blueF())); - } + static qreal luma(const QColor& color) { return lumag(gamma(color.redF()), gamma(color.greenF()), gamma(color.blueF())); } -private: - static qreal gamma(qreal n) - { - return pow(normalize(n), 2.2); - } - static qreal igamma(qreal n) - { - return pow(normalize(n), 1.0 / 2.2); - } - static qreal lumag(qreal r, qreal g, qreal b) - { - return r * yc[0] + g * yc[1] + b * yc[2]; - } + private: + static qreal gamma(qreal n) { return pow(normalize(n), 2.2); } + static qreal igamma(qreal n) { return pow(normalize(n), 1.0 / 2.2); } + static qreal lumag(qreal r, qreal g, qreal b) { return r * yc[0] + g * yc[1] + b * yc[2]; } }; static inline qreal mixQreal(qreal a, qreal b, qreal bias) { return a + (b - a) * bias; } -//END internal helper functions +// END internal helper functions -qreal Rainbow::luma(const QColor &color) +qreal Rainbow::luma(const QColor& color) { return KHCY::luma(color); } -void Rainbow::getHcy(const QColor &color, qreal *h, qreal *c, qreal *y, qreal *a) +void Rainbow::getHcy(const QColor& color, qreal* h, qreal* c, qreal* y, qreal* a) { - if (!c || !h || !y) - { + if (!c || !h || !y) { return; } KHCY khcy(color); *c = khcy.c; *h = khcy.h; *y = khcy.y; - if (a) - { + if (a) { *a = khcy.a; } } static qreal contrastRatioForLuma(qreal y1, qreal y2) { - if (y1 > y2) - { + if (y1 > y2) { return (y1 + 0.05) / (y2 + 0.05); - } - else - { + } else { return (y2 + 0.05) / (y1 + 0.05); } } -qreal Rainbow::contrastRatio(const QColor &c1, const QColor &c2) +qreal Rainbow::contrastRatio(const QColor& c1, const QColor& c2) { return contrastRatioForLuma(luma(c1), luma(c2)); } -QColor Rainbow::lighten(const QColor &color, qreal ky, qreal kc) +QColor Rainbow::lighten(const QColor& color, qreal ky, qreal kc) { KHCY c(color); c.y = 1.0 - normalize((1.0 - c.y) * (1.0 - ky)); @@ -264,7 +210,7 @@ QColor Rainbow::lighten(const QColor &color, qreal ky, qreal kc) return c.qColor(); } -QColor Rainbow::darken(const QColor &color, qreal ky, qreal kc) +QColor Rainbow::darken(const QColor& color, qreal ky, qreal kc) { KHCY c(color); c.y = normalize(c.y * (1.0 - ky)); @@ -272,7 +218,7 @@ QColor Rainbow::darken(const QColor &color, qreal ky, qreal kc) return c.qColor(); } -QColor Rainbow::shade(const QColor &color, qreal ky, qreal kc) +QColor Rainbow::shade(const QColor& color, qreal ky, qreal kc) { KHCY c(color); c.y = normalize(c.y + ky); @@ -280,7 +226,7 @@ QColor Rainbow::shade(const QColor &color, qreal ky, qreal kc) return c.qColor(); } -static QColor tintHelper(const QColor &base, qreal baseLuma, const QColor &color, qreal amount) +static QColor tintHelper(const QColor& base, qreal baseLuma, const QColor& color, qreal amount) { KHCY result(Rainbow::mix(base, color, pow(amount, 0.3))); result.y = mixQreal(baseLuma, result.y, amount); @@ -288,55 +234,45 @@ static QColor tintHelper(const QColor &base, qreal baseLuma, const QColor &color return result.qColor(); } -QColor Rainbow::tint(const QColor &base, const QColor &color, qreal amount) +QColor Rainbow::tint(const QColor& base, const QColor& color, qreal amount) { - if (amount <= 0.0) - { + if (amount <= 0.0) { return base; } - if (amount >= 1.0) - { + if (amount >= 1.0) { return color; } - if (qIsNaN(amount)) - { + if (qIsNaN(amount)) { return base; } - qreal baseLuma = luma(base); // cache value because luma call is expensive + qreal baseLuma = luma(base); // cache value because luma call is expensive double ri = contrastRatioForLuma(baseLuma, luma(color)); double rg = 1.0 + ((ri + 1.0) * amount * amount * amount); double u = 1.0, l = 0.0; QColor result; - for (int i = 12; i; --i) - { + for (int i = 12; i; --i) { double a = 0.5 * (l + u); result = tintHelper(base, baseLuma, color, a); double ra = contrastRatioForLuma(baseLuma, luma(result)); - if (ra > rg) - { + if (ra > rg) { u = a; - } - else - { + } else { l = a; } } return result; } -QColor Rainbow::mix(const QColor &c1, const QColor &c2, qreal bias) +QColor Rainbow::mix(const QColor& c1, const QColor& c2, qreal bias) { - if (bias <= 0.0) - { + if (bias <= 0.0) { return c1; } - if (bias >= 1.0) - { + if (bias >= 1.0) { return c2; } - if (qIsNaN(bias)) - { + if (qIsNaN(bias)) { return c1; } @@ -348,15 +284,14 @@ QColor Rainbow::mix(const QColor &c1, const QColor &c2, qreal bias) return QColor::fromRgbF(r, g, b, a); } -QColor Rainbow::overlayColors(const QColor &base, const QColor &paint, - QPainter::CompositionMode comp) +QColor Rainbow::overlayColors(const QColor& base, const QColor& paint, QPainter::CompositionMode comp) { // This isn't the fastest way, but should be "fast enough". // It's also the only safe way to use QPainter::CompositionMode QImage img(1, 1, QImage::Format_ARGB32_Premultiplied); QPainter p(&img); QColor start = base; - start.setAlpha(255); // opaque + start.setAlpha(255); // opaque p.fillRect(0, 0, 1, 1, start); p.setCompositionMode(comp); p.fillRect(0, 0, 1, 1, paint); diff --git a/libraries/systeminfo/include/distroutils.h b/libraries/systeminfo/include/distroutils.h index 2e85f4336..caa2688cf 100644 --- a/libraries/systeminfo/include/distroutils.h +++ b/libraries/systeminfo/include/distroutils.h @@ -1,23 +1,22 @@ -#include "sys.h" #include +#include "sys.h" namespace Sys { -struct LsbInfo -{ +struct LsbInfo { QString distributor; QString version; QString description; QString codename; }; -bool main_lsb_info(LsbInfo & out); -bool fallback_lsb_info(Sys::LsbInfo & out); -void lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out); +bool main_lsb_info(LsbInfo& out); +bool fallback_lsb_info(Sys::LsbInfo& out); +void lsb_postprocess(Sys::LsbInfo& lsb, Sys::DistributionInfo& out); Sys::DistributionInfo read_lsb_release(); -QString _extract_distribution(const QString & x); -QString _extract_version(const QString & x); +QString _extract_distribution(const QString& x); +QString _extract_version(const QString& x); Sys::DistributionInfo read_legacy_release(); Sys::DistributionInfo read_os_release(); -} +} // namespace Sys diff --git a/libraries/systeminfo/include/sys.h b/libraries/systeminfo/include/sys.h index 6a6a7c82f..dfebbe90b 100644 --- a/libraries/systeminfo/include/sys.h +++ b/libraries/systeminfo/include/sys.h @@ -1,19 +1,12 @@ #pragma once #include -namespace Sys -{ +namespace Sys { const uint64_t mebibyte = 1024ull * 1024ull; -enum class KernelType { - Undetermined, - Windows, - Darwin, - Linux -}; +enum class KernelType { Undetermined, Windows, Darwin, Linux }; -struct KernelInfo -{ +struct KernelInfo { QString kernelName; QString kernelVersion; @@ -26,25 +19,18 @@ struct KernelInfo KernelInfo getKernelInfo(); -struct DistributionInfo -{ +struct DistributionInfo { DistributionInfo operator+(const DistributionInfo& rhs) const { DistributionInfo out; - if(!distributionName.isEmpty()) - { + if (!distributionName.isEmpty()) { out.distributionName = distributionName; - } - else - { + } else { out.distributionName = rhs.distributionName; } - if(!distributionVersion.isEmpty()) - { + if (!distributionVersion.isEmpty()) { out.distributionVersion = distributionVersion; - } - else - { + } else { out.distributionVersion = rhs.distributionVersion; } return out; @@ -56,4 +42,4 @@ struct DistributionInfo DistributionInfo getDistributionInfo(); uint64_t getSystemRam(); -} +} // namespace Sys diff --git a/libraries/systeminfo/src/distroutils.cpp b/libraries/systeminfo/src/distroutils.cpp index 05e1bb8cd..57e6c8320 100644 --- a/libraries/systeminfo/src/distroutils.cpp +++ b/libraries/systeminfo/src/distroutils.cpp @@ -29,14 +29,14 @@ SOFTWARE. #include "distroutils.h" -#include -#include -#include -#include -#include #include #include +#include +#include +#include #include +#include +#include #include @@ -46,38 +46,27 @@ Sys::DistributionInfo Sys::read_os_release() QStringList files = { "/etc/os-release", "/usr/lib/os-release" }; QString name; QString version; - for (auto &file: files) - { - if(!QFile::exists(file)) - { + for (auto& file : files) { + if (!QFile::exists(file)) { continue; } QSettings settings(file, QSettings::IniFormat); - if(settings.contains("ID")) - { + if (settings.contains("ID")) { name = settings.value("ID").toString().toLower(); - } - else if (settings.contains("NAME")) - { + } else if (settings.contains("NAME")) { name = settings.value("NAME").toString().toLower(); - } - else - { + } else { continue; } - if(settings.contains("VERSION_ID")) - { + if (settings.contains("VERSION_ID")) { version = settings.value("VERSION_ID").toString().toLower(); - } - else if(settings.contains("VERSION")) - { + } else if (settings.contains("VERSION")) { version = settings.value("VERSION").toString().toLower(); } break; } - if(name.isEmpty()) - { + if (name.isEmpty()) { return out; } out.distributionName = name; @@ -85,33 +74,31 @@ Sys::DistributionInfo Sys::read_os_release() return out; } -bool Sys::main_lsb_info(Sys::LsbInfo & out) +bool Sys::main_lsb_info(Sys::LsbInfo& out) { - int status=0; + int status = 0; QProcess lsbProcess; QStringList arguments; arguments << "-a"; - lsbProcess.start("lsb_release", arguments); + lsbProcess.start("lsb_release", arguments); lsbProcess.waitForFinished(); status = lsbProcess.exitStatus(); QString output = lsbProcess.readAllStandardOutput(); qDebug() << output; lsbProcess.close(); - if(status == 0) - { + if (status == 0) { auto lines = output.split('\n'); - for(auto line:lines) - { + for (auto line : lines) { int index = line.indexOf(':'); auto key = line.left(index).trimmed(); auto value = line.mid(index + 1).toLower().trimmed(); - if(key == "Distributor ID") + if (key == "Distributor ID") out.distributor = value; - else if(key == "Release") + else if (key == "Release") out.version = value; - else if(key == "Description") + else if (key == "Description") out.description = value; - else if(key == "Codename") + else if (key == "Codename") out.codename = value; } return !out.distributor.isEmpty(); @@ -119,7 +106,7 @@ bool Sys::main_lsb_info(Sys::LsbInfo & out) return false; } -bool Sys::fallback_lsb_info(Sys::LsbInfo & out) +bool Sys::fallback_lsb_info(Sys::LsbInfo& out) { // running lsb_release failed, try to read the file instead // /etc/lsb-release format, if the file even exists, is non-standard. @@ -127,15 +114,12 @@ bool Sys::fallback_lsb_info(Sys::LsbInfo & out) // distributions install an /etc/lsb-release as part of the base // distribution, but `lsb_release` remains optional. QString file = "/etc/lsb-release"; - if (QFile::exists(file)) - { + if (QFile::exists(file)) { QSettings settings(file, QSettings::IniFormat); - if(settings.contains("DISTRIB_ID")) - { + if (settings.contains("DISTRIB_ID")) { out.distributor = settings.value("DISTRIB_ID").toString().toLower(); } - if(settings.contains("DISTRIB_RELEASE")) - { + if (settings.contains("DISTRIB_RELEASE")) { out.version = settings.value("DISTRIB_RELEASE").toString().toLower(); } return !out.distributor.isEmpty(); @@ -143,48 +127,34 @@ bool Sys::fallback_lsb_info(Sys::LsbInfo & out) return false; } -void Sys::lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out) +void Sys::lsb_postprocess(Sys::LsbInfo& lsb, Sys::DistributionInfo& out) { QString dist = lsb.distributor; QString vers = lsb.version; - if(dist.startsWith("redhatenterprise")) - { + if (dist.startsWith("redhatenterprise")) { dist = "rhel"; - } - else if(dist == "archlinux") - { + } else if (dist == "archlinux") { dist = "arch"; - } - else if (dist.startsWith("suse")) - { - if(lsb.description.startsWith("opensuse")) - { + } else if (dist.startsWith("suse")) { + if (lsb.description.startsWith("opensuse")) { dist = "opensuse"; - } - else if (lsb.description.startsWith("suse linux enterprise")) - { + } else if (lsb.description.startsWith("suse linux enterprise")) { dist = "sles"; } - } - else if (dist == "debian" and vers == "testing") - { + } else if (dist == "debian" and vers == "testing") { vers = lsb.codename; - } - else - { + } else { // ubuntu, debian, gentoo, scientific, slackware, ... ? #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) auto parts = dist.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts); #else auto parts = dist.split(QRegularExpression("\\s+"), QString::SkipEmptyParts); #endif - if(parts.size()) - { + if (parts.size()) { dist = parts[0]; } } - if(!dist.isEmpty()) - { + if (!dist.isEmpty()) { out.distributionName = dist; out.distributionVersion = vers; } @@ -193,10 +163,8 @@ void Sys::lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out) Sys::DistributionInfo Sys::read_lsb_release() { LsbInfo lsb; - if(!main_lsb_info(lsb)) - { - if(!fallback_lsb_info(lsb)) - { + if (!main_lsb_info(lsb)) { + if (!fallback_lsb_info(lsb)) { return Sys::DistributionInfo(); } } @@ -205,15 +173,13 @@ Sys::DistributionInfo Sys::read_lsb_release() return out; } -QString Sys::_extract_distribution(const QString & x) +QString Sys::_extract_distribution(const QString& x) { QString release = x.toLower(); - if (release.startsWith("red hat enterprise")) - { + if (release.startsWith("red hat enterprise")) { return "rhel"; } - if (release.startsWith("suse linux enterprise")) - { + if (release.startsWith("suse linux enterprise")) { return "sles"; } #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) @@ -221,14 +187,13 @@ QString Sys::_extract_distribution(const QString & x) #else QStringList list = release.split(QRegularExpression("\\s+"), QString::SkipEmptyParts); #endif - if(list.size()) - { + if (list.size()) { return list[0]; } return QString(); } -QString Sys::_extract_version(const QString & x) +QString Sys::_extract_version(const QString& x) { QRegularExpression versionish_string(QRegularExpression::anchoredPattern("\\d+(?:\\.\\d+)*$")); #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) @@ -236,11 +201,9 @@ QString Sys::_extract_version(const QString & x) #else QStringList list = x.split(QRegularExpression("\\s+"), QString::SkipEmptyParts); #endif - for(int i = list.size() - 1; i >= 0; --i) - { + for (int i = list.size() - 1; i >= 0; --i) { QString chunk = list[i]; - if(versionish_string.match(chunk).hasMatch()) - { + if (versionish_string.match(chunk).hasMatch()) { return chunk; } } @@ -249,43 +212,35 @@ QString Sys::_extract_version(const QString & x) Sys::DistributionInfo Sys::read_legacy_release() { - struct checkEntry - { + struct checkEntry { QString file; - std::function extract_distro; - std::function extract_version; + std::function extract_distro; + std::function extract_version; }; - QList checks = - { - {"/etc/arch-release", [](const QString &){ return "arch";}, [](const QString &){ return "rolling";}}, - {"/etc/slackware-version", &Sys::_extract_distribution, &Sys::_extract_version}, - {QString(), &Sys::_extract_distribution, &Sys::_extract_version}, - {"/etc/debian_version", [](const QString &){ return "debian";}, [](const QString & x){ return x;}}, + QList checks = { + { "/etc/arch-release", [](const QString&) { return "arch"; }, [](const QString&) { return "rolling"; } }, + { "/etc/slackware-version", &Sys::_extract_distribution, &Sys::_extract_version }, + { QString(), &Sys::_extract_distribution, &Sys::_extract_version }, + { "/etc/debian_version", [](const QString&) { return "debian"; }, [](const QString& x) { return x; } }, }; - for(auto & check: checks) - { + for (auto& check : checks) { QStringList files; - if(check.file.isNull()) - { + if (check.file.isNull()) { QDir etcDir("/etc"); - etcDir.setNameFilters({"*-release"}); + etcDir.setNameFilters({ "*-release" }); etcDir.setFilter(QDir::Files | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden); files = etcDir.entryList(); - } - else - { + } else { files.append(check.file); } - for (auto file : files) - { + for (auto file : files) { QFile relfile(file); - if(!relfile.open(QIODevice::ReadOnly | QIODevice::Text)) + if (!relfile.open(QIODevice::ReadOnly | QIODevice::Text)) continue; QString contents = QString::fromUtf8(relfile.readLine()).trimmed(); QString dist = check.extract_distro(contents); QString vers = check.extract_version(contents); - if(!dist.isEmpty()) - { + if (!dist.isEmpty()) { Sys::DistributionInfo out; out.distributionName = dist; out.distributionVersion = vers; @@ -295,4 +250,3 @@ Sys::DistributionInfo Sys::read_legacy_release() } return Sys::DistributionInfo(); } - diff --git a/libraries/systeminfo/src/sys_apple.cpp b/libraries/systeminfo/src/sys_apple.cpp index b6d62c1ae..5cf70f1aa 100644 --- a/libraries/systeminfo/src/sys_apple.cpp +++ b/libraries/systeminfo/src/sys_apple.cpp @@ -2,9 +2,9 @@ #include +#include #include #include -#include Sys::KernelInfo Sys::getKernelInfo() { @@ -22,18 +22,16 @@ Sys::KernelInfo Sys::getKernelInfo() out.kernelMinor = 0; out.kernelPatch = 0; auto sections = release.split('-'); - if(sections.size() >= 1) { + if (sections.size() >= 1) { auto versionParts = sections[0].split('.'); - if(versionParts.size() >= 3) { + if (versionParts.size() >= 3) { out.kernelMajor = versionParts[0].toInt(); out.kernelMinor = versionParts[1].toInt(); out.kernelPatch = versionParts[2].toInt(); - } - else { + } else { qWarning() << "Not enough version numbers in " << sections[0] << " found " << versionParts.size(); } - } - else { + } else { qWarning() << "Not enough '-' sections in " << release << " found " << sections.size(); } return out; @@ -45,12 +43,9 @@ uint64_t Sys::getSystemRam() { uint64_t memsize; size_t memsizesize = sizeof(memsize); - if(!sysctlbyname("hw.memsize", &memsize, &memsizesize, NULL, 0)) - { + if (!sysctlbyname("hw.memsize", &memsize, &memsizesize, NULL, 0)) { return memsize; - } - else - { + } else { return 0; } } diff --git a/libraries/systeminfo/src/sys_test.cpp b/libraries/systeminfo/src/sys_test.cpp index 9a5f9dfa2..50c75eb77 100644 --- a/libraries/systeminfo/src/sys_test.cpp +++ b/libraries/systeminfo/src/sys_test.cpp @@ -2,11 +2,9 @@ #include -class SysTest : public QObject -{ +class SysTest : public QObject { Q_OBJECT -private -slots: + private slots: void test_kernelNotNull() { @@ -14,15 +12,15 @@ slots: QVERIFY(!kinfo.kernelName.isEmpty()); QVERIFY(kinfo.kernelVersion != "0.0"); } -/* - void test_systemDistroNotNull() - { - auto kinfo = Sys::getDistributionInfo(); - QVERIFY(!kinfo.distributionName.isEmpty()); - QVERIFY(!kinfo.distributionVersion.isEmpty()); - qDebug() << "Distro: " << kinfo.distributionName << "version" << kinfo.distributionVersion; - } -*/ + /* + void test_systemDistroNotNull() + { + auto kinfo = Sys::getDistributionInfo(); + QVERIFY(!kinfo.distributionName.isEmpty()); + QVERIFY(!kinfo.distributionVersion.isEmpty()); + qDebug() << "Distro: " << kinfo.distributionName << "version" << kinfo.distributionVersion; + } + */ }; QTEST_GUILESS_MAIN(SysTest) diff --git a/libraries/systeminfo/src/sys_unix.cpp b/libraries/systeminfo/src/sys_unix.cpp index 3c63e73a4..4e075959a 100644 --- a/libraries/systeminfo/src/sys_unix.cpp +++ b/libraries/systeminfo/src/sys_unix.cpp @@ -6,9 +6,9 @@ #include #include +#include #include #include -#include Sys::KernelInfo Sys::getKernelInfo() { @@ -27,18 +27,16 @@ Sys::KernelInfo Sys::getKernelInfo() out.kernelMinor = 0; out.kernelPatch = 0; auto sections = release.split('-'); - if(sections.size() >= 1) { + if (sections.size() >= 1) { auto versionParts = sections[0].split('.'); - if(versionParts.size() >= 3) { + if (versionParts.size() >= 3) { out.kernelMajor = versionParts[0].toInt(); out.kernelMinor = versionParts[1].toInt(); out.kernelPatch = versionParts[2].toInt(); - } - else { + } else { qWarning() << "Not enough version numbers in " << sections[0] << " found " << versionParts.size(); } - } - else { + } else { qWarning() << "Not enough '-' sections in " << release << " found " << sections.size(); } return out; @@ -49,17 +47,12 @@ uint64_t Sys::getSystemRam() std::string token; #ifdef Q_OS_LINUX std::ifstream file("/proc/meminfo"); - while(file >> token) - { - if(token == "MemTotal:") - { + while (file >> token) { + if (token == "MemTotal:") { uint64_t mem; - if(file >> mem) - { + if (file >> mem) { return mem * 1024ull; - } - else - { + } else { return 0; } } @@ -68,18 +61,16 @@ uint64_t Sys::getSystemRam() } #elif defined(Q_OS_FREEBSD) char buff[512]; - FILE *fp = popen("sysctl hw.physmem", "r"); - if (fp != NULL) - { - while(fgets(buff, 512, fp) != NULL) - { - std::string str(buff); - uint64_t mem = std::stoull(str.substr(12, std::string::npos)); - return mem * 1024ull; - } + FILE* fp = popen("sysctl hw.physmem", "r"); + if (fp != NULL) { + while (fgets(buff, 512, fp) != NULL) { + std::string str(buff); + uint64_t mem = std::stoull(str.substr(12, std::string::npos)); + return mem * 1024ull; + } } #endif - return 0; // nothing found + return 0; // nothing found } Sys::DistributionInfo Sys::getDistributionInfo() @@ -88,18 +79,13 @@ Sys::DistributionInfo Sys::getDistributionInfo() DistributionInfo lsb_info = read_lsb_release(); DistributionInfo legacy_info = read_legacy_release(); DistributionInfo result = systemd_info + lsb_info + legacy_info; - if(result.distributionName.isNull()) - { + if (result.distributionName.isNull()) { result.distributionName = "unknown"; } - if(result.distributionVersion.isNull()) - { - if(result.distributionName == "arch") - { + if (result.distributionVersion.isNull()) { + if (result.distributionName == "arch") { result.distributionVersion = "rolling"; - } - else - { + } else { result.distributionVersion = "unknown"; } } diff --git a/libraries/systeminfo/src/sys_win32.cpp b/libraries/systeminfo/src/sys_win32.cpp index 5bf510cf8..2627761d1 100644 --- a/libraries/systeminfo/src/sys_win32.cpp +++ b/libraries/systeminfo/src/sys_win32.cpp @@ -22,7 +22,7 @@ uint64_t Sys::getSystemRam() { MEMORYSTATUSEX status; status.dwLength = sizeof(status); - GlobalMemoryStatusEx( &status ); + GlobalMemoryStatusEx(&status); // bytes return (uint64_t)status.ullTotalPhys; } diff --git a/renovate.json b/renovate.json index d97a8dc6c..71581e3b0 100644 --- a/renovate.json +++ b/renovate.json @@ -1,12 +1,12 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:base" - ], - "nix": { - "enabled": true - }, - "lockFileMaintenance": { - "enabled": true - } + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ], + "nix": { + "enabled": true + }, + "lockFileMaintenance": { + "enabled": true + } } diff --git a/tests/DataPackParse_test.cpp b/tests/DataPackParse_test.cpp index 61ce1e2b1..cd6ae8e8f 100644 --- a/tests/DataPackParse_test.cpp +++ b/tests/DataPackParse_test.cpp @@ -30,13 +30,13 @@ class DataPackParseTest : public QObject { Q_OBJECT - private slots: + private slots: void test_parseZIP() { QString source = QFINDTESTDATA("testdata/DataPackParse"); QString zip_dp = FS::PathCombine(source, "test_data_pack_boogaloo.zip"); - DataPack pack { QFileInfo(zip_dp) }; + DataPack pack{ QFileInfo(zip_dp) }; bool valid = DataPackUtils::processZIP(pack); @@ -50,7 +50,7 @@ class DataPackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/DataPackParse"); QString folder_dp = FS::PathCombine(source, "test_folder"); - DataPack pack { QFileInfo(folder_dp) }; + DataPack pack{ QFileInfo(folder_dp) }; bool valid = DataPackUtils::processFolder(pack); @@ -64,7 +64,7 @@ class DataPackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/DataPackParse"); QString folder_dp = FS::PathCombine(source, "another_test_folder"); - DataPack pack { QFileInfo(folder_dp) }; + DataPack pack{ QFileInfo(folder_dp) }; bool valid = DataPackUtils::process(pack); diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index fb35c8746..e19410423 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -1,7 +1,7 @@ -#include #include -#include #include +#include +#include #include @@ -11,16 +11,16 @@ // Snippet from https://github.com/gulrak/filesystem#using-it-as-single-file-header #ifdef __APPLE__ -#include // for deployment target to support pre-catalina targets without std::fs -#endif // __APPLE__ +#include // for deployment target to support pre-catalina targets without std::fs +#endif // __APPLE__ #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include) #if __has_include() && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) #define GHC_USE_STD_FS #include namespace fs = std::filesystem; -#endif // MacOS min version check -#endif // Other OSes version check +#endif // MacOS min version check +#endif // Other OSes version check #ifndef GHC_USE_STD_FS #include @@ -29,8 +29,6 @@ namespace fs = ghc::filesystem; #include - - class LinkTask : public Task { Q_OBJECT @@ -42,41 +40,30 @@ class LinkTask : public Task { m_lnk->debug(true); } - ~LinkTask() { - delete m_lnk; - } + ~LinkTask() { delete m_lnk; } - void matcher(const IPathMatcher *filter) - { - m_lnk->matcher(filter); - } + void matcher(const IPathMatcher* filter) { m_lnk->matcher(filter); } - void linkRecursively(bool recursive) + void linkRecursively(bool recursive) { m_lnk->linkRecursively(recursive); m_linkRecursive = recursive; } - void whitelist(bool b) - { - m_lnk->whitelist(b); - } + void whitelist(bool b) { m_lnk->whitelist(b); } - void setMaxDepth(int depth) - { - m_lnk->setMaxDepth(depth); - } + void setMaxDepth(int depth) { m_lnk->setMaxDepth(depth); } private: void executeTask() override { - if(!(*m_lnk)()){ + if (!(*m_lnk)()) { #if defined Q_OS_WIN32 if (!m_useHard) { qDebug() << "EXPECTED: Link failure, Windows requires permissions for symlinks"; qDebug() << "atempting to run with privelage"; - connect(m_lnk, &FS::create_link::finishedPrivileged, this, [&](bool gotResults){ + connect(m_lnk, &FS::create_link::finishedPrivileged, this, [&](bool gotResults) { if (gotResults) { emitSucceeded(); } else { @@ -87,32 +74,28 @@ class LinkTask : public Task { m_lnk->runPrivileged(); } else { qDebug() << "Link Failed!" << m_lnk->getOSError().value() << m_lnk->getOSError().message().c_str(); - } + } #else qDebug() << "Link Failed!" << m_lnk->getOSError().value() << m_lnk->getOSError().message().c_str(); #endif } else { emitSucceeded(); } - } - FS::create_link *m_lnk; + FS::create_link* m_lnk; [[maybe_unused]] bool m_useHard = false; bool m_linkRecursive = true; }; - -class FileSystemTest : public QObject -{ +class FileSystemTest : public QObject { Q_OBJECT const QString bothSlash = "/foo/"; const QString trailingSlash = "foo/"; const QString leadingSlash = "/foo"; -private -slots: + private slots: void test_pathCombine() { QCOMPARE(QString("/foo/foo"), FS::PathCombine(bothSlash, bothSlash)); @@ -130,12 +113,22 @@ slots: QTest::addColumn("path1"); QTest::addColumn("path2"); - QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc/def" << "ghi/jkl"; - QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/def/" << "ghi/jkl"; + QTest::newRow("qt 1") << "/abc/def/ghi/jkl" + << "/abc/def" + << "ghi/jkl"; + QTest::newRow("qt 2") << "/abc/def/ghi/jkl" + << "/abc/def/" + << "ghi/jkl"; #if defined(Q_OS_WIN) - QTest::newRow("win native, from C:") << "C:/abc" << "C:" << "abc"; - QTest::newRow("win native 1") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def" << "ghi\\jkl"; - QTest::newRow("win native 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def\\" << "ghi\\jkl"; + QTest::newRow("win native, from C:") << "C:/abc" + << "C:" + << "abc"; + QTest::newRow("win native 1") << "C:/abc/def/ghi/jkl" + << "C:\\abc\\def" + << "ghi\\jkl"; + QTest::newRow("win native 2") << "C:/abc/def/ghi/jkl" + << "C:\\abc\\def\\" + << "ghi\\jkl"; #endif } @@ -155,15 +148,39 @@ slots: QTest::addColumn("path2"); QTest::addColumn("path3"); - QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc" << "def" << "ghi/jkl"; - QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/" << "def" << "ghi/jkl"; - QTest::newRow("qt 3") << "/abc/def/ghi/jkl" << "/abc" << "def/" << "ghi/jkl"; - QTest::newRow("qt 4") << "/abc/def/ghi/jkl" << "/abc/" << "def/" << "ghi/jkl"; + QTest::newRow("qt 1") << "/abc/def/ghi/jkl" + << "/abc" + << "def" + << "ghi/jkl"; + QTest::newRow("qt 2") << "/abc/def/ghi/jkl" + << "/abc/" + << "def" + << "ghi/jkl"; + QTest::newRow("qt 3") << "/abc/def/ghi/jkl" + << "/abc" + << "def/" + << "ghi/jkl"; + QTest::newRow("qt 4") << "/abc/def/ghi/jkl" + << "/abc/" + << "def/" + << "ghi/jkl"; #if defined(Q_OS_WIN) - QTest::newRow("win 1") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def" << "ghi\\jkl"; - QTest::newRow("win 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl"; - QTest::newRow("win 3") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def\\" << "ghi\\jkl"; - QTest::newRow("win 4") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl"; + QTest::newRow("win 1") << "C:/abc/def/ghi/jkl" + << "C:\\abc" + << "def" + << "ghi\\jkl"; + QTest::newRow("win 2") << "C:/abc/def/ghi/jkl" + << "C:\\abc\\" + << "def" + << "ghi\\jkl"; + QTest::newRow("win 3") << "C:/abc/def/ghi/jkl" + << "C:\\abc" + << "def\\" + << "ghi\\jkl"; + QTest::newRow("win 4") << "C:/abc/def/ghi/jkl" + << "C:\\abc\\" + << "def" + << "ghi\\jkl"; #endif } @@ -180,8 +197,7 @@ slots: void test_copy() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -192,8 +208,7 @@ slots: FS::copy c(folder, target_dir.path()); c(); - for(auto entry: target_dir.entryList()) - { + for (auto entry : target_dir.entryList()) { qDebug() << entry; } QVERIFY(target_dir.entryList().contains("pack.mcmeta")); @@ -213,8 +228,7 @@ slots: void test_copy_with_blacklist() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -227,8 +241,7 @@ slots: c.matcher(&re); c(); - for(auto entry: target_dir.entryList()) - { + for (auto entry : target_dir.entryList()) { qDebug() << entry; } QVERIFY(!target_dir.entryList().contains("pack.mcmeta")); @@ -248,8 +261,7 @@ slots: void test_copy_with_whitelist() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -263,8 +275,7 @@ slots: c.whitelist(true); c(); - for(auto entry: target_dir.entryList()) - { + for (auto entry : target_dir.entryList()) { qDebug() << entry; } QVERIFY(target_dir.entryList().contains("pack.mcmeta")); @@ -284,8 +295,7 @@ slots: void test_copy_with_dot_hidden() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -298,7 +308,7 @@ slots: auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden; - for (auto entry: target_dir.entryList(filter)) { + for (auto entry : target_dir.entryList(filter)) { qDebug() << entry; } @@ -335,7 +345,7 @@ slots: auto filter = QDir::Filter::Files; - for (auto entry: target_dir.entryList(filter)) { + for (auto entry : target_dir.entryList(filter)) { qDebug() << entry; } @@ -348,12 +358,10 @@ slots: QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); } - void test_link() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -364,17 +372,13 @@ slots: LinkTask lnk_tsk(folder, target_dir.path()); lnk_tsk.linkRecursively(false); - QObject::connect(&lnk_tsk, &Task::finished, [&]{ - QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); - }); + QObject::connect(&lnk_tsk, &Task::finished, + [&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); }); lnk_tsk.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return lnk_tsk.isFinished(); - }, 100000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should."); - for(auto entry: target_dir.entryList()) - { + for (auto entry : target_dir.entryList()) { qDebug() << entry; QFileInfo entry_lnk_info(target_dir.filePath(entry)); if (!entry_lnk_info.isDir()) @@ -402,10 +406,9 @@ slots: void test_hard_link() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { // use working dir to prevent makeing a hard link to a tmpfs or across devices - QTemporaryDir tempDir("./tmp"); + QTemporaryDir tempDir("./tmp"); tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -415,23 +418,20 @@ slots: FS::create_link lnk(folder, target_dir.path()); lnk.useHardLinks(true); lnk.debug(true); - if(!lnk()){ + if (!lnk()) { qDebug() << "Link Failed!" << lnk.getOSError().value() << lnk.getOSError().message().c_str(); } - for(auto entry: target_dir.entryList()) - { + for (auto entry : target_dir.entryList()) { qDebug() << entry; QFileInfo entry_lnk_info(target_dir.filePath(entry)); QVERIFY(!entry_lnk_info.isSymLink()); QFileInfo entry_orig_info(QDir(folder).filePath(entry)); if (!entry_lnk_info.isDir()) { qDebug() << "hard link equivalency?" << entry_lnk_info.absoluteFilePath() << "vs" << entry_orig_info.absoluteFilePath(); - QVERIFY(fs::equivalent( - fs::path(StringUtils::toStdString(entry_lnk_info.absoluteFilePath())), - fs::path(StringUtils::toStdString(entry_orig_info.absoluteFilePath())) - )); - } + QVERIFY(fs::equivalent(fs::path(StringUtils::toStdString(entry_lnk_info.absoluteFilePath())), + fs::path(StringUtils::toStdString(entry_orig_info.absoluteFilePath())))); + } } QFileInfo lnk_info(target_dir.path()); @@ -455,8 +455,7 @@ slots: void test_link_with_blacklist() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -469,18 +468,13 @@ slots: RegexpMatcher re("[.]?mcmeta"); lnk_tsk.matcher(&re); lnk_tsk.linkRecursively(true); - QObject::connect(&lnk_tsk, &Task::finished, [&]{ - QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); - }); + QObject::connect(&lnk_tsk, &Task::finished, + [&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); }); lnk_tsk.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return lnk_tsk.isFinished(); - }, 100000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should."); - - for(auto entry: target_dir.entryList()) - { + for (auto entry : target_dir.entryList()) { qDebug() << entry; QFileInfo entry_lnk_info(target_dir.filePath(entry)); if (!entry_lnk_info.isDir()) @@ -507,8 +501,7 @@ slots: void test_link_with_whitelist() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -522,17 +515,13 @@ slots: lnk_tsk.matcher(&re); lnk_tsk.linkRecursively(true); lnk_tsk.whitelist(true); - QObject::connect(&lnk_tsk, &Task::finished, [&]{ - QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); - }); + QObject::connect(&lnk_tsk, &Task::finished, + [&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); }); lnk_tsk.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return lnk_tsk.isFinished(); - }, 100000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should."); - for(auto entry: target_dir.entryList()) - { + for (auto entry : target_dir.entryList()) { qDebug() << entry; QFileInfo entry_lnk_info(target_dir.filePath(entry)); if (!entry_lnk_info.isDir()) @@ -559,8 +548,7 @@ slots: void test_link_with_dot_hidden() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -571,18 +559,15 @@ slots: LinkTask lnk_tsk(folder, target_dir.path()); lnk_tsk.linkRecursively(true); - QObject::connect(&lnk_tsk, &Task::finished, [&]{ - QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); - }); + QObject::connect(&lnk_tsk, &Task::finished, + [&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); }); lnk_tsk.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return lnk_tsk.isFinished(); - }, 100000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should."); auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden; - for (auto entry: target_dir.entryList(filter)) { + for (auto entry : target_dir.entryList(filter)) { qDebug() << entry; QFileInfo entry_lnk_info(target_dir.filePath(entry)); if (!entry_lnk_info.isDir()) @@ -621,19 +606,16 @@ slots: qDebug() << tempDir.path(); qDebug() << target_dir.path(); - LinkTask lnk_tsk(file, target_dir.filePath("pack.mcmeta")); - QObject::connect(&lnk_tsk, &Task::finished, [&]{ - QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); - }); + LinkTask lnk_tsk(file, target_dir.filePath("pack.mcmeta")); + QObject::connect(&lnk_tsk, &Task::finished, + [&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); }); lnk_tsk.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return lnk_tsk.isFinished(); - }, 100000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should."); auto filter = QDir::Filter::Files; - for (auto entry: target_dir.entryList(filter)) { + for (auto entry : target_dir.entryList(filter)) { qDebug() << entry; } @@ -648,8 +630,7 @@ slots: void test_link_with_max_depth() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -661,22 +642,19 @@ slots: LinkTask lnk_tsk(folder, target_dir.path()); lnk_tsk.linkRecursively(true); lnk_tsk.setMaxDepth(0); - QObject::connect(&lnk_tsk, &Task::finished, [&]{ - QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); - }); + QObject::connect(&lnk_tsk, &Task::finished, + [&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); }); lnk_tsk.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return lnk_tsk.isFinished(); - }, 100000), "Task didn't finish as it should."); + QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should."); QVERIFY(!QFileInfo(target_dir.path()).isSymLink()); auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden; - for(auto entry: target_dir.entryList(filter)) - { + for (auto entry : target_dir.entryList(filter)) { qDebug() << entry; - if (entry == "." || entry == "..") continue; + if (entry == "." || entry == "..") + continue; QFileInfo entry_lnk_info(target_dir.filePath(entry)); QVERIFY(entry_lnk_info.isSymLink()); } @@ -687,8 +665,6 @@ slots: QVERIFY(target_dir.entryList().contains("pack.mcmeta")); QVERIFY(target_dir.entryList().contains("assets")); - - }; // first try variant without trailing / @@ -704,8 +680,7 @@ slots: void test_link_with_no_max_depth() { QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder"); - auto f = [&folder]() - { + auto f = [&folder]() { QTemporaryDir tempDir; tempDir.setAutoRemove(true); qDebug() << "From:" << folder << "To:" << tempDir.path(); @@ -717,24 +692,19 @@ slots: LinkTask lnk_tsk(folder, target_dir.path()); lnk_tsk.linkRecursively(true); lnk_tsk.setMaxDepth(-1); - QObject::connect(&lnk_tsk, &Task::finished, [&]{ - QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); - }); + QObject::connect(&lnk_tsk, &Task::finished, + [&] { QVERIFY2(lnk_tsk.wasSuccessful(), "Task finished but was not successful when it should have been."); }); lnk_tsk.start(); - QVERIFY2(QTest::qWaitFor([&]() { - return lnk_tsk.isFinished(); - }, 100000), "Task didn't finish as it should."); - + QVERIFY2(QTest::qWaitFor([&]() { return lnk_tsk.isFinished(); }, 100000), "Task didn't finish as it should."); std::function verify_check = [&](QString check_path) { QDir check_dir(check_path); auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden; - for(auto entry: check_dir.entryList(filter)) - { + for (auto entry : check_dir.entryList(filter)) { QFileInfo entry_lnk_info(check_dir.filePath(entry)); qDebug() << entry << check_dir.filePath(entry); - if (!entry_lnk_info.isDir()){ + if (!entry_lnk_info.isDir()) { QVERIFY(entry_lnk_info.isSymLink()); } else if (entry != "." && entry != "..") { qDebug() << "Decending tree to verify symlinks:" << check_dir.filePath(entry); @@ -742,9 +712,8 @@ slots: } } }; - + verify_check(target_dir.path()); - QFileInfo lnk_info(target_dir.path()); QVERIFY(lnk_info.exists()); @@ -763,7 +732,8 @@ slots: f(); } - void test_path_depth() { + void test_path_depth() + { QCOMPARE(FS::pathDepth(""), 0); QCOMPARE(FS::pathDepth("."), 0); QCOMPARE(FS::pathDepth("foo.txt"), 0); @@ -777,7 +747,8 @@ slots: QCOMPARE(FS::pathDepth("/baz/../bar/foo.txt"), 1); } - void test_path_trunc() { + void test_path_trunc() + { QCOMPARE(FS::pathTruncate("", 0), QDir::toNativeSeparators("")); QCOMPARE(FS::pathTruncate("foo.txt", 0), QDir::toNativeSeparators("")); QCOMPARE(FS::pathTruncate("foo.txt", 1), QDir::toNativeSeparators("")); diff --git a/tests/GZip_test.cpp b/tests/GZip_test.cpp index ccaa36101..c11ba2711 100644 --- a/tests/GZip_test.cpp +++ b/tests/GZip_test.cpp @@ -3,18 +3,16 @@ #include #include -void fib(int &prev, int &cur) +void fib(int& prev, int& cur) { auto ret = prev + cur; prev = cur; cur = ret; } -class GZipTest : public QObject -{ +class GZipTest : public QObject { Q_OBJECT -private -slots: + private slots: void test_Through() { @@ -27,8 +25,7 @@ slots: std::uniform_int_distribution idis(0, std::numeric_limits::max()); // initialize random buffer - for(int i = 0; i < size; i++) - { + for (int i = 0; i < size; i++) { random.append(static_cast(idis(eng))); } @@ -37,8 +34,7 @@ slots: int cur = 1; // test if fibonacci long random buffers pass through GZip - do - { + do { QByteArray copy = random; copy.resize(cur); compressed.clear(); diff --git a/tests/GradleSpecifier_test.cpp b/tests/GradleSpecifier_test.cpp index 850f83881..fa3c4ad9b 100644 --- a/tests/GradleSpecifier_test.cpp +++ b/tests/GradleSpecifier_test.cpp @@ -2,19 +2,11 @@ #include -class GradleSpecifierTest : public QObject -{ +class GradleSpecifierTest : public QObject { Q_OBJECT -private -slots: - void initTestCase() - { - - } - void cleanupTestCase() - { - - } + private slots: + void initTestCase() {} + void cleanupTestCase() {} void test_Positive_data() { @@ -40,8 +32,10 @@ slots: QTest::addColumn("spec"); QTest::addColumn("expected"); - QTest::newRow("3 parter") << "group.id:artifact:1.0" << "group/id/artifact/1.0/artifact-1.0.jar"; - QTest::newRow("doom") << "id.software:doom:1.666:demons@wad" << "id/software/doom/1.666/doom-1.666-demons.wad"; + QTest::newRow("3 parter") << "group.id:artifact:1.0" + << "group/id/artifact/1.0/artifact-1.0.jar"; + QTest::newRow("doom") << "id.software:doom:1.666:demons@wad" + << "id/software/doom/1.666/doom-1.666-demons.wad"; } void test_Path() { diff --git a/tests/Index_test.cpp b/tests/Index_test.cpp index 436b753e5..888021e24 100644 --- a/tests/Index_test.cpp +++ b/tests/Index_test.cpp @@ -3,14 +3,13 @@ #include #include -class IndexTest : public QObject -{ +class IndexTest : public QObject { Q_OBJECT -private -slots: + private slots: void test_hasUid_and_getList() { - Meta::Index windex({std::make_shared("list1"), std::make_shared("list2"), std::make_shared("list3")}); + Meta::Index windex({ std::make_shared("list1"), std::make_shared("list2"), + std::make_shared("list3") }); QVERIFY(windex.hasUid("list1")); QVERIFY(!windex.hasUid("asdf")); QVERIFY(windex.get("list2") != nullptr); @@ -20,13 +19,18 @@ slots: void test_merge() { - Meta::Index windex({std::make_shared("list1"), std::make_shared("list2"), std::make_shared("list3")}); + Meta::Index windex({ std::make_shared("list1"), std::make_shared("list2"), + std::make_shared("list3") }); QCOMPARE(windex.lists().size(), 3); - windex.merge(std::shared_ptr(new Meta::Index({std::make_shared("list1"), std::make_shared("list2"), std::make_shared("list3")}))); + windex.merge(std::shared_ptr( + new Meta::Index({ std::make_shared("list1"), std::make_shared("list2"), + std::make_shared("list3") }))); QCOMPARE(windex.lists().size(), 3); - windex.merge(std::shared_ptr(new Meta::Index({std::make_shared("list4"), std::make_shared("list2"), std::make_shared("list5")}))); + windex.merge(std::shared_ptr( + new Meta::Index({ std::make_shared("list4"), std::make_shared("list2"), + std::make_shared("list5") }))); QCOMPARE(windex.lists().size(), 5); - windex.merge(std::shared_ptr(new Meta::Index({std::make_shared("list6")}))); + windex.merge(std::shared_ptr(new Meta::Index({ std::make_shared("list6") }))); QCOMPARE(windex.lists().size(), 6); } }; diff --git a/tests/JavaVersion_test.cpp b/tests/JavaVersion_test.cpp index 76d9af2fe..fd2851954 100644 --- a/tests/JavaVersion_test.cpp +++ b/tests/JavaVersion_test.cpp @@ -2,11 +2,9 @@ #include -class JavaVersionTest : public QObject -{ +class JavaVersionTest : public QObject { Q_OBJECT -private -slots: + private slots: void test_Parse_data() { QTest::addColumn("string"); @@ -50,33 +48,54 @@ slots: QTest::addColumn("bigger"); // old format and new format equivalence - QTest::newRow("1.6.0_33 == 6.0.33") << "1.6.0_33" << "6.0.33" << false << true << false; + QTest::newRow("1.6.0_33 == 6.0.33") << "1.6.0_33" + << "6.0.33" << false << true << false; // old format major version - QTest::newRow("1.5.0_33 < 1.6.0_33") << "1.5.0_33" << "1.6.0_33" << true << false << false; + QTest::newRow("1.5.0_33 < 1.6.0_33") << "1.5.0_33" + << "1.6.0_33" << true << false << false; // new format - first release vs first security patch - QTest::newRow("9 < 9.0.1") << "9" << "9.0.1" << true << false << false; - QTest::newRow("9.0.1 > 9") << "9.0.1" << "9" << false << false << true; + QTest::newRow("9 < 9.0.1") << "9" + << "9.0.1" << true << false << false; + QTest::newRow("9.0.1 > 9") << "9.0.1" + << "9" << false << false << true; // new format - first minor vs first release/security patch - QTest::newRow("9.1 > 9.0.1") << "9.1" << "9.0.1" << false << false << true; - QTest::newRow("9.0.1 < 9.1") << "9.0.1" << "9.1" << true << false << false; - QTest::newRow("9.1 > 9") << "9.1" << "9" << false << false << true; - QTest::newRow("9 > 9.1") << "9" << "9.1" << true << false << false; + QTest::newRow("9.1 > 9.0.1") << "9.1" + << "9.0.1" << false << false << true; + QTest::newRow("9.0.1 < 9.1") << "9.0.1" + << "9.1" << true << false << false; + QTest::newRow("9.1 > 9") << "9.1" + << "9" << false << false << true; + QTest::newRow("9 > 9.1") << "9" + << "9.1" << true << false << false; // new format - omitted numbers - QTest::newRow("9 == 9.0") << "9" << "9.0" << false << true << false; - QTest::newRow("9 == 9.0.0") << "9" << "9.0.0" << false << true << false; - QTest::newRow("9.0 == 9.0.0") << "9.0" << "9.0.0" << false << true << false; + QTest::newRow("9 == 9.0") << "9" + << "9.0" << false << true << false; + QTest::newRow("9 == 9.0.0") << "9" + << "9.0.0" << false << true << false; + QTest::newRow("9.0 == 9.0.0") << "9.0" + << "9.0.0" << false << true << false; // early access and prereleases compared to final release - QTest::newRow("9-ea < 9") << "9-ea" << "9" << true << false << false; - QTest::newRow("9 < 9.0.1-ea") << "9" << "9.0.1-ea" << true << false << false; - QTest::newRow("9.0.1-ea > 9") << "9.0.1-ea" << "9" << false << false << true; + QTest::newRow("9-ea < 9") << "9-ea" + << "9" << true << false << false; + QTest::newRow("9 < 9.0.1-ea") << "9" + << "9.0.1-ea" << true << false << false; + QTest::newRow("9.0.1-ea > 9") << "9.0.1-ea" + << "9" << false << false << true; // prerelease difference only testing - QTest::newRow("9-1 == 9-1") << "9-1" << "9-1" << false << true << false; - QTest::newRow("9-1 < 9-2") << "9-1" << "9-2" << true << false << false; - QTest::newRow("9-5 < 9-20") << "9-5" << "9-20" << true << false << false; - QTest::newRow("9-rc1 < 9-rc2") << "9-rc1" << "9-rc2" << true << false << false; - QTest::newRow("9-rc5 < 9-rc20") << "9-rc5" << "9-rc20" << true << false << false; - QTest::newRow("9-rc < 9-rc2") << "9-rc" << "9-rc2" << true << false << false; - QTest::newRow("9-ea < 9-rc") << "9-ea" << "9-rc" << true << false << false; + QTest::newRow("9-1 == 9-1") << "9-1" + << "9-1" << false << true << false; + QTest::newRow("9-1 < 9-2") << "9-1" + << "9-2" << true << false << false; + QTest::newRow("9-5 < 9-20") << "9-5" + << "9-20" << true << false << false; + QTest::newRow("9-rc1 < 9-rc2") << "9-rc1" + << "9-rc2" << true << false << false; + QTest::newRow("9-rc5 < 9-rc20") << "9-rc5" + << "9-rc20" << true << false << false; + QTest::newRow("9-rc < 9-rc2") << "9-rc" + << "9-rc2" << true << false << false; + QTest::newRow("9-ea < 9-rc") << "9-ea" + << "9-rc" << true << false << false; } void test_Sort() { diff --git a/tests/Library_test.cpp b/tests/Library_test.cpp index db8380c7f..e8090c097 100644 --- a/tests/Library_test.cpp +++ b/tests/Library_test.cpp @@ -35,17 +35,16 @@ #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include -class LibraryTest : public QObject -{ +class LibraryTest : public QObject { Q_OBJECT -private: + private: LibraryPtr readMojangJson(const QString path) { QFile jsonFile(path); @@ -56,20 +55,17 @@ private: return MojangVersionFormat::libraryFromJson(problems, QJsonDocument::fromJson(data).object(), path); } // get absolute path to expected storage, assuming default cache prefix - QStringList getStorage(QString relative) - { - return {FS::PathCombine(cache->getBasePath("libraries"), relative)}; - } + QStringList getStorage(QString relative) { return { FS::PathCombine(cache->getBasePath("libraries"), relative) }; } - RuntimeContext dummyContext(QString system = "linux", QString arch = "64", QString realArch = "amd64") { + RuntimeContext dummyContext(QString system = "linux", QString arch = "64", QString realArch = "amd64") + { RuntimeContext r; r.javaArchitecture = arch; r.javaRealArchitecture = realArch; r.system = system; return r; } -private -slots: + private slots: void initTestCase() { cache.reset(new HttpMetaCache()); @@ -111,7 +107,7 @@ slots: test.setHint("local"); auto downloads = test.getDownloads(r, cache.get(), failedFiles, QString()); QCOMPARE(downloads.size(), 0); - QCOMPARE(failedFiles, {"testname-testversion.jar"}); + QCOMPARE(failedFiles, { "testname-testversion.jar" }); } void test_legacy_url_local_override() { @@ -127,7 +123,7 @@ slots: QStringList jar, native, native32, native64; test.getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Library")); - QCOMPARE(jar, {QFileInfo(QFINDTESTDATA("testdata/Library/codecwav-20101023.jar")).absoluteFilePath()}); + QCOMPARE(jar, { QFileInfo(QFINDTESTDATA("testdata/Library/codecwav-20101023.jar")).absoluteFilePath() }); QCOMPARE(native, {}); QCOMPARE(native32, {}); QCOMPARE(native64, {}); @@ -158,9 +154,9 @@ slots: { RuntimeContext r = dummyContext(); Library test("test.package:testname:testversion"); - test.m_nativeClassifiers["linux"]="linux-${arch}"; - test.m_nativeClassifiers["osx"]="osx-${arch}"; - test.m_nativeClassifiers["windows"]="windows-${arch}"; + test.m_nativeClassifiers["linux"] = "linux-${arch}"; + test.m_nativeClassifiers["osx"] = "osx-${arch}"; + test.m_nativeClassifiers["windows"] = "windows-${arch}"; QCOMPARE(test.isNative(), true); test.setRepositoryURL("file://foo/bar"); { @@ -212,7 +208,7 @@ slots: { RuntimeContext r = dummyContext(); Library test("test.package:testname:testversion"); - test.m_nativeClassifiers["linux"]="linux-${arch}"; + test.m_nativeClassifiers["linux"] = "linux-${arch}"; test.setHint("local"); QCOMPARE(test.isNative(), true); test.setRepositoryURL("file://foo/bar"); @@ -221,12 +217,13 @@ slots: test.getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Library")); QCOMPARE(jar, {}); QCOMPARE(native, {}); - QCOMPARE(native32, {QFileInfo(QFINDTESTDATA("testdata/Library/testname-testversion-linux-32.jar")).absoluteFilePath()}); - QCOMPARE(native64, {QFileInfo(QFINDTESTDATA("testdata/Library") + "/testname-testversion-linux-64.jar").absoluteFilePath()}); + QCOMPARE(native32, { QFileInfo(QFINDTESTDATA("testdata/Library/testname-testversion-linux-32.jar")).absoluteFilePath() }); + QCOMPARE(native64, { QFileInfo(QFINDTESTDATA("testdata/Library") + "/testname-testversion-linux-64.jar").absoluteFilePath() }); QStringList failedFiles; auto dls = test.getDownloads(r, cache.get(), failedFiles, QFINDTESTDATA("testdata/Library")); QCOMPARE(dls.size(), 0); - QCOMPARE(failedFiles, {QFileInfo(QFINDTESTDATA("testdata/Library") + "/testname-testversion-linux-64.jar").absoluteFilePath()}); + QCOMPARE(failedFiles, + { QFileInfo(QFINDTESTDATA("testdata/Library") + "/testname-testversion-linux-64.jar").absoluteFilePath() }); } } void test_onenine() @@ -254,7 +251,7 @@ slots: { QStringList jar, native, native32, native64; test->getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Library")); - QCOMPARE(jar, {QFileInfo(QFINDTESTDATA("testdata/Library/codecwav-20101023.jar")).absoluteFilePath()}); + QCOMPARE(jar, { QFileInfo(QFINDTESTDATA("testdata/Library/codecwav-20101023.jar")).absoluteFilePath() }); QCOMPARE(native, {}); QCOMPARE(native32, {}); QCOMPARE(native64, {}); @@ -275,7 +272,7 @@ slots: { QStringList jar, native, native32, native64; test->getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Library")); - QCOMPARE(jar, {QFileInfo(QFINDTESTDATA("testdata/Library/codecwav-20101023.jar")).absoluteFilePath()}); + QCOMPARE(jar, { QFileInfo(QFINDTESTDATA("testdata/Library/codecwav-20101023.jar")).absoluteFilePath() }); QCOMPARE(native, {}); QCOMPARE(native32, {}); QCOMPARE(native64, {}); @@ -295,14 +292,16 @@ slots: QStringList jar, native, native32, native64; test->getApplicableFiles(r, jar, native, native32, native64, QString()); QCOMPARE(jar, QStringList()); - QCOMPARE(native, getStorage("org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar")); + QCOMPARE(native, + getStorage("org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar")); QCOMPARE(native32, {}); QCOMPARE(native64, {}); QStringList failedFiles; auto dls = test->getDownloads(r, cache.get(), failedFiles, QString()); QCOMPARE(dls.size(), 1); QCOMPARE(failedFiles, {}); - QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar")); + QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/" + "lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar")); } void test_onenine_native_arch() { @@ -318,10 +317,13 @@ slots: auto dls = test->getDownloads(r, cache.get(), failedFiles, QString()); QCOMPARE(dls.size(), 2); QCOMPARE(failedFiles, {}); - QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar")); - QCOMPARE(dls[1]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar")); + QCOMPARE(dls[0]->m_url, + QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar")); + QCOMPARE(dls[1]->m_url, + QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar")); } -private: + + private: std::unique_ptr cache; QString dataDir; }; diff --git a/tests/MojangVersionFormat_test.cpp b/tests/MojangVersionFormat_test.cpp index 219fbfa25..9ff5d78c0 100644 --- a/tests/MojangVersionFormat_test.cpp +++ b/tests/MojangVersionFormat_test.cpp @@ -1,10 +1,9 @@ -#include #include +#include #include -class MojangVersionFormatTest : public QObject -{ +class MojangVersionFormatTest : public QObject { Q_OBJECT static QJsonDocument readJson(const QString path) @@ -15,7 +14,7 @@ class MojangVersionFormatTest : public QObject jsonFile.close(); return QJsonDocument::fromJson(data); } - static void writeJson(const char *file, QJsonDocument doc) + static void writeJson(const char* file, QJsonDocument doc) { QFile jsonFile(file); jsonFile.open(QIODevice::WriteOnly | QIODevice::Text); @@ -25,8 +24,7 @@ class MojangVersionFormatTest : public QObject jsonFile.close(); } -private -slots: + private slots: void test_Through_Simple() { QJsonDocument doc = readJson(QFINDTESTDATA("testdata/MojangVersionFormat/1.9-simple.json")); @@ -50,4 +48,3 @@ slots: QTEST_GUILESS_MAIN(MojangVersionFormatTest) #include "MojangVersionFormat_test.moc" - diff --git a/tests/Packwiz_test.cpp b/tests/Packwiz_test.cpp index 292894699..6f4aa5d1b 100644 --- a/tests/Packwiz_test.cpp +++ b/tests/Packwiz_test.cpp @@ -26,9 +26,9 @@ class PackwizTest : public QObject { Q_OBJECT private slots: - // Files taken from https://github.com/packwiz/packwiz-example-pack - void loadFromFile_Modrinth() - { + // Files taken from https://github.com/packwiz/packwiz-example-pack + void loadFromFile_Modrinth() + { QString source = QFINDTESTDATA("testdata/Packwiz"); QDir index_dir(source); @@ -43,15 +43,17 @@ class PackwizTest : public QObject { QCOMPARE(metadata.name, "Borderless Mining"); QCOMPARE(metadata.filename, "borderless-mining-1.1.1+1.18.jar"); QCOMPARE(metadata.side, "client"); - + QCOMPARE(metadata.url, QUrl("https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar")); QCOMPARE(metadata.hash_format, "sha512"); - QCOMPARE(metadata.hash, "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba63623064499b3188d"); + QCOMPARE(metadata.hash, + "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba6362306449" + "9b3188d"); QCOMPARE(metadata.provider, ModPlatform::ResourceProvider::MODRINTH); QCOMPARE(metadata.version(), "ug2qKTPR"); QCOMPARE(metadata.mod_id(), "kYq5qkSL"); - } + } void loadFromFile_Curseforge() { @@ -71,7 +73,7 @@ class PackwizTest : public QObject { QCOMPARE(metadata.name, "Screenshot to Clipboard (Fabric)"); QCOMPARE(metadata.filename, "screenshot-to-clipboard-1.0.7-fabric.jar"); QCOMPARE(metadata.side, "both"); - + QCOMPARE(metadata.url, QUrl("https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar")); QCOMPARE(metadata.hash_format, "murmur2"); QCOMPARE(metadata.hash, "1781245820"); diff --git a/tests/ParseUtils_test.cpp b/tests/ParseUtils_test.cpp index 02208fdf2..0f64a6017 100644 --- a/tests/ParseUtils_test.cpp +++ b/tests/ParseUtils_test.cpp @@ -2,27 +2,16 @@ #include -class ParseUtilsTest : public QObject -{ +class ParseUtilsTest : public QObject { Q_OBJECT -private -slots: + private slots: void test_Through_data() { QTest::addColumn("timestamp"); - const char * timestamps[] = - { - "2016-02-29T13:49:54+01:00", - "2016-02-26T15:21:11+00:01", - "2016-02-24T15:52:36+01:13", - "2016-02-18T17:41:00+00:00", - "2016-02-17T15:23:19+00:00", - "2016-02-16T15:22:39+09:22", - "2016-02-10T15:06:41+00:00", - "2016-02-04T15:28:02-05:33" - }; - for(unsigned i = 0; i < (sizeof(timestamps) / sizeof(const char *)); i++) - { + const char* timestamps[] = { "2016-02-29T13:49:54+01:00", "2016-02-26T15:21:11+00:01", "2016-02-24T15:52:36+01:13", + "2016-02-18T17:41:00+00:00", "2016-02-17T15:23:19+00:00", "2016-02-16T15:22:39+09:22", + "2016-02-10T15:06:41+00:00", "2016-02-04T15:28:02-05:33" }; + for (unsigned i = 0; i < (sizeof(timestamps) / sizeof(const char*)); i++) { QTest::newRow(timestamps[i]) << QString(timestamps[i]); } } @@ -35,7 +24,6 @@ slots: QCOMPARE(time_serialized, timestamp); } - }; QTEST_GUILESS_MAIN(ParseUtilsTest) diff --git a/tests/ResourceFolderModel_test.cpp b/tests/ResourceFolderModel_test.cpp index 962d89f11..8012d4df0 100644 --- a/tests/ResourceFolderModel_test.cpp +++ b/tests/ResourceFolderModel_test.cpp @@ -1,40 +1,40 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (C) 2022 Sefa Eyeoglu -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 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. -*/ + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -#include #include +#include #include #include "BaseInstance.h" @@ -61,12 +61,10 @@ \ disconnect(&model, nullptr, &loop, nullptr); -class ResourceFolderModelTest : public QObject -{ +class ResourceFolderModelTest : public QObject { Q_OBJECT -private -slots: + private slots: // test for GH-1178 - install a folder with files to a mod list void test_1178() { @@ -76,8 +74,7 @@ slots: // sanity check QVERIFY(!source.endsWith('/')); - auto verify = [](QString path) - { + auto verify = [](QString path) { QDir target_dir(FS::PathCombine(path, "test_folder")); QVERIFY(target_dir.entryList().contains("pack.mcmeta")); QVERIFY(target_dir.entryList().contains("assets")); @@ -161,23 +158,17 @@ slots: QCOMPARE(model.size(), 0); - { - EXEC_UPDATE_TASK(model.installResource(file_mod), QVERIFY) - } + { EXEC_UPDATE_TASK(model.installResource(file_mod), QVERIFY) } QCOMPARE(model.size(), 1); qDebug() << "Added first mod."; - { - EXEC_UPDATE_TASK(model.startWatching(), ) - } + { EXEC_UPDATE_TASK(model.startWatching(), ) } QCOMPARE(model.size(), 1); qDebug() << "Started watching the temp folder."; - - { - EXEC_UPDATE_TASK(model.installResource(folder_resource), QVERIFY) - } + + { EXEC_UPDATE_TASK(model.installResource(folder_resource), QVERIFY) } QCOMPARE(model.size(), 2); qDebug() << "Added second mod."; @@ -189,7 +180,7 @@ slots: QCOMPARE(model.size(), 1); qDebug() << "Removed first mod."; - QString mod_file_name {model.at(0).fileinfo().fileName()}; + QString mod_file_name{ model.at(0).fileinfo().fileName() }; QVERIFY(!mod_file_name.isEmpty()); { @@ -212,10 +203,7 @@ slots: QCOMPARE(model.size(), 0); - { - EXEC_UPDATE_TASK(model.installResource(folder_resource), QVERIFY) - } - { + { EXEC_UPDATE_TASK(model.installResource(folder_resource), QVERIFY) } { EXEC_UPDATE_TASK(model.installResource(file_mod), QVERIFY) } @@ -228,8 +216,8 @@ slots: auto& res_2 = model.at(0).type() == ResourceType::FOLDER ? model.at(0) : model.at(1); auto id_1 = res_1.internal_id(); auto id_2 = res_2.internal_id(); - bool initial_enabled_res_2 = res_2.enabled(); - bool initial_enabled_res_1 = res_1.enabled(); + bool initial_enabled_res_2 = res_2.enabled(); + bool initial_enabled_res_1 = res_1.enabled(); QVERIFY(res_1.type() != ResourceType::FOLDER && res_1.type() != ResourceType::UNKNOWN); qDebug() << "res_1 is of the correct type."; diff --git a/tests/ResourceModel_test.cpp b/tests/ResourceModel_test.cpp index 11629cb86..b589758aa 100644 --- a/tests/ResourceModel_test.cpp +++ b/tests/ResourceModel_test.cpp @@ -59,7 +59,8 @@ class DummyResourceModel : public ResourceModel { class ResourceModelTest : public QObject { Q_OBJECT private slots: - void test_abstract_item_model() { + void test_abstract_item_model() + { auto dummy = DummyResourceModel(); auto tester = QAbstractItemModelTester(&dummy); } diff --git a/tests/ResourcePackParse_test.cpp b/tests/ResourcePackParse_test.cpp index 7f2f86bf1..1dcce3249 100644 --- a/tests/ResourcePackParse_test.cpp +++ b/tests/ResourcePackParse_test.cpp @@ -27,18 +27,20 @@ class ResourcePackParseTest : public QObject { Q_OBJECT - private slots: + private slots: void test_parseZIP() { QString source = QFINDTESTDATA("testdata/ResourcePackParse"); QString zip_rp = FS::PathCombine(source, "test_resource_pack_idk.zip"); - ResourcePack pack { QFileInfo(zip_rp) }; + ResourcePack pack{ QFileInfo(zip_rp) }; bool valid = ResourcePackUtils::processZIP(pack, ResourcePackUtils::ProcessingLevel::BasicInfoOnly); QVERIFY(pack.packFormat() == 3); - QVERIFY(pack.description() == "um dois, feijão com arroz, três quatro, feijão no prato, cinco seis, café inglês, sete oito, comer biscoito, nove dez comer pastéis!!"); + QVERIFY(pack.description() == + "um dois, feijão com arroz, três quatro, feijão no prato, cinco seis, café inglês, sete oito, comer biscoito, nove dez " + "comer pastéis!!"); QVERIFY(valid == true); } @@ -47,7 +49,7 @@ class ResourcePackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/ResourcePackParse"); QString folder_rp = FS::PathCombine(source, "test_folder"); - ResourcePack pack { QFileInfo(folder_rp) }; + ResourcePack pack{ QFileInfo(folder_rp) }; bool valid = ResourcePackUtils::processFolder(pack, ResourcePackUtils::ProcessingLevel::BasicInfoOnly); @@ -61,13 +63,13 @@ class ResourcePackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/ResourcePackParse"); QString folder_rp = FS::PathCombine(source, "another_test_folder"); - ResourcePack pack { QFileInfo(folder_rp) }; + ResourcePack pack{ QFileInfo(folder_rp) }; bool valid = ResourcePackUtils::process(pack, ResourcePackUtils::ProcessingLevel::BasicInfoOnly); QVERIFY(pack.packFormat() == 6); QVERIFY(pack.description() == "o quartel pegou fogo, policia deu sinal, acode acode acode a bandeira nacional"); - QVERIFY(valid == false); // no assets dir + QVERIFY(valid == false); // no assets dir } }; diff --git a/tests/ShaderPackParse_test.cpp b/tests/ShaderPackParse_test.cpp index 7df105c61..898278103 100644 --- a/tests/ShaderPackParse_test.cpp +++ b/tests/ShaderPackParse_test.cpp @@ -31,13 +31,13 @@ class ShaderPackParseTest : public QObject { Q_OBJECT - private slots: + private slots: void test_parseZIP() { QString source = QFINDTESTDATA("testdata/ShaderPackParse"); QString zip_sp = FS::PathCombine(source, "shaderpack1.zip"); - ShaderPack pack { QFileInfo(zip_sp) }; + ShaderPack pack{ QFileInfo(zip_sp) }; bool valid = ShaderPackUtils::processZIP(pack); @@ -50,7 +50,7 @@ class ShaderPackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/ShaderPackParse"); QString folder_sp = FS::PathCombine(source, "shaderpack2"); - ShaderPack pack { QFileInfo(folder_sp) }; + ShaderPack pack{ QFileInfo(folder_sp) }; bool valid = ShaderPackUtils::processFolder(pack); @@ -63,7 +63,7 @@ class ShaderPackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/ShaderPackParse"); QString folder_sp = FS::PathCombine(source, "shaderpack3.zip"); - ShaderPack pack { QFileInfo(folder_sp) }; + ShaderPack pack{ QFileInfo(folder_sp) }; bool valid = ShaderPackUtils::process(pack); diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp index 5bc737655..abc9be905 100644 --- a/tests/Task_test.cpp +++ b/tests/Task_test.cpp @@ -31,7 +31,7 @@ class BasicTask_MultiStep : public Task { private: auto isMultiStep() const -> bool override { return true; } - void executeTask() override {} + void executeTask() override {} }; class BigConcurrentTask : public ConcurrentTask { @@ -66,7 +66,10 @@ class BigConcurrentTaskThread : public QThread { } connect(&big_task, &Task::finished, this, &QThread::quit); - connect(&m_deadline, &QTimer::timeout, this, [&] { passed_the_deadline = true; quit(); }); + connect(&m_deadline, &QTimer::timeout, this, [&] { + passed_the_deadline = true; + quit(); + }); m_deadline.start(); big_task.run(); diff --git a/tests/TexturePackParse_test.cpp b/tests/TexturePackParse_test.cpp index 4ddc0a3a1..558529287 100644 --- a/tests/TexturePackParse_test.cpp +++ b/tests/TexturePackParse_test.cpp @@ -28,13 +28,13 @@ class TexturePackParseTest : public QObject { Q_OBJECT - private slots: + private slots: void test_parseZIP() { QString source = QFINDTESTDATA("testdata/TexturePackParse"); QString zip_rp = FS::PathCombine(source, "test_texture_pack_idk.zip"); - TexturePack pack { QFileInfo(zip_rp) }; + TexturePack pack{ QFileInfo(zip_rp) }; bool valid = TexturePackUtils::processZIP(pack); @@ -47,7 +47,7 @@ class TexturePackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/TexturePackParse"); QString folder_rp = FS::PathCombine(source, "test_texturefolder"); - TexturePack pack { QFileInfo(folder_rp) }; + TexturePack pack{ QFileInfo(folder_rp) }; bool valid = TexturePackUtils::processFolder(pack, TexturePackUtils::ProcessingLevel::BasicInfoOnly); @@ -60,7 +60,7 @@ class TexturePackParseTest : public QObject { QString source = QFINDTESTDATA("testdata/TexturePackParse"); QString folder_rp = FS::PathCombine(source, "another_test_texturefolder"); - TexturePack pack { QFileInfo(folder_rp) }; + TexturePack pack{ QFileInfo(folder_rp) }; bool valid = TexturePackUtils::process(pack, TexturePackUtils::ProcessingLevel::BasicInfoOnly); diff --git a/tests/Version_test.cpp b/tests/Version_test.cpp index f5488cbce..d25bf7bb5 100644 --- a/tests/Version_test.cpp +++ b/tests/Version_test.cpp @@ -34,33 +34,48 @@ class VersionTest : public QObject { { addDataColumns(); - QTest::newRow("equal, explicit") << "1.2.0" << "1.2.0" << false << true; - QTest::newRow("equal, two-digit") << "1.42" << "1.42" << false << true; + QTest::newRow("equal, explicit") << "1.2.0" + << "1.2.0" << false << true; + QTest::newRow("equal, two-digit") << "1.42" + << "1.42" << false << true; - QTest::newRow("lessThan, explicit 1") << "1.2.0" << "1.2.1" << true << false; - QTest::newRow("lessThan, explicit 2") << "1.2.0" << "1.3.0" << true << false; - QTest::newRow("lessThan, explicit 3") << "1.2.0" << "2.2.0" << true << false; - QTest::newRow("lessThan, implicit 1") << "1.2" << "1.2.0" << true << false; - QTest::newRow("lessThan, implicit 2") << "1.2" << "1.2.1" << true << false; - QTest::newRow("lessThan, implicit 3") << "1.2" << "1.3.0" << true << false; - QTest::newRow("lessThan, implicit 4") << "1.2" << "2.2.0" << true << false; - QTest::newRow("lessThan, two-digit") << "1.41" << "1.42" << true << false; + QTest::newRow("lessThan, explicit 1") << "1.2.0" + << "1.2.1" << true << false; + QTest::newRow("lessThan, explicit 2") << "1.2.0" + << "1.3.0" << true << false; + QTest::newRow("lessThan, explicit 3") << "1.2.0" + << "2.2.0" << true << false; + QTest::newRow("lessThan, implicit 1") << "1.2" + << "1.2.0" << true << false; + QTest::newRow("lessThan, implicit 2") << "1.2" + << "1.2.1" << true << false; + QTest::newRow("lessThan, implicit 3") << "1.2" + << "1.3.0" << true << false; + QTest::newRow("lessThan, implicit 4") << "1.2" + << "2.2.0" << true << false; + QTest::newRow("lessThan, two-digit") << "1.41" + << "1.42" << true << false; - QTest::newRow("greaterThan, explicit 1") << "1.2.1" << "1.2.0" << false << false; - QTest::newRow("greaterThan, explicit 2") << "1.3.0" << "1.2.0" << false << false; - QTest::newRow("greaterThan, explicit 3") << "2.2.0" << "1.2.0" << false << false; - QTest::newRow("greaterThan, implicit 1") << "1.2.0" << "1.2" << false << false; - QTest::newRow("greaterThan, implicit 2") << "1.2.1" << "1.2" << false << false; - QTest::newRow("greaterThan, implicit 3") << "1.3.0" << "1.2" << false << false; - QTest::newRow("greaterThan, implicit 4") << "2.2.0" << "1.2" << false << false; - QTest::newRow("greaterThan, two-digit") << "1.42" << "1.41" << false << false; + QTest::newRow("greaterThan, explicit 1") << "1.2.1" + << "1.2.0" << false << false; + QTest::newRow("greaterThan, explicit 2") << "1.3.0" + << "1.2.0" << false << false; + QTest::newRow("greaterThan, explicit 3") << "2.2.0" + << "1.2.0" << false << false; + QTest::newRow("greaterThan, implicit 1") << "1.2.0" + << "1.2" << false << false; + QTest::newRow("greaterThan, implicit 2") << "1.2.1" + << "1.2" << false << false; + QTest::newRow("greaterThan, implicit 3") << "1.3.0" + << "1.2" << false << false; + QTest::newRow("greaterThan, implicit 4") << "2.2.0" + << "1.2" << false << false; + QTest::newRow("greaterThan, two-digit") << "1.42" + << "1.41" << false << false; } private slots: - void test_versionCompare_data() - { - setupVersions(); - } + void test_versionCompare_data() { setupVersions(); } void test_versionCompare() { @@ -85,12 +100,12 @@ class VersionTest : public QObject { QDir test_vector_dir(QFINDTESTDATA("testdata/Version")); - QFile vector_file{test_vector_dir.absoluteFilePath("test_vectors.txt")}; + QFile vector_file{ test_vector_dir.absoluteFilePath("test_vectors.txt") }; vector_file.open(QFile::OpenModeFlag::ReadOnly); int test_number = 0; - const QString test_name_template { "FlexVer test #%1 (%2)" }; + const QString test_name_template{ "FlexVer test #%1 (%2)" }; for (auto line = vector_file.readLine(); !vector_file.atEnd(); line = vector_file.readLine()) { line = line.simplified(); if (line.startsWith('#') || line.isEmpty()) @@ -100,8 +115,8 @@ class VersionTest : public QObject { auto split_line = line.split('<'); if (split_line.size() == 2) { - QString first{split_line.first().simplified()}; - QString second{split_line.last().simplified()}; + QString first{ split_line.first().simplified() }; + QString second{ split_line.last().simplified() }; auto new_test_name = test_name_template.arg(QString::number(test_number), "lessThan"); m_flex_test_names.append(new_test_name); @@ -112,8 +127,8 @@ class VersionTest : public QObject { split_line = line.split('='); if (split_line.size() == 2) { - QString first{split_line.first().simplified()}; - QString second{split_line.last().simplified()}; + QString first{ split_line.first().simplified() }; + QString second{ split_line.last().simplified() }; auto new_test_name = test_name_template.arg(QString::number(test_number), "equals"); m_flex_test_names.append(new_test_name); @@ -124,8 +139,8 @@ class VersionTest : public QObject { split_line = line.split('>'); if (split_line.size() == 2) { - QString first{split_line.first().simplified()}; - QString second{split_line.last().simplified()}; + QString first{ split_line.first().simplified() }; + QString second{ split_line.last().simplified() }; auto new_test_name = test_name_template.arg(QString::number(test_number), "greaterThan"); m_flex_test_names.append(new_test_name); diff --git a/tests/WorldSaveParse_test.cpp b/tests/WorldSaveParse_test.cpp index 4a8c3d29c..8dabaeb51 100644 --- a/tests/WorldSaveParse_test.cpp +++ b/tests/WorldSaveParse_test.cpp @@ -31,13 +31,13 @@ class WorldSaveParseTest : public QObject { Q_OBJECT - private slots: + private slots: void test_parseZIP() { QString source = QFINDTESTDATA("testdata/WorldSaveParse"); - QString zip_ws = FS::PathCombine(source, "minecraft_save_1.zip") ; - WorldSave save { QFileInfo(zip_ws) }; + QString zip_ws = FS::PathCombine(source, "minecraft_save_1.zip"); + WorldSave save{ QFileInfo(zip_ws) }; bool valid = WorldSaveUtils::processZIP(save); @@ -45,13 +45,13 @@ class WorldSaveParseTest : public QObject { QVERIFY(save.saveDirName() == "world_1"); QVERIFY(valid == true); } - + void test_parse_ZIP2() { QString source = QFINDTESTDATA("testdata/WorldSaveParse"); - QString zip_ws = FS::PathCombine(source, "minecraft_save_2.zip") ; - WorldSave save { QFileInfo(zip_ws) }; + QString zip_ws = FS::PathCombine(source, "minecraft_save_2.zip"); + WorldSave save{ QFileInfo(zip_ws) }; bool valid = WorldSaveUtils::processZIP(save); @@ -59,13 +59,13 @@ class WorldSaveParseTest : public QObject { QVERIFY(save.saveDirName() == "world_2"); QVERIFY(valid == true); } - + void test_parseFolder() { QString source = QFINDTESTDATA("testdata/WorldSaveParse"); QString folder_ws = FS::PathCombine(source, "minecraft_save_3"); - WorldSave save { QFileInfo(folder_ws) }; + WorldSave save{ QFileInfo(folder_ws) }; bool valid = WorldSaveUtils::processFolder(save); @@ -79,7 +79,7 @@ class WorldSaveParseTest : public QObject { QString source = QFINDTESTDATA("testdata/WorldSaveParse"); QString folder_ws = FS::PathCombine(source, "minecraft_save_4"); - WorldSave save { QFileInfo(folder_ws) }; + WorldSave save{ QFileInfo(folder_ws) }; bool valid = WorldSaveUtils::process(save); diff --git a/tests/testdata/MojangVersionFormat/1.9-simple.json b/tests/testdata/MojangVersionFormat/1.9-simple.json index 574c5b065..c71bc6553 100644 --- a/tests/testdata/MojangVersionFormat/1.9-simple.json +++ b/tests/testdata/MojangVersionFormat/1.9-simple.json @@ -190,7 +190,8 @@ } ], "mainClass": "net.minecraft.client.main.Main", - "minecraftArguments": "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}", + "minecraftArguments": + "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}", "minimumLauncherVersion": 18, "releaseTime": "2016-02-29T13:49:54+00:00", "time": "2016-03-01T13:14:53+00:00", diff --git a/tests/testdata/MojangVersionFormat/1.9.json b/tests/testdata/MojangVersionFormat/1.9.json index 697c60590..b298634ad 100644 --- a/tests/testdata/MojangVersionFormat/1.9.json +++ b/tests/testdata/MojangVersionFormat/1.9.json @@ -335,7 +335,8 @@ "path": "org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar", "sha1": "d51a7c040a721d13efdfbd34f8b257b2df882ad0", "size": 173887, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar" } }, "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209", @@ -357,26 +358,33 @@ "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar", "sha1": "b04f3ee8f5e43fa3b162981b50bb72fe1acabb33", "size": 22, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar" }, "classifiers": { "natives-linux": { - "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar", + "path": + "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar", "sha1": "931074f46c795d2f7b30ed6395df5715cfd7675b", "size": 578680, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar" }, "natives-osx": { - "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar", + "path": + "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar", "sha1": "bcab850f8f487c3f4c4dbabde778bb82bd1a40ed", "size": 426822, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar" }, "natives-windows": { - "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar", + "path": + "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar", "sha1": "b84d5102b9dbfabfeb5e43c7e2828d98a7fc80e0", "size": 613748, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar" } } }, @@ -428,7 +436,8 @@ "path": "org/lwjgl/lwjgl/lwjgl_util/2.9.2-nightly-20140822/lwjgl_util-2.9.2-nightly-20140822.jar", "sha1": "f0e612c840a7639c1f77f68d72a28dae2f0c8490", "size": 173887, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.2-nightly-20140822/lwjgl_util-2.9.2-nightly-20140822.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.2-nightly-20140822/lwjgl_util-2.9.2-nightly-20140822.jar" } }, "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.2-nightly-20140822", @@ -445,22 +454,28 @@ "downloads": { "classifiers": { "natives-linux": { - "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar", + "path": + "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar", "sha1": "d898a33b5d0a6ef3fed3a4ead506566dce6720a5", "size": 578539, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-linux.jar" }, "natives-osx": { - "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar", + "path": + "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar", "sha1": "79f5ce2fea02e77fe47a3c745219167a542121d7", "size": 468116, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar" }, "natives-windows": { - "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar", + "path": + "org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar", "sha1": "78b2a55ce4dc29c6b3ec4df8ca165eba05f9b341", "size": 613680, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.2-nightly-20140822/lwjgl-platform-2.9.2-nightly-20140822-natives-windows.jar" } } }, @@ -491,7 +506,8 @@ "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar", "sha1": "7ff832a6eb9ab6a767f1ade2b548092d0fa64795", "size": 10362, - "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar" + "url": + "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar" }, "natives-osx": { "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar", @@ -503,7 +519,8 @@ "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar", "sha1": "385ee093e01f587f30ee1c8a2ee7d408fd732e16", "size": 155179, - "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar" + "url": + "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar" } } }, @@ -521,7 +538,8 @@ } ], "mainClass": "net.minecraft.client.main.Main", - "minecraftArguments": "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}", + "minecraftArguments": + "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}", "minimumLauncherVersion": 18, "releaseTime": "2016-02-29T13:49:54+00:00", "time": "2016-03-01T13:14:53+00:00", diff --git a/tests/testdata/MojangVersionFormat/lib-native.json b/tests/testdata/MojangVersionFormat/lib-native.json index 5b9f3b556..e7a6094f9 100644 --- a/tests/testdata/MojangVersionFormat/lib-native.json +++ b/tests/testdata/MojangVersionFormat/lib-native.json @@ -4,26 +4,30 @@ "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar", "sha1": "b04f3ee8f5e43fa3b162981b50bb72fe1acabb33", "size": 22, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar" }, "classifiers": { "natives-linux": { "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar", "sha1": "931074f46c795d2f7b30ed6395df5715cfd7675b", "size": 578680, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar" }, "natives-osx": { "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar", "sha1": "bcab850f8f487c3f4c4dbabde778bb82bd1a40ed", "size": 426822, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar" }, "natives-windows": { "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar", "sha1": "b84d5102b9dbfabfeb5e43c7e2828d98a7fc80e0", "size": 613748, - "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar" + "url": + "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar" } } }, diff --git a/tests/testdata/PackageManifest/1.8.0_202-x64.json b/tests/testdata/PackageManifest/1.8.0_202-x64.json index 3d99d719b..eaf67a7ac 100644 --- a/tests/testdata/PackageManifest/1.8.0_202-x64.json +++ b/tests/testdata/PackageManifest/1.8.0_202-x64.json @@ -1 +1,4667 @@ -{"files": {"COPYRIGHT": {"downloads": {"lzma": {"sha1": "dd860e040807f7e53ae89da5f28dd73d57ac605d", "size": 1431, "url": "https://launcher.mojang.com/v1/objects/dd860e040807f7e53ae89da5f28dd73d57ac605d/COPYRIGHT"}, "raw": {"sha1": "c725183c757011e7ba96c83c1e86ee7e8b516a2b", "size": 3244, "url": "https://launcher.mojang.com/v1/objects/c725183c757011e7ba96c83c1e86ee7e8b516a2b/COPYRIGHT"}}, "executable": false, "type": "file"}, "LICENSE": {"downloads": {"raw": {"sha1": "3e86865deec0814c958bcf7fb87f790bccc0e8bd", "size": 40, "url": "https://launcher.mojang.com/v1/objects/3e86865deec0814c958bcf7fb87f790bccc0e8bd/LICENSE"}}, "executable": false, "type": "file"}, "README": {"downloads": {"raw": {"sha1": "f90331df1e5badeadc501d8dd70714c62a920204", "size": 46, "url": "https://launcher.mojang.com/v1/objects/f90331df1e5badeadc501d8dd70714c62a920204/README"}}, "executable": false, "type": "file"}, "THIRDPARTYLICENSEREADME-JAVAFX.txt": {"downloads": {"lzma": {"sha1": "4fee85109d7ff04b982d0576dabd15397f599125", "size": 15455, "url": "https://launcher.mojang.com/v1/objects/4fee85109d7ff04b982d0576dabd15397f599125/THIRDPARTYLICENSEREADME-JAVAFX.txt"}, "raw": {"sha1": "56ff42f87607b997b52ae0ef8bf315e36932e870", "size": 112724, "url": "https://launcher.mojang.com/v1/objects/56ff42f87607b997b52ae0ef8bf315e36932e870/THIRDPARTYLICENSEREADME-JAVAFX.txt"}}, "executable": false, "type": "file"}, "THIRDPARTYLICENSEREADME.txt": {"downloads": {"lzma": {"sha1": "419c1414ba46ae9dbfd38cf4e0601fff61644429", "size": 32266, "url": "https://launcher.mojang.com/v1/objects/419c1414ba46ae9dbfd38cf4e0601fff61644429/THIRDPARTYLICENSEREADME.txt"}, "raw": {"sha1": "b83c3f32261de3e48ccd20614a11e066b1ec9027", "size": 153824, "url": "https://launcher.mojang.com/v1/objects/b83c3f32261de3e48ccd20614a11e066b1ec9027/THIRDPARTYLICENSEREADME.txt"}}, "executable": false, "type": "file"}, "Welcome.html": {"downloads": {"lzma": {"sha1": "01c21a74b4aafb7cbe0388233c43cbdf77dcaaea", "size": 528, "url": "https://launcher.mojang.com/v1/objects/01c21a74b4aafb7cbe0388233c43cbdf77dcaaea/Welcome.html"}, "raw": {"sha1": "d98ae54f03dac87419abc19b97e315830c2da55f", "size": 955, "url": "https://launcher.mojang.com/v1/objects/d98ae54f03dac87419abc19b97e315830c2da55f/Welcome.html"}}, "executable": false, "type": "file"}, "bin": {"type": "directory"}, "bin/ControlPanel": {"target": "jcontrol", "type": "link"}, "bin/java": {"downloads": {"lzma": {"sha1": "3857eea1d59e1bc545c67a753ed2768254807b8a", "size": 2088, "url": "https://launcher.mojang.com/v1/objects/3857eea1d59e1bc545c67a753ed2768254807b8a/java"}, "raw": {"sha1": "3d20560fb5d1a49cb689c2226972e92e06d27ba6", "size": 8464, "url": "https://launcher.mojang.com/v1/objects/3d20560fb5d1a49cb689c2226972e92e06d27ba6/java"}}, "executable": true, "type": "file"}, "bin/javaws": {"downloads": {"lzma": {"sha1": "a6bec5c049e76c4488294a256a2084ea23ddb440", "size": 38173, "url": "https://launcher.mojang.com/v1/objects/a6bec5c049e76c4488294a256a2084ea23ddb440/javaws"}, "raw": {"sha1": "955c0f0066e2f893b0c2b3ccd83e223722e4ab74", "size": 140296, "url": "https://launcher.mojang.com/v1/objects/955c0f0066e2f893b0c2b3ccd83e223722e4ab74/javaws"}}, "executable": true, "type": "file"}, "bin/jcontrol": {"downloads": {"lzma": {"sha1": "40c5e33748f252e1d950b579a4185ab2c23fc908", "size": 2166, "url": "https://launcher.mojang.com/v1/objects/40c5e33748f252e1d950b579a4185ab2c23fc908/jcontrol"}, "raw": {"sha1": "ed541733c8b51e34349c1f8010b277e58ad73f1e", "size": 6264, "url": "https://launcher.mojang.com/v1/objects/ed541733c8b51e34349c1f8010b277e58ad73f1e/jcontrol"}}, "executable": true, "type": "file"}, "bin/jjs": {"downloads": {"lzma": {"sha1": "d44d1ac421979f7671921986214812095a5b0e3b", "size": 2168, "url": "https://launcher.mojang.com/v1/objects/d44d1ac421979f7671921986214812095a5b0e3b/jjs"}, "raw": {"sha1": "f00f944c3dbe556793b5dc686aaeee3e5722e99b", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/f00f944c3dbe556793b5dc686aaeee3e5722e99b/jjs"}}, "executable": true, "type": "file"}, "bin/keytool": {"downloads": {"lzma": {"sha1": "93c607dce450976667c382f609a367167bdec05c", "size": 2175, "url": "https://launcher.mojang.com/v1/objects/93c607dce450976667c382f609a367167bdec05c/keytool"}, "raw": {"sha1": "7114b561546270e441e9ed1bcc24e5188c068a42", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/7114b561546270e441e9ed1bcc24e5188c068a42/keytool"}}, "executable": true, "type": "file"}, "bin/orbd": {"downloads": {"lzma": {"sha1": "b27dfded5e2b2f6f02c555971c94e46ca14ac81b", "size": 2254, "url": "https://launcher.mojang.com/v1/objects/b27dfded5e2b2f6f02c555971c94e46ca14ac81b/orbd"}, "raw": {"sha1": "7f31217fecb3dbbd89f1dd3783fca58793a66fd2", "size": 8656, "url": "https://launcher.mojang.com/v1/objects/7f31217fecb3dbbd89f1dd3783fca58793a66fd2/orbd"}}, "executable": true, "type": "file"}, "bin/pack200": {"downloads": {"lzma": {"sha1": "b52da4497b49b1508b6225a5740857ddb8f52e97", "size": 2183, "url": "https://launcher.mojang.com/v1/objects/b52da4497b49b1508b6225a5740857ddb8f52e97/pack200"}, "raw": {"sha1": "16ef3e801efb57e50bc6477a27a9d95d02d0775b", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/16ef3e801efb57e50bc6477a27a9d95d02d0775b/pack200"}}, "executable": true, "type": "file"}, "bin/policytool": {"downloads": {"lzma": {"sha1": "87da4c07da45f3d1a1a9d732af197cd39bf69d10", "size": 2182, "url": "https://launcher.mojang.com/v1/objects/87da4c07da45f3d1a1a9d732af197cd39bf69d10/policytool"}, "raw": {"sha1": "a52a29424470cb9b8db5c2fb1751d0b697a7ec8e", "size": 8592, "url": "https://launcher.mojang.com/v1/objects/a52a29424470cb9b8db5c2fb1751d0b697a7ec8e/policytool"}}, "executable": true, "type": "file"}, "bin/rmid": {"downloads": {"lzma": {"sha1": "1494c1174fde0c0a93ea117bc7edf7eb936c0512", "size": 2172, "url": "https://launcher.mojang.com/v1/objects/1494c1174fde0c0a93ea117bc7edf7eb936c0512/rmid"}, "raw": {"sha1": "5c8710e1ab924e5b09a07bcb4c6e106293bbd1a8", "size": 8584, "url": "https://launcher.mojang.com/v1/objects/5c8710e1ab924e5b09a07bcb4c6e106293bbd1a8/rmid"}}, "executable": true, "type": "file"}, "bin/rmiregistry": {"downloads": {"lzma": {"sha1": "7070cf2ec5a5e520a880bae699431edf02083e7e", "size": 2174, "url": "https://launcher.mojang.com/v1/objects/7070cf2ec5a5e520a880bae699431edf02083e7e/rmiregistry"}, "raw": {"sha1": "5f518daa7050028d5d9d849634c73136f2b23a54", "size": 8592, "url": "https://launcher.mojang.com/v1/objects/5f518daa7050028d5d9d849634c73136f2b23a54/rmiregistry"}}, "executable": true, "type": "file"}, "bin/servertool": {"downloads": {"lzma": {"sha1": "1db683a11cc9b7313426c84412f4d95be2fa7ccd", "size": 2185, "url": "https://launcher.mojang.com/v1/objects/1db683a11cc9b7313426c84412f4d95be2fa7ccd/servertool"}, "raw": {"sha1": "49d0ebfeb265ce5a8733e1014541ea2525674a60", "size": 8592, "url": "https://launcher.mojang.com/v1/objects/49d0ebfeb265ce5a8733e1014541ea2525674a60/servertool"}}, "executable": true, "type": "file"}, "bin/tnameserv": {"downloads": {"lzma": {"sha1": "36da9c9a2c5a8b662a3f8d52ca67339bce1c2714", "size": 2291, "url": "https://launcher.mojang.com/v1/objects/36da9c9a2c5a8b662a3f8d52ca67339bce1c2714/tnameserv"}, "raw": {"sha1": "09d998f8efcb6f55d0d87f59e08f8b89662796d9", "size": 8656, "url": "https://launcher.mojang.com/v1/objects/09d998f8efcb6f55d0d87f59e08f8b89662796d9/tnameserv"}}, "executable": true, "type": "file"}, "bin/unpack200": {"downloads": {"lzma": {"sha1": "344959e32fc7ee19eebe7b3cf5ab6d1a7d6641f2", "size": 79721, "url": "https://launcher.mojang.com/v1/objects/344959e32fc7ee19eebe7b3cf5ab6d1a7d6641f2/unpack200"}, "raw": {"sha1": "5dd933132f1b202e19e0c8e093f7113711cfdfc1", "size": 182616, "url": "https://launcher.mojang.com/v1/objects/5dd933132f1b202e19e0c8e093f7113711cfdfc1/unpack200"}}, "executable": true, "type": "file"}, "lib": {"type": "directory"}, "lib/amd64": {"type": "directory"}, "lib/amd64/jli": {"type": "directory"}, "lib/amd64/jli/libjli.so": {"downloads": {"lzma": {"sha1": "372331ee8e375888f798a2e88180a94493e141b0", "size": 48327, "url": "https://launcher.mojang.com/v1/objects/372331ee8e375888f798a2e88180a94493e141b0/libjli.so"}, "raw": {"sha1": "73b0cf8b7415686bc40c561ff77ff2740ccf7a44", "size": 108616, "url": "https://launcher.mojang.com/v1/objects/73b0cf8b7415686bc40c561ff77ff2740ccf7a44/libjli.so"}}, "executable": true, "type": "file"}, "lib/amd64/jvm.cfg": {"downloads": {"lzma": {"sha1": "86bcfebec37b38415525ffd77d3eaf70d0b1b4ca", "size": 435, "url": "https://launcher.mojang.com/v1/objects/86bcfebec37b38415525ffd77d3eaf70d0b1b4ca/jvm.cfg"}, "raw": {"sha1": "84b38bdc745de446ba0ca0232ea3aaf2efd721da", "size": 627, "url": "https://launcher.mojang.com/v1/objects/84b38bdc745de446ba0ca0232ea3aaf2efd721da/jvm.cfg"}}, "executable": false, "type": "file"}, "lib/amd64/libavplugin-53.so": {"downloads": {"lzma": {"sha1": "a332366762d9efc7b845a682b7edce62db44618c", "size": 14747, "url": "https://launcher.mojang.com/v1/objects/a332366762d9efc7b845a682b7edce62db44618c/libavplugin-53.so"}, "raw": {"sha1": "9bd1473dd8a0dc7950c7af1cc69a45548df26eb5", "size": 51720, "url": "https://launcher.mojang.com/v1/objects/9bd1473dd8a0dc7950c7af1cc69a45548df26eb5/libavplugin-53.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-54.so": {"downloads": {"lzma": {"sha1": "2c615852a0720a275163e00597c1f711f11341da", "size": 15153, "url": "https://launcher.mojang.com/v1/objects/2c615852a0720a275163e00597c1f711f11341da/libavplugin-54.so"}, "raw": {"sha1": "8808050c5949c4800b42d1b19b1f8b0d120bcacb", "size": 51768, "url": "https://launcher.mojang.com/v1/objects/8808050c5949c4800b42d1b19b1f8b0d120bcacb/libavplugin-54.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-55.so": {"downloads": {"lzma": {"sha1": "39ee8e7fe14f0010c78973962800f539c3e4c16b", "size": 15168, "url": "https://launcher.mojang.com/v1/objects/39ee8e7fe14f0010c78973962800f539c3e4c16b/libavplugin-55.so"}, "raw": {"sha1": "f10ea4ea3489e96d8d161a96790133c417ec44e1", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/f10ea4ea3489e96d8d161a96790133c417ec44e1/libavplugin-55.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-56.so": {"downloads": {"lzma": {"sha1": "abe7feced5a559f1bdc868526dc69484e0e591a0", "size": 15169, "url": "https://launcher.mojang.com/v1/objects/abe7feced5a559f1bdc868526dc69484e0e591a0/libavplugin-56.so"}, "raw": {"sha1": "e5bfcbff5a5a5a5993a3e689a05ef358c131a3ed", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/e5bfcbff5a5a5a5993a3e689a05ef358c131a3ed/libavplugin-56.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-57.so": {"downloads": {"lzma": {"sha1": "4dd26b4ef2294b6929dcb2c7546b47eac5cc78a9", "size": 15174, "url": "https://launcher.mojang.com/v1/objects/4dd26b4ef2294b6929dcb2c7546b47eac5cc78a9/libavplugin-57.so"}, "raw": {"sha1": "2949e7ff9b0ac90e8943c211cff141ab12eec3f8", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/2949e7ff9b0ac90e8943c211cff141ab12eec3f8/libavplugin-57.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-ffmpeg-56.so": {"downloads": {"lzma": {"sha1": "c688ba1cfa442bf18bee43b2fa870b4dc1ce3fb6", "size": 15231, "url": "https://launcher.mojang.com/v1/objects/c688ba1cfa442bf18bee43b2fa870b4dc1ce3fb6/libavplugin-ffmpeg-56.so"}, "raw": {"sha1": "0d36c971a9ad99fc2292092fdec3a4179b1021b9", "size": 51920, "url": "https://launcher.mojang.com/v1/objects/0d36c971a9ad99fc2292092fdec3a4179b1021b9/libavplugin-ffmpeg-56.so"}}, "executable": true, "type": "file"}, "lib/amd64/libavplugin-ffmpeg-57.so": {"downloads": {"lzma": {"sha1": "087426bdbffebcfa372a438e863785f4ffbe9a6b", "size": 15180, "url": "https://launcher.mojang.com/v1/objects/087426bdbffebcfa372a438e863785f4ffbe9a6b/libavplugin-ffmpeg-57.so"}, "raw": {"sha1": "5e9c4eb4b49eb8e57c01003ec73a1eb8d6d8c462", "size": 51784, "url": "https://launcher.mojang.com/v1/objects/5e9c4eb4b49eb8e57c01003ec73a1eb8d6d8c462/libavplugin-ffmpeg-57.so"}}, "executable": true, "type": "file"}, "lib/amd64/libawt.so": {"downloads": {"lzma": {"sha1": "018be58b205b73c842a55df811b70d0e8237216e", "size": 195720, "url": "https://launcher.mojang.com/v1/objects/018be58b205b73c842a55df811b70d0e8237216e/libawt.so"}, "raw": {"sha1": "02632cd326e3161c00a7e784599dd7b9ee053dce", "size": 759184, "url": "https://launcher.mojang.com/v1/objects/02632cd326e3161c00a7e784599dd7b9ee053dce/libawt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libawt_headless.so": {"downloads": {"lzma": {"sha1": "7ac2517cff75d4bbb0a0412a9b5f18c74ea188fa", "size": 11211, "url": "https://launcher.mojang.com/v1/objects/7ac2517cff75d4bbb0a0412a9b5f18c74ea188fa/libawt_headless.so"}, "raw": {"sha1": "862157ec957008d0911c5daedc004b3a202623a4", "size": 39176, "url": "https://launcher.mojang.com/v1/objects/862157ec957008d0911c5daedc004b3a202623a4/libawt_headless.so"}}, "executable": true, "type": "file"}, "lib/amd64/libawt_xawt.so": {"downloads": {"lzma": {"sha1": "d536a96af27dfe35de6bb2c8759d51c488cdd8d4", "size": 149598, "url": "https://launcher.mojang.com/v1/objects/d536a96af27dfe35de6bb2c8759d51c488cdd8d4/libawt_xawt.so"}, "raw": {"sha1": "28232b3e01b6f11bfe098bfc6eafc3a513dcebf1", "size": 470232, "url": "https://launcher.mojang.com/v1/objects/28232b3e01b6f11bfe098bfc6eafc3a513dcebf1/libawt_xawt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libbci.so": {"downloads": {"lzma": {"sha1": "c36fad091d11e64c815d5ca17c0ef7a55b0776b1", "size": 3509, "url": "https://launcher.mojang.com/v1/objects/c36fad091d11e64c815d5ca17c0ef7a55b0776b1/libbci.so"}, "raw": {"sha1": "33824051db1ccb6332e22c2b63231055240d0af0", "size": 12760, "url": "https://launcher.mojang.com/v1/objects/33824051db1ccb6332e22c2b63231055240d0af0/libbci.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdcpr.so": {"downloads": {"lzma": {"sha1": "70c6b0933a37f2b1124d6e7c131039241fe796ee", "size": 75969, "url": "https://launcher.mojang.com/v1/objects/70c6b0933a37f2b1124d6e7c131039241fe796ee/libdcpr.so"}, "raw": {"sha1": "fa7001bc5d80579e2716590f3eee8027da0beae7", "size": 204456, "url": "https://launcher.mojang.com/v1/objects/fa7001bc5d80579e2716590f3eee8027da0beae7/libdcpr.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdecora_sse.so": {"downloads": {"lzma": {"sha1": "514acc017dfb6cefaf8cc6d18006ce55781cc9bc", "size": 24397, "url": "https://launcher.mojang.com/v1/objects/514acc017dfb6cefaf8cc6d18006ce55781cc9bc/libdecora_sse.so"}, "raw": {"sha1": "d0c84233504c916e548e29f513e25f6a7479abfc", "size": 74912, "url": "https://launcher.mojang.com/v1/objects/d0c84233504c916e548e29f513e25f6a7479abfc/libdecora_sse.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdeploy.so": {"downloads": {"lzma": {"sha1": "6cf31fd98301c749ac0d2c7825f6d925a4409760", "size": 168999, "url": "https://launcher.mojang.com/v1/objects/6cf31fd98301c749ac0d2c7825f6d925a4409760/libdeploy.so"}, "raw": {"sha1": "b3832e97ed8ca794884b56a591b83d02a2c0c06f", "size": 642368, "url": "https://launcher.mojang.com/v1/objects/b3832e97ed8ca794884b56a591b83d02a2c0c06f/libdeploy.so"}}, "executable": true, "type": "file"}, "lib/amd64/libdt_socket.so": {"downloads": {"lzma": {"sha1": "4cc5c880dbb6fa180436d12d60f0abec8ebb59dc", "size": 7784, "url": "https://launcher.mojang.com/v1/objects/4cc5c880dbb6fa180436d12d60f0abec8ebb59dc/libdt_socket.so"}, "raw": {"sha1": "91ce96f252b8139fc12f0f224ed5b1a041767ab7", "size": 24616, "url": "https://launcher.mojang.com/v1/objects/91ce96f252b8139fc12f0f224ed5b1a041767ab7/libdt_socket.so"}}, "executable": true, "type": "file"}, "lib/amd64/libfontmanager.so": {"downloads": {"lzma": {"sha1": "f94e5e94c71c603ff4d3cd1e7e3d9e181fcc145d", "size": 146951, "url": "https://launcher.mojang.com/v1/objects/f94e5e94c71c603ff4d3cd1e7e3d9e181fcc145d/libfontmanager.so"}, "raw": {"sha1": "2428e805f2c53d1283a033dfd11a86fbb7bd7159", "size": 490672, "url": "https://launcher.mojang.com/v1/objects/2428e805f2c53d1283a033dfd11a86fbb7bd7159/libfontmanager.so"}}, "executable": true, "type": "file"}, "lib/amd64/libfxplugins.so": {"downloads": {"lzma": {"sha1": "a640143365d382a5ad743a784bc2f3706d9d6d67", "size": 50048, "url": "https://launcher.mojang.com/v1/objects/a640143365d382a5ad743a784bc2f3706d9d6d67/libfxplugins.so"}, "raw": {"sha1": "0fd4ac04a84c131f1aaee9e6b0898ff9ea69e3ee", "size": 151448, "url": "https://launcher.mojang.com/v1/objects/0fd4ac04a84c131f1aaee9e6b0898ff9ea69e3ee/libfxplugins.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglass.so": {"downloads": {"lzma": {"sha1": "f1ff517714fa5f2c861f33b32db823fe851541f1", "size": 2856, "url": "https://launcher.mojang.com/v1/objects/f1ff517714fa5f2c861f33b32db823fe851541f1/libglass.so"}, "raw": {"sha1": "e7f4fece30ac727be8148d33b8256abd3a41cef9", "size": 13072, "url": "https://launcher.mojang.com/v1/objects/e7f4fece30ac727be8148d33b8256abd3a41cef9/libglass.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglassgtk2.so": {"downloads": {"lzma": {"sha1": "15b90f7a2baacd15e80aa9785d87cf1e4258376d", "size": 220476, "url": "https://launcher.mojang.com/v1/objects/15b90f7a2baacd15e80aa9785d87cf1e4258376d/libglassgtk2.so"}, "raw": {"sha1": "e30a634c2ff2143bdee512360553d6e0304f33b2", "size": 844984, "url": "https://launcher.mojang.com/v1/objects/e30a634c2ff2143bdee512360553d6e0304f33b2/libglassgtk2.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglassgtk3.so": {"downloads": {"lzma": {"sha1": "868c231165f8c9043b7f0e7de208ec023f06a6e7", "size": 220560, "url": "https://launcher.mojang.com/v1/objects/868c231165f8c9043b7f0e7de208ec023f06a6e7/libglassgtk3.so"}, "raw": {"sha1": "762a11a2b376b7b5a2a7cad780715524fdd176d5", "size": 845304, "url": "https://launcher.mojang.com/v1/objects/762a11a2b376b7b5a2a7cad780715524fdd176d5/libglassgtk3.so"}}, "executable": true, "type": "file"}, "lib/amd64/libglib-lite.so": {"downloads": {"lzma": {"sha1": "61b8871242febe1be262de167dc20ae94bf964b4", "size": 457046, "url": "https://launcher.mojang.com/v1/objects/61b8871242febe1be262de167dc20ae94bf964b4/libglib-lite.so"}, "raw": {"sha1": "63afa060fc3f120af76128e51d32603fc4336fa8", "size": 1538352, "url": "https://launcher.mojang.com/v1/objects/63afa060fc3f120af76128e51d32603fc4336fa8/libglib-lite.so"}}, "executable": true, "type": "file"}, "lib/amd64/libgstreamer-lite.so": {"downloads": {"lzma": {"sha1": "2447dc368406ba1b989a29937d41924620e01988", "size": 673056, "url": "https://launcher.mojang.com/v1/objects/2447dc368406ba1b989a29937d41924620e01988/libgstreamer-lite.so"}, "raw": {"sha1": "5505e7ca592ac64371d3db8fe53bcb602e9723d3", "size": 2263872, "url": "https://launcher.mojang.com/v1/objects/5505e7ca592ac64371d3db8fe53bcb602e9723d3/libgstreamer-lite.so"}}, "executable": true, "type": "file"}, "lib/amd64/libhprof.so": {"downloads": {"lzma": {"sha1": "94a5589c818db1fb1cf1881e24e217c309fce2e4", "size": 64471, "url": "https://launcher.mojang.com/v1/objects/94a5589c818db1fb1cf1881e24e217c309fce2e4/libhprof.so"}, "raw": {"sha1": "4bb9bdeef6133b6dd558d52d691b077c03e9b0ee", "size": 175504, "url": "https://launcher.mojang.com/v1/objects/4bb9bdeef6133b6dd558d52d691b077c03e9b0ee/libhprof.so"}}, "executable": true, "type": "file"}, "lib/amd64/libinstrument.so": {"downloads": {"lzma": {"sha1": "84ffea356caf725b42c86a8ebc9587f477ddde29", "size": 18603, "url": "https://launcher.mojang.com/v1/objects/84ffea356caf725b42c86a8ebc9587f477ddde29/libinstrument.so"}, "raw": {"sha1": "cb8009769601e3fecd7ea2b36c344f737b1a9da7", "size": 51560, "url": "https://launcher.mojang.com/v1/objects/cb8009769601e3fecd7ea2b36c344f737b1a9da7/libinstrument.so"}}, "executable": true, "type": "file"}, "lib/amd64/libj2gss.so": {"downloads": {"lzma": {"sha1": "4b2aa699506b126098b585a9617ce1c05707fa29", "size": 14132, "url": "https://launcher.mojang.com/v1/objects/4b2aa699506b126098b585a9617ce1c05707fa29/libj2gss.so"}, "raw": {"sha1": "cbce4a302b255d4d1924ef7606f038af766c5e86", "size": 47688, "url": "https://launcher.mojang.com/v1/objects/cbce4a302b255d4d1924ef7606f038af766c5e86/libj2gss.so"}}, "executable": true, "type": "file"}, "lib/amd64/libj2pcsc.so": {"downloads": {"lzma": {"sha1": "2361d3b2e3da48593c391b29b0d2b5409e4c55e5", "size": 5074, "url": "https://launcher.mojang.com/v1/objects/2361d3b2e3da48593c391b29b0d2b5409e4c55e5/libj2pcsc.so"}, "raw": {"sha1": "1274178492e7a3e997e12f67794616f7c3d8d0b9", "size": 18296, "url": "https://launcher.mojang.com/v1/objects/1274178492e7a3e997e12f67794616f7c3d8d0b9/libj2pcsc.so"}}, "executable": true, "type": "file"}, "lib/amd64/libj2pkcs11.so": {"downloads": {"lzma": {"sha1": "ef927e2790ba05931d0f0bdd63da3d275a834946", "size": 21573, "url": "https://launcher.mojang.com/v1/objects/ef927e2790ba05931d0f0bdd63da3d275a834946/libj2pkcs11.so"}, "raw": {"sha1": "bd4f2af9bfdc6168633d1920c1a1415de06bb45a", "size": 79472, "url": "https://launcher.mojang.com/v1/objects/bd4f2af9bfdc6168633d1920c1a1415de06bb45a/libj2pkcs11.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjaas_unix.so": {"downloads": {"lzma": {"sha1": "7f7e843544ee1eb1454a5826bdd4218685b79430", "size": 2404, "url": "https://launcher.mojang.com/v1/objects/7f7e843544ee1eb1454a5826bdd4218685b79430/libjaas_unix.so"}, "raw": {"sha1": "4c517925c7d464a5b719898eb0bea1b04df31f1f", "size": 8192, "url": "https://launcher.mojang.com/v1/objects/4c517925c7d464a5b719898eb0bea1b04df31f1f/libjaas_unix.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjava.so": {"downloads": {"lzma": {"sha1": "5eee7a42600a44a8bb8d6d7f510fd96a29637ac0", "size": 63113, "url": "https://launcher.mojang.com/v1/objects/5eee7a42600a44a8bb8d6d7f510fd96a29637ac0/libjava.so"}, "raw": {"sha1": "e280aeddf3fc0ec664aef7efc0e0e197a54aaf02", "size": 227672, "url": "https://launcher.mojang.com/v1/objects/e280aeddf3fc0ec664aef7efc0e0e197a54aaf02/libjava.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjava_crw_demo.so": {"downloads": {"lzma": {"sha1": "b197cf23ae3556eb0b45c663f0a8cb62408b961e", "size": 10412, "url": "https://launcher.mojang.com/v1/objects/b197cf23ae3556eb0b45c663f0a8cb62408b961e/libjava_crw_demo.so"}, "raw": {"sha1": "18f20f906977c90d0090b41dbda8dd5cfead5a4c", "size": 26144, "url": "https://launcher.mojang.com/v1/objects/18f20f906977c90d0090b41dbda8dd5cfead5a4c/libjava_crw_demo.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font.so": {"downloads": {"lzma": {"sha1": "ffbba0e5022f829412b86063d8a90f95f16709b1", "size": 5608, "url": "https://launcher.mojang.com/v1/objects/ffbba0e5022f829412b86063d8a90f95f16709b1/libjavafx_font.so"}, "raw": {"sha1": "8634a0aca612fc40420a4a7cc8af4cc46cfc6725", "size": 17104, "url": "https://launcher.mojang.com/v1/objects/8634a0aca612fc40420a4a7cc8af4cc46cfc6725/libjavafx_font.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font_freetype.so": {"downloads": {"lzma": {"sha1": "310271eda8a2ac264ffc3640a9d847b49438d0bd", "size": 6942, "url": "https://launcher.mojang.com/v1/objects/310271eda8a2ac264ffc3640a9d847b49438d0bd/libjavafx_font_freetype.so"}, "raw": {"sha1": "3e7572d047c12ba2bc43acec7f98a67c20af8042", "size": 27616, "url": "https://launcher.mojang.com/v1/objects/3e7572d047c12ba2bc43acec7f98a67c20af8042/libjavafx_font_freetype.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font_pango.so": {"downloads": {"lzma": {"sha1": "a7bcf0669e70b0f43099a99c81e6b6440cb40ac0", "size": 5820, "url": "https://launcher.mojang.com/v1/objects/a7bcf0669e70b0f43099a99c81e6b6440cb40ac0/libjavafx_font_pango.so"}, "raw": {"sha1": "f0b775cc9a514c7ee8b4d6fb300653ce548caf10", "size": 25560, "url": "https://launcher.mojang.com/v1/objects/f0b775cc9a514c7ee8b4d6fb300653ce548caf10/libjavafx_font_pango.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_font_t2k.so": {"downloads": {"lzma": {"sha1": "551c29dc7c7fc83223aa36a6187f7e0c5d650538", "size": 431450, "url": "https://launcher.mojang.com/v1/objects/551c29dc7c7fc83223aa36a6187f7e0c5d650538/libjavafx_font_t2k.so"}, "raw": {"sha1": "91e5813057c3b852d411540160f8ad05fb9f1ed3", "size": 1486128, "url": "https://launcher.mojang.com/v1/objects/91e5813057c3b852d411540160f8ad05fb9f1ed3/libjavafx_font_t2k.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjavafx_iio.so": {"downloads": {"lzma": {"sha1": "c832998fd5e06ed6dcd6428816194c350785420c", "size": 101479, "url": "https://launcher.mojang.com/v1/objects/c832998fd5e06ed6dcd6428816194c350785420c/libjavafx_iio.so"}, "raw": {"sha1": "dcdf68cb25677b76c1cf0bb94294e6e9880a6678", "size": 256336, "url": "https://launcher.mojang.com/v1/objects/dcdf68cb25677b76c1cf0bb94294e6e9880a6678/libjavafx_iio.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjawt.so": {"downloads": {"lzma": {"sha1": "c1ced6aad5c69ff444dc67d0fd7e333558953831", "size": 1872, "url": "https://launcher.mojang.com/v1/objects/c1ced6aad5c69ff444dc67d0fd7e333558953831/libjawt.so"}, "raw": {"sha1": "c5032f2c6fa40bea24e56605cf76b26a27e87b67", "size": 8048, "url": "https://launcher.mojang.com/v1/objects/c5032f2c6fa40bea24e56605cf76b26a27e87b67/libjawt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjdwp.so": {"downloads": {"lzma": {"sha1": "c1aabbb3f5a624b9ad10ed871a1d83510a99b646", "size": 94884, "url": "https://launcher.mojang.com/v1/objects/c1aabbb3f5a624b9ad10ed871a1d83510a99b646/libjdwp.so"}, "raw": {"sha1": "a043e97be47937f6f552e94cf79c76c1c57f9594", "size": 272248, "url": "https://launcher.mojang.com/v1/objects/a043e97be47937f6f552e94cf79c76c1c57f9594/libjdwp.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjfr.so": {"downloads": {"lzma": {"sha1": "11b8e6bfffdccbacbf9dd29dea4b90b753f3c1b7", "size": 8780, "url": "https://launcher.mojang.com/v1/objects/11b8e6bfffdccbacbf9dd29dea4b90b753f3c1b7/libjfr.so"}, "raw": {"sha1": "312392dd186b11c418183e818f1928e8685a07e5", "size": 28384, "url": "https://launcher.mojang.com/v1/objects/312392dd186b11c418183e818f1928e8685a07e5/libjfr.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjfxmedia.so": {"downloads": {"lzma": {"sha1": "a4e7a126eb648ce6e5e6dc151831da37d8334139", "size": 391897, "url": "https://launcher.mojang.com/v1/objects/a4e7a126eb648ce6e5e6dc151831da37d8334139/libjfxmedia.so"}, "raw": {"sha1": "5fa54944327a6012c3d34cb5c1c4432762178dc8", "size": 1636376, "url": "https://launcher.mojang.com/v1/objects/5fa54944327a6012c3d34cb5c1c4432762178dc8/libjfxmedia.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjfxwebkit.so": {"downloads": {"lzma": {"sha1": "b274debd222cdcc2ee84160ebb95144b3880bc97", "size": 20492825, "url": "https://launcher.mojang.com/v1/objects/b274debd222cdcc2ee84160ebb95144b3880bc97/libjfxwebkit.so"}, "raw": {"sha1": "ecee564c3b2f645131b35bb3004abd4caeabd291", "size": 91014584, "url": "https://launcher.mojang.com/v1/objects/ecee564c3b2f645131b35bb3004abd4caeabd291/libjfxwebkit.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjpeg.so": {"downloads": {"lzma": {"sha1": "9ad55e370c5eaaa73c3158339db3c368b1aaf0cb", "size": 113072, "url": "https://launcher.mojang.com/v1/objects/9ad55e370c5eaaa73c3158339db3c368b1aaf0cb/libjpeg.so"}, "raw": {"sha1": "651e6d53ae67db1f0efbf7f104447a9b49b7e333", "size": 292520, "url": "https://launcher.mojang.com/v1/objects/651e6d53ae67db1f0efbf7f104447a9b49b7e333/libjpeg.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsdt.so": {"downloads": {"lzma": {"sha1": "04b6d1361a34c496b5f652b2477784d69b8b6baf", "size": 3964, "url": "https://launcher.mojang.com/v1/objects/04b6d1361a34c496b5f652b2477784d69b8b6baf/libjsdt.so"}, "raw": {"sha1": "82b48a82bf6183d34cf00a0f81661b45c616f31b", "size": 12904, "url": "https://launcher.mojang.com/v1/objects/82b48a82bf6183d34cf00a0f81661b45c616f31b/libjsdt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsig.so": {"downloads": {"lzma": {"sha1": "37d3b89abde397216cc4ecb1339d8543d99b8428", "size": 3536, "url": "https://launcher.mojang.com/v1/objects/37d3b89abde397216cc4ecb1339d8543d99b8428/libjsig.so"}, "raw": {"sha1": "42e52ba1bcbe0362ab24bcf65c93797354db6fb9", "size": 13336, "url": "https://launcher.mojang.com/v1/objects/42e52ba1bcbe0362ab24bcf65c93797354db6fb9/libjsig.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsound.so": {"downloads": {"lzma": {"sha1": "7e3c565d74d8ffae716f32b05544fa4a6f108adc", "size": 2002, "url": "https://launcher.mojang.com/v1/objects/7e3c565d74d8ffae716f32b05544fa4a6f108adc/libjsound.so"}, "raw": {"sha1": "0c0fc63b92d7b83c9960fa80d45c80553ea20254", "size": 8232, "url": "https://launcher.mojang.com/v1/objects/0c0fc63b92d7b83c9960fa80d45c80553ea20254/libjsound.so"}}, "executable": true, "type": "file"}, "lib/amd64/libjsoundalsa.so": {"downloads": {"lzma": {"sha1": "b06c51858a25ff776519495f1b9b3d9f604b089f", "size": 23097, "url": "https://launcher.mojang.com/v1/objects/b06c51858a25ff776519495f1b9b3d9f604b089f/libjsoundalsa.so"}, "raw": {"sha1": "281d37f0326d4a12dc7ea316ead09c198ff7bdf7", "size": 83256, "url": "https://launcher.mojang.com/v1/objects/281d37f0326d4a12dc7ea316ead09c198ff7bdf7/libjsoundalsa.so"}}, "executable": true, "type": "file"}, "lib/amd64/liblcms.so": {"downloads": {"lzma": {"sha1": "7a239baba2086cae49114b382b74b971da02f08e", "size": 176175, "url": "https://launcher.mojang.com/v1/objects/7a239baba2086cae49114b382b74b971da02f08e/liblcms.so"}, "raw": {"sha1": "c8895cc3c3d023d9e059225969ab67954772c0a1", "size": 526872, "url": "https://launcher.mojang.com/v1/objects/c8895cc3c3d023d9e059225969ab67954772c0a1/liblcms.so"}}, "executable": true, "type": "file"}, "lib/amd64/libmanagement.so": {"downloads": {"lzma": {"sha1": "aed3fdbcefd1716abfc6a306687c8b741cbb318e", "size": 12838, "url": "https://launcher.mojang.com/v1/objects/aed3fdbcefd1716abfc6a306687c8b741cbb318e/libmanagement.so"}, "raw": {"sha1": "eba35f61e0d50e30874b7c7b335edf2d52662423", "size": 51808, "url": "https://launcher.mojang.com/v1/objects/eba35f61e0d50e30874b7c7b335edf2d52662423/libmanagement.so"}}, "executable": true, "type": "file"}, "lib/amd64/libmlib_image.so": {"downloads": {"lzma": {"sha1": "1bb181f079492d55c7a458e96488cd17fe0a7b86", "size": 310272, "url": "https://launcher.mojang.com/v1/objects/1bb181f079492d55c7a458e96488cd17fe0a7b86/libmlib_image.so"}, "raw": {"sha1": "c973c450d33873675945d4694be484e3427f58f1", "size": 1048136, "url": "https://launcher.mojang.com/v1/objects/c973c450d33873675945d4694be484e3427f58f1/libmlib_image.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnet.so": {"downloads": {"lzma": {"sha1": "9dd79703b6deb86e0321afe01c6ac508263c8312", "size": 38123, "url": "https://launcher.mojang.com/v1/objects/9dd79703b6deb86e0321afe01c6ac508263c8312/libnet.so"}, "raw": {"sha1": "b3a17b7d53fcdf1e689e1ec29ce851eee6022ead", "size": 116920, "url": "https://launcher.mojang.com/v1/objects/b3a17b7d53fcdf1e689e1ec29ce851eee6022ead/libnet.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnio.so": {"downloads": {"lzma": {"sha1": "5697c89d5d5d9b74f2e1555fcbba79dd4049e287", "size": 24445, "url": "https://launcher.mojang.com/v1/objects/5697c89d5d5d9b74f2e1555fcbba79dd4049e287/libnio.so"}, "raw": {"sha1": "573bf8f64dbcc397f8abd3e1da28f90ab0679f5b", "size": 93872, "url": "https://launcher.mojang.com/v1/objects/573bf8f64dbcc397f8abd3e1da28f90ab0679f5b/libnio.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnpjp2.so": {"downloads": {"lzma": {"sha1": "6fe53b5951ff740e7f2ef7ffe5975af26da06718", "size": 57892, "url": "https://launcher.mojang.com/v1/objects/6fe53b5951ff740e7f2ef7ffe5975af26da06718/libnpjp2.so"}, "raw": {"sha1": "2bb13c53a4280379253475e51216b97eed1d4ce3", "size": 216592, "url": "https://launcher.mojang.com/v1/objects/2bb13c53a4280379253475e51216b97eed1d4ce3/libnpjp2.so"}}, "executable": true, "type": "file"}, "lib/amd64/libnpt.so": {"downloads": {"lzma": {"sha1": "1b170b09a32b1b8b6624fa5d1f94ec60b2bf3876", "size": 5070, "url": "https://launcher.mojang.com/v1/objects/1b170b09a32b1b8b6624fa5d1f94ec60b2bf3876/libnpt.so"}, "raw": {"sha1": "6b1ff6b9b4624f3cc7801f221c82b8046fb76364", "size": 17504, "url": "https://launcher.mojang.com/v1/objects/6b1ff6b9b4624f3cc7801f221c82b8046fb76364/libnpt.so"}}, "executable": true, "type": "file"}, "lib/amd64/libprism_common.so": {"downloads": {"lzma": {"sha1": "f4aca04c90bc7505851c074a08b2c31cae1f94fa", "size": 23315, "url": "https://launcher.mojang.com/v1/objects/f4aca04c90bc7505851c074a08b2c31cae1f94fa/libprism_common.so"}, "raw": {"sha1": "b00866b6ed8646a29a334d46e297267552f27de8", "size": 59008, "url": "https://launcher.mojang.com/v1/objects/b00866b6ed8646a29a334d46e297267552f27de8/libprism_common.so"}}, "executable": true, "type": "file"}, "lib/amd64/libprism_es2.so": {"downloads": {"lzma": {"sha1": "7ff4173c338c7a6f370f231670055737e032da3e", "size": 18416, "url": "https://launcher.mojang.com/v1/objects/7ff4173c338c7a6f370f231670055737e032da3e/libprism_es2.so"}, "raw": {"sha1": "1390a1dc14345e5a948148e59195d62f3a83863f", "size": 63808, "url": "https://launcher.mojang.com/v1/objects/1390a1dc14345e5a948148e59195d62f3a83863f/libprism_es2.so"}}, "executable": true, "type": "file"}, "lib/amd64/libprism_sw.so": {"downloads": {"lzma": {"sha1": "6728e8bf7b214067d715be6fe0325910d63c2468", "size": 29457, "url": "https://launcher.mojang.com/v1/objects/6728e8bf7b214067d715be6fe0325910d63c2468/libprism_sw.so"}, "raw": {"sha1": "7a6c34cb2bbcde411778d1b3f8677c39e32c3ac4", "size": 71608, "url": "https://launcher.mojang.com/v1/objects/7a6c34cb2bbcde411778d1b3f8677c39e32c3ac4/libprism_sw.so"}}, "executable": true, "type": "file"}, "lib/amd64/libresource.so": {"downloads": {"lzma": {"sha1": "1e35e63f1e74915fba620f1febf420b919d49bc5", "size": 2633, "url": "https://launcher.mojang.com/v1/objects/1e35e63f1e74915fba620f1febf420b919d49bc5/libresource.so"}, "raw": {"sha1": "57490353ad0d83ab1930355213dea269795434fe", "size": 13456, "url": "https://launcher.mojang.com/v1/objects/57490353ad0d83ab1930355213dea269795434fe/libresource.so"}}, "executable": true, "type": "file"}, "lib/amd64/libsctp.so": {"downloads": {"lzma": {"sha1": "4340132ed250d7849a016e071be773eaedd33aa8", "size": 9332, "url": "https://launcher.mojang.com/v1/objects/4340132ed250d7849a016e071be773eaedd33aa8/libsctp.so"}, "raw": {"sha1": "4a80e743750f127c0d5a359f5cd60b97e7ee12ae", "size": 29552, "url": "https://launcher.mojang.com/v1/objects/4a80e743750f127c0d5a359f5cd60b97e7ee12ae/libsctp.so"}}, "executable": true, "type": "file"}, "lib/amd64/libsplashscreen.so": {"downloads": {"lzma": {"sha1": "b226c8dbd73a548fc2b042ee6db6cc80e727597c", "size": 190305, "url": "https://launcher.mojang.com/v1/objects/b226c8dbd73a548fc2b042ee6db6cc80e727597c/libsplashscreen.so"}, "raw": {"sha1": "87d6a491f5ba7e6c4d972264a0c9063afea567a2", "size": 441376, "url": "https://launcher.mojang.com/v1/objects/87d6a491f5ba7e6c4d972264a0c9063afea567a2/libsplashscreen.so"}}, "executable": true, "type": "file"}, "lib/amd64/libsunec.so": {"downloads": {"lzma": {"sha1": "6ebba98fab1e3d872d1363235b76497f6f9babdc", "size": 88829, "url": "https://launcher.mojang.com/v1/objects/6ebba98fab1e3d872d1363235b76497f6f9babdc/libsunec.so"}, "raw": {"sha1": "3b262a0a530f6e4e539aed2cd27b4de1d0ed8859", "size": 283368, "url": "https://launcher.mojang.com/v1/objects/3b262a0a530f6e4e539aed2cd27b4de1d0ed8859/libsunec.so"}}, "executable": true, "type": "file"}, "lib/amd64/libt2k.so": {"downloads": {"lzma": {"sha1": "602cb812ef0b350ccf56ce209a260ddbe3743d92", "size": 190720, "url": "https://launcher.mojang.com/v1/objects/602cb812ef0b350ccf56ce209a260ddbe3743d92/libt2k.so"}, "raw": {"sha1": "b072c56df997f61e15e6b5a43b8907b0d25c2043", "size": 504840, "url": "https://launcher.mojang.com/v1/objects/b072c56df997f61e15e6b5a43b8907b0d25c2043/libt2k.so"}}, "executable": true, "type": "file"}, "lib/amd64/libunpack.so": {"downloads": {"lzma": {"sha1": "7107b615e941074f0b14c31c88fb67200aacd37f", "size": 70308, "url": "https://launcher.mojang.com/v1/objects/7107b615e941074f0b14c31c88fb67200aacd37f/libunpack.so"}, "raw": {"sha1": "b05ff862ed87928ed91e80e5604673c5ea710a53", "size": 197712, "url": "https://launcher.mojang.com/v1/objects/b05ff862ed87928ed91e80e5604673c5ea710a53/libunpack.so"}}, "executable": true, "type": "file"}, "lib/amd64/libverify.so": {"downloads": {"lzma": {"sha1": "ecd98efb8c7da441a8c3580e8f5598f3cb4165b1", "size": 21885, "url": "https://launcher.mojang.com/v1/objects/ecd98efb8c7da441a8c3580e8f5598f3cb4165b1/libverify.so"}, "raw": {"sha1": "e2c8d92531c45ab9be69ffb72c87fa12e9e59827", "size": 66112, "url": "https://launcher.mojang.com/v1/objects/e2c8d92531c45ab9be69ffb72c87fa12e9e59827/libverify.so"}}, "executable": true, "type": "file"}, "lib/amd64/libzip.so": {"downloads": {"lzma": {"sha1": "7c562342e3f7b138dc978495447e3e6a96c2cf45", "size": 54876, "url": "https://launcher.mojang.com/v1/objects/7c562342e3f7b138dc978495447e3e6a96c2cf45/libzip.so"}, "raw": {"sha1": "5f4bf35a5c3e8f8c650e891d1031589b8ab6d77f", "size": 127016, "url": "https://launcher.mojang.com/v1/objects/5f4bf35a5c3e8f8c650e891d1031589b8ab6d77f/libzip.so"}}, "executable": true, "type": "file"}, "lib/amd64/server": {"type": "directory"}, "lib/amd64/server/Xusage.txt": {"downloads": {"lzma": {"sha1": "acb2da24a4c765887df83985e4c26d6be302a0a3", "size": 629, "url": "https://launcher.mojang.com/v1/objects/acb2da24a4c765887df83985e4c26d6be302a0a3/Xusage.txt"}, "raw": {"sha1": "6983727eafe140f9dd793c78aa6f3e007438243a", "size": 1423, "url": "https://launcher.mojang.com/v1/objects/6983727eafe140f9dd793c78aa6f3e007438243a/Xusage.txt"}}, "executable": false, "type": "file"}, "lib/amd64/server/libjsig.so": {"target": "../libjsig.so", "type": "link"}, "lib/amd64/server/libjvm.so": {"downloads": {"lzma": {"sha1": "d5c6f3338aaa6712f79d680ac8c3e31beebaa886", "size": 4154311, "url": "https://launcher.mojang.com/v1/objects/d5c6f3338aaa6712f79d680ac8c3e31beebaa886/libjvm.so"}, "raw": {"sha1": "23a98e1eb505cc3fb91bc0cb2adb71ab9270e9ca", "size": 17045016, "url": "https://launcher.mojang.com/v1/objects/23a98e1eb505cc3fb91bc0cb2adb71ab9270e9ca/libjvm.so"}}, "executable": true, "type": "file"}, "lib/applet": {"type": "directory"}, "lib/calendars.properties": {"downloads": {"lzma": {"sha1": "4a757c23f2942bd802a4f80235131146d9267750", "size": 558, "url": "https://launcher.mojang.com/v1/objects/4a757c23f2942bd802a4f80235131146d9267750/calendars.properties"}, "raw": {"sha1": "42ebb0988124433b8f2a6e5d9a74ed41240bcfc6", "size": 1378, "url": "https://launcher.mojang.com/v1/objects/42ebb0988124433b8f2a6e5d9a74ed41240bcfc6/calendars.properties"}}, "executable": false, "type": "file"}, "lib/charsets.jar": {"downloads": {"lzma": {"sha1": "2bf44143b2ad9d7d55045a4de4a562330c194dc0", "size": 412367, "url": "https://launcher.mojang.com/v1/objects/2bf44143b2ad9d7d55045a4de4a562330c194dc0/charsets.jar"}, "raw": {"sha1": "d73ab9f8de255a7e112ddd13622bf7f6b18c8447", "size": 3135615, "url": "https://launcher.mojang.com/v1/objects/d73ab9f8de255a7e112ddd13622bf7f6b18c8447/charsets.jar"}}, "executable": false, "type": "file"}, "lib/classlist": {"downloads": {"lzma": {"sha1": "14e7c73d21b8513b0aff8d86e5cb34c52021fbca", "size": 15024, "url": "https://launcher.mojang.com/v1/objects/14e7c73d21b8513b0aff8d86e5cb34c52021fbca/classlist"}, "raw": {"sha1": "9c0404b63c87e2fed35e3a6cd137d6cf876c42bd", "size": 84311, "url": "https://launcher.mojang.com/v1/objects/9c0404b63c87e2fed35e3a6cd137d6cf876c42bd/classlist"}}, "executable": false, "type": "file"}, "lib/cmm": {"type": "directory"}, "lib/cmm/CIEXYZ.pf": {"downloads": {"lzma": {"sha1": "fcc5ca2fd3f45cac3434b480fa3ce00007e96529", "size": 8964, "url": "https://launcher.mojang.com/v1/objects/fcc5ca2fd3f45cac3434b480fa3ce00007e96529/CIEXYZ.pf"}, "raw": {"sha1": "b7779924c70554647b87c2a86159ca7781e929f8", "size": 51236, "url": "https://launcher.mojang.com/v1/objects/b7779924c70554647b87c2a86159ca7781e929f8/CIEXYZ.pf"}}, "executable": false, "type": "file"}, "lib/cmm/GRAY.pf": {"downloads": {"lzma": {"sha1": "5388ccfe67d3131d6d02143d8e8895003ab14ff6", "size": 299, "url": "https://launcher.mojang.com/v1/objects/5388ccfe67d3131d6d02143d8e8895003ab14ff6/GRAY.pf"}, "raw": {"sha1": "27f93961d66b8230d0cdb8b166bc8b4153d5bc2d", "size": 632, "url": "https://launcher.mojang.com/v1/objects/27f93961d66b8230d0cdb8b166bc8b4153d5bc2d/GRAY.pf"}}, "executable": false, "type": "file"}, "lib/cmm/LINEAR_RGB.pf": {"downloads": {"lzma": {"sha1": "2bd90f09c8deb64b1729d6b8173c78f9e9cab27b", "size": 678, "url": "https://launcher.mojang.com/v1/objects/2bd90f09c8deb64b1729d6b8173c78f9e9cab27b/LINEAR_RGB.pf"}, "raw": {"sha1": "7913274c2f73bafcf888f09ff60990b100214ede", "size": 1044, "url": "https://launcher.mojang.com/v1/objects/7913274c2f73bafcf888f09ff60990b100214ede/LINEAR_RGB.pf"}}, "executable": false, "type": "file"}, "lib/cmm/PYCC.pf": {"downloads": {"lzma": {"sha1": "dbb2197ecff3fcdd142e9006490c8cb5c8d19af8", "size": 171521, "url": "https://launcher.mojang.com/v1/objects/dbb2197ecff3fcdd142e9006490c8cb5c8d19af8/PYCC.pf"}, "raw": {"sha1": "4f7eed05b8f0eea7bcdc8f8f7aaeb1925ce7b144", "size": 274474, "url": "https://launcher.mojang.com/v1/objects/4f7eed05b8f0eea7bcdc8f8f7aaeb1925ce7b144/PYCC.pf"}}, "executable": false, "type": "file"}, "lib/cmm/sRGB.pf": {"downloads": {"raw": {"sha1": "9eaea0911d89d63e39e95f2e2116eaec7e0bb91e", "size": 3144, "url": "https://launcher.mojang.com/v1/objects/9eaea0911d89d63e39e95f2e2116eaec7e0bb91e/sRGB.pf"}}, "executable": false, "type": "file"}, "lib/content-types.properties": {"downloads": {"lzma": {"sha1": "43a23d9a6c637c128b14cfa3feced93cbcf85b1a", "size": 1617, "url": "https://launcher.mojang.com/v1/objects/43a23d9a6c637c128b14cfa3feced93cbcf85b1a/content-types.properties"}, "raw": {"sha1": "b21698017c4a2866b5fabe59681b7592e72c83b1", "size": 5916, "url": "https://launcher.mojang.com/v1/objects/b21698017c4a2866b5fabe59681b7592e72c83b1/content-types.properties"}}, "executable": false, "type": "file"}, "lib/currency.data": {"downloads": {"lzma": {"sha1": "451b3f166ea34ef2aefbb01606ea5adcc0d65b42", "size": 1184, "url": "https://launcher.mojang.com/v1/objects/451b3f166ea34ef2aefbb01606ea5adcc0d65b42/currency.data"}, "raw": {"sha1": "bf524381a7a9b9d5bbab48069c583d2936e367a1", "size": 4134, "url": "https://launcher.mojang.com/v1/objects/bf524381a7a9b9d5bbab48069c583d2936e367a1/currency.data"}}, "executable": false, "type": "file"}, "lib/deploy": {"type": "directory"}, "lib/deploy.jar": {"downloads": {"raw": {"sha1": "fbe1de8fcd9a3d482c59414dce9311e4194766c9", "size": 2255881, "url": "https://launcher.mojang.com/v1/objects/fbe1de8fcd9a3d482c59414dce9311e4194766c9/deploy.jar"}}, "executable": false, "type": "file"}, "lib/deploy/MixedCodeMainDialog.ui": {"downloads": {"lzma": {"sha1": "7d812964343d1e978442f5c847c709784fc18fc0", "size": 683, "url": "https://launcher.mojang.com/v1/objects/7d812964343d1e978442f5c847c709784fc18fc0/MixedCodeMainDialog.ui"}, "raw": {"sha1": "c9b1af1c229e54b2d8a3d642d4f0bb31dc15be79", "size": 4507, "url": "https://launcher.mojang.com/v1/objects/c9b1af1c229e54b2d8a3d642d4f0bb31dc15be79/MixedCodeMainDialog.ui"}}, "executable": false, "type": "file"}, "lib/deploy/MixedCodeMainDialogJs.ui": {"downloads": {"lzma": {"sha1": "54fb58dbcc59e35e0ae896d0e266ae0c5bcf85c2", "size": 792, "url": "https://launcher.mojang.com/v1/objects/54fb58dbcc59e35e0ae896d0e266ae0c5bcf85c2/MixedCodeMainDialogJs.ui"}, "raw": {"sha1": "ad6337fb6d46750e14c12b439a5856f4b6864d0d", "size": 6110, "url": "https://launcher.mojang.com/v1/objects/ad6337fb6d46750e14c12b439a5856f4b6864d0d/MixedCodeMainDialogJs.ui"}}, "executable": false, "type": "file"}, "lib/deploy/cautionshield.icns": {"downloads": {"lzma": {"sha1": "7cea751dc168605054ec38ce8bfa71812be405c1", "size": 2333, "url": "https://launcher.mojang.com/v1/objects/7cea751dc168605054ec38ce8bfa71812be405c1/cautionshield.icns"}, "raw": {"sha1": "1de7ed5d5fc75aa1bcede088c655bee3bde64c38", "size": 3588, "url": "https://launcher.mojang.com/v1/objects/1de7ed5d5fc75aa1bcede088c655bee3bde64c38/cautionshield.icns"}}, "executable": false, "type": "file"}, "lib/deploy/ffjcext.zip": {"downloads": {"lzma": {"sha1": "80bcb9b3794f69d87dba93e90230f288e651e798", "size": 1809, "url": "https://launcher.mojang.com/v1/objects/80bcb9b3794f69d87dba93e90230f288e651e798/ffjcext.zip"}, "raw": {"sha1": "76d051ca7d3666ff25ea8eb9957a05574a45287f", "size": 13454, "url": "https://launcher.mojang.com/v1/objects/76d051ca7d3666ff25ea8eb9957a05574a45287f/ffjcext.zip"}}, "executable": false, "type": "file"}, "lib/deploy/java-icon.ico": {"downloads": {"lzma": {"sha1": "2a24f0207d7ab5976a8b0d92b4b381d49e895c9d", "size": 8468, "url": "https://launcher.mojang.com/v1/objects/2a24f0207d7ab5976a8b0d92b4b381d49e895c9d/java-icon.ico"}, "raw": {"sha1": "2997ceb26ff49a7d7c5e7a2405b5fb50b62c7914", "size": 29926, "url": "https://launcher.mojang.com/v1/objects/2997ceb26ff49a7d7c5e7a2405b5fb50b62c7914/java-icon.ico"}}, "executable": false, "type": "file"}, "lib/deploy/messages.properties": {"downloads": {"lzma": {"sha1": "c1e16f80dc0b1f1a591cecf3cbab4ba5e47492f4", "size": 1225, "url": "https://launcher.mojang.com/v1/objects/c1e16f80dc0b1f1a591cecf3cbab4ba5e47492f4/messages.properties"}, "raw": {"sha1": "dc52841c708e3c1eb2a044088a43396d1291bb5e", "size": 2860, "url": "https://launcher.mojang.com/v1/objects/dc52841c708e3c1eb2a044088a43396d1291bb5e/messages.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_de.properties": {"downloads": {"lzma": {"sha1": "42b42e6e1d2cb2d781f2226bde612ce519b29bc8", "size": 1394, "url": "https://launcher.mojang.com/v1/objects/42b42e6e1d2cb2d781f2226bde612ce519b29bc8/messages_de.properties"}, "raw": {"sha1": "d989fe1b8f7904888d5102294ebefd28d932ecdb", "size": 3306, "url": "https://launcher.mojang.com/v1/objects/d989fe1b8f7904888d5102294ebefd28d932ecdb/messages_de.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_es.properties": {"downloads": {"lzma": {"sha1": "c4a653e9802ca982e892b45d88c1e259c09e8c8e", "size": 1404, "url": "https://launcher.mojang.com/v1/objects/c4a653e9802ca982e892b45d88c1e259c09e8c8e/messages_es.properties"}, "raw": {"sha1": "1b0334b79db481c3a59be6915d5118d760c97baa", "size": 3600, "url": "https://launcher.mojang.com/v1/objects/1b0334b79db481c3a59be6915d5118d760c97baa/messages_es.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_fr.properties": {"downloads": {"lzma": {"sha1": "2d8dee07e3f5aab7318a22e169810b216ac44f97", "size": 1401, "url": "https://launcher.mojang.com/v1/objects/2d8dee07e3f5aab7318a22e169810b216ac44f97/messages_fr.properties"}, "raw": {"sha1": "69bd2d03c2064f8679de5b4e430ea61b567c69c5", "size": 3409, "url": "https://launcher.mojang.com/v1/objects/69bd2d03c2064f8679de5b4e430ea61b567c69c5/messages_fr.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_it.properties": {"downloads": {"lzma": {"sha1": "7c28cdd8d9e34355ba0fc03004c4f64749cae57e", "size": 1375, "url": "https://launcher.mojang.com/v1/objects/7c28cdd8d9e34355ba0fc03004c4f64749cae57e/messages_it.properties"}, "raw": {"sha1": "dbe49949308f28540a42ae6cd2ad58afbf615592", "size": 3223, "url": "https://launcher.mojang.com/v1/objects/dbe49949308f28540a42ae6cd2ad58afbf615592/messages_it.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_ja.properties": {"downloads": {"lzma": {"sha1": "9a6a4c086e48b9e615b72b6bbebb3c724d178ff4", "size": 1680, "url": "https://launcher.mojang.com/v1/objects/9a6a4c086e48b9e615b72b6bbebb3c724d178ff4/messages_ja.properties"}, "raw": {"sha1": "751170a7cdefcb1226604ac3f8196e06a04fd7ac", "size": 6349, "url": "https://launcher.mojang.com/v1/objects/751170a7cdefcb1226604ac3f8196e06a04fd7ac/messages_ja.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_ko.properties": {"downloads": {"lzma": {"sha1": "0c57c2ebfa0830f816657a384898487fc492efac", "size": 1645, "url": "https://launcher.mojang.com/v1/objects/0c57c2ebfa0830f816657a384898487fc492efac/messages_ko.properties"}, "raw": {"sha1": "bf9e055b5ab138ad6d49769e2b7630b7938848d6", "size": 5712, "url": "https://launcher.mojang.com/v1/objects/bf9e055b5ab138ad6d49769e2b7630b7938848d6/messages_ko.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_pt_BR.properties": {"downloads": {"lzma": {"sha1": "f8364dba0aa0a7e445a1a8d0e7ad66b996f70063", "size": 1388, "url": "https://launcher.mojang.com/v1/objects/f8364dba0aa0a7e445a1a8d0e7ad66b996f70063/messages_pt_BR.properties"}, "raw": {"sha1": "24e4951743521ab9a11381c77bd0cdb1ed30f5b5", "size": 3285, "url": "https://launcher.mojang.com/v1/objects/24e4951743521ab9a11381c77bd0cdb1ed30f5b5/messages_pt_BR.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_sv.properties": {"downloads": {"lzma": {"sha1": "65e5897d552258141aacf02f087c7c9c33ad0727", "size": 1355, "url": "https://launcher.mojang.com/v1/objects/65e5897d552258141aacf02f087c7c9c33ad0727/messages_sv.properties"}, "raw": {"sha1": "bb5a4aa0ba499f6b1916a83e3c7922a4583b4adb", "size": 3384, "url": "https://launcher.mojang.com/v1/objects/bb5a4aa0ba499f6b1916a83e3c7922a4583b4adb/messages_sv.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_zh_CN.properties": {"downloads": {"lzma": {"sha1": "de7d39a6e6748e9f47e842c9da90f515921c222c", "size": 1506, "url": "https://launcher.mojang.com/v1/objects/de7d39a6e6748e9f47e842c9da90f515921c222c/messages_zh_CN.properties"}, "raw": {"sha1": "1c2b96673dddd3596890ef4fc22017d484a1f652", "size": 4072, "url": "https://launcher.mojang.com/v1/objects/1c2b96673dddd3596890ef4fc22017d484a1f652/messages_zh_CN.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_zh_HK.properties": {"downloads": {"lzma": {"sha1": "e8d0e3a63caa2535a4f361033941f34dcc170a7e", "size": 1529, "url": "https://launcher.mojang.com/v1/objects/e8d0e3a63caa2535a4f361033941f34dcc170a7e/messages_zh_TW.properties"}, "raw": {"sha1": "37a57aad121c14c25e149206179728fa62203bf0", "size": 3752, "url": "https://launcher.mojang.com/v1/objects/37a57aad121c14c25e149206179728fa62203bf0/messages_zh_TW.properties"}}, "executable": false, "type": "file"}, "lib/deploy/messages_zh_TW.properties": {"downloads": {"lzma": {"sha1": "e8d0e3a63caa2535a4f361033941f34dcc170a7e", "size": 1529, "url": "https://launcher.mojang.com/v1/objects/e8d0e3a63caa2535a4f361033941f34dcc170a7e/messages_zh_TW.properties"}, "raw": {"sha1": "37a57aad121c14c25e149206179728fa62203bf0", "size": 3752, "url": "https://launcher.mojang.com/v1/objects/37a57aad121c14c25e149206179728fa62203bf0/messages_zh_TW.properties"}}, "executable": false, "type": "file"}, "lib/deploy/mixcode_s.png": {"downloads": {"raw": {"sha1": "4604e9f265eec97bccd0151c3a81afa9e69499e5", "size": 3115, "url": "https://launcher.mojang.com/v1/objects/4604e9f265eec97bccd0151c3a81afa9e69499e5/mixcode_s.png"}}, "executable": false, "type": "file"}, "lib/deploy/splash.gif": {"downloads": {"raw": {"sha1": "20e7aec75f6d036d504277542e507eb7dc24aae8", "size": 8590, "url": "https://launcher.mojang.com/v1/objects/20e7aec75f6d036d504277542e507eb7dc24aae8/splash.gif"}}, "executable": false, "type": "file"}, "lib/deploy/splash@2x.gif": {"downloads": {"raw": {"sha1": "0ae4a5bda2a6d628fac51462390b503c99509fdc", "size": 15276, "url": "https://launcher.mojang.com/v1/objects/0ae4a5bda2a6d628fac51462390b503c99509fdc/splash2x.gif"}}, "executable": false, "type": "file"}, "lib/deploy/splash_11-lic.gif": {"downloads": {"raw": {"sha1": "8def364e07f40142822df84b5bb4f50846cb5e4e", "size": 7805, "url": "https://launcher.mojang.com/v1/objects/8def364e07f40142822df84b5bb4f50846cb5e4e/splash_11-lic.gif"}}, "executable": false, "type": "file"}, "lib/deploy/splash_11@2x-lic.gif": {"downloads": {"raw": {"sha1": "d2bff9bbf7920ca743b81a0ee23b0719b4d057ca", "size": 12250, "url": "https://launcher.mojang.com/v1/objects/d2bff9bbf7920ca743b81a0ee23b0719b4d057ca/splash_11%402x-lic.gif"}}, "executable": false, "type": "file"}, "lib/desktop": {"type": "directory"}, "lib/desktop/applications": {"type": "directory"}, "lib/desktop/applications/sun-java.desktop": {"downloads": {"lzma": {"sha1": "109d1cdf165f38da92da70b403ca940192a7a9a8", "size": 536, "url": "https://launcher.mojang.com/v1/objects/109d1cdf165f38da92da70b403ca940192a7a9a8/sun-java.desktop"}, "raw": {"sha1": "d346dfe90505603ce5aff5a3c6c2e4a23d5bd990", "size": 777, "url": "https://launcher.mojang.com/v1/objects/d346dfe90505603ce5aff5a3c6c2e4a23d5bd990/sun-java.desktop"}}, "executable": false, "type": "file"}, "lib/desktop/applications/sun-javaws.desktop": {"downloads": {"lzma": {"sha1": "5e1815e7f83515881e6998584dc6bb02c5bef09a", "size": 451, "url": "https://launcher.mojang.com/v1/objects/5e1815e7f83515881e6998584dc6bb02c5bef09a/sun-javaws.desktop"}, "raw": {"sha1": "50ce8e519b836e0f53d58ce1a359d98b6cafdda6", "size": 619, "url": "https://launcher.mojang.com/v1/objects/50ce8e519b836e0f53d58ce1a359d98b6cafdda6/sun-javaws.desktop"}}, "executable": false, "type": "file"}, "lib/desktop/applications/sun_java.desktop": {"downloads": {"lzma": {"sha1": "49ab0ccb54c3be68281d05055bc56a88b1281d3c", "size": 447, "url": "https://launcher.mojang.com/v1/objects/49ab0ccb54c3be68281d05055bc56a88b1281d3c/sun_java.desktop"}, "raw": {"sha1": "79120ee8160ad6f3c9b90c2641fb7edf3af96b5d", "size": 624, "url": "https://launcher.mojang.com/v1/objects/79120ee8160ad6f3c9b90c2641fb7edf3af96b5d/sun_java.desktop"}}, "executable": false, "type": "file"}, "lib/desktop/icons": {"type": "directory"}, "lib/desktop/icons/HighContrast": {"type": "directory"}, "lib/desktop/icons/HighContrast/16x16": {"type": "directory"}, "lib/desktop/icons/HighContrast/16x16/apps": {"type": "directory"}, "lib/desktop/icons/HighContrast/16x16/apps/sun-java.png": {"downloads": {"raw": {"sha1": "366e7a48e9e4fb92eaeabbcaeb4626122a66cecb", "size": 417, "url": "https://launcher.mojang.com/v1/objects/366e7a48e9e4fb92eaeabbcaeb4626122a66cecb/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/16x16/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "366e7a48e9e4fb92eaeabbcaeb4626122a66cecb", "size": 417, "url": "https://launcher.mojang.com/v1/objects/366e7a48e9e4fb92eaeabbcaeb4626122a66cecb/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/16x16/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "366e7a48e9e4fb92eaeabbcaeb4626122a66cecb", "size": 417, "url": "https://launcher.mojang.com/v1/objects/366e7a48e9e4fb92eaeabbcaeb4626122a66cecb/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/16x16/mimetypes": {"type": "directory"}, "lib/desktop/icons/HighContrast/16x16/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "629c48907368ecf32d2395b6459c367f79d84689", "size": 464, "url": "https://launcher.mojang.com/v1/objects/629c48907368ecf32d2395b6459c367f79d84689/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "629c48907368ecf32d2395b6459c367f79d84689", "size": 464, "url": "https://launcher.mojang.com/v1/objects/629c48907368ecf32d2395b6459c367f79d84689/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/16x16/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "629c48907368ecf32d2395b6459c367f79d84689", "size": 464, "url": "https://launcher.mojang.com/v1/objects/629c48907368ecf32d2395b6459c367f79d84689/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/48x48": {"type": "directory"}, "lib/desktop/icons/HighContrast/48x48/apps": {"type": "directory"}, "lib/desktop/icons/HighContrast/48x48/apps/sun-java.png": {"downloads": {"raw": {"sha1": "8373482d072684e09830dbdb97a76ea264c9f4e9", "size": 3451, "url": "https://launcher.mojang.com/v1/objects/8373482d072684e09830dbdb97a76ea264c9f4e9/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/48x48/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "8373482d072684e09830dbdb97a76ea264c9f4e9", "size": 3451, "url": "https://launcher.mojang.com/v1/objects/8373482d072684e09830dbdb97a76ea264c9f4e9/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/48x48/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "8373482d072684e09830dbdb97a76ea264c9f4e9", "size": 3451, "url": "https://launcher.mojang.com/v1/objects/8373482d072684e09830dbdb97a76ea264c9f4e9/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/48x48/mimetypes": {"type": "directory"}, "lib/desktop/icons/HighContrast/48x48/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "56a4996519f8f3541eba7b7a7a69bcdcd8ed0410", "size": 2088, "url": "https://launcher.mojang.com/v1/objects/56a4996519f8f3541eba7b7a7a69bcdcd8ed0410/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "56a4996519f8f3541eba7b7a7a69bcdcd8ed0410", "size": 2088, "url": "https://launcher.mojang.com/v1/objects/56a4996519f8f3541eba7b7a7a69bcdcd8ed0410/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrast/48x48/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "56a4996519f8f3541eba7b7a7a69bcdcd8ed0410", "size": 2088, "url": "https://launcher.mojang.com/v1/objects/56a4996519f8f3541eba7b7a7a69bcdcd8ed0410/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse": {"type": "directory"}, "lib/desktop/icons/HighContrastInverse/16x16": {"type": "directory"}, "lib/desktop/icons/HighContrastInverse/16x16/apps": {"type": "directory"}, "lib/desktop/icons/HighContrastInverse/16x16/apps/sun-java.png": {"downloads": {"raw": {"sha1": "bf0995acb94aa794e73c5b971282ff13ffe42793", "size": 402, "url": "https://launcher.mojang.com/v1/objects/bf0995acb94aa794e73c5b971282ff13ffe42793/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/16x16/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "bf0995acb94aa794e73c5b971282ff13ffe42793", "size": 402, "url": "https://launcher.mojang.com/v1/objects/bf0995acb94aa794e73c5b971282ff13ffe42793/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/16x16/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "bf0995acb94aa794e73c5b971282ff13ffe42793", "size": 402, "url": "https://launcher.mojang.com/v1/objects/bf0995acb94aa794e73c5b971282ff13ffe42793/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/16x16/mimetypes": {"type": "directory"}, "lib/desktop/icons/HighContrastInverse/16x16/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "1477eceda25e162fcda2e69ee3906091973d8344", "size": 473, "url": "https://launcher.mojang.com/v1/objects/1477eceda25e162fcda2e69ee3906091973d8344/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "1477eceda25e162fcda2e69ee3906091973d8344", "size": 473, "url": "https://launcher.mojang.com/v1/objects/1477eceda25e162fcda2e69ee3906091973d8344/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/16x16/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "1477eceda25e162fcda2e69ee3906091973d8344", "size": 473, "url": "https://launcher.mojang.com/v1/objects/1477eceda25e162fcda2e69ee3906091973d8344/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/48x48": {"type": "directory"}, "lib/desktop/icons/HighContrastInverse/48x48/apps": {"type": "directory"}, "lib/desktop/icons/HighContrastInverse/48x48/apps/sun-java.png": {"downloads": {"raw": {"sha1": "413da160dd9899b95f53d4cc11f5ee0550cc6585", "size": 3410, "url": "https://launcher.mojang.com/v1/objects/413da160dd9899b95f53d4cc11f5ee0550cc6585/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/48x48/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "413da160dd9899b95f53d4cc11f5ee0550cc6585", "size": 3410, "url": "https://launcher.mojang.com/v1/objects/413da160dd9899b95f53d4cc11f5ee0550cc6585/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/48x48/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "413da160dd9899b95f53d4cc11f5ee0550cc6585", "size": 3410, "url": "https://launcher.mojang.com/v1/objects/413da160dd9899b95f53d4cc11f5ee0550cc6585/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/48x48/mimetypes": {"type": "directory"}, "lib/desktop/icons/HighContrastInverse/48x48/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "d66e04dfa25c196bec2e201547325b79846ab674", "size": 2085, "url": "https://launcher.mojang.com/v1/objects/d66e04dfa25c196bec2e201547325b79846ab674/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "d66e04dfa25c196bec2e201547325b79846ab674", "size": 2085, "url": "https://launcher.mojang.com/v1/objects/d66e04dfa25c196bec2e201547325b79846ab674/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/HighContrastInverse/48x48/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "d66e04dfa25c196bec2e201547325b79846ab674", "size": 2085, "url": "https://launcher.mojang.com/v1/objects/d66e04dfa25c196bec2e201547325b79846ab674/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast": {"type": "directory"}, "lib/desktop/icons/LowContrast/16x16": {"type": "directory"}, "lib/desktop/icons/LowContrast/16x16/apps": {"type": "directory"}, "lib/desktop/icons/LowContrast/16x16/apps/sun-java.png": {"downloads": {"raw": {"sha1": "f93b7cf0a6d27d664a7f09dab6933b2768536f52", "size": 519, "url": "https://launcher.mojang.com/v1/objects/f93b7cf0a6d27d664a7f09dab6933b2768536f52/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/16x16/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "f93b7cf0a6d27d664a7f09dab6933b2768536f52", "size": 519, "url": "https://launcher.mojang.com/v1/objects/f93b7cf0a6d27d664a7f09dab6933b2768536f52/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/16x16/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "f93b7cf0a6d27d664a7f09dab6933b2768536f52", "size": 519, "url": "https://launcher.mojang.com/v1/objects/f93b7cf0a6d27d664a7f09dab6933b2768536f52/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/16x16/mimetypes": {"type": "directory"}, "lib/desktop/icons/LowContrast/16x16/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "0aa1605877280b88de1f1cc3e7e4bdbeed968a73", "size": 525, "url": "https://launcher.mojang.com/v1/objects/0aa1605877280b88de1f1cc3e7e4bdbeed968a73/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "0aa1605877280b88de1f1cc3e7e4bdbeed968a73", "size": 525, "url": "https://launcher.mojang.com/v1/objects/0aa1605877280b88de1f1cc3e7e4bdbeed968a73/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/16x16/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "0aa1605877280b88de1f1cc3e7e4bdbeed968a73", "size": 525, "url": "https://launcher.mojang.com/v1/objects/0aa1605877280b88de1f1cc3e7e4bdbeed968a73/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/48x48": {"type": "directory"}, "lib/desktop/icons/LowContrast/48x48/apps": {"type": "directory"}, "lib/desktop/icons/LowContrast/48x48/apps/sun-java.png": {"downloads": {"raw": {"sha1": "1fcf4fd6da61873b5f21b39412da26509734b7cc", "size": 1507, "url": "https://launcher.mojang.com/v1/objects/1fcf4fd6da61873b5f21b39412da26509734b7cc/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/48x48/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "1fcf4fd6da61873b5f21b39412da26509734b7cc", "size": 1507, "url": "https://launcher.mojang.com/v1/objects/1fcf4fd6da61873b5f21b39412da26509734b7cc/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/48x48/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "1fcf4fd6da61873b5f21b39412da26509734b7cc", "size": 1507, "url": "https://launcher.mojang.com/v1/objects/1fcf4fd6da61873b5f21b39412da26509734b7cc/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/48x48/mimetypes": {"type": "directory"}, "lib/desktop/icons/LowContrast/48x48/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "e36636b1c04dc283c18adf669b892d54b15d3ee6", "size": 1948, "url": "https://launcher.mojang.com/v1/objects/e36636b1c04dc283c18adf669b892d54b15d3ee6/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "e36636b1c04dc283c18adf669b892d54b15d3ee6", "size": 1948, "url": "https://launcher.mojang.com/v1/objects/e36636b1c04dc283c18adf669b892d54b15d3ee6/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/LowContrast/48x48/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "e36636b1c04dc283c18adf669b892d54b15d3ee6", "size": 1948, "url": "https://launcher.mojang.com/v1/objects/e36636b1c04dc283c18adf669b892d54b15d3ee6/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor": {"type": "directory"}, "lib/desktop/icons/hicolor/16x16": {"type": "directory"}, "lib/desktop/icons/hicolor/16x16/apps": {"type": "directory"}, "lib/desktop/icons/hicolor/16x16/apps/sun-java.png": {"downloads": {"raw": {"sha1": "e91d05bfe9b889bf8a227908b597cab4630da8f2", "size": 383, "url": "https://launcher.mojang.com/v1/objects/e91d05bfe9b889bf8a227908b597cab4630da8f2/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/16x16/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "e91d05bfe9b889bf8a227908b597cab4630da8f2", "size": 383, "url": "https://launcher.mojang.com/v1/objects/e91d05bfe9b889bf8a227908b597cab4630da8f2/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/16x16/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "e91d05bfe9b889bf8a227908b597cab4630da8f2", "size": 383, "url": "https://launcher.mojang.com/v1/objects/e91d05bfe9b889bf8a227908b597cab4630da8f2/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/16x16/mimetypes": {"type": "directory"}, "lib/desktop/icons/hicolor/16x16/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "d2f6abe8e498aeecb334fb43f63001d34dbf6ea5", "size": 783, "url": "https://launcher.mojang.com/v1/objects/d2f6abe8e498aeecb334fb43f63001d34dbf6ea5/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "d2f6abe8e498aeecb334fb43f63001d34dbf6ea5", "size": 783, "url": "https://launcher.mojang.com/v1/objects/d2f6abe8e498aeecb334fb43f63001d34dbf6ea5/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/16x16/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "d2f6abe8e498aeecb334fb43f63001d34dbf6ea5", "size": 783, "url": "https://launcher.mojang.com/v1/objects/d2f6abe8e498aeecb334fb43f63001d34dbf6ea5/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/48x48": {"type": "directory"}, "lib/desktop/icons/hicolor/48x48/apps": {"type": "directory"}, "lib/desktop/icons/hicolor/48x48/apps/sun-java.png": {"downloads": {"raw": {"sha1": "6c90a38eaada9c32a678a282be18ec5b43a84264", "size": 1439, "url": "https://launcher.mojang.com/v1/objects/6c90a38eaada9c32a678a282be18ec5b43a84264/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/48x48/apps/sun-javaws.png": {"downloads": {"raw": {"sha1": "6c90a38eaada9c32a678a282be18ec5b43a84264", "size": 1439, "url": "https://launcher.mojang.com/v1/objects/6c90a38eaada9c32a678a282be18ec5b43a84264/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/48x48/apps/sun-jcontrol.png": {"downloads": {"raw": {"sha1": "6c90a38eaada9c32a678a282be18ec5b43a84264", "size": 1439, "url": "https://launcher.mojang.com/v1/objects/6c90a38eaada9c32a678a282be18ec5b43a84264/sun-javaws.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/48x48/mimetypes": {"type": "directory"}, "lib/desktop/icons/hicolor/48x48/mimetypes/gnome-mime-application-x-java-archive.png": {"downloads": {"raw": {"sha1": "4d5e6e0c41d1076bc86f3ab157c88a41a5716997", "size": 3202, "url": "https://launcher.mojang.com/v1/objects/4d5e6e0c41d1076bc86f3ab157c88a41a5716997/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": {"downloads": {"raw": {"sha1": "4d5e6e0c41d1076bc86f3ab157c88a41a5716997", "size": 3202, "url": "https://launcher.mojang.com/v1/objects/4d5e6e0c41d1076bc86f3ab157c88a41a5716997/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/icons/hicolor/48x48/mimetypes/gnome-mime-text-x-java.png": {"downloads": {"raw": {"sha1": "4d5e6e0c41d1076bc86f3ab157c88a41a5716997", "size": 3202, "url": "https://launcher.mojang.com/v1/objects/4d5e6e0c41d1076bc86f3ab157c88a41a5716997/gnome-mime-application-x-java-archive.png"}}, "executable": false, "type": "file"}, "lib/desktop/mime": {"type": "directory"}, "lib/desktop/mime/packages": {"type": "directory"}, "lib/desktop/mime/packages/x-java-archive.xml": {"downloads": {"lzma": {"sha1": "841230729f0a59de2a1071d155d96358232b2ba1", "size": 591, "url": "https://launcher.mojang.com/v1/objects/841230729f0a59de2a1071d155d96358232b2ba1/x-java-archive.xml"}, "raw": {"sha1": "b6297fd36efa799312961f95ebf0c85c920d5037", "size": 1822, "url": "https://launcher.mojang.com/v1/objects/b6297fd36efa799312961f95ebf0c85c920d5037/x-java-archive.xml"}}, "executable": false, "type": "file"}, "lib/desktop/mime/packages/x-java-jnlp-file.xml": {"downloads": {"lzma": {"sha1": "abf9acbe7c18027c4f036c4e42bb2cf1115525fa", "size": 302, "url": "https://launcher.mojang.com/v1/objects/abf9acbe7c18027c4f036c4e42bb2cf1115525fa/x-java-jnlp-file.xml"}, "raw": {"sha1": "72f03da83ddb76c9105f619fcfa4dbdad70e6b30", "size": 412, "url": "https://launcher.mojang.com/v1/objects/72f03da83ddb76c9105f619fcfa4dbdad70e6b30/x-java-jnlp-file.xml"}}, "executable": false, "type": "file"}, "lib/ext": {"type": "directory"}, "lib/ext/cldrdata.jar": {"downloads": {"raw": {"sha1": "6cacc961942d3f02a88907aa8f2eaae8e20c95a0", "size": 3860502, "url": "https://launcher.mojang.com/v1/objects/6cacc961942d3f02a88907aa8f2eaae8e20c95a0/cldrdata.jar"}}, "executable": false, "type": "file"}, "lib/ext/dnsns.jar": {"downloads": {"raw": {"sha1": "93bebdd7514e53ae31d60c5daba673878c8822ec", "size": 8286, "url": "https://launcher.mojang.com/v1/objects/93bebdd7514e53ae31d60c5daba673878c8822ec/dnsns.jar"}}, "executable": false, "type": "file"}, "lib/ext/jaccess.jar": {"downloads": {"raw": {"sha1": "2f54879df7c29ec67c40d40cfc95c0d4a968bea1", "size": 44516, "url": "https://launcher.mojang.com/v1/objects/2f54879df7c29ec67c40d40cfc95c0d4a968bea1/jaccess.jar"}}, "executable": false, "type": "file"}, "lib/ext/jfxrt.jar": {"downloads": {"lzma": {"sha1": "a6c5b6a782ba360ada6651f5322dcab88c75711c", "size": 3374270, "url": "https://launcher.mojang.com/v1/objects/a6c5b6a782ba360ada6651f5322dcab88c75711c/jfxrt.jar"}, "raw": {"sha1": "1ad7a876f045399c23ee4ab7dee380a04ca2ac08", "size": 18508094, "url": "https://launcher.mojang.com/v1/objects/1ad7a876f045399c23ee4ab7dee380a04ca2ac08/jfxrt.jar"}}, "executable": false, "type": "file"}, "lib/ext/localedata.jar": {"downloads": {"raw": {"sha1": "0cc9f550d4e410b5aa29dbfd2c1b5c99391c7f70", "size": 1178926, "url": "https://launcher.mojang.com/v1/objects/0cc9f550d4e410b5aa29dbfd2c1b5c99391c7f70/localedata.jar"}}, "executable": false, "type": "file"}, "lib/ext/meta-index": {"downloads": {"lzma": {"sha1": "1359457529f42bacf495afcb68149ae036442dd9", "size": 594, "url": "https://launcher.mojang.com/v1/objects/1359457529f42bacf495afcb68149ae036442dd9/meta-index"}, "raw": {"sha1": "334649c6e2d5d7248211f30855e97cfcb4558851", "size": 1269, "url": "https://launcher.mojang.com/v1/objects/334649c6e2d5d7248211f30855e97cfcb4558851/meta-index"}}, "executable": false, "type": "file"}, "lib/ext/nashorn.jar": {"downloads": {"raw": {"sha1": "dec5dd17a0f52ae79dfbfb38840bffb8b7a679a5", "size": 2023869, "url": "https://launcher.mojang.com/v1/objects/dec5dd17a0f52ae79dfbfb38840bffb8b7a679a5/nashorn.jar"}}, "executable": false, "type": "file"}, "lib/ext/sunec.jar": {"downloads": {"raw": {"sha1": "bf1c817820341a246f7130fe046e8310b03d04f6", "size": 41672, "url": "https://launcher.mojang.com/v1/objects/bf1c817820341a246f7130fe046e8310b03d04f6/sunec.jar"}}, "executable": false, "type": "file"}, "lib/ext/sunjce_provider.jar": {"downloads": {"raw": {"sha1": "bb3494e4b5cb3c3e60da767207731f18b267cb34", "size": 279326, "url": "https://launcher.mojang.com/v1/objects/bb3494e4b5cb3c3e60da767207731f18b267cb34/sunjce_provider.jar"}}, "executable": false, "type": "file"}, "lib/ext/sunpkcs11.jar": {"downloads": {"raw": {"sha1": "5bb1dedc3344cd3bb86828d4aa8ca82f4a606ed4", "size": 250218, "url": "https://launcher.mojang.com/v1/objects/5bb1dedc3344cd3bb86828d4aa8ca82f4a606ed4/sunpkcs11.jar"}}, "executable": false, "type": "file"}, "lib/ext/zipfs.jar": {"downloads": {"raw": {"sha1": "37b338f0e8e60d6396f51275130e8110816d7b30", "size": 68964, "url": "https://launcher.mojang.com/v1/objects/37b338f0e8e60d6396f51275130e8110816d7b30/zipfs.jar"}}, "executable": false, "type": "file"}, "lib/flavormap.properties": {"downloads": {"lzma": {"sha1": "2d5ef19ee77ccfc95c9413eea155cde59a48fadd", "size": 1541, "url": "https://launcher.mojang.com/v1/objects/2d5ef19ee77ccfc95c9413eea155cde59a48fadd/flavormap.properties"}, "raw": {"sha1": "4e66e8fe12d7f8b3b0c4e1a1915f329bb1fbf6d2", "size": 3901, "url": "https://launcher.mojang.com/v1/objects/4e66e8fe12d7f8b3b0c4e1a1915f329bb1fbf6d2/flavormap.properties"}}, "executable": false, "type": "file"}, "lib/fontconfig.RedHat.5.bfc": {"downloads": {"lzma": {"sha1": "5197f6e387f16458b7408134e38b06f20f625e4c", "size": 795, "url": "https://launcher.mojang.com/v1/objects/5197f6e387f16458b7408134e38b06f20f625e4c/fontconfig.RedHat.5.bfc"}, "raw": {"sha1": "fb806ada6e68f16a9fe2b726a39d9ef5a835c0c2", "size": 4532, "url": "https://launcher.mojang.com/v1/objects/fb806ada6e68f16a9fe2b726a39d9ef5a835c0c2/fontconfig.RedHat.5.bfc"}}, "executable": false, "type": "file"}, "lib/fontconfig.RedHat.5.properties.src": {"downloads": {"lzma": {"sha1": "3897ae198e96e5a687c9c9b218ff5df60c868e0d", "size": 1089, "url": "https://launcher.mojang.com/v1/objects/3897ae198e96e5a687c9c9b218ff5df60c868e0d/fontconfig.RedHat.5.properties.src"}, "raw": {"sha1": "c67d1a06cb37b66e69560c9f5e4be7cf08af0493", "size": 8841, "url": "https://launcher.mojang.com/v1/objects/c67d1a06cb37b66e69560c9f5e4be7cf08af0493/fontconfig.RedHat.5.properties.src"}}, "executable": false, "type": "file"}, "lib/fontconfig.RedHat.6.bfc": {"downloads": {"lzma": {"sha1": "ef2f5d1f8d620be9927db45d3a28bd75777245cb", "size": 818, "url": "https://launcher.mojang.com/v1/objects/ef2f5d1f8d620be9927db45d3a28bd75777245cb/fontconfig.RedHat.6.bfc"}, "raw": {"sha1": "9ba3b3e2c621c31d0ef1b2053c80f77419a19965", "size": 4250, "url": "https://launcher.mojang.com/v1/objects/9ba3b3e2c621c31d0ef1b2053c80f77419a19965/fontconfig.RedHat.6.bfc"}}, "executable": false, "type": "file"}, "lib/fontconfig.RedHat.6.properties.src": {"downloads": {"lzma": {"sha1": "74f4148f9d7ec3d67bbd724834d478a72cfdb0db", "size": 1111, "url": "https://launcher.mojang.com/v1/objects/74f4148f9d7ec3d67bbd724834d478a72cfdb0db/fontconfig.RedHat.6.properties.src"}, "raw": {"sha1": "768e58d4d314621c38daf9fde6d67119f370acd9", "size": 8735, "url": "https://launcher.mojang.com/v1/objects/768e58d4d314621c38daf9fde6d67119f370acd9/fontconfig.RedHat.6.properties.src"}}, "executable": false, "type": "file"}, "lib/fontconfig.SuSE.10.bfc": {"downloads": {"lzma": {"sha1": "d8fe9b1d8d02368dcd452de93024c6f60670eb87", "size": 1083, "url": "https://launcher.mojang.com/v1/objects/d8fe9b1d8d02368dcd452de93024c6f60670eb87/fontconfig.SuSE.10.bfc"}, "raw": {"sha1": "ffd0dfbd1553e15b11649a73a0b3f48318138e0d", "size": 6702, "url": "https://launcher.mojang.com/v1/objects/ffd0dfbd1553e15b11649a73a0b3f48318138e0d/fontconfig.SuSE.10.bfc"}}, "executable": false, "type": "file"}, "lib/fontconfig.SuSE.10.properties.src": {"downloads": {"lzma": {"sha1": "2c382bd741a9e23114be3da82dee8290ebfca8a9", "size": 1555, "url": "https://launcher.mojang.com/v1/objects/2c382bd741a9e23114be3da82dee8290ebfca8a9/fontconfig.SuSE.10.properties.src"}, "raw": {"sha1": "a38dbdbbc514567b8281e1aea726865f37e97894", "size": 16772, "url": "https://launcher.mojang.com/v1/objects/a38dbdbbc514567b8281e1aea726865f37e97894/fontconfig.SuSE.10.properties.src"}}, "executable": false, "type": "file"}, "lib/fontconfig.SuSE.11.bfc": {"downloads": {"lzma": {"sha1": "2b78cbf11289c9858951fea7180696ba3b7176d6", "size": 1092, "url": "https://launcher.mojang.com/v1/objects/2b78cbf11289c9858951fea7180696ba3b7176d6/fontconfig.SuSE.11.bfc"}, "raw": {"sha1": "a4d8500fcb47f6327460a95851b1368660da8302", "size": 7032, "url": "https://launcher.mojang.com/v1/objects/a4d8500fcb47f6327460a95851b1368660da8302/fontconfig.SuSE.11.bfc"}}, "executable": false, "type": "file"}, "lib/fontconfig.SuSE.11.properties.src": {"downloads": {"lzma": {"sha1": "5c1635803906e2c59d36492dec724dd7ae49a5ab", "size": 1589, "url": "https://launcher.mojang.com/v1/objects/5c1635803906e2c59d36492dec724dd7ae49a5ab/fontconfig.SuSE.11.properties.src"}, "raw": {"sha1": "c4b69589e41a7279a71866a9134213be19cdf88d", "size": 16781, "url": "https://launcher.mojang.com/v1/objects/c4b69589e41a7279a71866a9134213be19cdf88d/fontconfig.SuSE.11.properties.src"}}, "executable": false, "type": "file"}, "lib/fontconfig.Turbo.bfc": {"downloads": {"lzma": {"sha1": "1c771325d9ee4af209a3db92294451d58962c7a4", "size": 822, "url": "https://launcher.mojang.com/v1/objects/1c771325d9ee4af209a3db92294451d58962c7a4/fontconfig.Turbo.bfc"}, "raw": {"sha1": "f24368deeb85cc9d0781083bc56e773518d72219", "size": 4668, "url": "https://launcher.mojang.com/v1/objects/f24368deeb85cc9d0781083bc56e773518d72219/fontconfig.Turbo.bfc"}}, "executable": false, "type": "file"}, "lib/fontconfig.Turbo.properties.src": {"downloads": {"lzma": {"sha1": "7748ffa17e2c8a34754138efa963ba39bd1cbbb3", "size": 1113, "url": "https://launcher.mojang.com/v1/objects/7748ffa17e2c8a34754138efa963ba39bd1cbbb3/fontconfig.Turbo.properties.src"}, "raw": {"sha1": "2bb7258bed7ccd4f117e4e5f892c9b13424b0c82", "size": 9192, "url": "https://launcher.mojang.com/v1/objects/2bb7258bed7ccd4f117e4e5f892c9b13424b0c82/fontconfig.Turbo.properties.src"}}, "executable": false, "type": "file"}, "lib/fontconfig.bfc": {"downloads": {"lzma": {"sha1": "be6d49ee8c64f458c4f0e64254963fec48d25150", "size": 286, "url": "https://launcher.mojang.com/v1/objects/be6d49ee8c64f458c4f0e64254963fec48d25150/fontconfig.bfc"}, "raw": {"sha1": "de39b0e19637f58d92a0188122514aa7247ebb5b", "size": 1678, "url": "https://launcher.mojang.com/v1/objects/de39b0e19637f58d92a0188122514aa7247ebb5b/fontconfig.bfc"}}, "executable": false, "type": "file"}, "lib/fontconfig.properties.src": {"downloads": {"lzma": {"sha1": "9498d5e00e5401200667687e826e28c60fa60ba4", "size": 417, "url": "https://launcher.mojang.com/v1/objects/9498d5e00e5401200667687e826e28c60fa60ba4/fontconfig.properties.src"}, "raw": {"sha1": "3617ff1424fd204415242565541facf862b16eb4", "size": 1938, "url": "https://launcher.mojang.com/v1/objects/3617ff1424fd204415242565541facf862b16eb4/fontconfig.properties.src"}}, "executable": false, "type": "file"}, "lib/fonts": {"type": "directory"}, "lib/fonts/LucidaBrightDemiBold.ttf": {"downloads": {"lzma": {"sha1": "4f748750831a7719440dff5457f4d207d0f24d21", "size": 42347, "url": "https://launcher.mojang.com/v1/objects/4f748750831a7719440dff5457f4d207d0f24d21/LucidaBrightDemiBold.ttf"}, "raw": {"sha1": "b5c97f985639e19a3b712193ee48b55dda581fd1", "size": 75144, "url": "https://launcher.mojang.com/v1/objects/b5c97f985639e19a3b712193ee48b55dda581fd1/LucidaBrightDemiBold.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/LucidaBrightDemiItalic.ttf": {"downloads": {"lzma": {"sha1": "f82e9a688553c100ecb98412b985807ed56dff5d", "size": 43119, "url": "https://launcher.mojang.com/v1/objects/f82e9a688553c100ecb98412b985807ed56dff5d/LucidaBrightDemiItalic.ttf"}, "raw": {"sha1": "1fd1f757febf3e5f5fbb7fbf7a56587a40d57de7", "size": 75124, "url": "https://launcher.mojang.com/v1/objects/1fd1f757febf3e5f5fbb7fbf7a56587a40d57de7/LucidaBrightDemiItalic.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/LucidaBrightItalic.ttf": {"downloads": {"lzma": {"sha1": "6d630df719271319c3d53f90a3d425118b908266", "size": 46206, "url": "https://launcher.mojang.com/v1/objects/6d630df719271319c3d53f90a3d425118b908266/LucidaBrightItalic.ttf"}, "raw": {"sha1": "aa5c037865c563726ecd63d61ca26443589be425", "size": 80856, "url": "https://launcher.mojang.com/v1/objects/aa5c037865c563726ecd63d61ca26443589be425/LucidaBrightItalic.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/LucidaBrightRegular.ttf": {"downloads": {"lzma": {"sha1": "4b2e31aaec2238b6ecf9f845bad0a1c6d09fbbfe", "size": 181085, "url": "https://launcher.mojang.com/v1/objects/4b2e31aaec2238b6ecf9f845bad0a1c6d09fbbfe/LucidaBrightRegular.ttf"}, "raw": {"sha1": "5d7ed564791c900a8786936930ba99385653139c", "size": 344908, "url": "https://launcher.mojang.com/v1/objects/5d7ed564791c900a8786936930ba99385653139c/LucidaBrightRegular.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/LucidaSansDemiBold.ttf": {"downloads": {"lzma": {"sha1": "079b16dc3c4918ab1f4f760b6dc5e6586c219042", "size": 173229, "url": "https://launcher.mojang.com/v1/objects/079b16dc3c4918ab1f4f760b6dc5e6586c219042/LucidaSansDemiBold.ttf"}, "raw": {"sha1": "92b79fefc35e96190250c602a8fed85276b32a95", "size": 317896, "url": "https://launcher.mojang.com/v1/objects/92b79fefc35e96190250c602a8fed85276b32a95/LucidaSansDemiBold.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/LucidaSansRegular.ttf": {"downloads": {"lzma": {"sha1": "64a65d7b94d7153d20957ef6d06bebb4dd0f48e4", "size": 326062, "url": "https://launcher.mojang.com/v1/objects/64a65d7b94d7153d20957ef6d06bebb4dd0f48e4/LucidaSansRegular.ttf"}, "raw": {"sha1": "39cc8bcb8d4a71d4657fc92ef0b9f4e3e9e67add", "size": 698236, "url": "https://launcher.mojang.com/v1/objects/39cc8bcb8d4a71d4657fc92ef0b9f4e3e9e67add/LucidaSansRegular.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/LucidaTypewriterBold.ttf": {"downloads": {"lzma": {"sha1": "cdb017f7c34bea0802bc5ea5583aef721ed99c49", "size": 130412, "url": "https://launcher.mojang.com/v1/objects/cdb017f7c34bea0802bc5ea5583aef721ed99c49/LucidaTypewriterBold.ttf"}, "raw": {"sha1": "a5da2eb49448f461470387c939f0e69119310e0b", "size": 234068, "url": "https://launcher.mojang.com/v1/objects/a5da2eb49448f461470387c939f0e69119310e0b/LucidaTypewriterBold.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/LucidaTypewriterRegular.ttf": {"downloads": {"lzma": {"sha1": "aeda4a09a53783b0dc97de8e20071bea874cbfe5", "size": 135184, "url": "https://launcher.mojang.com/v1/objects/aeda4a09a53783b0dc97de8e20071bea874cbfe5/LucidaTypewriterRegular.ttf"}, "raw": {"sha1": "c144dcafe4faf2e79cfd74d8134a631f30234db1", "size": 242700, "url": "https://launcher.mojang.com/v1/objects/c144dcafe4faf2e79cfd74d8134a631f30234db1/LucidaTypewriterRegular.ttf"}}, "executable": false, "type": "file"}, "lib/fonts/fonts.dir": {"downloads": {"lzma": {"sha1": "68f2dd93b215ec8b8d9409d2b9c825632c6b907d", "size": 273, "url": "https://launcher.mojang.com/v1/objects/68f2dd93b215ec8b8d9409d2b9c825632c6b907d/fonts.dir"}, "raw": {"sha1": "97f40cca185c954adf5cc582345a7cb8e4c50578", "size": 4041, "url": "https://launcher.mojang.com/v1/objects/97f40cca185c954adf5cc582345a7cb8e4c50578/fonts.dir"}}, "executable": false, "type": "file"}, "lib/hijrah-config-umalqura.properties": {"downloads": {"lzma": {"sha1": "02e8d296e3b18a450f1ed1547cbf2b7275664c9a", "size": 1969, "url": "https://launcher.mojang.com/v1/objects/02e8d296e3b18a450f1ed1547cbf2b7275664c9a/hijrah-config-umalqura.properties"}, "raw": {"sha1": "84aa425100740722e91f4725caf849e7863d12ba", "size": 13962, "url": "https://launcher.mojang.com/v1/objects/84aa425100740722e91f4725caf849e7863d12ba/hijrah-config-umalqura.properties"}}, "executable": false, "type": "file"}, "lib/images": {"type": "directory"}, "lib/images/cursors": {"type": "directory"}, "lib/images/cursors/cursors.properties": {"downloads": {"lzma": {"sha1": "612bd0f610ee1023947c4a2a8d3fc7d6f97e7d8f", "size": 385, "url": "https://launcher.mojang.com/v1/objects/612bd0f610ee1023947c4a2a8d3fc7d6f97e7d8f/cursors.properties"}, "raw": {"sha1": "f2b9a22ddd0a77869497a64f28f07e89a7d41f48", "size": 1274, "url": "https://launcher.mojang.com/v1/objects/f2b9a22ddd0a77869497a64f28f07e89a7d41f48/cursors.properties"}}, "executable": false, "type": "file"}, "lib/images/cursors/invalid32x32.gif": {"downloads": {"raw": {"sha1": "259edc45b4569427e8319895a444f4295d54348f", "size": 153, "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif"}}, "executable": false, "type": "file"}, "lib/images/cursors/motif_CopyDrop32x32.gif": {"downloads": {"raw": {"sha1": "eb7620fae702172aa663a19d170a0b929d3b11d1", "size": 158, "url": "https://launcher.mojang.com/v1/objects/eb7620fae702172aa663a19d170a0b929d3b11d1/motif_CopyDrop32x32.gif"}}, "executable": false, "type": "file"}, "lib/images/cursors/motif_CopyNoDrop32x32.gif": {"downloads": {"raw": {"sha1": "259edc45b4569427e8319895a444f4295d54348f", "size": 153, "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif"}}, "executable": false, "type": "file"}, "lib/images/cursors/motif_LinkDrop32x32.gif": {"downloads": {"raw": {"sha1": "9699137f990c240e714481563181069c8f6c17bb", "size": 162, "url": "https://launcher.mojang.com/v1/objects/9699137f990c240e714481563181069c8f6c17bb/motif_LinkDrop32x32.gif"}}, "executable": false, "type": "file"}, "lib/images/cursors/motif_LinkNoDrop32x32.gif": {"downloads": {"raw": {"sha1": "259edc45b4569427e8319895a444f4295d54348f", "size": 153, "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif"}}, "executable": false, "type": "file"}, "lib/images/cursors/motif_MoveDrop32x32.gif": {"downloads": {"raw": {"sha1": "03c1617ce3c5ab8af03e46d30a8c8f31ab57fb1b", "size": 141, "url": "https://launcher.mojang.com/v1/objects/03c1617ce3c5ab8af03e46d30a8c8f31ab57fb1b/motif_MoveDrop32x32.gif"}}, "executable": false, "type": "file"}, "lib/images/cursors/motif_MoveNoDrop32x32.gif": {"downloads": {"raw": {"sha1": "259edc45b4569427e8319895a444f4295d54348f", "size": 153, "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif"}}, "executable": false, "type": "file"}, "lib/images/icons": {"type": "directory"}, "lib/images/icons/sun-java.png": {"downloads": {"raw": {"sha1": "d101b693aa054f51097eebdfeed8b8a6ca7b55b8", "size": 4707, "url": "https://launcher.mojang.com/v1/objects/d101b693aa054f51097eebdfeed8b8a6ca7b55b8/sun-java.png"}}, "executable": false, "type": "file"}, "lib/images/icons/sun-java_HighContrast.png": {"downloads": {"raw": {"sha1": "a6b1e418d6b5d03719b96f61f0c5236a60970151", "size": 3729, "url": "https://launcher.mojang.com/v1/objects/a6b1e418d6b5d03719b96f61f0c5236a60970151/sun-java_HighContrast.png"}}, "executable": false, "type": "file"}, "lib/images/icons/sun-java_HighContrastInverse.png": {"downloads": {"raw": {"sha1": "2dda28b9bddc9b5b018e3e8a8b062a99d9b2f887", "size": 3777, "url": "https://launcher.mojang.com/v1/objects/2dda28b9bddc9b5b018e3e8a8b062a99d9b2f887/sun-java_HighContrastInverse.png"}}, "executable": false, "type": "file"}, "lib/images/icons/sun-java_LowContrast.png": {"downloads": {"raw": {"sha1": "7714cc4e894c3626c8da6fe742ed22b2829122d9", "size": 4012, "url": "https://launcher.mojang.com/v1/objects/7714cc4e894c3626c8da6fe742ed22b2829122d9/sun-java_LowContrast.png"}}, "executable": false, "type": "file"}, "lib/javafx.properties": {"downloads": {"raw": {"sha1": "49e6b75d109e5fd3f6cbe7cc5fa9a7980796d14d", "size": 56, "url": "https://launcher.mojang.com/v1/objects/49e6b75d109e5fd3f6cbe7cc5fa9a7980796d14d/javafx.properties"}}, "executable": false, "type": "file"}, "lib/javaws.jar": {"downloads": {"raw": {"sha1": "04fa5ae04ead65b91be5dee575497e49ffd49fe9", "size": 488118, "url": "https://launcher.mojang.com/v1/objects/04fa5ae04ead65b91be5dee575497e49ffd49fe9/javaws.jar"}}, "executable": false, "type": "file"}, "lib/jce.jar": {"downloads": {"raw": {"sha1": "5460adee09cc5fc8829c0acfc46c34670a7d70a0", "size": 115646, "url": "https://launcher.mojang.com/v1/objects/5460adee09cc5fc8829c0acfc46c34670a7d70a0/jce.jar"}}, "executable": false, "type": "file"}, "lib/jexec": {"downloads": {"lzma": {"sha1": "2d4323d4e060f8126d026ca6c03b8972aedd2fab", "size": 3311, "url": "https://launcher.mojang.com/v1/objects/2d4323d4e060f8126d026ca6c03b8972aedd2fab/jexec"}, "raw": {"sha1": "6aa01f1d8d103974164bcfaea03c04eeeefd7d41", "size": 13376, "url": "https://launcher.mojang.com/v1/objects/6aa01f1d8d103974164bcfaea03c04eeeefd7d41/jexec"}}, "executable": true, "type": "file"}, "lib/jfr": {"type": "directory"}, "lib/jfr.jar": {"downloads": {"lzma": {"sha1": "5b9d615c91c72f4fe356d9b4105946679452d1e1", "size": 137982, "url": "https://launcher.mojang.com/v1/objects/5b9d615c91c72f4fe356d9b4105946679452d1e1/jfr.jar"}, "raw": {"sha1": "0f3fd66a336703d935bdc22ad8082bc51d34e534", "size": 560713, "url": "https://launcher.mojang.com/v1/objects/0f3fd66a336703d935bdc22ad8082bc51d34e534/jfr.jar"}}, "executable": false, "type": "file"}, "lib/jfr/default.jfc": {"downloads": {"lzma": {"sha1": "373ddd878146dd8ce8991c2c5115a05a82859bdb", "size": 2207, "url": "https://launcher.mojang.com/v1/objects/373ddd878146dd8ce8991c2c5115a05a82859bdb/default.jfc"}, "raw": {"sha1": "1a64b68d0e7d43f8149faba94440be54f4f24527", "size": 20109, "url": "https://launcher.mojang.com/v1/objects/1a64b68d0e7d43f8149faba94440be54f4f24527/default.jfc"}}, "executable": false, "type": "file"}, "lib/jfr/profile.jfc": {"downloads": {"lzma": {"sha1": "3dcdc5feee3ccfb66bc8726b666944cd4bdadae3", "size": 2199, "url": "https://launcher.mojang.com/v1/objects/3dcdc5feee3ccfb66bc8726b666944cd4bdadae3/profile.jfc"}, "raw": {"sha1": "5d7d08a595f76322c51ae43ea966fbba6b69eebe", "size": 20065, "url": "https://launcher.mojang.com/v1/objects/5d7d08a595f76322c51ae43ea966fbba6b69eebe/profile.jfc"}}, "executable": false, "type": "file"}, "lib/jfxswt.jar": {"downloads": {"raw": {"sha1": "99d9a264c898d84c01e1c42565e7fe1a89dcd72d", "size": 33932, "url": "https://launcher.mojang.com/v1/objects/99d9a264c898d84c01e1c42565e7fe1a89dcd72d/jfxswt.jar"}}, "executable": false, "type": "file"}, "lib/jsse.jar": {"downloads": {"lzma": {"sha1": "94a17dfbc2e76cd12c33970a15341424f875a9ce", "size": 187549, "url": "https://launcher.mojang.com/v1/objects/94a17dfbc2e76cd12c33970a15341424f875a9ce/jsse.jar"}, "raw": {"sha1": "92c5c626e8a2d16f41272c0e404d4f992dd8310a", "size": 675599, "url": "https://launcher.mojang.com/v1/objects/92c5c626e8a2d16f41272c0e404d4f992dd8310a/jsse.jar"}}, "executable": false, "type": "file"}, "lib/jvm.hprof.txt": {"downloads": {"lzma": {"sha1": "eccdb240a815b2a83a502749339b27bb8669965b", "size": 1863, "url": "https://launcher.mojang.com/v1/objects/eccdb240a815b2a83a502749339b27bb8669965b/jvm.hprof.txt"}, "raw": {"sha1": "fbd61d52534cdd0c15df332114d469c65d001e33", "size": 4226, "url": "https://launcher.mojang.com/v1/objects/fbd61d52534cdd0c15df332114d469c65d001e33/jvm.hprof.txt"}}, "executable": false, "type": "file"}, "lib/locale": {"type": "directory"}, "lib/locale/de": {"type": "directory"}, "lib/locale/de/LC_MESSAGES": {"type": "directory"}, "lib/locale/de/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "3061d922907cc557208109088fc6ab81d577ff6f", "size": 970, "url": "https://launcher.mojang.com/v1/objects/3061d922907cc557208109088fc6ab81d577ff6f/sunw_java_plugin.mo"}, "raw": {"sha1": "5b223a3d723ac1cfce63623fb109f2868d47d1b7", "size": 2483, "url": "https://launcher.mojang.com/v1/objects/5b223a3d723ac1cfce63623fb109f2868d47d1b7/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/es": {"type": "directory"}, "lib/locale/es/LC_MESSAGES": {"type": "directory"}, "lib/locale/es/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "24338049a89b323e17182b3a3006b50565d4fa0f", "size": 979, "url": "https://launcher.mojang.com/v1/objects/24338049a89b323e17182b3a3006b50565d4fa0f/sunw_java_plugin.mo"}, "raw": {"sha1": "6cc63dc97f2fdb2ed799e48b1dc98c4f37cdecc1", "size": 2477, "url": "https://launcher.mojang.com/v1/objects/6cc63dc97f2fdb2ed799e48b1dc98c4f37cdecc1/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/fr": {"type": "directory"}, "lib/locale/fr/LC_MESSAGES": {"type": "directory"}, "lib/locale/fr/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "22796a48ef39f57d2d6fa70f41308e493d7f05c1", "size": 1033, "url": "https://launcher.mojang.com/v1/objects/22796a48ef39f57d2d6fa70f41308e493d7f05c1/sunw_java_plugin.mo"}, "raw": {"sha1": "d9d5b458db6e83fdf85c3526aeee3f57c4929840", "size": 2746, "url": "https://launcher.mojang.com/v1/objects/d9d5b458db6e83fdf85c3526aeee3f57c4929840/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/it": {"type": "directory"}, "lib/locale/it/LC_MESSAGES": {"type": "directory"}, "lib/locale/it/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "59a4cae38bfb8927745674d0efc2f284bc277987", "size": 958, "url": "https://launcher.mojang.com/v1/objects/59a4cae38bfb8927745674d0efc2f284bc277987/sunw_java_plugin.mo"}, "raw": {"sha1": "f6e72e3b2141ccc3dffab10ae14a754e494577ba", "size": 2434, "url": "https://launcher.mojang.com/v1/objects/f6e72e3b2141ccc3dffab10ae14a754e494577ba/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/ja": {"type": "directory"}, "lib/locale/ja/LC_MESSAGES": {"type": "directory"}, "lib/locale/ja/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "7d6aeed563e1cefcf0224cf522048468088884a9", "size": 1036, "url": "https://launcher.mojang.com/v1/objects/7d6aeed563e1cefcf0224cf522048468088884a9/sunw_java_plugin.mo"}, "raw": {"sha1": "378881a8cb8dd2aebb43eacd0c68519be4f258b1", "size": 2415, "url": "https://launcher.mojang.com/v1/objects/378881a8cb8dd2aebb43eacd0c68519be4f258b1/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/ko": {"type": "directory"}, "lib/locale/ko.UTF-8": {"type": "directory"}, "lib/locale/ko.UTF-8/LC_MESSAGES": {"type": "directory"}, "lib/locale/ko.UTF-8/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "12ee3b21511e8497d95ea0ba9d6fe519227d0b16", "size": 1069, "url": "https://launcher.mojang.com/v1/objects/12ee3b21511e8497d95ea0ba9d6fe519227d0b16/sunw_java_plugin.mo"}, "raw": {"sha1": "cb19df01c59662dbe2f4050b1290d374b82fe1fa", "size": 2753, "url": "https://launcher.mojang.com/v1/objects/cb19df01c59662dbe2f4050b1290d374b82fe1fa/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/ko/LC_MESSAGES": {"type": "directory"}, "lib/locale/ko/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "6e2e47c64c360517fd436bc79c823b5679a1efe6", "size": 996, "url": "https://launcher.mojang.com/v1/objects/6e2e47c64c360517fd436bc79c823b5679a1efe6/sunw_java_plugin.mo"}, "raw": {"sha1": "12c8a118d150c78f719314df6dec49a967af71e9", "size": 2399, "url": "https://launcher.mojang.com/v1/objects/12c8a118d150c78f719314df6dec49a967af71e9/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/pt_BR": {"type": "directory"}, "lib/locale/pt_BR/LC_MESSAGES": {"type": "directory"}, "lib/locale/pt_BR/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "bcaa7e7916493f071f1bf64bf58c6b038e3569c9", "size": 940, "url": "https://launcher.mojang.com/v1/objects/bcaa7e7916493f071f1bf64bf58c6b038e3569c9/sunw_java_plugin.mo"}, "raw": {"sha1": "a3bc0c43994c53c59bba94982cf95f6d36283dd0", "size": 2420, "url": "https://launcher.mojang.com/v1/objects/a3bc0c43994c53c59bba94982cf95f6d36283dd0/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/sv": {"type": "directory"}, "lib/locale/sv/LC_MESSAGES": {"type": "directory"}, "lib/locale/sv/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "76017835d6261fe2eedbcbe5eb08a7484c3080c5", "size": 946, "url": "https://launcher.mojang.com/v1/objects/76017835d6261fe2eedbcbe5eb08a7484c3080c5/sunw_java_plugin.mo"}, "raw": {"sha1": "09a47686edec4bbb34e82fbd08559f8bb6266544", "size": 2359, "url": "https://launcher.mojang.com/v1/objects/09a47686edec4bbb34e82fbd08559f8bb6266544/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/zh": {"type": "directory"}, "lib/locale/zh.GBK": {"type": "directory"}, "lib/locale/zh.GBK/LC_MESSAGES": {"type": "directory"}, "lib/locale/zh.GBK/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "75fd04045bf5890b8bb822770bfdb90a2e9ea65b", "size": 902, "url": "https://launcher.mojang.com/v1/objects/75fd04045bf5890b8bb822770bfdb90a2e9ea65b/sunw_java_plugin.mo"}, "raw": {"sha1": "7006fe7767b8807441a1f359a90509b3e507b0d1", "size": 2002, "url": "https://launcher.mojang.com/v1/objects/7006fe7767b8807441a1f359a90509b3e507b0d1/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/zh/LC_MESSAGES": {"type": "directory"}, "lib/locale/zh/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "75fd04045bf5890b8bb822770bfdb90a2e9ea65b", "size": 902, "url": "https://launcher.mojang.com/v1/objects/75fd04045bf5890b8bb822770bfdb90a2e9ea65b/sunw_java_plugin.mo"}, "raw": {"sha1": "7006fe7767b8807441a1f359a90509b3e507b0d1", "size": 2002, "url": "https://launcher.mojang.com/v1/objects/7006fe7767b8807441a1f359a90509b3e507b0d1/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/zh_HK.BIG5HK": {"type": "directory"}, "lib/locale/zh_HK.BIG5HK/LC_MESSAGES": {"type": "directory"}, "lib/locale/zh_HK.BIG5HK/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "3a1397bb1b1741697be1479232b6d9599940c851", "size": 912, "url": "https://launcher.mojang.com/v1/objects/3a1397bb1b1741697be1479232b6d9599940c851/sunw_java_plugin.mo"}, "raw": {"sha1": "c6023544067278c78599921f1032de353ff7da42", "size": 2025, "url": "https://launcher.mojang.com/v1/objects/c6023544067278c78599921f1032de353ff7da42/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/zh_TW": {"type": "directory"}, "lib/locale/zh_TW.BIG5": {"type": "directory"}, "lib/locale/zh_TW.BIG5/LC_MESSAGES": {"type": "directory"}, "lib/locale/zh_TW.BIG5/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "3a1397bb1b1741697be1479232b6d9599940c851", "size": 912, "url": "https://launcher.mojang.com/v1/objects/3a1397bb1b1741697be1479232b6d9599940c851/sunw_java_plugin.mo"}, "raw": {"sha1": "c6023544067278c78599921f1032de353ff7da42", "size": 2025, "url": "https://launcher.mojang.com/v1/objects/c6023544067278c78599921f1032de353ff7da42/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/locale/zh_TW/LC_MESSAGES": {"type": "directory"}, "lib/locale/zh_TW/LC_MESSAGES/sunw_java_plugin.mo": {"downloads": {"lzma": {"sha1": "c05e610e75182f0c4e77f3e7a4d9670ed62bf63c", "size": 897, "url": "https://launcher.mojang.com/v1/objects/c05e610e75182f0c4e77f3e7a4d9670ed62bf63c/sunw_java_plugin.mo"}, "raw": {"sha1": "f9b972dd059eae3cd337dfcef6a178e8ed8a7db6", "size": 2025, "url": "https://launcher.mojang.com/v1/objects/f9b972dd059eae3cd337dfcef6a178e8ed8a7db6/sunw_java_plugin.mo"}}, "executable": false, "type": "file"}, "lib/logging.properties": {"downloads": {"lzma": {"sha1": "642202a58e5216d086ad37c0b5a633be802edc78", "size": 896, "url": "https://launcher.mojang.com/v1/objects/642202a58e5216d086ad37c0b5a633be802edc78/logging.properties"}, "raw": {"sha1": "89da8094484891f9ec1fa40c6c8b61f94c5869d0", "size": 2455, "url": "https://launcher.mojang.com/v1/objects/89da8094484891f9ec1fa40c6c8b61f94c5869d0/logging.properties"}}, "executable": false, "type": "file"}, "lib/management": {"type": "directory"}, "lib/management-agent.jar": {"downloads": {"lzma": {"sha1": "3ea0bf17e14b3428296a0f4011bf4025fcbfa4bd", "size": 243, "url": "https://launcher.mojang.com/v1/objects/3ea0bf17e14b3428296a0f4011bf4025fcbfa4bd/management-agent.jar"}, "raw": {"sha1": "9fbed36522aa3a80bac08a328942cbc5ef39ca8e", "size": 381, "url": "https://launcher.mojang.com/v1/objects/9fbed36522aa3a80bac08a328942cbc5ef39ca8e/management-agent.jar"}}, "executable": false, "type": "file"}, "lib/management/jmxremote.access": {"downloads": {"lzma": {"sha1": "69042ff1b14165db19c9d728614639dec16d6a31", "size": 1419, "url": "https://launcher.mojang.com/v1/objects/69042ff1b14165db19c9d728614639dec16d6a31/jmxremote.access"}, "raw": {"sha1": "21200eaad898ba4a2a8834a032efb6616fabb930", "size": 3998, "url": "https://launcher.mojang.com/v1/objects/21200eaad898ba4a2a8834a032efb6616fabb930/jmxremote.access"}}, "executable": false, "type": "file"}, "lib/management/jmxremote.password.template": {"downloads": {"lzma": {"sha1": "556c64b1e920766f8867be3964de6e49f5b81a60", "size": 1129, "url": "https://launcher.mojang.com/v1/objects/556c64b1e920766f8867be3964de6e49f5b81a60/jmxremote.password.template"}, "raw": {"sha1": "c1e0f01408bf20fbbb8b4810520c725f70050db5", "size": 2856, "url": "https://launcher.mojang.com/v1/objects/c1e0f01408bf20fbbb8b4810520c725f70050db5/jmxremote.password.template"}}, "executable": false, "type": "file"}, "lib/management/management.properties": {"downloads": {"lzma": {"sha1": "3e52f9baa6394ca6956845424c607e5cde5d3c67", "size": 3176, "url": "https://launcher.mojang.com/v1/objects/3e52f9baa6394ca6956845424c607e5cde5d3c67/management.properties"}, "raw": {"sha1": "e0451d8d7d9e84d7b1c39ec7d00993307a5cbbf1", "size": 14630, "url": "https://launcher.mojang.com/v1/objects/e0451d8d7d9e84d7b1c39ec7d00993307a5cbbf1/management.properties"}}, "executable": false, "type": "file"}, "lib/management/snmp.acl.template": {"downloads": {"lzma": {"sha1": "9a4aa6396c3b488b0663bed5e5ecb762985669c9", "size": 1121, "url": "https://launcher.mojang.com/v1/objects/9a4aa6396c3b488b0663bed5e5ecb762985669c9/snmp.acl.template"}, "raw": {"sha1": "2e9f9ac287274532eb1f0d1afcefd7f3e97cc794", "size": 3376, "url": "https://launcher.mojang.com/v1/objects/2e9f9ac287274532eb1f0d1afcefd7f3e97cc794/snmp.acl.template"}}, "executable": false, "type": "file"}, "lib/meta-index": {"downloads": {"lzma": {"sha1": "1ac60b31362fda4725c665b591c5fbe384cbc8c1", "size": 788, "url": "https://launcher.mojang.com/v1/objects/1ac60b31362fda4725c665b591c5fbe384cbc8c1/meta-index"}, "raw": {"sha1": "bf204f09242203e713c31785158a0792f9edb600", "size": 2034, "url": "https://launcher.mojang.com/v1/objects/bf204f09242203e713c31785158a0792f9edb600/meta-index"}}, "executable": false, "type": "file"}, "lib/net.properties": {"downloads": {"lzma": {"sha1": "e9ec3981a0797bf55bb87b24d9eb651ce7e6916b", "size": 1830, "url": "https://launcher.mojang.com/v1/objects/e9ec3981a0797bf55bb87b24d9eb651ce7e6916b/net.properties"}, "raw": {"sha1": "fd9471742eb759f4478bb1de9a0dc0527265b6ea", "size": 5352, "url": "https://launcher.mojang.com/v1/objects/fd9471742eb759f4478bb1de9a0dc0527265b6ea/net.properties"}}, "executable": false, "type": "file"}, "lib/oblique-fonts": {"type": "directory"}, "lib/oblique-fonts/LucidaSansDemiOblique.ttf": {"downloads": {"lzma": {"sha1": "49c8980c1b89bbdbab59d0f5bd5bebf0afcb93b2", "size": 38580, "url": "https://launcher.mojang.com/v1/objects/49c8980c1b89bbdbab59d0f5bd5bebf0afcb93b2/LucidaSansDemiOblique.ttf"}, "raw": {"sha1": "53e4e12a675ac222469341c3dbc102464a1be4c7", "size": 91352, "url": "https://launcher.mojang.com/v1/objects/53e4e12a675ac222469341c3dbc102464a1be4c7/LucidaSansDemiOblique.ttf"}}, "executable": false, "type": "file"}, "lib/oblique-fonts/LucidaSansOblique.ttf": {"downloads": {"lzma": {"sha1": "553123c0edcd08035dede4ffd92b5b81c9a7538a", "size": 116575, "url": "https://launcher.mojang.com/v1/objects/553123c0edcd08035dede4ffd92b5b81c9a7538a/LucidaSansOblique.ttf"}, "raw": {"sha1": "95a195ad4fc520b3e395c85b747fc3024d118dd9", "size": 253724, "url": "https://launcher.mojang.com/v1/objects/95a195ad4fc520b3e395c85b747fc3024d118dd9/LucidaSansOblique.ttf"}}, "executable": false, "type": "file"}, "lib/oblique-fonts/LucidaTypewriterBoldOblique.ttf": {"downloads": {"lzma": {"sha1": "2475b08151556ad4d89bb1d2b6494c6bee9abd82", "size": 29954, "url": "https://launcher.mojang.com/v1/objects/2475b08151556ad4d89bb1d2b6494c6bee9abd82/LucidaTypewriterBoldOblique.ttf"}, "raw": {"sha1": "f331fc8b0cc494702bc46b690f2b8eed36469a02", "size": 63168, "url": "https://launcher.mojang.com/v1/objects/f331fc8b0cc494702bc46b690f2b8eed36469a02/LucidaTypewriterBoldOblique.ttf"}}, "executable": false, "type": "file"}, "lib/oblique-fonts/LucidaTypewriterOblique.ttf": {"downloads": {"lzma": {"sha1": "5b970bc3b7abb21dce1aa28ff7f03459d351e552", "size": 60133, "url": "https://launcher.mojang.com/v1/objects/5b970bc3b7abb21dce1aa28ff7f03459d351e552/LucidaTypewriterOblique.ttf"}, "raw": {"sha1": "f8ea00db73f8a89a27674d050edc37c2280930e1", "size": 137484, "url": "https://launcher.mojang.com/v1/objects/f8ea00db73f8a89a27674d050edc37c2280930e1/LucidaTypewriterOblique.ttf"}}, "executable": false, "type": "file"}, "lib/oblique-fonts/fonts.dir": {"downloads": {"lzma": {"sha1": "067528c789bd713c7c3f34e779aa6e2e8253dcf6", "size": 188, "url": "https://launcher.mojang.com/v1/objects/067528c789bd713c7c3f34e779aa6e2e8253dcf6/fonts.dir"}, "raw": {"sha1": "5aee54ffba9e33de56fd84ef64fa496b898585bb", "size": 2115, "url": "https://launcher.mojang.com/v1/objects/5aee54ffba9e33de56fd84ef64fa496b898585bb/fonts.dir"}}, "executable": false, "type": "file"}, "lib/plugin.jar": {"downloads": {"raw": {"sha1": "3f250842c79112bae5369e372025b166990820e8", "size": 950772, "url": "https://launcher.mojang.com/v1/objects/3f250842c79112bae5369e372025b166990820e8/plugin.jar"}}, "executable": false, "type": "file"}, "lib/psfont.properties.ja": {"downloads": {"lzma": {"sha1": "7ca1cc244ed251cd1eb2347f1eea37d7d18c8ad4", "size": 701, "url": "https://launcher.mojang.com/v1/objects/7ca1cc244ed251cd1eb2347f1eea37d7d18c8ad4/psfont.properties.ja"}, "raw": {"sha1": "56ed1c661eeede17b4fae8c9de7b5edbad387abc", "size": 2796, "url": "https://launcher.mojang.com/v1/objects/56ed1c661eeede17b4fae8c9de7b5edbad387abc/psfont.properties.ja"}}, "executable": false, "type": "file"}, "lib/psfontj2d.properties": {"downloads": {"lzma": {"sha1": "4252fa01af8739a3545e2b705e3383892e22ab40", "size": 2278, "url": "https://launcher.mojang.com/v1/objects/4252fa01af8739a3545e2b705e3383892e22ab40/psfontj2d.properties"}, "raw": {"sha1": "aa327a22a49967f4d74afeee6726f505f209692f", "size": 10393, "url": "https://launcher.mojang.com/v1/objects/aa327a22a49967f4d74afeee6726f505f209692f/psfontj2d.properties"}}, "executable": false, "type": "file"}, "lib/resources.jar": {"downloads": {"lzma": {"sha1": "1b0e08441750dc17efe4b527aa146da6cc14e8a6", "size": 579294, "url": "https://launcher.mojang.com/v1/objects/1b0e08441750dc17efe4b527aa146da6cc14e8a6/resources.jar"}, "raw": {"sha1": "daa021906e4648d4c37e798c11733dc2047f2da1", "size": 3505206, "url": "https://launcher.mojang.com/v1/objects/daa021906e4648d4c37e798c11733dc2047f2da1/resources.jar"}}, "executable": false, "type": "file"}, "lib/rt.jar": {"downloads": {"lzma": {"sha1": "fc4a8681aeda29c2a2a3fd11bad7729543283f3d", "size": 14378994, "url": "https://launcher.mojang.com/v1/objects/fc4a8681aeda29c2a2a3fd11bad7729543283f3d/rt.jar"}, "raw": {"sha1": "5396b0954a20f3210f1f4f1886ead30880d6ebfe", "size": 66334986, "url": "https://launcher.mojang.com/v1/objects/5396b0954a20f3210f1f4f1886ead30880d6ebfe/rt.jar"}}, "executable": false, "type": "file"}, "lib/security": {"type": "directory"}, "lib/security/blacklist": {"downloads": {"lzma": {"sha1": "8206fce6c1d91a39fdf78e8e79e953913994a1cd", "size": 1969, "url": "https://launcher.mojang.com/v1/objects/8206fce6c1d91a39fdf78e8e79e953913994a1cd/blacklist"}, "raw": {"sha1": "d4ffb3857eab403955ce9d156e46d056061e6a5a", "size": 4054, "url": "https://launcher.mojang.com/v1/objects/d4ffb3857eab403955ce9d156e46d056061e6a5a/blacklist"}}, "executable": false, "type": "file"}, "lib/security/blacklisted.certs": {"downloads": {"lzma": {"sha1": "8311bead054caf6cfe678d4b7998de4caaabfa53", "size": 806, "url": "https://launcher.mojang.com/v1/objects/8311bead054caf6cfe678d4b7998de4caaabfa53/blacklisted.certs"}, "raw": {"sha1": "c5c005c29a80493f5c31cd7eb629ac1b9c752404", "size": 1273, "url": "https://launcher.mojang.com/v1/objects/c5c005c29a80493f5c31cd7eb629ac1b9c752404/blacklisted.certs"}}, "executable": false, "type": "file"}, "lib/security/cacerts": {"downloads": {"lzma": {"sha1": "654dd94809655d5b28385cbb5eba8d6ad9f2c1aa", "size": 67802, "url": "https://launcher.mojang.com/v1/objects/654dd94809655d5b28385cbb5eba8d6ad9f2c1aa/cacerts"}, "raw": {"sha1": "2917859c443c68e19f93abcd1315c3c2904cbef9", "size": 104430, "url": "https://launcher.mojang.com/v1/objects/2917859c443c68e19f93abcd1315c3c2904cbef9/cacerts"}}, "executable": false, "type": "file"}, "lib/security/java.policy": {"downloads": {"lzma": {"sha1": "b601c420d02ef3dbd8595453d08fdef91134e8b5", "size": 647, "url": "https://launcher.mojang.com/v1/objects/b601c420d02ef3dbd8595453d08fdef91134e8b5/java.policy"}, "raw": {"sha1": "c0112209a567b3b523cfed7041709f9440227968", "size": 2466, "url": "https://launcher.mojang.com/v1/objects/c0112209a567b3b523cfed7041709f9440227968/java.policy"}}, "executable": false, "type": "file"}, "lib/security/java.security": {"downloads": {"lzma": {"sha1": "531620e82ca0365ce8dc97096bb0ac5a7ace5952", "size": 10959, "url": "https://launcher.mojang.com/v1/objects/531620e82ca0365ce8dc97096bb0ac5a7ace5952/java.security"}, "raw": {"sha1": "5dcc17a168c53d0b366784e520bd4d55aa61ac18", "size": 41528, "url": "https://launcher.mojang.com/v1/objects/5dcc17a168c53d0b366784e520bd4d55aa61ac18/java.security"}}, "executable": false, "type": "file"}, "lib/security/javaws.policy": {"downloads": {"raw": {"sha1": "4384ca5e4d32f7dd86d8baddd1e690730d74e694", "size": 98, "url": "https://launcher.mojang.com/v1/objects/4384ca5e4d32f7dd86d8baddd1e690730d74e694/javaws.policy"}}, "executable": false, "type": "file"}, "lib/security/policy": {"type": "directory"}, "lib/security/policy/limited": {"type": "directory"}, "lib/security/policy/limited/US_export_policy.jar": {"downloads": {"raw": {"sha1": "7d69ea3b385bc067738520f1b5c549e1084be285", "size": 3026, "url": "https://launcher.mojang.com/v1/objects/7d69ea3b385bc067738520f1b5c549e1084be285/US_export_policy.jar"}}, "executable": false, "type": "file"}, "lib/security/policy/limited/local_policy.jar": {"downloads": {"raw": {"sha1": "238b8826e110f58acb2e1959773b0a577cd4d569", "size": 3527, "url": "https://launcher.mojang.com/v1/objects/238b8826e110f58acb2e1959773b0a577cd4d569/local_policy.jar"}}, "executable": false, "type": "file"}, "lib/security/policy/unlimited": {"type": "directory"}, "lib/security/policy/unlimited/US_export_policy.jar": {"downloads": {"raw": {"sha1": "f6fb2af1e87fc622cda194a7d6b5f5f069653ff1", "size": 3023, "url": "https://launcher.mojang.com/v1/objects/f6fb2af1e87fc622cda194a7d6b5f5f069653ff1/US_export_policy.jar"}}, "executable": false, "type": "file"}, "lib/security/policy/unlimited/local_policy.jar": {"downloads": {"raw": {"sha1": "517368ab2cbaf6b42ea0b963f98eeedd996e83e3", "size": 3035, "url": "https://launcher.mojang.com/v1/objects/517368ab2cbaf6b42ea0b963f98eeedd996e83e3/local_policy.jar"}}, "executable": false, "type": "file"}, "lib/security/trusted.libraries": {"downloads": {"raw": {"sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "size": 0, "url": "https://launcher.mojang.com/v1/objects/da39a3ee5e6b4b0d3255bfef95601890afd80709/trusted.libraries"}}, "executable": false, "type": "file"}, "lib/sound.properties": {"downloads": {"lzma": {"sha1": "3b5f7e4ec437d79048af35094290577f483b3fe1", "size": 473, "url": "https://launcher.mojang.com/v1/objects/3b5f7e4ec437d79048af35094290577f483b3fe1/sound.properties"}, "raw": {"sha1": "9afceb218059d981d0fa9f07aad3c5097cf41b0c", "size": 1210, "url": "https://launcher.mojang.com/v1/objects/9afceb218059d981d0fa9f07aad3c5097cf41b0c/sound.properties"}}, "executable": false, "type": "file"}, "lib/tzdb.dat": {"downloads": {"lzma": {"sha1": "39c69339965484afe89c14111baeeb862fdefd97", "size": 32547, "url": "https://launcher.mojang.com/v1/objects/39c69339965484afe89c14111baeeb862fdefd97/tzdb.dat"}, "raw": {"sha1": "b59c07e3619271a3b9861e999f4b138e971baf69", "size": 105734, "url": "https://launcher.mojang.com/v1/objects/b59c07e3619271a3b9861e999f4b138e971baf69/tzdb.dat"}}, "executable": false, "type": "file"}, "man": {"type": "directory"}, "man/ja": {"target": "ja_JP.UTF-8", "type": "link"}, "man/ja_JP.UTF-8": {"type": "directory"}, "man/ja_JP.UTF-8/man1": {"type": "directory"}, "man/ja_JP.UTF-8/man1/java.1": {"downloads": {"lzma": {"sha1": "f9da09710b6c6df23c256e324a0c4df00a0d6ded", "size": 25461, "url": "https://launcher.mojang.com/v1/objects/f9da09710b6c6df23c256e324a0c4df00a0d6ded/java.1"}, "raw": {"sha1": "b0b12a0bb66e6171771ca4b1dfca32fb759bcaec", "size": 148688, "url": "https://launcher.mojang.com/v1/objects/b0b12a0bb66e6171771ca4b1dfca32fb759bcaec/java.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/javaws.1": {"downloads": {"lzma": {"sha1": "6188fae453ca09ccb19be5c9f4d2059926b36267", "size": 2154, "url": "https://launcher.mojang.com/v1/objects/6188fae453ca09ccb19be5c9f4d2059926b36267/javaws.1"}, "raw": {"sha1": "8f39d928870268ace07bedfebd18db1e1d07fc37", "size": 6641, "url": "https://launcher.mojang.com/v1/objects/8f39d928870268ace07bedfebd18db1e1d07fc37/javaws.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/jjs.1": {"downloads": {"lzma": {"sha1": "6e42b989d28b185dc1aab50c0389834e649a37d4", "size": 3452, "url": "https://launcher.mojang.com/v1/objects/6e42b989d28b185dc1aab50c0389834e649a37d4/jjs.1"}, "raw": {"sha1": "e023322a2013912315a2bd1034e6f829a27c76e0", "size": 11365, "url": "https://launcher.mojang.com/v1/objects/e023322a2013912315a2bd1034e6f829a27c76e0/jjs.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/keytool.1": {"downloads": {"lzma": {"sha1": "a78134a4bddd53d684a70aa677e51a215db1c9cb", "size": 20698, "url": "https://launcher.mojang.com/v1/objects/a78134a4bddd53d684a70aa677e51a215db1c9cb/keytool.1"}, "raw": {"sha1": "148583c837eaaf6333ccfd8c9e8df08574e14b0c", "size": 111033, "url": "https://launcher.mojang.com/v1/objects/148583c837eaaf6333ccfd8c9e8df08574e14b0c/keytool.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/orbd.1": {"downloads": {"lzma": {"sha1": "326af0dcbff173ef8aee29163dbe146d7389cc3e", "size": 4225, "url": "https://launcher.mojang.com/v1/objects/326af0dcbff173ef8aee29163dbe146d7389cc3e/orbd.1"}, "raw": {"sha1": "95651622d33c08286858ec337edd3ea72acd93dc", "size": 16092, "url": "https://launcher.mojang.com/v1/objects/95651622d33c08286858ec337edd3ea72acd93dc/orbd.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/pack200.1": {"downloads": {"lzma": {"sha1": "e0eedafa748c61a44e5be4355fe9d44b05048e80", "size": 4293, "url": "https://launcher.mojang.com/v1/objects/e0eedafa748c61a44e5be4355fe9d44b05048e80/pack200.1"}, "raw": {"sha1": "aa21a0ab75707f7fc66e83c7a392e69b37ddf80e", "size": 14482, "url": "https://launcher.mojang.com/v1/objects/aa21a0ab75707f7fc66e83c7a392e69b37ddf80e/pack200.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/policytool.1": {"downloads": {"lzma": {"sha1": "3c766ed12dab58166169d35680c392a6be1814a1", "size": 1380, "url": "https://launcher.mojang.com/v1/objects/3c766ed12dab58166169d35680c392a6be1814a1/policytool.1"}, "raw": {"sha1": "80879c74e072a98fad6f32b3283331aaf9bd002f", "size": 4020, "url": "https://launcher.mojang.com/v1/objects/80879c74e072a98fad6f32b3283331aaf9bd002f/policytool.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/rmid.1": {"downloads": {"lzma": {"sha1": "1e20779d990beacc32a48237777d670fcc47ca14", "size": 4836, "url": "https://launcher.mojang.com/v1/objects/1e20779d990beacc32a48237777d670fcc47ca14/rmid.1"}, "raw": {"sha1": "7e40cb8003d098d6e36f45640b26f979ac94b5c5", "size": 19715, "url": "https://launcher.mojang.com/v1/objects/7e40cb8003d098d6e36f45640b26f979ac94b5c5/rmid.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/rmiregistry.1": {"downloads": {"lzma": {"sha1": "aaf4ffe07e954f8696eef1ecb7a5e244628d0ad9", "size": 1627, "url": "https://launcher.mojang.com/v1/objects/aaf4ffe07e954f8696eef1ecb7a5e244628d0ad9/rmiregistry.1"}, "raw": {"sha1": "c53c52f3ae7a011c135894c9fc51b741e729c33d", "size": 4557, "url": "https://launcher.mojang.com/v1/objects/c53c52f3ae7a011c135894c9fc51b741e729c33d/rmiregistry.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/servertool.1": {"downloads": {"lzma": {"sha1": "3b9e624e9d1cf2959b438a35061162e2100ddecd", "size": 2626, "url": "https://launcher.mojang.com/v1/objects/3b9e624e9d1cf2959b438a35061162e2100ddecd/servertool.1"}, "raw": {"sha1": "50ab8bcd9dd9d0b1a3d81348fbce1c8f82e7189e", "size": 9081, "url": "https://launcher.mojang.com/v1/objects/50ab8bcd9dd9d0b1a3d81348fbce1c8f82e7189e/servertool.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/tnameserv.1": {"downloads": {"lzma": {"sha1": "bb3106ff74c60a76de3d20659b9c2128c70f3bf2", "size": 4478, "url": "https://launcher.mojang.com/v1/objects/bb3106ff74c60a76de3d20659b9c2128c70f3bf2/tnameserv.1"}, "raw": {"sha1": "01e714671ecd1167edcb5310b16a9c59c33c3eaa", "size": 17722, "url": "https://launcher.mojang.com/v1/objects/01e714671ecd1167edcb5310b16a9c59c33c3eaa/tnameserv.1"}}, "executable": false, "type": "file"}, "man/ja_JP.UTF-8/man1/unpack200.1": {"downloads": {"lzma": {"sha1": "c115a881cf800b08df294df55d9f250ae944e33c", "size": 1973, "url": "https://launcher.mojang.com/v1/objects/c115a881cf800b08df294df55d9f250ae944e33c/unpack200.1"}, "raw": {"sha1": "7c882bba0067367a41ad84868d18793b8a7397a3", "size": 5382, "url": "https://launcher.mojang.com/v1/objects/7c882bba0067367a41ad84868d18793b8a7397a3/unpack200.1"}}, "executable": false, "type": "file"}, "man/man1": {"type": "directory"}, "man/man1/java.1": {"downloads": {"lzma": {"sha1": "06a6b0275c202bf698d73ca71f95618d56d81c15", "size": 25796, "url": "https://launcher.mojang.com/v1/objects/06a6b0275c202bf698d73ca71f95618d56d81c15/java.1"}, "raw": {"sha1": "69fec7a341aa91f18dbdcdb95952dede7e1b689a", "size": 124796, "url": "https://launcher.mojang.com/v1/objects/69fec7a341aa91f18dbdcdb95952dede7e1b689a/java.1"}}, "executable": false, "type": "file"}, "man/man1/javaws.1": {"downloads": {"lzma": {"sha1": "4bae251c6dfb5420f56928815cf80d0b6d517a1f", "size": 1759, "url": "https://launcher.mojang.com/v1/objects/4bae251c6dfb5420f56928815cf80d0b6d517a1f/javaws.1"}, "raw": {"sha1": "e61e44e101b1bc119c2d2d4b10320f38b36a8036", "size": 4897, "url": "https://launcher.mojang.com/v1/objects/e61e44e101b1bc119c2d2d4b10320f38b36a8036/javaws.1"}}, "executable": false, "type": "file"}, "man/man1/jjs.1": {"downloads": {"lzma": {"sha1": "29683cf2bd47015c9461b688749ddffd95f6671d", "size": 1881, "url": "https://launcher.mojang.com/v1/objects/29683cf2bd47015c9461b688749ddffd95f6671d/jjs.1"}, "raw": {"sha1": "78d419bd3a7f3e0802d5220e690429194b5d1beb", "size": 4932, "url": "https://launcher.mojang.com/v1/objects/78d419bd3a7f3e0802d5220e690429194b5d1beb/jjs.1"}}, "executable": false, "type": "file"}, "man/man1/keytool.1": {"downloads": {"lzma": {"sha1": "b67e5126d43713ee3675706724b34061578b42db", "size": 19690, "url": "https://launcher.mojang.com/v1/objects/b67e5126d43713ee3675706724b34061578b42db/keytool.1"}, "raw": {"sha1": "4c976f86057ab779763fcfb98f5702ebef47f629", "size": 86925, "url": "https://launcher.mojang.com/v1/objects/4c976f86057ab779763fcfb98f5702ebef47f629/keytool.1"}}, "executable": false, "type": "file"}, "man/man1/orbd.1": {"downloads": {"lzma": {"sha1": "147064d6f7e027002e296bb246ae572d0ce0495b", "size": 3708, "url": "https://launcher.mojang.com/v1/objects/147064d6f7e027002e296bb246ae572d0ce0495b/orbd.1"}, "raw": {"sha1": "64201e1846fcf1dcc45c786ffeab89426d1c7742", "size": 12180, "url": "https://launcher.mojang.com/v1/objects/64201e1846fcf1dcc45c786ffeab89426d1c7742/orbd.1"}}, "executable": false, "type": "file"}, "man/man1/pack200.1": {"downloads": {"lzma": {"sha1": "fe17486bbe9c58cf4182fa056b9cd124e8295607", "size": 3724, "url": "https://launcher.mojang.com/v1/objects/fe17486bbe9c58cf4182fa056b9cd124e8295607/pack200.1"}, "raw": {"sha1": "26826cf52b89924f2d2a60d6cda798891875eae6", "size": 11623, "url": "https://launcher.mojang.com/v1/objects/26826cf52b89924f2d2a60d6cda798891875eae6/pack200.1"}}, "executable": false, "type": "file"}, "man/man1/policytool.1": {"downloads": {"lzma": {"sha1": "bd154e7c39aca71d15b2098c588866f8d95bc743", "size": 1122, "url": "https://launcher.mojang.com/v1/objects/bd154e7c39aca71d15b2098c588866f8d95bc743/policytool.1"}, "raw": {"sha1": "ab296625155d9a2b25ecc2b4feff2f741b3ad136", "size": 3235, "url": "https://launcher.mojang.com/v1/objects/ab296625155d9a2b25ecc2b4feff2f741b3ad136/policytool.1"}}, "executable": false, "type": "file"}, "man/man1/rmid.1": {"downloads": {"lzma": {"sha1": "6a7da234e7f43ebca5c4ba8cd862fda3be62fbaa", "size": 4255, "url": "https://launcher.mojang.com/v1/objects/6a7da234e7f43ebca5c4ba8cd862fda3be62fbaa/rmid.1"}, "raw": {"sha1": "6f10e214d7950a6a8460524e41dc700f112f89e5", "size": 15979, "url": "https://launcher.mojang.com/v1/objects/6f10e214d7950a6a8460524e41dc700f112f89e5/rmid.1"}}, "executable": false, "type": "file"}, "man/man1/rmiregistry.1": {"downloads": {"lzma": {"sha1": "f40dd17e3a734600ad1828b0c42d3a1685c4c520", "size": 1301, "url": "https://launcher.mojang.com/v1/objects/f40dd17e3a734600ad1828b0c42d3a1685c4c520/rmiregistry.1"}, "raw": {"sha1": "d9a3d23fab689df5bb9a792b88f462f939b49f70", "size": 3449, "url": "https://launcher.mojang.com/v1/objects/d9a3d23fab689df5bb9a792b88f462f939b49f70/rmiregistry.1"}}, "executable": false, "type": "file"}, "man/man1/servertool.1": {"downloads": {"lzma": {"sha1": "74f1e10712202cd3ca0ff5833de05b7ee67092e1", "size": 2307, "url": "https://launcher.mojang.com/v1/objects/74f1e10712202cd3ca0ff5833de05b7ee67092e1/servertool.1"}, "raw": {"sha1": "e6c7b510740ac8681a9bfb5f4ee1f0306125b728", "size": 7237, "url": "https://launcher.mojang.com/v1/objects/e6c7b510740ac8681a9bfb5f4ee1f0306125b728/servertool.1"}}, "executable": false, "type": "file"}, "man/man1/tnameserv.1": {"downloads": {"lzma": {"sha1": "4bec7f4e070d023f124f9352a8971d7acd249a15", "size": 3955, "url": "https://launcher.mojang.com/v1/objects/4bec7f4e070d023f124f9352a8971d7acd249a15/tnameserv.1"}, "raw": {"sha1": "a31dbbe800d49cb371fab9a4b73d22c3bf8799ad", "size": 15747, "url": "https://launcher.mojang.com/v1/objects/a31dbbe800d49cb371fab9a4b73d22c3bf8799ad/tnameserv.1"}}, "executable": false, "type": "file"}, "man/man1/unpack200.1": {"downloads": {"lzma": {"sha1": "f8e73863187929debf2ea6dadefb2995ec7917e7", "size": 1672, "url": "https://launcher.mojang.com/v1/objects/f8e73863187929debf2ea6dadefb2995ec7917e7/unpack200.1"}, "raw": {"sha1": "437f7233d738cb9b822e99003127049005663e0f", "size": 4244, "url": "https://launcher.mojang.com/v1/objects/437f7233d738cb9b822e99003127049005663e0f/unpack200.1"}}, "executable": false, "type": "file"}, "plugin": {"type": "directory"}, "plugin/desktop": {"type": "directory"}, "plugin/desktop/sun_java.desktop": {"downloads": {"lzma": {"sha1": "49ab0ccb54c3be68281d05055bc56a88b1281d3c", "size": 447, "url": "https://launcher.mojang.com/v1/objects/49ab0ccb54c3be68281d05055bc56a88b1281d3c/sun_java.desktop"}, "raw": {"sha1": "79120ee8160ad6f3c9b90c2641fb7edf3af96b5d", "size": 624, "url": "https://launcher.mojang.com/v1/objects/79120ee8160ad6f3c9b90c2641fb7edf3af96b5d/sun_java.desktop"}}, "executable": false, "type": "file"}, "plugin/desktop/sun_java.png": {"downloads": {"raw": {"sha1": "699c41e97a35414e72a80327a54d6e14e874e951", "size": 4351, "url": "https://launcher.mojang.com/v1/objects/699c41e97a35414e72a80327a54d6e14e874e951/sun_java.png"}}, "executable": false, "type": "file"}, "release": {"downloads": {"raw": {"sha1": "cb462682644c0275d94a45b759108815f3112064", "size": 424, "url": "https://launcher.mojang.com/v1/objects/cb462682644c0275d94a45b759108815f3112064/release"}}, "executable": false, "type": "file"}}} \ No newline at end of file +{ + "files": { + "COPYRIGHT": { + "downloads": { + "lzma": { + "sha1": "dd860e040807f7e53ae89da5f28dd73d57ac605d", + "size": 1431, + "url": "https://launcher.mojang.com/v1/objects/dd860e040807f7e53ae89da5f28dd73d57ac605d/COPYRIGHT" + }, + "raw": { + "sha1": "c725183c757011e7ba96c83c1e86ee7e8b516a2b", + "size": 3244, + "url": "https://launcher.mojang.com/v1/objects/c725183c757011e7ba96c83c1e86ee7e8b516a2b/COPYRIGHT" + } + }, + "executable": false, + "type": "file" + }, + "LICENSE": { + "downloads": { + "raw": { + "sha1": "3e86865deec0814c958bcf7fb87f790bccc0e8bd", + "size": 40, + "url": "https://launcher.mojang.com/v1/objects/3e86865deec0814c958bcf7fb87f790bccc0e8bd/LICENSE" + } + }, + "executable": false, + "type": "file" + }, + "README": { + "downloads": { + "raw": { + "sha1": "f90331df1e5badeadc501d8dd70714c62a920204", + "size": 46, + "url": "https://launcher.mojang.com/v1/objects/f90331df1e5badeadc501d8dd70714c62a920204/README" + } + }, + "executable": false, + "type": "file" + }, + "THIRDPARTYLICENSEREADME-JAVAFX.txt": { + "downloads": { + "lzma": { + "sha1": "4fee85109d7ff04b982d0576dabd15397f599125", + "size": 15455, + "url": + "https://launcher.mojang.com/v1/objects/4fee85109d7ff04b982d0576dabd15397f599125/THIRDPARTYLICENSEREADME-JAVAFX.txt" + }, + "raw": { + "sha1": "56ff42f87607b997b52ae0ef8bf315e36932e870", + "size": 112724, + "url": + "https://launcher.mojang.com/v1/objects/56ff42f87607b997b52ae0ef8bf315e36932e870/THIRDPARTYLICENSEREADME-JAVAFX.txt" + } + }, + "executable": false, + "type": "file" + }, + "THIRDPARTYLICENSEREADME.txt": { + "downloads": { + "lzma": { + "sha1": "419c1414ba46ae9dbfd38cf4e0601fff61644429", + "size": 32266, + "url": "https://launcher.mojang.com/v1/objects/419c1414ba46ae9dbfd38cf4e0601fff61644429/THIRDPARTYLICENSEREADME.txt" + }, + "raw": { + "sha1": "b83c3f32261de3e48ccd20614a11e066b1ec9027", + "size": 153824, + "url": "https://launcher.mojang.com/v1/objects/b83c3f32261de3e48ccd20614a11e066b1ec9027/THIRDPARTYLICENSEREADME.txt" + } + }, + "executable": false, + "type": "file" + }, + "Welcome.html": { + "downloads": { + "lzma": { + "sha1": "01c21a74b4aafb7cbe0388233c43cbdf77dcaaea", + "size": 528, + "url": "https://launcher.mojang.com/v1/objects/01c21a74b4aafb7cbe0388233c43cbdf77dcaaea/Welcome.html" + }, + "raw": { + "sha1": "d98ae54f03dac87419abc19b97e315830c2da55f", + "size": 955, + "url": "https://launcher.mojang.com/v1/objects/d98ae54f03dac87419abc19b97e315830c2da55f/Welcome.html" + } + }, + "executable": false, + "type": "file" + }, + "bin": { + "type": "directory" + }, + "bin/ControlPanel": { + "target": "jcontrol", + "type": "link" + }, + "bin/java": { + "downloads": { + "lzma": { + "sha1": "3857eea1d59e1bc545c67a753ed2768254807b8a", + "size": 2088, + "url": "https://launcher.mojang.com/v1/objects/3857eea1d59e1bc545c67a753ed2768254807b8a/java" + }, + "raw": { + "sha1": "3d20560fb5d1a49cb689c2226972e92e06d27ba6", + "size": 8464, + "url": "https://launcher.mojang.com/v1/objects/3d20560fb5d1a49cb689c2226972e92e06d27ba6/java" + } + }, + "executable": true, + "type": "file" + }, + "bin/javaws": { + "downloads": { + "lzma": { + "sha1": "a6bec5c049e76c4488294a256a2084ea23ddb440", + "size": 38173, + "url": "https://launcher.mojang.com/v1/objects/a6bec5c049e76c4488294a256a2084ea23ddb440/javaws" + }, + "raw": { + "sha1": "955c0f0066e2f893b0c2b3ccd83e223722e4ab74", + "size": 140296, + "url": "https://launcher.mojang.com/v1/objects/955c0f0066e2f893b0c2b3ccd83e223722e4ab74/javaws" + } + }, + "executable": true, + "type": "file" + }, + "bin/jcontrol": { + "downloads": { + "lzma": { + "sha1": "40c5e33748f252e1d950b579a4185ab2c23fc908", + "size": 2166, + "url": "https://launcher.mojang.com/v1/objects/40c5e33748f252e1d950b579a4185ab2c23fc908/jcontrol" + }, + "raw": { + "sha1": "ed541733c8b51e34349c1f8010b277e58ad73f1e", + "size": 6264, + "url": "https://launcher.mojang.com/v1/objects/ed541733c8b51e34349c1f8010b277e58ad73f1e/jcontrol" + } + }, + "executable": true, + "type": "file" + }, + "bin/jjs": { + "downloads": { + "lzma": { + "sha1": "d44d1ac421979f7671921986214812095a5b0e3b", + "size": 2168, + "url": "https://launcher.mojang.com/v1/objects/d44d1ac421979f7671921986214812095a5b0e3b/jjs" + }, + "raw": { + "sha1": "f00f944c3dbe556793b5dc686aaeee3e5722e99b", + "size": 8584, + "url": "https://launcher.mojang.com/v1/objects/f00f944c3dbe556793b5dc686aaeee3e5722e99b/jjs" + } + }, + "executable": true, + "type": "file" + }, + "bin/keytool": { + "downloads": { + "lzma": { + "sha1": "93c607dce450976667c382f609a367167bdec05c", + "size": 2175, + "url": "https://launcher.mojang.com/v1/objects/93c607dce450976667c382f609a367167bdec05c/keytool" + }, + "raw": { + "sha1": "7114b561546270e441e9ed1bcc24e5188c068a42", + "size": 8584, + "url": "https://launcher.mojang.com/v1/objects/7114b561546270e441e9ed1bcc24e5188c068a42/keytool" + } + }, + "executable": true, + "type": "file" + }, + "bin/orbd": { + "downloads": { + "lzma": { + "sha1": "b27dfded5e2b2f6f02c555971c94e46ca14ac81b", + "size": 2254, + "url": "https://launcher.mojang.com/v1/objects/b27dfded5e2b2f6f02c555971c94e46ca14ac81b/orbd" + }, + "raw": { + "sha1": "7f31217fecb3dbbd89f1dd3783fca58793a66fd2", + "size": 8656, + "url": "https://launcher.mojang.com/v1/objects/7f31217fecb3dbbd89f1dd3783fca58793a66fd2/orbd" + } + }, + "executable": true, + "type": "file" + }, + "bin/pack200": { + "downloads": { + "lzma": { + "sha1": "b52da4497b49b1508b6225a5740857ddb8f52e97", + "size": 2183, + "url": "https://launcher.mojang.com/v1/objects/b52da4497b49b1508b6225a5740857ddb8f52e97/pack200" + }, + "raw": { + "sha1": "16ef3e801efb57e50bc6477a27a9d95d02d0775b", + "size": 8584, + "url": "https://launcher.mojang.com/v1/objects/16ef3e801efb57e50bc6477a27a9d95d02d0775b/pack200" + } + }, + "executable": true, + "type": "file" + }, + "bin/policytool": { + "downloads": { + "lzma": { + "sha1": "87da4c07da45f3d1a1a9d732af197cd39bf69d10", + "size": 2182, + "url": "https://launcher.mojang.com/v1/objects/87da4c07da45f3d1a1a9d732af197cd39bf69d10/policytool" + }, + "raw": { + "sha1": "a52a29424470cb9b8db5c2fb1751d0b697a7ec8e", + "size": 8592, + "url": "https://launcher.mojang.com/v1/objects/a52a29424470cb9b8db5c2fb1751d0b697a7ec8e/policytool" + } + }, + "executable": true, + "type": "file" + }, + "bin/rmid": { + "downloads": { + "lzma": { + "sha1": "1494c1174fde0c0a93ea117bc7edf7eb936c0512", + "size": 2172, + "url": "https://launcher.mojang.com/v1/objects/1494c1174fde0c0a93ea117bc7edf7eb936c0512/rmid" + }, + "raw": { + "sha1": "5c8710e1ab924e5b09a07bcb4c6e106293bbd1a8", + "size": 8584, + "url": "https://launcher.mojang.com/v1/objects/5c8710e1ab924e5b09a07bcb4c6e106293bbd1a8/rmid" + } + }, + "executable": true, + "type": "file" + }, + "bin/rmiregistry": { + "downloads": { + "lzma": { + "sha1": "7070cf2ec5a5e520a880bae699431edf02083e7e", + "size": 2174, + "url": "https://launcher.mojang.com/v1/objects/7070cf2ec5a5e520a880bae699431edf02083e7e/rmiregistry" + }, + "raw": { + "sha1": "5f518daa7050028d5d9d849634c73136f2b23a54", + "size": 8592, + "url": "https://launcher.mojang.com/v1/objects/5f518daa7050028d5d9d849634c73136f2b23a54/rmiregistry" + } + }, + "executable": true, + "type": "file" + }, + "bin/servertool": { + "downloads": { + "lzma": { + "sha1": "1db683a11cc9b7313426c84412f4d95be2fa7ccd", + "size": 2185, + "url": "https://launcher.mojang.com/v1/objects/1db683a11cc9b7313426c84412f4d95be2fa7ccd/servertool" + }, + "raw": { + "sha1": "49d0ebfeb265ce5a8733e1014541ea2525674a60", + "size": 8592, + "url": "https://launcher.mojang.com/v1/objects/49d0ebfeb265ce5a8733e1014541ea2525674a60/servertool" + } + }, + "executable": true, + "type": "file" + }, + "bin/tnameserv": { + "downloads": { + "lzma": { + "sha1": "36da9c9a2c5a8b662a3f8d52ca67339bce1c2714", + "size": 2291, + "url": "https://launcher.mojang.com/v1/objects/36da9c9a2c5a8b662a3f8d52ca67339bce1c2714/tnameserv" + }, + "raw": { + "sha1": "09d998f8efcb6f55d0d87f59e08f8b89662796d9", + "size": 8656, + "url": "https://launcher.mojang.com/v1/objects/09d998f8efcb6f55d0d87f59e08f8b89662796d9/tnameserv" + } + }, + "executable": true, + "type": "file" + }, + "bin/unpack200": { + "downloads": { + "lzma": { + "sha1": "344959e32fc7ee19eebe7b3cf5ab6d1a7d6641f2", + "size": 79721, + "url": "https://launcher.mojang.com/v1/objects/344959e32fc7ee19eebe7b3cf5ab6d1a7d6641f2/unpack200" + }, + "raw": { + "sha1": "5dd933132f1b202e19e0c8e093f7113711cfdfc1", + "size": 182616, + "url": "https://launcher.mojang.com/v1/objects/5dd933132f1b202e19e0c8e093f7113711cfdfc1/unpack200" + } + }, + "executable": true, + "type": "file" + }, + "lib": { + "type": "directory" + }, + "lib/amd64": { + "type": "directory" + }, + "lib/amd64/jli": { + "type": "directory" + }, + "lib/amd64/jli/libjli.so": { + "downloads": { + "lzma": { + "sha1": "372331ee8e375888f798a2e88180a94493e141b0", + "size": 48327, + "url": "https://launcher.mojang.com/v1/objects/372331ee8e375888f798a2e88180a94493e141b0/libjli.so" + }, + "raw": { + "sha1": "73b0cf8b7415686bc40c561ff77ff2740ccf7a44", + "size": 108616, + "url": "https://launcher.mojang.com/v1/objects/73b0cf8b7415686bc40c561ff77ff2740ccf7a44/libjli.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/jvm.cfg": { + "downloads": { + "lzma": { + "sha1": "86bcfebec37b38415525ffd77d3eaf70d0b1b4ca", + "size": 435, + "url": "https://launcher.mojang.com/v1/objects/86bcfebec37b38415525ffd77d3eaf70d0b1b4ca/jvm.cfg" + }, + "raw": { + "sha1": "84b38bdc745de446ba0ca0232ea3aaf2efd721da", + "size": 627, + "url": "https://launcher.mojang.com/v1/objects/84b38bdc745de446ba0ca0232ea3aaf2efd721da/jvm.cfg" + } + }, + "executable": false, + "type": "file" + }, + "lib/amd64/libavplugin-53.so": { + "downloads": { + "lzma": { + "sha1": "a332366762d9efc7b845a682b7edce62db44618c", + "size": 14747, + "url": "https://launcher.mojang.com/v1/objects/a332366762d9efc7b845a682b7edce62db44618c/libavplugin-53.so" + }, + "raw": { + "sha1": "9bd1473dd8a0dc7950c7af1cc69a45548df26eb5", + "size": 51720, + "url": "https://launcher.mojang.com/v1/objects/9bd1473dd8a0dc7950c7af1cc69a45548df26eb5/libavplugin-53.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libavplugin-54.so": { + "downloads": { + "lzma": { + "sha1": "2c615852a0720a275163e00597c1f711f11341da", + "size": 15153, + "url": "https://launcher.mojang.com/v1/objects/2c615852a0720a275163e00597c1f711f11341da/libavplugin-54.so" + }, + "raw": { + "sha1": "8808050c5949c4800b42d1b19b1f8b0d120bcacb", + "size": 51768, + "url": "https://launcher.mojang.com/v1/objects/8808050c5949c4800b42d1b19b1f8b0d120bcacb/libavplugin-54.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libavplugin-55.so": { + "downloads": { + "lzma": { + "sha1": "39ee8e7fe14f0010c78973962800f539c3e4c16b", + "size": 15168, + "url": "https://launcher.mojang.com/v1/objects/39ee8e7fe14f0010c78973962800f539c3e4c16b/libavplugin-55.so" + }, + "raw": { + "sha1": "f10ea4ea3489e96d8d161a96790133c417ec44e1", + "size": 51784, + "url": "https://launcher.mojang.com/v1/objects/f10ea4ea3489e96d8d161a96790133c417ec44e1/libavplugin-55.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libavplugin-56.so": { + "downloads": { + "lzma": { + "sha1": "abe7feced5a559f1bdc868526dc69484e0e591a0", + "size": 15169, + "url": "https://launcher.mojang.com/v1/objects/abe7feced5a559f1bdc868526dc69484e0e591a0/libavplugin-56.so" + }, + "raw": { + "sha1": "e5bfcbff5a5a5a5993a3e689a05ef358c131a3ed", + "size": 51784, + "url": "https://launcher.mojang.com/v1/objects/e5bfcbff5a5a5a5993a3e689a05ef358c131a3ed/libavplugin-56.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libavplugin-57.so": { + "downloads": { + "lzma": { + "sha1": "4dd26b4ef2294b6929dcb2c7546b47eac5cc78a9", + "size": 15174, + "url": "https://launcher.mojang.com/v1/objects/4dd26b4ef2294b6929dcb2c7546b47eac5cc78a9/libavplugin-57.so" + }, + "raw": { + "sha1": "2949e7ff9b0ac90e8943c211cff141ab12eec3f8", + "size": 51784, + "url": "https://launcher.mojang.com/v1/objects/2949e7ff9b0ac90e8943c211cff141ab12eec3f8/libavplugin-57.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libavplugin-ffmpeg-56.so": { + "downloads": { + "lzma": { + "sha1": "c688ba1cfa442bf18bee43b2fa870b4dc1ce3fb6", + "size": 15231, + "url": "https://launcher.mojang.com/v1/objects/c688ba1cfa442bf18bee43b2fa870b4dc1ce3fb6/libavplugin-ffmpeg-56.so" + }, + "raw": { + "sha1": "0d36c971a9ad99fc2292092fdec3a4179b1021b9", + "size": 51920, + "url": "https://launcher.mojang.com/v1/objects/0d36c971a9ad99fc2292092fdec3a4179b1021b9/libavplugin-ffmpeg-56.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libavplugin-ffmpeg-57.so": { + "downloads": { + "lzma": { + "sha1": "087426bdbffebcfa372a438e863785f4ffbe9a6b", + "size": 15180, + "url": "https://launcher.mojang.com/v1/objects/087426bdbffebcfa372a438e863785f4ffbe9a6b/libavplugin-ffmpeg-57.so" + }, + "raw": { + "sha1": "5e9c4eb4b49eb8e57c01003ec73a1eb8d6d8c462", + "size": 51784, + "url": "https://launcher.mojang.com/v1/objects/5e9c4eb4b49eb8e57c01003ec73a1eb8d6d8c462/libavplugin-ffmpeg-57.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libawt.so": { + "downloads": { + "lzma": { + "sha1": "018be58b205b73c842a55df811b70d0e8237216e", + "size": 195720, + "url": "https://launcher.mojang.com/v1/objects/018be58b205b73c842a55df811b70d0e8237216e/libawt.so" + }, + "raw": { + "sha1": "02632cd326e3161c00a7e784599dd7b9ee053dce", + "size": 759184, + "url": "https://launcher.mojang.com/v1/objects/02632cd326e3161c00a7e784599dd7b9ee053dce/libawt.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libawt_headless.so": { + "downloads": { + "lzma": { + "sha1": "7ac2517cff75d4bbb0a0412a9b5f18c74ea188fa", + "size": 11211, + "url": "https://launcher.mojang.com/v1/objects/7ac2517cff75d4bbb0a0412a9b5f18c74ea188fa/libawt_headless.so" + }, + "raw": { + "sha1": "862157ec957008d0911c5daedc004b3a202623a4", + "size": 39176, + "url": "https://launcher.mojang.com/v1/objects/862157ec957008d0911c5daedc004b3a202623a4/libawt_headless.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libawt_xawt.so": { + "downloads": { + "lzma": { + "sha1": "d536a96af27dfe35de6bb2c8759d51c488cdd8d4", + "size": 149598, + "url": "https://launcher.mojang.com/v1/objects/d536a96af27dfe35de6bb2c8759d51c488cdd8d4/libawt_xawt.so" + }, + "raw": { + "sha1": "28232b3e01b6f11bfe098bfc6eafc3a513dcebf1", + "size": 470232, + "url": "https://launcher.mojang.com/v1/objects/28232b3e01b6f11bfe098bfc6eafc3a513dcebf1/libawt_xawt.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libbci.so": { + "downloads": { + "lzma": { + "sha1": "c36fad091d11e64c815d5ca17c0ef7a55b0776b1", + "size": 3509, + "url": "https://launcher.mojang.com/v1/objects/c36fad091d11e64c815d5ca17c0ef7a55b0776b1/libbci.so" + }, + "raw": { + "sha1": "33824051db1ccb6332e22c2b63231055240d0af0", + "size": 12760, + "url": "https://launcher.mojang.com/v1/objects/33824051db1ccb6332e22c2b63231055240d0af0/libbci.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libdcpr.so": { + "downloads": { + "lzma": { + "sha1": "70c6b0933a37f2b1124d6e7c131039241fe796ee", + "size": 75969, + "url": "https://launcher.mojang.com/v1/objects/70c6b0933a37f2b1124d6e7c131039241fe796ee/libdcpr.so" + }, + "raw": { + "sha1": "fa7001bc5d80579e2716590f3eee8027da0beae7", + "size": 204456, + "url": "https://launcher.mojang.com/v1/objects/fa7001bc5d80579e2716590f3eee8027da0beae7/libdcpr.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libdecora_sse.so": { + "downloads": { + "lzma": { + "sha1": "514acc017dfb6cefaf8cc6d18006ce55781cc9bc", + "size": 24397, + "url": "https://launcher.mojang.com/v1/objects/514acc017dfb6cefaf8cc6d18006ce55781cc9bc/libdecora_sse.so" + }, + "raw": { + "sha1": "d0c84233504c916e548e29f513e25f6a7479abfc", + "size": 74912, + "url": "https://launcher.mojang.com/v1/objects/d0c84233504c916e548e29f513e25f6a7479abfc/libdecora_sse.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libdeploy.so": { + "downloads": { + "lzma": { + "sha1": "6cf31fd98301c749ac0d2c7825f6d925a4409760", + "size": 168999, + "url": "https://launcher.mojang.com/v1/objects/6cf31fd98301c749ac0d2c7825f6d925a4409760/libdeploy.so" + }, + "raw": { + "sha1": "b3832e97ed8ca794884b56a591b83d02a2c0c06f", + "size": 642368, + "url": "https://launcher.mojang.com/v1/objects/b3832e97ed8ca794884b56a591b83d02a2c0c06f/libdeploy.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libdt_socket.so": { + "downloads": { + "lzma": { + "sha1": "4cc5c880dbb6fa180436d12d60f0abec8ebb59dc", + "size": 7784, + "url": "https://launcher.mojang.com/v1/objects/4cc5c880dbb6fa180436d12d60f0abec8ebb59dc/libdt_socket.so" + }, + "raw": { + "sha1": "91ce96f252b8139fc12f0f224ed5b1a041767ab7", + "size": 24616, + "url": "https://launcher.mojang.com/v1/objects/91ce96f252b8139fc12f0f224ed5b1a041767ab7/libdt_socket.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libfontmanager.so": { + "downloads": { + "lzma": { + "sha1": "f94e5e94c71c603ff4d3cd1e7e3d9e181fcc145d", + "size": 146951, + "url": "https://launcher.mojang.com/v1/objects/f94e5e94c71c603ff4d3cd1e7e3d9e181fcc145d/libfontmanager.so" + }, + "raw": { + "sha1": "2428e805f2c53d1283a033dfd11a86fbb7bd7159", + "size": 490672, + "url": "https://launcher.mojang.com/v1/objects/2428e805f2c53d1283a033dfd11a86fbb7bd7159/libfontmanager.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libfxplugins.so": { + "downloads": { + "lzma": { + "sha1": "a640143365d382a5ad743a784bc2f3706d9d6d67", + "size": 50048, + "url": "https://launcher.mojang.com/v1/objects/a640143365d382a5ad743a784bc2f3706d9d6d67/libfxplugins.so" + }, + "raw": { + "sha1": "0fd4ac04a84c131f1aaee9e6b0898ff9ea69e3ee", + "size": 151448, + "url": "https://launcher.mojang.com/v1/objects/0fd4ac04a84c131f1aaee9e6b0898ff9ea69e3ee/libfxplugins.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libglass.so": { + "downloads": { + "lzma": { + "sha1": "f1ff517714fa5f2c861f33b32db823fe851541f1", + "size": 2856, + "url": "https://launcher.mojang.com/v1/objects/f1ff517714fa5f2c861f33b32db823fe851541f1/libglass.so" + }, + "raw": { + "sha1": "e7f4fece30ac727be8148d33b8256abd3a41cef9", + "size": 13072, + "url": "https://launcher.mojang.com/v1/objects/e7f4fece30ac727be8148d33b8256abd3a41cef9/libglass.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libglassgtk2.so": { + "downloads": { + "lzma": { + "sha1": "15b90f7a2baacd15e80aa9785d87cf1e4258376d", + "size": 220476, + "url": "https://launcher.mojang.com/v1/objects/15b90f7a2baacd15e80aa9785d87cf1e4258376d/libglassgtk2.so" + }, + "raw": { + "sha1": "e30a634c2ff2143bdee512360553d6e0304f33b2", + "size": 844984, + "url": "https://launcher.mojang.com/v1/objects/e30a634c2ff2143bdee512360553d6e0304f33b2/libglassgtk2.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libglassgtk3.so": { + "downloads": { + "lzma": { + "sha1": "868c231165f8c9043b7f0e7de208ec023f06a6e7", + "size": 220560, + "url": "https://launcher.mojang.com/v1/objects/868c231165f8c9043b7f0e7de208ec023f06a6e7/libglassgtk3.so" + }, + "raw": { + "sha1": "762a11a2b376b7b5a2a7cad780715524fdd176d5", + "size": 845304, + "url": "https://launcher.mojang.com/v1/objects/762a11a2b376b7b5a2a7cad780715524fdd176d5/libglassgtk3.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libglib-lite.so": { + "downloads": { + "lzma": { + "sha1": "61b8871242febe1be262de167dc20ae94bf964b4", + "size": 457046, + "url": "https://launcher.mojang.com/v1/objects/61b8871242febe1be262de167dc20ae94bf964b4/libglib-lite.so" + }, + "raw": { + "sha1": "63afa060fc3f120af76128e51d32603fc4336fa8", + "size": 1538352, + "url": "https://launcher.mojang.com/v1/objects/63afa060fc3f120af76128e51d32603fc4336fa8/libglib-lite.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libgstreamer-lite.so": { + "downloads": { + "lzma": { + "sha1": "2447dc368406ba1b989a29937d41924620e01988", + "size": 673056, + "url": "https://launcher.mojang.com/v1/objects/2447dc368406ba1b989a29937d41924620e01988/libgstreamer-lite.so" + }, + "raw": { + "sha1": "5505e7ca592ac64371d3db8fe53bcb602e9723d3", + "size": 2263872, + "url": "https://launcher.mojang.com/v1/objects/5505e7ca592ac64371d3db8fe53bcb602e9723d3/libgstreamer-lite.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libhprof.so": { + "downloads": { + "lzma": { + "sha1": "94a5589c818db1fb1cf1881e24e217c309fce2e4", + "size": 64471, + "url": "https://launcher.mojang.com/v1/objects/94a5589c818db1fb1cf1881e24e217c309fce2e4/libhprof.so" + }, + "raw": { + "sha1": "4bb9bdeef6133b6dd558d52d691b077c03e9b0ee", + "size": 175504, + "url": "https://launcher.mojang.com/v1/objects/4bb9bdeef6133b6dd558d52d691b077c03e9b0ee/libhprof.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libinstrument.so": { + "downloads": { + "lzma": { + "sha1": "84ffea356caf725b42c86a8ebc9587f477ddde29", + "size": 18603, + "url": "https://launcher.mojang.com/v1/objects/84ffea356caf725b42c86a8ebc9587f477ddde29/libinstrument.so" + }, + "raw": { + "sha1": "cb8009769601e3fecd7ea2b36c344f737b1a9da7", + "size": 51560, + "url": "https://launcher.mojang.com/v1/objects/cb8009769601e3fecd7ea2b36c344f737b1a9da7/libinstrument.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libj2gss.so": { + "downloads": { + "lzma": { + "sha1": "4b2aa699506b126098b585a9617ce1c05707fa29", + "size": 14132, + "url": "https://launcher.mojang.com/v1/objects/4b2aa699506b126098b585a9617ce1c05707fa29/libj2gss.so" + }, + "raw": { + "sha1": "cbce4a302b255d4d1924ef7606f038af766c5e86", + "size": 47688, + "url": "https://launcher.mojang.com/v1/objects/cbce4a302b255d4d1924ef7606f038af766c5e86/libj2gss.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libj2pcsc.so": { + "downloads": { + "lzma": { + "sha1": "2361d3b2e3da48593c391b29b0d2b5409e4c55e5", + "size": 5074, + "url": "https://launcher.mojang.com/v1/objects/2361d3b2e3da48593c391b29b0d2b5409e4c55e5/libj2pcsc.so" + }, + "raw": { + "sha1": "1274178492e7a3e997e12f67794616f7c3d8d0b9", + "size": 18296, + "url": "https://launcher.mojang.com/v1/objects/1274178492e7a3e997e12f67794616f7c3d8d0b9/libj2pcsc.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libj2pkcs11.so": { + "downloads": { + "lzma": { + "sha1": "ef927e2790ba05931d0f0bdd63da3d275a834946", + "size": 21573, + "url": "https://launcher.mojang.com/v1/objects/ef927e2790ba05931d0f0bdd63da3d275a834946/libj2pkcs11.so" + }, + "raw": { + "sha1": "bd4f2af9bfdc6168633d1920c1a1415de06bb45a", + "size": 79472, + "url": "https://launcher.mojang.com/v1/objects/bd4f2af9bfdc6168633d1920c1a1415de06bb45a/libj2pkcs11.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjaas_unix.so": { + "downloads": { + "lzma": { + "sha1": "7f7e843544ee1eb1454a5826bdd4218685b79430", + "size": 2404, + "url": "https://launcher.mojang.com/v1/objects/7f7e843544ee1eb1454a5826bdd4218685b79430/libjaas_unix.so" + }, + "raw": { + "sha1": "4c517925c7d464a5b719898eb0bea1b04df31f1f", + "size": 8192, + "url": "https://launcher.mojang.com/v1/objects/4c517925c7d464a5b719898eb0bea1b04df31f1f/libjaas_unix.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjava.so": { + "downloads": { + "lzma": { + "sha1": "5eee7a42600a44a8bb8d6d7f510fd96a29637ac0", + "size": 63113, + "url": "https://launcher.mojang.com/v1/objects/5eee7a42600a44a8bb8d6d7f510fd96a29637ac0/libjava.so" + }, + "raw": { + "sha1": "e280aeddf3fc0ec664aef7efc0e0e197a54aaf02", + "size": 227672, + "url": "https://launcher.mojang.com/v1/objects/e280aeddf3fc0ec664aef7efc0e0e197a54aaf02/libjava.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjava_crw_demo.so": { + "downloads": { + "lzma": { + "sha1": "b197cf23ae3556eb0b45c663f0a8cb62408b961e", + "size": 10412, + "url": "https://launcher.mojang.com/v1/objects/b197cf23ae3556eb0b45c663f0a8cb62408b961e/libjava_crw_demo.so" + }, + "raw": { + "sha1": "18f20f906977c90d0090b41dbda8dd5cfead5a4c", + "size": 26144, + "url": "https://launcher.mojang.com/v1/objects/18f20f906977c90d0090b41dbda8dd5cfead5a4c/libjava_crw_demo.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjavafx_font.so": { + "downloads": { + "lzma": { + "sha1": "ffbba0e5022f829412b86063d8a90f95f16709b1", + "size": 5608, + "url": "https://launcher.mojang.com/v1/objects/ffbba0e5022f829412b86063d8a90f95f16709b1/libjavafx_font.so" + }, + "raw": { + "sha1": "8634a0aca612fc40420a4a7cc8af4cc46cfc6725", + "size": 17104, + "url": "https://launcher.mojang.com/v1/objects/8634a0aca612fc40420a4a7cc8af4cc46cfc6725/libjavafx_font.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjavafx_font_freetype.so": { + "downloads": { + "lzma": { + "sha1": "310271eda8a2ac264ffc3640a9d847b49438d0bd", + "size": 6942, + "url": "https://launcher.mojang.com/v1/objects/310271eda8a2ac264ffc3640a9d847b49438d0bd/libjavafx_font_freetype.so" + }, + "raw": { + "sha1": "3e7572d047c12ba2bc43acec7f98a67c20af8042", + "size": 27616, + "url": "https://launcher.mojang.com/v1/objects/3e7572d047c12ba2bc43acec7f98a67c20af8042/libjavafx_font_freetype.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjavafx_font_pango.so": { + "downloads": { + "lzma": { + "sha1": "a7bcf0669e70b0f43099a99c81e6b6440cb40ac0", + "size": 5820, + "url": "https://launcher.mojang.com/v1/objects/a7bcf0669e70b0f43099a99c81e6b6440cb40ac0/libjavafx_font_pango.so" + }, + "raw": { + "sha1": "f0b775cc9a514c7ee8b4d6fb300653ce548caf10", + "size": 25560, + "url": "https://launcher.mojang.com/v1/objects/f0b775cc9a514c7ee8b4d6fb300653ce548caf10/libjavafx_font_pango.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjavafx_font_t2k.so": { + "downloads": { + "lzma": { + "sha1": "551c29dc7c7fc83223aa36a6187f7e0c5d650538", + "size": 431450, + "url": "https://launcher.mojang.com/v1/objects/551c29dc7c7fc83223aa36a6187f7e0c5d650538/libjavafx_font_t2k.so" + }, + "raw": { + "sha1": "91e5813057c3b852d411540160f8ad05fb9f1ed3", + "size": 1486128, + "url": "https://launcher.mojang.com/v1/objects/91e5813057c3b852d411540160f8ad05fb9f1ed3/libjavafx_font_t2k.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjavafx_iio.so": { + "downloads": { + "lzma": { + "sha1": "c832998fd5e06ed6dcd6428816194c350785420c", + "size": 101479, + "url": "https://launcher.mojang.com/v1/objects/c832998fd5e06ed6dcd6428816194c350785420c/libjavafx_iio.so" + }, + "raw": { + "sha1": "dcdf68cb25677b76c1cf0bb94294e6e9880a6678", + "size": 256336, + "url": "https://launcher.mojang.com/v1/objects/dcdf68cb25677b76c1cf0bb94294e6e9880a6678/libjavafx_iio.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjawt.so": { + "downloads": { + "lzma": { + "sha1": "c1ced6aad5c69ff444dc67d0fd7e333558953831", + "size": 1872, + "url": "https://launcher.mojang.com/v1/objects/c1ced6aad5c69ff444dc67d0fd7e333558953831/libjawt.so" + }, + "raw": { + "sha1": "c5032f2c6fa40bea24e56605cf76b26a27e87b67", + "size": 8048, + "url": "https://launcher.mojang.com/v1/objects/c5032f2c6fa40bea24e56605cf76b26a27e87b67/libjawt.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjdwp.so": { + "downloads": { + "lzma": { + "sha1": "c1aabbb3f5a624b9ad10ed871a1d83510a99b646", + "size": 94884, + "url": "https://launcher.mojang.com/v1/objects/c1aabbb3f5a624b9ad10ed871a1d83510a99b646/libjdwp.so" + }, + "raw": { + "sha1": "a043e97be47937f6f552e94cf79c76c1c57f9594", + "size": 272248, + "url": "https://launcher.mojang.com/v1/objects/a043e97be47937f6f552e94cf79c76c1c57f9594/libjdwp.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjfr.so": { + "downloads": { + "lzma": { + "sha1": "11b8e6bfffdccbacbf9dd29dea4b90b753f3c1b7", + "size": 8780, + "url": "https://launcher.mojang.com/v1/objects/11b8e6bfffdccbacbf9dd29dea4b90b753f3c1b7/libjfr.so" + }, + "raw": { + "sha1": "312392dd186b11c418183e818f1928e8685a07e5", + "size": 28384, + "url": "https://launcher.mojang.com/v1/objects/312392dd186b11c418183e818f1928e8685a07e5/libjfr.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjfxmedia.so": { + "downloads": { + "lzma": { + "sha1": "a4e7a126eb648ce6e5e6dc151831da37d8334139", + "size": 391897, + "url": "https://launcher.mojang.com/v1/objects/a4e7a126eb648ce6e5e6dc151831da37d8334139/libjfxmedia.so" + }, + "raw": { + "sha1": "5fa54944327a6012c3d34cb5c1c4432762178dc8", + "size": 1636376, + "url": "https://launcher.mojang.com/v1/objects/5fa54944327a6012c3d34cb5c1c4432762178dc8/libjfxmedia.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjfxwebkit.so": { + "downloads": { + "lzma": { + "sha1": "b274debd222cdcc2ee84160ebb95144b3880bc97", + "size": 20492825, + "url": "https://launcher.mojang.com/v1/objects/b274debd222cdcc2ee84160ebb95144b3880bc97/libjfxwebkit.so" + }, + "raw": { + "sha1": "ecee564c3b2f645131b35bb3004abd4caeabd291", + "size": 91014584, + "url": "https://launcher.mojang.com/v1/objects/ecee564c3b2f645131b35bb3004abd4caeabd291/libjfxwebkit.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjpeg.so": { + "downloads": { + "lzma": { + "sha1": "9ad55e370c5eaaa73c3158339db3c368b1aaf0cb", + "size": 113072, + "url": "https://launcher.mojang.com/v1/objects/9ad55e370c5eaaa73c3158339db3c368b1aaf0cb/libjpeg.so" + }, + "raw": { + "sha1": "651e6d53ae67db1f0efbf7f104447a9b49b7e333", + "size": 292520, + "url": "https://launcher.mojang.com/v1/objects/651e6d53ae67db1f0efbf7f104447a9b49b7e333/libjpeg.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjsdt.so": { + "downloads": { + "lzma": { + "sha1": "04b6d1361a34c496b5f652b2477784d69b8b6baf", + "size": 3964, + "url": "https://launcher.mojang.com/v1/objects/04b6d1361a34c496b5f652b2477784d69b8b6baf/libjsdt.so" + }, + "raw": { + "sha1": "82b48a82bf6183d34cf00a0f81661b45c616f31b", + "size": 12904, + "url": "https://launcher.mojang.com/v1/objects/82b48a82bf6183d34cf00a0f81661b45c616f31b/libjsdt.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjsig.so": { + "downloads": { + "lzma": { + "sha1": "37d3b89abde397216cc4ecb1339d8543d99b8428", + "size": 3536, + "url": "https://launcher.mojang.com/v1/objects/37d3b89abde397216cc4ecb1339d8543d99b8428/libjsig.so" + }, + "raw": { + "sha1": "42e52ba1bcbe0362ab24bcf65c93797354db6fb9", + "size": 13336, + "url": "https://launcher.mojang.com/v1/objects/42e52ba1bcbe0362ab24bcf65c93797354db6fb9/libjsig.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjsound.so": { + "downloads": { + "lzma": { + "sha1": "7e3c565d74d8ffae716f32b05544fa4a6f108adc", + "size": 2002, + "url": "https://launcher.mojang.com/v1/objects/7e3c565d74d8ffae716f32b05544fa4a6f108adc/libjsound.so" + }, + "raw": { + "sha1": "0c0fc63b92d7b83c9960fa80d45c80553ea20254", + "size": 8232, + "url": "https://launcher.mojang.com/v1/objects/0c0fc63b92d7b83c9960fa80d45c80553ea20254/libjsound.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libjsoundalsa.so": { + "downloads": { + "lzma": { + "sha1": "b06c51858a25ff776519495f1b9b3d9f604b089f", + "size": 23097, + "url": "https://launcher.mojang.com/v1/objects/b06c51858a25ff776519495f1b9b3d9f604b089f/libjsoundalsa.so" + }, + "raw": { + "sha1": "281d37f0326d4a12dc7ea316ead09c198ff7bdf7", + "size": 83256, + "url": "https://launcher.mojang.com/v1/objects/281d37f0326d4a12dc7ea316ead09c198ff7bdf7/libjsoundalsa.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/liblcms.so": { + "downloads": { + "lzma": { + "sha1": "7a239baba2086cae49114b382b74b971da02f08e", + "size": 176175, + "url": "https://launcher.mojang.com/v1/objects/7a239baba2086cae49114b382b74b971da02f08e/liblcms.so" + }, + "raw": { + "sha1": "c8895cc3c3d023d9e059225969ab67954772c0a1", + "size": 526872, + "url": "https://launcher.mojang.com/v1/objects/c8895cc3c3d023d9e059225969ab67954772c0a1/liblcms.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libmanagement.so": { + "downloads": { + "lzma": { + "sha1": "aed3fdbcefd1716abfc6a306687c8b741cbb318e", + "size": 12838, + "url": "https://launcher.mojang.com/v1/objects/aed3fdbcefd1716abfc6a306687c8b741cbb318e/libmanagement.so" + }, + "raw": { + "sha1": "eba35f61e0d50e30874b7c7b335edf2d52662423", + "size": 51808, + "url": "https://launcher.mojang.com/v1/objects/eba35f61e0d50e30874b7c7b335edf2d52662423/libmanagement.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libmlib_image.so": { + "downloads": { + "lzma": { + "sha1": "1bb181f079492d55c7a458e96488cd17fe0a7b86", + "size": 310272, + "url": "https://launcher.mojang.com/v1/objects/1bb181f079492d55c7a458e96488cd17fe0a7b86/libmlib_image.so" + }, + "raw": { + "sha1": "c973c450d33873675945d4694be484e3427f58f1", + "size": 1048136, + "url": "https://launcher.mojang.com/v1/objects/c973c450d33873675945d4694be484e3427f58f1/libmlib_image.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libnet.so": { + "downloads": { + "lzma": { + "sha1": "9dd79703b6deb86e0321afe01c6ac508263c8312", + "size": 38123, + "url": "https://launcher.mojang.com/v1/objects/9dd79703b6deb86e0321afe01c6ac508263c8312/libnet.so" + }, + "raw": { + "sha1": "b3a17b7d53fcdf1e689e1ec29ce851eee6022ead", + "size": 116920, + "url": "https://launcher.mojang.com/v1/objects/b3a17b7d53fcdf1e689e1ec29ce851eee6022ead/libnet.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libnio.so": { + "downloads": { + "lzma": { + "sha1": "5697c89d5d5d9b74f2e1555fcbba79dd4049e287", + "size": 24445, + "url": "https://launcher.mojang.com/v1/objects/5697c89d5d5d9b74f2e1555fcbba79dd4049e287/libnio.so" + }, + "raw": { + "sha1": "573bf8f64dbcc397f8abd3e1da28f90ab0679f5b", + "size": 93872, + "url": "https://launcher.mojang.com/v1/objects/573bf8f64dbcc397f8abd3e1da28f90ab0679f5b/libnio.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libnpjp2.so": { + "downloads": { + "lzma": { + "sha1": "6fe53b5951ff740e7f2ef7ffe5975af26da06718", + "size": 57892, + "url": "https://launcher.mojang.com/v1/objects/6fe53b5951ff740e7f2ef7ffe5975af26da06718/libnpjp2.so" + }, + "raw": { + "sha1": "2bb13c53a4280379253475e51216b97eed1d4ce3", + "size": 216592, + "url": "https://launcher.mojang.com/v1/objects/2bb13c53a4280379253475e51216b97eed1d4ce3/libnpjp2.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libnpt.so": { + "downloads": { + "lzma": { + "sha1": "1b170b09a32b1b8b6624fa5d1f94ec60b2bf3876", + "size": 5070, + "url": "https://launcher.mojang.com/v1/objects/1b170b09a32b1b8b6624fa5d1f94ec60b2bf3876/libnpt.so" + }, + "raw": { + "sha1": "6b1ff6b9b4624f3cc7801f221c82b8046fb76364", + "size": 17504, + "url": "https://launcher.mojang.com/v1/objects/6b1ff6b9b4624f3cc7801f221c82b8046fb76364/libnpt.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libprism_common.so": { + "downloads": { + "lzma": { + "sha1": "f4aca04c90bc7505851c074a08b2c31cae1f94fa", + "size": 23315, + "url": "https://launcher.mojang.com/v1/objects/f4aca04c90bc7505851c074a08b2c31cae1f94fa/libprism_common.so" + }, + "raw": { + "sha1": "b00866b6ed8646a29a334d46e297267552f27de8", + "size": 59008, + "url": "https://launcher.mojang.com/v1/objects/b00866b6ed8646a29a334d46e297267552f27de8/libprism_common.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libprism_es2.so": { + "downloads": { + "lzma": { + "sha1": "7ff4173c338c7a6f370f231670055737e032da3e", + "size": 18416, + "url": "https://launcher.mojang.com/v1/objects/7ff4173c338c7a6f370f231670055737e032da3e/libprism_es2.so" + }, + "raw": { + "sha1": "1390a1dc14345e5a948148e59195d62f3a83863f", + "size": 63808, + "url": "https://launcher.mojang.com/v1/objects/1390a1dc14345e5a948148e59195d62f3a83863f/libprism_es2.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libprism_sw.so": { + "downloads": { + "lzma": { + "sha1": "6728e8bf7b214067d715be6fe0325910d63c2468", + "size": 29457, + "url": "https://launcher.mojang.com/v1/objects/6728e8bf7b214067d715be6fe0325910d63c2468/libprism_sw.so" + }, + "raw": { + "sha1": "7a6c34cb2bbcde411778d1b3f8677c39e32c3ac4", + "size": 71608, + "url": "https://launcher.mojang.com/v1/objects/7a6c34cb2bbcde411778d1b3f8677c39e32c3ac4/libprism_sw.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libresource.so": { + "downloads": { + "lzma": { + "sha1": "1e35e63f1e74915fba620f1febf420b919d49bc5", + "size": 2633, + "url": "https://launcher.mojang.com/v1/objects/1e35e63f1e74915fba620f1febf420b919d49bc5/libresource.so" + }, + "raw": { + "sha1": "57490353ad0d83ab1930355213dea269795434fe", + "size": 13456, + "url": "https://launcher.mojang.com/v1/objects/57490353ad0d83ab1930355213dea269795434fe/libresource.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libsctp.so": { + "downloads": { + "lzma": { + "sha1": "4340132ed250d7849a016e071be773eaedd33aa8", + "size": 9332, + "url": "https://launcher.mojang.com/v1/objects/4340132ed250d7849a016e071be773eaedd33aa8/libsctp.so" + }, + "raw": { + "sha1": "4a80e743750f127c0d5a359f5cd60b97e7ee12ae", + "size": 29552, + "url": "https://launcher.mojang.com/v1/objects/4a80e743750f127c0d5a359f5cd60b97e7ee12ae/libsctp.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libsplashscreen.so": { + "downloads": { + "lzma": { + "sha1": "b226c8dbd73a548fc2b042ee6db6cc80e727597c", + "size": 190305, + "url": "https://launcher.mojang.com/v1/objects/b226c8dbd73a548fc2b042ee6db6cc80e727597c/libsplashscreen.so" + }, + "raw": { + "sha1": "87d6a491f5ba7e6c4d972264a0c9063afea567a2", + "size": 441376, + "url": "https://launcher.mojang.com/v1/objects/87d6a491f5ba7e6c4d972264a0c9063afea567a2/libsplashscreen.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libsunec.so": { + "downloads": { + "lzma": { + "sha1": "6ebba98fab1e3d872d1363235b76497f6f9babdc", + "size": 88829, + "url": "https://launcher.mojang.com/v1/objects/6ebba98fab1e3d872d1363235b76497f6f9babdc/libsunec.so" + }, + "raw": { + "sha1": "3b262a0a530f6e4e539aed2cd27b4de1d0ed8859", + "size": 283368, + "url": "https://launcher.mojang.com/v1/objects/3b262a0a530f6e4e539aed2cd27b4de1d0ed8859/libsunec.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libt2k.so": { + "downloads": { + "lzma": { + "sha1": "602cb812ef0b350ccf56ce209a260ddbe3743d92", + "size": 190720, + "url": "https://launcher.mojang.com/v1/objects/602cb812ef0b350ccf56ce209a260ddbe3743d92/libt2k.so" + }, + "raw": { + "sha1": "b072c56df997f61e15e6b5a43b8907b0d25c2043", + "size": 504840, + "url": "https://launcher.mojang.com/v1/objects/b072c56df997f61e15e6b5a43b8907b0d25c2043/libt2k.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libunpack.so": { + "downloads": { + "lzma": { + "sha1": "7107b615e941074f0b14c31c88fb67200aacd37f", + "size": 70308, + "url": "https://launcher.mojang.com/v1/objects/7107b615e941074f0b14c31c88fb67200aacd37f/libunpack.so" + }, + "raw": { + "sha1": "b05ff862ed87928ed91e80e5604673c5ea710a53", + "size": 197712, + "url": "https://launcher.mojang.com/v1/objects/b05ff862ed87928ed91e80e5604673c5ea710a53/libunpack.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libverify.so": { + "downloads": { + "lzma": { + "sha1": "ecd98efb8c7da441a8c3580e8f5598f3cb4165b1", + "size": 21885, + "url": "https://launcher.mojang.com/v1/objects/ecd98efb8c7da441a8c3580e8f5598f3cb4165b1/libverify.so" + }, + "raw": { + "sha1": "e2c8d92531c45ab9be69ffb72c87fa12e9e59827", + "size": 66112, + "url": "https://launcher.mojang.com/v1/objects/e2c8d92531c45ab9be69ffb72c87fa12e9e59827/libverify.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/libzip.so": { + "downloads": { + "lzma": { + "sha1": "7c562342e3f7b138dc978495447e3e6a96c2cf45", + "size": 54876, + "url": "https://launcher.mojang.com/v1/objects/7c562342e3f7b138dc978495447e3e6a96c2cf45/libzip.so" + }, + "raw": { + "sha1": "5f4bf35a5c3e8f8c650e891d1031589b8ab6d77f", + "size": 127016, + "url": "https://launcher.mojang.com/v1/objects/5f4bf35a5c3e8f8c650e891d1031589b8ab6d77f/libzip.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/amd64/server": { + "type": "directory" + }, + "lib/amd64/server/Xusage.txt": { + "downloads": { + "lzma": { + "sha1": "acb2da24a4c765887df83985e4c26d6be302a0a3", + "size": 629, + "url": "https://launcher.mojang.com/v1/objects/acb2da24a4c765887df83985e4c26d6be302a0a3/Xusage.txt" + }, + "raw": { + "sha1": "6983727eafe140f9dd793c78aa6f3e007438243a", + "size": 1423, + "url": "https://launcher.mojang.com/v1/objects/6983727eafe140f9dd793c78aa6f3e007438243a/Xusage.txt" + } + }, + "executable": false, + "type": "file" + }, + "lib/amd64/server/libjsig.so": { + "target": "../libjsig.so", + "type": "link" + }, + "lib/amd64/server/libjvm.so": { + "downloads": { + "lzma": { + "sha1": "d5c6f3338aaa6712f79d680ac8c3e31beebaa886", + "size": 4154311, + "url": "https://launcher.mojang.com/v1/objects/d5c6f3338aaa6712f79d680ac8c3e31beebaa886/libjvm.so" + }, + "raw": { + "sha1": "23a98e1eb505cc3fb91bc0cb2adb71ab9270e9ca", + "size": 17045016, + "url": "https://launcher.mojang.com/v1/objects/23a98e1eb505cc3fb91bc0cb2adb71ab9270e9ca/libjvm.so" + } + }, + "executable": true, + "type": "file" + }, + "lib/applet": { + "type": "directory" + }, + "lib/calendars.properties": { + "downloads": { + "lzma": { + "sha1": "4a757c23f2942bd802a4f80235131146d9267750", + "size": 558, + "url": "https://launcher.mojang.com/v1/objects/4a757c23f2942bd802a4f80235131146d9267750/calendars.properties" + }, + "raw": { + "sha1": "42ebb0988124433b8f2a6e5d9a74ed41240bcfc6", + "size": 1378, + "url": "https://launcher.mojang.com/v1/objects/42ebb0988124433b8f2a6e5d9a74ed41240bcfc6/calendars.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/charsets.jar": { + "downloads": { + "lzma": { + "sha1": "2bf44143b2ad9d7d55045a4de4a562330c194dc0", + "size": 412367, + "url": "https://launcher.mojang.com/v1/objects/2bf44143b2ad9d7d55045a4de4a562330c194dc0/charsets.jar" + }, + "raw": { + "sha1": "d73ab9f8de255a7e112ddd13622bf7f6b18c8447", + "size": 3135615, + "url": "https://launcher.mojang.com/v1/objects/d73ab9f8de255a7e112ddd13622bf7f6b18c8447/charsets.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/classlist": { + "downloads": { + "lzma": { + "sha1": "14e7c73d21b8513b0aff8d86e5cb34c52021fbca", + "size": 15024, + "url": "https://launcher.mojang.com/v1/objects/14e7c73d21b8513b0aff8d86e5cb34c52021fbca/classlist" + }, + "raw": { + "sha1": "9c0404b63c87e2fed35e3a6cd137d6cf876c42bd", + "size": 84311, + "url": "https://launcher.mojang.com/v1/objects/9c0404b63c87e2fed35e3a6cd137d6cf876c42bd/classlist" + } + }, + "executable": false, + "type": "file" + }, + "lib/cmm": { + "type": "directory" + }, + "lib/cmm/CIEXYZ.pf": { + "downloads": { + "lzma": { + "sha1": "fcc5ca2fd3f45cac3434b480fa3ce00007e96529", + "size": 8964, + "url": "https://launcher.mojang.com/v1/objects/fcc5ca2fd3f45cac3434b480fa3ce00007e96529/CIEXYZ.pf" + }, + "raw": { + "sha1": "b7779924c70554647b87c2a86159ca7781e929f8", + "size": 51236, + "url": "https://launcher.mojang.com/v1/objects/b7779924c70554647b87c2a86159ca7781e929f8/CIEXYZ.pf" + } + }, + "executable": false, + "type": "file" + }, + "lib/cmm/GRAY.pf": { + "downloads": { + "lzma": { + "sha1": "5388ccfe67d3131d6d02143d8e8895003ab14ff6", + "size": 299, + "url": "https://launcher.mojang.com/v1/objects/5388ccfe67d3131d6d02143d8e8895003ab14ff6/GRAY.pf" + }, + "raw": { + "sha1": "27f93961d66b8230d0cdb8b166bc8b4153d5bc2d", + "size": 632, + "url": "https://launcher.mojang.com/v1/objects/27f93961d66b8230d0cdb8b166bc8b4153d5bc2d/GRAY.pf" + } + }, + "executable": false, + "type": "file" + }, + "lib/cmm/LINEAR_RGB.pf": { + "downloads": { + "lzma": { + "sha1": "2bd90f09c8deb64b1729d6b8173c78f9e9cab27b", + "size": 678, + "url": "https://launcher.mojang.com/v1/objects/2bd90f09c8deb64b1729d6b8173c78f9e9cab27b/LINEAR_RGB.pf" + }, + "raw": { + "sha1": "7913274c2f73bafcf888f09ff60990b100214ede", + "size": 1044, + "url": "https://launcher.mojang.com/v1/objects/7913274c2f73bafcf888f09ff60990b100214ede/LINEAR_RGB.pf" + } + }, + "executable": false, + "type": "file" + }, + "lib/cmm/PYCC.pf": { + "downloads": { + "lzma": { + "sha1": "dbb2197ecff3fcdd142e9006490c8cb5c8d19af8", + "size": 171521, + "url": "https://launcher.mojang.com/v1/objects/dbb2197ecff3fcdd142e9006490c8cb5c8d19af8/PYCC.pf" + }, + "raw": { + "sha1": "4f7eed05b8f0eea7bcdc8f8f7aaeb1925ce7b144", + "size": 274474, + "url": "https://launcher.mojang.com/v1/objects/4f7eed05b8f0eea7bcdc8f8f7aaeb1925ce7b144/PYCC.pf" + } + }, + "executable": false, + "type": "file" + }, + "lib/cmm/sRGB.pf": { + "downloads": { + "raw": { + "sha1": "9eaea0911d89d63e39e95f2e2116eaec7e0bb91e", + "size": 3144, + "url": "https://launcher.mojang.com/v1/objects/9eaea0911d89d63e39e95f2e2116eaec7e0bb91e/sRGB.pf" + } + }, + "executable": false, + "type": "file" + }, + "lib/content-types.properties": { + "downloads": { + "lzma": { + "sha1": "43a23d9a6c637c128b14cfa3feced93cbcf85b1a", + "size": 1617, + "url": "https://launcher.mojang.com/v1/objects/43a23d9a6c637c128b14cfa3feced93cbcf85b1a/content-types.properties" + }, + "raw": { + "sha1": "b21698017c4a2866b5fabe59681b7592e72c83b1", + "size": 5916, + "url": "https://launcher.mojang.com/v1/objects/b21698017c4a2866b5fabe59681b7592e72c83b1/content-types.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/currency.data": { + "downloads": { + "lzma": { + "sha1": "451b3f166ea34ef2aefbb01606ea5adcc0d65b42", + "size": 1184, + "url": "https://launcher.mojang.com/v1/objects/451b3f166ea34ef2aefbb01606ea5adcc0d65b42/currency.data" + }, + "raw": { + "sha1": "bf524381a7a9b9d5bbab48069c583d2936e367a1", + "size": 4134, + "url": "https://launcher.mojang.com/v1/objects/bf524381a7a9b9d5bbab48069c583d2936e367a1/currency.data" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy": { + "type": "directory" + }, + "lib/deploy.jar": { + "downloads": { + "raw": { + "sha1": "fbe1de8fcd9a3d482c59414dce9311e4194766c9", + "size": 2255881, + "url": "https://launcher.mojang.com/v1/objects/fbe1de8fcd9a3d482c59414dce9311e4194766c9/deploy.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/MixedCodeMainDialog.ui": { + "downloads": { + "lzma": { + "sha1": "7d812964343d1e978442f5c847c709784fc18fc0", + "size": 683, + "url": "https://launcher.mojang.com/v1/objects/7d812964343d1e978442f5c847c709784fc18fc0/MixedCodeMainDialog.ui" + }, + "raw": { + "sha1": "c9b1af1c229e54b2d8a3d642d4f0bb31dc15be79", + "size": 4507, + "url": "https://launcher.mojang.com/v1/objects/c9b1af1c229e54b2d8a3d642d4f0bb31dc15be79/MixedCodeMainDialog.ui" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/MixedCodeMainDialogJs.ui": { + "downloads": { + "lzma": { + "sha1": "54fb58dbcc59e35e0ae896d0e266ae0c5bcf85c2", + "size": 792, + "url": "https://launcher.mojang.com/v1/objects/54fb58dbcc59e35e0ae896d0e266ae0c5bcf85c2/MixedCodeMainDialogJs.ui" + }, + "raw": { + "sha1": "ad6337fb6d46750e14c12b439a5856f4b6864d0d", + "size": 6110, + "url": "https://launcher.mojang.com/v1/objects/ad6337fb6d46750e14c12b439a5856f4b6864d0d/MixedCodeMainDialogJs.ui" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/cautionshield.icns": { + "downloads": { + "lzma": { + "sha1": "7cea751dc168605054ec38ce8bfa71812be405c1", + "size": 2333, + "url": "https://launcher.mojang.com/v1/objects/7cea751dc168605054ec38ce8bfa71812be405c1/cautionshield.icns" + }, + "raw": { + "sha1": "1de7ed5d5fc75aa1bcede088c655bee3bde64c38", + "size": 3588, + "url": "https://launcher.mojang.com/v1/objects/1de7ed5d5fc75aa1bcede088c655bee3bde64c38/cautionshield.icns" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/ffjcext.zip": { + "downloads": { + "lzma": { + "sha1": "80bcb9b3794f69d87dba93e90230f288e651e798", + "size": 1809, + "url": "https://launcher.mojang.com/v1/objects/80bcb9b3794f69d87dba93e90230f288e651e798/ffjcext.zip" + }, + "raw": { + "sha1": "76d051ca7d3666ff25ea8eb9957a05574a45287f", + "size": 13454, + "url": "https://launcher.mojang.com/v1/objects/76d051ca7d3666ff25ea8eb9957a05574a45287f/ffjcext.zip" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/java-icon.ico": { + "downloads": { + "lzma": { + "sha1": "2a24f0207d7ab5976a8b0d92b4b381d49e895c9d", + "size": 8468, + "url": "https://launcher.mojang.com/v1/objects/2a24f0207d7ab5976a8b0d92b4b381d49e895c9d/java-icon.ico" + }, + "raw": { + "sha1": "2997ceb26ff49a7d7c5e7a2405b5fb50b62c7914", + "size": 29926, + "url": "https://launcher.mojang.com/v1/objects/2997ceb26ff49a7d7c5e7a2405b5fb50b62c7914/java-icon.ico" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages.properties": { + "downloads": { + "lzma": { + "sha1": "c1e16f80dc0b1f1a591cecf3cbab4ba5e47492f4", + "size": 1225, + "url": "https://launcher.mojang.com/v1/objects/c1e16f80dc0b1f1a591cecf3cbab4ba5e47492f4/messages.properties" + }, + "raw": { + "sha1": "dc52841c708e3c1eb2a044088a43396d1291bb5e", + "size": 2860, + "url": "https://launcher.mojang.com/v1/objects/dc52841c708e3c1eb2a044088a43396d1291bb5e/messages.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_de.properties": { + "downloads": { + "lzma": { + "sha1": "42b42e6e1d2cb2d781f2226bde612ce519b29bc8", + "size": 1394, + "url": "https://launcher.mojang.com/v1/objects/42b42e6e1d2cb2d781f2226bde612ce519b29bc8/messages_de.properties" + }, + "raw": { + "sha1": "d989fe1b8f7904888d5102294ebefd28d932ecdb", + "size": 3306, + "url": "https://launcher.mojang.com/v1/objects/d989fe1b8f7904888d5102294ebefd28d932ecdb/messages_de.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_es.properties": { + "downloads": { + "lzma": { + "sha1": "c4a653e9802ca982e892b45d88c1e259c09e8c8e", + "size": 1404, + "url": "https://launcher.mojang.com/v1/objects/c4a653e9802ca982e892b45d88c1e259c09e8c8e/messages_es.properties" + }, + "raw": { + "sha1": "1b0334b79db481c3a59be6915d5118d760c97baa", + "size": 3600, + "url": "https://launcher.mojang.com/v1/objects/1b0334b79db481c3a59be6915d5118d760c97baa/messages_es.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_fr.properties": { + "downloads": { + "lzma": { + "sha1": "2d8dee07e3f5aab7318a22e169810b216ac44f97", + "size": 1401, + "url": "https://launcher.mojang.com/v1/objects/2d8dee07e3f5aab7318a22e169810b216ac44f97/messages_fr.properties" + }, + "raw": { + "sha1": "69bd2d03c2064f8679de5b4e430ea61b567c69c5", + "size": 3409, + "url": "https://launcher.mojang.com/v1/objects/69bd2d03c2064f8679de5b4e430ea61b567c69c5/messages_fr.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_it.properties": { + "downloads": { + "lzma": { + "sha1": "7c28cdd8d9e34355ba0fc03004c4f64749cae57e", + "size": 1375, + "url": "https://launcher.mojang.com/v1/objects/7c28cdd8d9e34355ba0fc03004c4f64749cae57e/messages_it.properties" + }, + "raw": { + "sha1": "dbe49949308f28540a42ae6cd2ad58afbf615592", + "size": 3223, + "url": "https://launcher.mojang.com/v1/objects/dbe49949308f28540a42ae6cd2ad58afbf615592/messages_it.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_ja.properties": { + "downloads": { + "lzma": { + "sha1": "9a6a4c086e48b9e615b72b6bbebb3c724d178ff4", + "size": 1680, + "url": "https://launcher.mojang.com/v1/objects/9a6a4c086e48b9e615b72b6bbebb3c724d178ff4/messages_ja.properties" + }, + "raw": { + "sha1": "751170a7cdefcb1226604ac3f8196e06a04fd7ac", + "size": 6349, + "url": "https://launcher.mojang.com/v1/objects/751170a7cdefcb1226604ac3f8196e06a04fd7ac/messages_ja.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_ko.properties": { + "downloads": { + "lzma": { + "sha1": "0c57c2ebfa0830f816657a384898487fc492efac", + "size": 1645, + "url": "https://launcher.mojang.com/v1/objects/0c57c2ebfa0830f816657a384898487fc492efac/messages_ko.properties" + }, + "raw": { + "sha1": "bf9e055b5ab138ad6d49769e2b7630b7938848d6", + "size": 5712, + "url": "https://launcher.mojang.com/v1/objects/bf9e055b5ab138ad6d49769e2b7630b7938848d6/messages_ko.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_pt_BR.properties": { + "downloads": { + "lzma": { + "sha1": "f8364dba0aa0a7e445a1a8d0e7ad66b996f70063", + "size": 1388, + "url": "https://launcher.mojang.com/v1/objects/f8364dba0aa0a7e445a1a8d0e7ad66b996f70063/messages_pt_BR.properties" + }, + "raw": { + "sha1": "24e4951743521ab9a11381c77bd0cdb1ed30f5b5", + "size": 3285, + "url": "https://launcher.mojang.com/v1/objects/24e4951743521ab9a11381c77bd0cdb1ed30f5b5/messages_pt_BR.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_sv.properties": { + "downloads": { + "lzma": { + "sha1": "65e5897d552258141aacf02f087c7c9c33ad0727", + "size": 1355, + "url": "https://launcher.mojang.com/v1/objects/65e5897d552258141aacf02f087c7c9c33ad0727/messages_sv.properties" + }, + "raw": { + "sha1": "bb5a4aa0ba499f6b1916a83e3c7922a4583b4adb", + "size": 3384, + "url": "https://launcher.mojang.com/v1/objects/bb5a4aa0ba499f6b1916a83e3c7922a4583b4adb/messages_sv.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_zh_CN.properties": { + "downloads": { + "lzma": { + "sha1": "de7d39a6e6748e9f47e842c9da90f515921c222c", + "size": 1506, + "url": "https://launcher.mojang.com/v1/objects/de7d39a6e6748e9f47e842c9da90f515921c222c/messages_zh_CN.properties" + }, + "raw": { + "sha1": "1c2b96673dddd3596890ef4fc22017d484a1f652", + "size": 4072, + "url": "https://launcher.mojang.com/v1/objects/1c2b96673dddd3596890ef4fc22017d484a1f652/messages_zh_CN.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_zh_HK.properties": { + "downloads": { + "lzma": { + "sha1": "e8d0e3a63caa2535a4f361033941f34dcc170a7e", + "size": 1529, + "url": "https://launcher.mojang.com/v1/objects/e8d0e3a63caa2535a4f361033941f34dcc170a7e/messages_zh_TW.properties" + }, + "raw": { + "sha1": "37a57aad121c14c25e149206179728fa62203bf0", + "size": 3752, + "url": "https://launcher.mojang.com/v1/objects/37a57aad121c14c25e149206179728fa62203bf0/messages_zh_TW.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/messages_zh_TW.properties": { + "downloads": { + "lzma": { + "sha1": "e8d0e3a63caa2535a4f361033941f34dcc170a7e", + "size": 1529, + "url": "https://launcher.mojang.com/v1/objects/e8d0e3a63caa2535a4f361033941f34dcc170a7e/messages_zh_TW.properties" + }, + "raw": { + "sha1": "37a57aad121c14c25e149206179728fa62203bf0", + "size": 3752, + "url": "https://launcher.mojang.com/v1/objects/37a57aad121c14c25e149206179728fa62203bf0/messages_zh_TW.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/mixcode_s.png": { + "downloads": { + "raw": { + "sha1": "4604e9f265eec97bccd0151c3a81afa9e69499e5", + "size": 3115, + "url": "https://launcher.mojang.com/v1/objects/4604e9f265eec97bccd0151c3a81afa9e69499e5/mixcode_s.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/splash.gif": { + "downloads": { + "raw": { + "sha1": "20e7aec75f6d036d504277542e507eb7dc24aae8", + "size": 8590, + "url": "https://launcher.mojang.com/v1/objects/20e7aec75f6d036d504277542e507eb7dc24aae8/splash.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/splash@2x.gif": { + "downloads": { + "raw": { + "sha1": "0ae4a5bda2a6d628fac51462390b503c99509fdc", + "size": 15276, + "url": "https://launcher.mojang.com/v1/objects/0ae4a5bda2a6d628fac51462390b503c99509fdc/splash2x.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/splash_11-lic.gif": { + "downloads": { + "raw": { + "sha1": "8def364e07f40142822df84b5bb4f50846cb5e4e", + "size": 7805, + "url": "https://launcher.mojang.com/v1/objects/8def364e07f40142822df84b5bb4f50846cb5e4e/splash_11-lic.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/deploy/splash_11@2x-lic.gif": { + "downloads": { + "raw": { + "sha1": "d2bff9bbf7920ca743b81a0ee23b0719b4d057ca", + "size": 12250, + "url": "https://launcher.mojang.com/v1/objects/d2bff9bbf7920ca743b81a0ee23b0719b4d057ca/splash_11%402x-lic.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop": { + "type": "directory" + }, + "lib/desktop/applications": { + "type": "directory" + }, + "lib/desktop/applications/sun-java.desktop": { + "downloads": { + "lzma": { + "sha1": "109d1cdf165f38da92da70b403ca940192a7a9a8", + "size": 536, + "url": "https://launcher.mojang.com/v1/objects/109d1cdf165f38da92da70b403ca940192a7a9a8/sun-java.desktop" + }, + "raw": { + "sha1": "d346dfe90505603ce5aff5a3c6c2e4a23d5bd990", + "size": 777, + "url": "https://launcher.mojang.com/v1/objects/d346dfe90505603ce5aff5a3c6c2e4a23d5bd990/sun-java.desktop" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/applications/sun-javaws.desktop": { + "downloads": { + "lzma": { + "sha1": "5e1815e7f83515881e6998584dc6bb02c5bef09a", + "size": 451, + "url": "https://launcher.mojang.com/v1/objects/5e1815e7f83515881e6998584dc6bb02c5bef09a/sun-javaws.desktop" + }, + "raw": { + "sha1": "50ce8e519b836e0f53d58ce1a359d98b6cafdda6", + "size": 619, + "url": "https://launcher.mojang.com/v1/objects/50ce8e519b836e0f53d58ce1a359d98b6cafdda6/sun-javaws.desktop" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/applications/sun_java.desktop": { + "downloads": { + "lzma": { + "sha1": "49ab0ccb54c3be68281d05055bc56a88b1281d3c", + "size": 447, + "url": "https://launcher.mojang.com/v1/objects/49ab0ccb54c3be68281d05055bc56a88b1281d3c/sun_java.desktop" + }, + "raw": { + "sha1": "79120ee8160ad6f3c9b90c2641fb7edf3af96b5d", + "size": 624, + "url": "https://launcher.mojang.com/v1/objects/79120ee8160ad6f3c9b90c2641fb7edf3af96b5d/sun_java.desktop" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast/16x16": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast/16x16/apps": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast/16x16/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "366e7a48e9e4fb92eaeabbcaeb4626122a66cecb", + "size": 417, + "url": "https://launcher.mojang.com/v1/objects/366e7a48e9e4fb92eaeabbcaeb4626122a66cecb/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/16x16/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "366e7a48e9e4fb92eaeabbcaeb4626122a66cecb", + "size": 417, + "url": "https://launcher.mojang.com/v1/objects/366e7a48e9e4fb92eaeabbcaeb4626122a66cecb/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/16x16/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "366e7a48e9e4fb92eaeabbcaeb4626122a66cecb", + "size": 417, + "url": "https://launcher.mojang.com/v1/objects/366e7a48e9e4fb92eaeabbcaeb4626122a66cecb/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/16x16/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast/16x16/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "629c48907368ecf32d2395b6459c367f79d84689", + "size": 464, + "url": + "https://launcher.mojang.com/v1/objects/629c48907368ecf32d2395b6459c367f79d84689/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "629c48907368ecf32d2395b6459c367f79d84689", + "size": 464, + "url": + "https://launcher.mojang.com/v1/objects/629c48907368ecf32d2395b6459c367f79d84689/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/16x16/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "629c48907368ecf32d2395b6459c367f79d84689", + "size": 464, + "url": + "https://launcher.mojang.com/v1/objects/629c48907368ecf32d2395b6459c367f79d84689/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/48x48": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast/48x48/apps": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast/48x48/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "8373482d072684e09830dbdb97a76ea264c9f4e9", + "size": 3451, + "url": "https://launcher.mojang.com/v1/objects/8373482d072684e09830dbdb97a76ea264c9f4e9/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/48x48/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "8373482d072684e09830dbdb97a76ea264c9f4e9", + "size": 3451, + "url": "https://launcher.mojang.com/v1/objects/8373482d072684e09830dbdb97a76ea264c9f4e9/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/48x48/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "8373482d072684e09830dbdb97a76ea264c9f4e9", + "size": 3451, + "url": "https://launcher.mojang.com/v1/objects/8373482d072684e09830dbdb97a76ea264c9f4e9/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/48x48/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/HighContrast/48x48/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "56a4996519f8f3541eba7b7a7a69bcdcd8ed0410", + "size": 2088, + "url": + "https://launcher.mojang.com/v1/objects/56a4996519f8f3541eba7b7a7a69bcdcd8ed0410/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "56a4996519f8f3541eba7b7a7a69bcdcd8ed0410", + "size": 2088, + "url": + "https://launcher.mojang.com/v1/objects/56a4996519f8f3541eba7b7a7a69bcdcd8ed0410/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrast/48x48/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "56a4996519f8f3541eba7b7a7a69bcdcd8ed0410", + "size": 2088, + "url": + "https://launcher.mojang.com/v1/objects/56a4996519f8f3541eba7b7a7a69bcdcd8ed0410/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse": { + "type": "directory" + }, + "lib/desktop/icons/HighContrastInverse/16x16": { + "type": "directory" + }, + "lib/desktop/icons/HighContrastInverse/16x16/apps": { + "type": "directory" + }, + "lib/desktop/icons/HighContrastInverse/16x16/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "bf0995acb94aa794e73c5b971282ff13ffe42793", + "size": 402, + "url": "https://launcher.mojang.com/v1/objects/bf0995acb94aa794e73c5b971282ff13ffe42793/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/16x16/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "bf0995acb94aa794e73c5b971282ff13ffe42793", + "size": 402, + "url": "https://launcher.mojang.com/v1/objects/bf0995acb94aa794e73c5b971282ff13ffe42793/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/16x16/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "bf0995acb94aa794e73c5b971282ff13ffe42793", + "size": 402, + "url": "https://launcher.mojang.com/v1/objects/bf0995acb94aa794e73c5b971282ff13ffe42793/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/16x16/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/HighContrastInverse/16x16/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "1477eceda25e162fcda2e69ee3906091973d8344", + "size": 473, + "url": + "https://launcher.mojang.com/v1/objects/1477eceda25e162fcda2e69ee3906091973d8344/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "1477eceda25e162fcda2e69ee3906091973d8344", + "size": 473, + "url": + "https://launcher.mojang.com/v1/objects/1477eceda25e162fcda2e69ee3906091973d8344/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/16x16/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "1477eceda25e162fcda2e69ee3906091973d8344", + "size": 473, + "url": + "https://launcher.mojang.com/v1/objects/1477eceda25e162fcda2e69ee3906091973d8344/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/48x48": { + "type": "directory" + }, + "lib/desktop/icons/HighContrastInverse/48x48/apps": { + "type": "directory" + }, + "lib/desktop/icons/HighContrastInverse/48x48/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "413da160dd9899b95f53d4cc11f5ee0550cc6585", + "size": 3410, + "url": "https://launcher.mojang.com/v1/objects/413da160dd9899b95f53d4cc11f5ee0550cc6585/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/48x48/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "413da160dd9899b95f53d4cc11f5ee0550cc6585", + "size": 3410, + "url": "https://launcher.mojang.com/v1/objects/413da160dd9899b95f53d4cc11f5ee0550cc6585/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/48x48/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "413da160dd9899b95f53d4cc11f5ee0550cc6585", + "size": 3410, + "url": "https://launcher.mojang.com/v1/objects/413da160dd9899b95f53d4cc11f5ee0550cc6585/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/48x48/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/HighContrastInverse/48x48/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "d66e04dfa25c196bec2e201547325b79846ab674", + "size": 2085, + "url": + "https://launcher.mojang.com/v1/objects/d66e04dfa25c196bec2e201547325b79846ab674/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "d66e04dfa25c196bec2e201547325b79846ab674", + "size": 2085, + "url": + "https://launcher.mojang.com/v1/objects/d66e04dfa25c196bec2e201547325b79846ab674/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/HighContrastInverse/48x48/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "d66e04dfa25c196bec2e201547325b79846ab674", + "size": 2085, + "url": + "https://launcher.mojang.com/v1/objects/d66e04dfa25c196bec2e201547325b79846ab674/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast": { + "type": "directory" + }, + "lib/desktop/icons/LowContrast/16x16": { + "type": "directory" + }, + "lib/desktop/icons/LowContrast/16x16/apps": { + "type": "directory" + }, + "lib/desktop/icons/LowContrast/16x16/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "f93b7cf0a6d27d664a7f09dab6933b2768536f52", + "size": 519, + "url": "https://launcher.mojang.com/v1/objects/f93b7cf0a6d27d664a7f09dab6933b2768536f52/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/16x16/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "f93b7cf0a6d27d664a7f09dab6933b2768536f52", + "size": 519, + "url": "https://launcher.mojang.com/v1/objects/f93b7cf0a6d27d664a7f09dab6933b2768536f52/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/16x16/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "f93b7cf0a6d27d664a7f09dab6933b2768536f52", + "size": 519, + "url": "https://launcher.mojang.com/v1/objects/f93b7cf0a6d27d664a7f09dab6933b2768536f52/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/16x16/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/LowContrast/16x16/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "0aa1605877280b88de1f1cc3e7e4bdbeed968a73", + "size": 525, + "url": + "https://launcher.mojang.com/v1/objects/0aa1605877280b88de1f1cc3e7e4bdbeed968a73/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "0aa1605877280b88de1f1cc3e7e4bdbeed968a73", + "size": 525, + "url": + "https://launcher.mojang.com/v1/objects/0aa1605877280b88de1f1cc3e7e4bdbeed968a73/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/16x16/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "0aa1605877280b88de1f1cc3e7e4bdbeed968a73", + "size": 525, + "url": + "https://launcher.mojang.com/v1/objects/0aa1605877280b88de1f1cc3e7e4bdbeed968a73/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/48x48": { + "type": "directory" + }, + "lib/desktop/icons/LowContrast/48x48/apps": { + "type": "directory" + }, + "lib/desktop/icons/LowContrast/48x48/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "1fcf4fd6da61873b5f21b39412da26509734b7cc", + "size": 1507, + "url": "https://launcher.mojang.com/v1/objects/1fcf4fd6da61873b5f21b39412da26509734b7cc/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/48x48/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "1fcf4fd6da61873b5f21b39412da26509734b7cc", + "size": 1507, + "url": "https://launcher.mojang.com/v1/objects/1fcf4fd6da61873b5f21b39412da26509734b7cc/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/48x48/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "1fcf4fd6da61873b5f21b39412da26509734b7cc", + "size": 1507, + "url": "https://launcher.mojang.com/v1/objects/1fcf4fd6da61873b5f21b39412da26509734b7cc/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/48x48/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/LowContrast/48x48/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "e36636b1c04dc283c18adf669b892d54b15d3ee6", + "size": 1948, + "url": + "https://launcher.mojang.com/v1/objects/e36636b1c04dc283c18adf669b892d54b15d3ee6/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "e36636b1c04dc283c18adf669b892d54b15d3ee6", + "size": 1948, + "url": + "https://launcher.mojang.com/v1/objects/e36636b1c04dc283c18adf669b892d54b15d3ee6/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/LowContrast/48x48/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "e36636b1c04dc283c18adf669b892d54b15d3ee6", + "size": 1948, + "url": + "https://launcher.mojang.com/v1/objects/e36636b1c04dc283c18adf669b892d54b15d3ee6/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor": { + "type": "directory" + }, + "lib/desktop/icons/hicolor/16x16": { + "type": "directory" + }, + "lib/desktop/icons/hicolor/16x16/apps": { + "type": "directory" + }, + "lib/desktop/icons/hicolor/16x16/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "e91d05bfe9b889bf8a227908b597cab4630da8f2", + "size": 383, + "url": "https://launcher.mojang.com/v1/objects/e91d05bfe9b889bf8a227908b597cab4630da8f2/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/16x16/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "e91d05bfe9b889bf8a227908b597cab4630da8f2", + "size": 383, + "url": "https://launcher.mojang.com/v1/objects/e91d05bfe9b889bf8a227908b597cab4630da8f2/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/16x16/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "e91d05bfe9b889bf8a227908b597cab4630da8f2", + "size": 383, + "url": "https://launcher.mojang.com/v1/objects/e91d05bfe9b889bf8a227908b597cab4630da8f2/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/16x16/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/hicolor/16x16/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "d2f6abe8e498aeecb334fb43f63001d34dbf6ea5", + "size": 783, + "url": + "https://launcher.mojang.com/v1/objects/d2f6abe8e498aeecb334fb43f63001d34dbf6ea5/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/16x16/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "d2f6abe8e498aeecb334fb43f63001d34dbf6ea5", + "size": 783, + "url": + "https://launcher.mojang.com/v1/objects/d2f6abe8e498aeecb334fb43f63001d34dbf6ea5/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/16x16/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "d2f6abe8e498aeecb334fb43f63001d34dbf6ea5", + "size": 783, + "url": + "https://launcher.mojang.com/v1/objects/d2f6abe8e498aeecb334fb43f63001d34dbf6ea5/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/48x48": { + "type": "directory" + }, + "lib/desktop/icons/hicolor/48x48/apps": { + "type": "directory" + }, + "lib/desktop/icons/hicolor/48x48/apps/sun-java.png": { + "downloads": { + "raw": { + "sha1": "6c90a38eaada9c32a678a282be18ec5b43a84264", + "size": 1439, + "url": "https://launcher.mojang.com/v1/objects/6c90a38eaada9c32a678a282be18ec5b43a84264/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/48x48/apps/sun-javaws.png": { + "downloads": { + "raw": { + "sha1": "6c90a38eaada9c32a678a282be18ec5b43a84264", + "size": 1439, + "url": "https://launcher.mojang.com/v1/objects/6c90a38eaada9c32a678a282be18ec5b43a84264/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/48x48/apps/sun-jcontrol.png": { + "downloads": { + "raw": { + "sha1": "6c90a38eaada9c32a678a282be18ec5b43a84264", + "size": 1439, + "url": "https://launcher.mojang.com/v1/objects/6c90a38eaada9c32a678a282be18ec5b43a84264/sun-javaws.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/48x48/mimetypes": { + "type": "directory" + }, + "lib/desktop/icons/hicolor/48x48/mimetypes/gnome-mime-application-x-java-archive.png": { + "downloads": { + "raw": { + "sha1": "4d5e6e0c41d1076bc86f3ab157c88a41a5716997", + "size": 3202, + "url": + "https://launcher.mojang.com/v1/objects/4d5e6e0c41d1076bc86f3ab157c88a41a5716997/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/48x48/mimetypes/gnome-mime-application-x-java-jnlp-file.png": { + "downloads": { + "raw": { + "sha1": "4d5e6e0c41d1076bc86f3ab157c88a41a5716997", + "size": 3202, + "url": + "https://launcher.mojang.com/v1/objects/4d5e6e0c41d1076bc86f3ab157c88a41a5716997/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/icons/hicolor/48x48/mimetypes/gnome-mime-text-x-java.png": { + "downloads": { + "raw": { + "sha1": "4d5e6e0c41d1076bc86f3ab157c88a41a5716997", + "size": 3202, + "url": + "https://launcher.mojang.com/v1/objects/4d5e6e0c41d1076bc86f3ab157c88a41a5716997/gnome-mime-application-x-java-archive.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/mime": { + "type": "directory" + }, + "lib/desktop/mime/packages": { + "type": "directory" + }, + "lib/desktop/mime/packages/x-java-archive.xml": { + "downloads": { + "lzma": { + "sha1": "841230729f0a59de2a1071d155d96358232b2ba1", + "size": 591, + "url": "https://launcher.mojang.com/v1/objects/841230729f0a59de2a1071d155d96358232b2ba1/x-java-archive.xml" + }, + "raw": { + "sha1": "b6297fd36efa799312961f95ebf0c85c920d5037", + "size": 1822, + "url": "https://launcher.mojang.com/v1/objects/b6297fd36efa799312961f95ebf0c85c920d5037/x-java-archive.xml" + } + }, + "executable": false, + "type": "file" + }, + "lib/desktop/mime/packages/x-java-jnlp-file.xml": { + "downloads": { + "lzma": { + "sha1": "abf9acbe7c18027c4f036c4e42bb2cf1115525fa", + "size": 302, + "url": "https://launcher.mojang.com/v1/objects/abf9acbe7c18027c4f036c4e42bb2cf1115525fa/x-java-jnlp-file.xml" + }, + "raw": { + "sha1": "72f03da83ddb76c9105f619fcfa4dbdad70e6b30", + "size": 412, + "url": "https://launcher.mojang.com/v1/objects/72f03da83ddb76c9105f619fcfa4dbdad70e6b30/x-java-jnlp-file.xml" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext": { + "type": "directory" + }, + "lib/ext/cldrdata.jar": { + "downloads": { + "raw": { + "sha1": "6cacc961942d3f02a88907aa8f2eaae8e20c95a0", + "size": 3860502, + "url": "https://launcher.mojang.com/v1/objects/6cacc961942d3f02a88907aa8f2eaae8e20c95a0/cldrdata.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/dnsns.jar": { + "downloads": { + "raw": { + "sha1": "93bebdd7514e53ae31d60c5daba673878c8822ec", + "size": 8286, + "url": "https://launcher.mojang.com/v1/objects/93bebdd7514e53ae31d60c5daba673878c8822ec/dnsns.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/jaccess.jar": { + "downloads": { + "raw": { + "sha1": "2f54879df7c29ec67c40d40cfc95c0d4a968bea1", + "size": 44516, + "url": "https://launcher.mojang.com/v1/objects/2f54879df7c29ec67c40d40cfc95c0d4a968bea1/jaccess.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/jfxrt.jar": { + "downloads": { + "lzma": { + "sha1": "a6c5b6a782ba360ada6651f5322dcab88c75711c", + "size": 3374270, + "url": "https://launcher.mojang.com/v1/objects/a6c5b6a782ba360ada6651f5322dcab88c75711c/jfxrt.jar" + }, + "raw": { + "sha1": "1ad7a876f045399c23ee4ab7dee380a04ca2ac08", + "size": 18508094, + "url": "https://launcher.mojang.com/v1/objects/1ad7a876f045399c23ee4ab7dee380a04ca2ac08/jfxrt.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/localedata.jar": { + "downloads": { + "raw": { + "sha1": "0cc9f550d4e410b5aa29dbfd2c1b5c99391c7f70", + "size": 1178926, + "url": "https://launcher.mojang.com/v1/objects/0cc9f550d4e410b5aa29dbfd2c1b5c99391c7f70/localedata.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/meta-index": { + "downloads": { + "lzma": { + "sha1": "1359457529f42bacf495afcb68149ae036442dd9", + "size": 594, + "url": "https://launcher.mojang.com/v1/objects/1359457529f42bacf495afcb68149ae036442dd9/meta-index" + }, + "raw": { + "sha1": "334649c6e2d5d7248211f30855e97cfcb4558851", + "size": 1269, + "url": "https://launcher.mojang.com/v1/objects/334649c6e2d5d7248211f30855e97cfcb4558851/meta-index" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/nashorn.jar": { + "downloads": { + "raw": { + "sha1": "dec5dd17a0f52ae79dfbfb38840bffb8b7a679a5", + "size": 2023869, + "url": "https://launcher.mojang.com/v1/objects/dec5dd17a0f52ae79dfbfb38840bffb8b7a679a5/nashorn.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/sunec.jar": { + "downloads": { + "raw": { + "sha1": "bf1c817820341a246f7130fe046e8310b03d04f6", + "size": 41672, + "url": "https://launcher.mojang.com/v1/objects/bf1c817820341a246f7130fe046e8310b03d04f6/sunec.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/sunjce_provider.jar": { + "downloads": { + "raw": { + "sha1": "bb3494e4b5cb3c3e60da767207731f18b267cb34", + "size": 279326, + "url": "https://launcher.mojang.com/v1/objects/bb3494e4b5cb3c3e60da767207731f18b267cb34/sunjce_provider.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/sunpkcs11.jar": { + "downloads": { + "raw": { + "sha1": "5bb1dedc3344cd3bb86828d4aa8ca82f4a606ed4", + "size": 250218, + "url": "https://launcher.mojang.com/v1/objects/5bb1dedc3344cd3bb86828d4aa8ca82f4a606ed4/sunpkcs11.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/ext/zipfs.jar": { + "downloads": { + "raw": { + "sha1": "37b338f0e8e60d6396f51275130e8110816d7b30", + "size": 68964, + "url": "https://launcher.mojang.com/v1/objects/37b338f0e8e60d6396f51275130e8110816d7b30/zipfs.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/flavormap.properties": { + "downloads": { + "lzma": { + "sha1": "2d5ef19ee77ccfc95c9413eea155cde59a48fadd", + "size": 1541, + "url": "https://launcher.mojang.com/v1/objects/2d5ef19ee77ccfc95c9413eea155cde59a48fadd/flavormap.properties" + }, + "raw": { + "sha1": "4e66e8fe12d7f8b3b0c4e1a1915f329bb1fbf6d2", + "size": 3901, + "url": "https://launcher.mojang.com/v1/objects/4e66e8fe12d7f8b3b0c4e1a1915f329bb1fbf6d2/flavormap.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.RedHat.5.bfc": { + "downloads": { + "lzma": { + "sha1": "5197f6e387f16458b7408134e38b06f20f625e4c", + "size": 795, + "url": "https://launcher.mojang.com/v1/objects/5197f6e387f16458b7408134e38b06f20f625e4c/fontconfig.RedHat.5.bfc" + }, + "raw": { + "sha1": "fb806ada6e68f16a9fe2b726a39d9ef5a835c0c2", + "size": 4532, + "url": "https://launcher.mojang.com/v1/objects/fb806ada6e68f16a9fe2b726a39d9ef5a835c0c2/fontconfig.RedHat.5.bfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.RedHat.5.properties.src": { + "downloads": { + "lzma": { + "sha1": "3897ae198e96e5a687c9c9b218ff5df60c868e0d", + "size": 1089, + "url": + "https://launcher.mojang.com/v1/objects/3897ae198e96e5a687c9c9b218ff5df60c868e0d/fontconfig.RedHat.5.properties.src" + }, + "raw": { + "sha1": "c67d1a06cb37b66e69560c9f5e4be7cf08af0493", + "size": 8841, + "url": + "https://launcher.mojang.com/v1/objects/c67d1a06cb37b66e69560c9f5e4be7cf08af0493/fontconfig.RedHat.5.properties.src" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.RedHat.6.bfc": { + "downloads": { + "lzma": { + "sha1": "ef2f5d1f8d620be9927db45d3a28bd75777245cb", + "size": 818, + "url": "https://launcher.mojang.com/v1/objects/ef2f5d1f8d620be9927db45d3a28bd75777245cb/fontconfig.RedHat.6.bfc" + }, + "raw": { + "sha1": "9ba3b3e2c621c31d0ef1b2053c80f77419a19965", + "size": 4250, + "url": "https://launcher.mojang.com/v1/objects/9ba3b3e2c621c31d0ef1b2053c80f77419a19965/fontconfig.RedHat.6.bfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.RedHat.6.properties.src": { + "downloads": { + "lzma": { + "sha1": "74f4148f9d7ec3d67bbd724834d478a72cfdb0db", + "size": 1111, + "url": + "https://launcher.mojang.com/v1/objects/74f4148f9d7ec3d67bbd724834d478a72cfdb0db/fontconfig.RedHat.6.properties.src" + }, + "raw": { + "sha1": "768e58d4d314621c38daf9fde6d67119f370acd9", + "size": 8735, + "url": + "https://launcher.mojang.com/v1/objects/768e58d4d314621c38daf9fde6d67119f370acd9/fontconfig.RedHat.6.properties.src" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.SuSE.10.bfc": { + "downloads": { + "lzma": { + "sha1": "d8fe9b1d8d02368dcd452de93024c6f60670eb87", + "size": 1083, + "url": "https://launcher.mojang.com/v1/objects/d8fe9b1d8d02368dcd452de93024c6f60670eb87/fontconfig.SuSE.10.bfc" + }, + "raw": { + "sha1": "ffd0dfbd1553e15b11649a73a0b3f48318138e0d", + "size": 6702, + "url": "https://launcher.mojang.com/v1/objects/ffd0dfbd1553e15b11649a73a0b3f48318138e0d/fontconfig.SuSE.10.bfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.SuSE.10.properties.src": { + "downloads": { + "lzma": { + "sha1": "2c382bd741a9e23114be3da82dee8290ebfca8a9", + "size": 1555, + "url": + "https://launcher.mojang.com/v1/objects/2c382bd741a9e23114be3da82dee8290ebfca8a9/fontconfig.SuSE.10.properties.src" + }, + "raw": { + "sha1": "a38dbdbbc514567b8281e1aea726865f37e97894", + "size": 16772, + "url": + "https://launcher.mojang.com/v1/objects/a38dbdbbc514567b8281e1aea726865f37e97894/fontconfig.SuSE.10.properties.src" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.SuSE.11.bfc": { + "downloads": { + "lzma": { + "sha1": "2b78cbf11289c9858951fea7180696ba3b7176d6", + "size": 1092, + "url": "https://launcher.mojang.com/v1/objects/2b78cbf11289c9858951fea7180696ba3b7176d6/fontconfig.SuSE.11.bfc" + }, + "raw": { + "sha1": "a4d8500fcb47f6327460a95851b1368660da8302", + "size": 7032, + "url": "https://launcher.mojang.com/v1/objects/a4d8500fcb47f6327460a95851b1368660da8302/fontconfig.SuSE.11.bfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.SuSE.11.properties.src": { + "downloads": { + "lzma": { + "sha1": "5c1635803906e2c59d36492dec724dd7ae49a5ab", + "size": 1589, + "url": + "https://launcher.mojang.com/v1/objects/5c1635803906e2c59d36492dec724dd7ae49a5ab/fontconfig.SuSE.11.properties.src" + }, + "raw": { + "sha1": "c4b69589e41a7279a71866a9134213be19cdf88d", + "size": 16781, + "url": + "https://launcher.mojang.com/v1/objects/c4b69589e41a7279a71866a9134213be19cdf88d/fontconfig.SuSE.11.properties.src" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.Turbo.bfc": { + "downloads": { + "lzma": { + "sha1": "1c771325d9ee4af209a3db92294451d58962c7a4", + "size": 822, + "url": "https://launcher.mojang.com/v1/objects/1c771325d9ee4af209a3db92294451d58962c7a4/fontconfig.Turbo.bfc" + }, + "raw": { + "sha1": "f24368deeb85cc9d0781083bc56e773518d72219", + "size": 4668, + "url": "https://launcher.mojang.com/v1/objects/f24368deeb85cc9d0781083bc56e773518d72219/fontconfig.Turbo.bfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.Turbo.properties.src": { + "downloads": { + "lzma": { + "sha1": "7748ffa17e2c8a34754138efa963ba39bd1cbbb3", + "size": 1113, + "url": "https://launcher.mojang.com/v1/objects/7748ffa17e2c8a34754138efa963ba39bd1cbbb3/fontconfig.Turbo.properties.src" + }, + "raw": { + "sha1": "2bb7258bed7ccd4f117e4e5f892c9b13424b0c82", + "size": 9192, + "url": "https://launcher.mojang.com/v1/objects/2bb7258bed7ccd4f117e4e5f892c9b13424b0c82/fontconfig.Turbo.properties.src" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.bfc": { + "downloads": { + "lzma": { + "sha1": "be6d49ee8c64f458c4f0e64254963fec48d25150", + "size": 286, + "url": "https://launcher.mojang.com/v1/objects/be6d49ee8c64f458c4f0e64254963fec48d25150/fontconfig.bfc" + }, + "raw": { + "sha1": "de39b0e19637f58d92a0188122514aa7247ebb5b", + "size": 1678, + "url": "https://launcher.mojang.com/v1/objects/de39b0e19637f58d92a0188122514aa7247ebb5b/fontconfig.bfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/fontconfig.properties.src": { + "downloads": { + "lzma": { + "sha1": "9498d5e00e5401200667687e826e28c60fa60ba4", + "size": 417, + "url": "https://launcher.mojang.com/v1/objects/9498d5e00e5401200667687e826e28c60fa60ba4/fontconfig.properties.src" + }, + "raw": { + "sha1": "3617ff1424fd204415242565541facf862b16eb4", + "size": 1938, + "url": "https://launcher.mojang.com/v1/objects/3617ff1424fd204415242565541facf862b16eb4/fontconfig.properties.src" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts": { + "type": "directory" + }, + "lib/fonts/LucidaBrightDemiBold.ttf": { + "downloads": { + "lzma": { + "sha1": "4f748750831a7719440dff5457f4d207d0f24d21", + "size": 42347, + "url": "https://launcher.mojang.com/v1/objects/4f748750831a7719440dff5457f4d207d0f24d21/LucidaBrightDemiBold.ttf" + }, + "raw": { + "sha1": "b5c97f985639e19a3b712193ee48b55dda581fd1", + "size": 75144, + "url": "https://launcher.mojang.com/v1/objects/b5c97f985639e19a3b712193ee48b55dda581fd1/LucidaBrightDemiBold.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/LucidaBrightDemiItalic.ttf": { + "downloads": { + "lzma": { + "sha1": "f82e9a688553c100ecb98412b985807ed56dff5d", + "size": 43119, + "url": "https://launcher.mojang.com/v1/objects/f82e9a688553c100ecb98412b985807ed56dff5d/LucidaBrightDemiItalic.ttf" + }, + "raw": { + "sha1": "1fd1f757febf3e5f5fbb7fbf7a56587a40d57de7", + "size": 75124, + "url": "https://launcher.mojang.com/v1/objects/1fd1f757febf3e5f5fbb7fbf7a56587a40d57de7/LucidaBrightDemiItalic.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/LucidaBrightItalic.ttf": { + "downloads": { + "lzma": { + "sha1": "6d630df719271319c3d53f90a3d425118b908266", + "size": 46206, + "url": "https://launcher.mojang.com/v1/objects/6d630df719271319c3d53f90a3d425118b908266/LucidaBrightItalic.ttf" + }, + "raw": { + "sha1": "aa5c037865c563726ecd63d61ca26443589be425", + "size": 80856, + "url": "https://launcher.mojang.com/v1/objects/aa5c037865c563726ecd63d61ca26443589be425/LucidaBrightItalic.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/LucidaBrightRegular.ttf": { + "downloads": { + "lzma": { + "sha1": "4b2e31aaec2238b6ecf9f845bad0a1c6d09fbbfe", + "size": 181085, + "url": "https://launcher.mojang.com/v1/objects/4b2e31aaec2238b6ecf9f845bad0a1c6d09fbbfe/LucidaBrightRegular.ttf" + }, + "raw": { + "sha1": "5d7ed564791c900a8786936930ba99385653139c", + "size": 344908, + "url": "https://launcher.mojang.com/v1/objects/5d7ed564791c900a8786936930ba99385653139c/LucidaBrightRegular.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/LucidaSansDemiBold.ttf": { + "downloads": { + "lzma": { + "sha1": "079b16dc3c4918ab1f4f760b6dc5e6586c219042", + "size": 173229, + "url": "https://launcher.mojang.com/v1/objects/079b16dc3c4918ab1f4f760b6dc5e6586c219042/LucidaSansDemiBold.ttf" + }, + "raw": { + "sha1": "92b79fefc35e96190250c602a8fed85276b32a95", + "size": 317896, + "url": "https://launcher.mojang.com/v1/objects/92b79fefc35e96190250c602a8fed85276b32a95/LucidaSansDemiBold.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/LucidaSansRegular.ttf": { + "downloads": { + "lzma": { + "sha1": "64a65d7b94d7153d20957ef6d06bebb4dd0f48e4", + "size": 326062, + "url": "https://launcher.mojang.com/v1/objects/64a65d7b94d7153d20957ef6d06bebb4dd0f48e4/LucidaSansRegular.ttf" + }, + "raw": { + "sha1": "39cc8bcb8d4a71d4657fc92ef0b9f4e3e9e67add", + "size": 698236, + "url": "https://launcher.mojang.com/v1/objects/39cc8bcb8d4a71d4657fc92ef0b9f4e3e9e67add/LucidaSansRegular.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/LucidaTypewriterBold.ttf": { + "downloads": { + "lzma": { + "sha1": "cdb017f7c34bea0802bc5ea5583aef721ed99c49", + "size": 130412, + "url": "https://launcher.mojang.com/v1/objects/cdb017f7c34bea0802bc5ea5583aef721ed99c49/LucidaTypewriterBold.ttf" + }, + "raw": { + "sha1": "a5da2eb49448f461470387c939f0e69119310e0b", + "size": 234068, + "url": "https://launcher.mojang.com/v1/objects/a5da2eb49448f461470387c939f0e69119310e0b/LucidaTypewriterBold.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/LucidaTypewriterRegular.ttf": { + "downloads": { + "lzma": { + "sha1": "aeda4a09a53783b0dc97de8e20071bea874cbfe5", + "size": 135184, + "url": "https://launcher.mojang.com/v1/objects/aeda4a09a53783b0dc97de8e20071bea874cbfe5/LucidaTypewriterRegular.ttf" + }, + "raw": { + "sha1": "c144dcafe4faf2e79cfd74d8134a631f30234db1", + "size": 242700, + "url": "https://launcher.mojang.com/v1/objects/c144dcafe4faf2e79cfd74d8134a631f30234db1/LucidaTypewriterRegular.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/fonts/fonts.dir": { + "downloads": { + "lzma": { + "sha1": "68f2dd93b215ec8b8d9409d2b9c825632c6b907d", + "size": 273, + "url": "https://launcher.mojang.com/v1/objects/68f2dd93b215ec8b8d9409d2b9c825632c6b907d/fonts.dir" + }, + "raw": { + "sha1": "97f40cca185c954adf5cc582345a7cb8e4c50578", + "size": 4041, + "url": "https://launcher.mojang.com/v1/objects/97f40cca185c954adf5cc582345a7cb8e4c50578/fonts.dir" + } + }, + "executable": false, + "type": "file" + }, + "lib/hijrah-config-umalqura.properties": { + "downloads": { + "lzma": { + "sha1": "02e8d296e3b18a450f1ed1547cbf2b7275664c9a", + "size": 1969, + "url": + "https://launcher.mojang.com/v1/objects/02e8d296e3b18a450f1ed1547cbf2b7275664c9a/hijrah-config-umalqura.properties" + }, + "raw": { + "sha1": "84aa425100740722e91f4725caf849e7863d12ba", + "size": 13962, + "url": + "https://launcher.mojang.com/v1/objects/84aa425100740722e91f4725caf849e7863d12ba/hijrah-config-umalqura.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/images": { + "type": "directory" + }, + "lib/images/cursors": { + "type": "directory" + }, + "lib/images/cursors/cursors.properties": { + "downloads": { + "lzma": { + "sha1": "612bd0f610ee1023947c4a2a8d3fc7d6f97e7d8f", + "size": 385, + "url": "https://launcher.mojang.com/v1/objects/612bd0f610ee1023947c4a2a8d3fc7d6f97e7d8f/cursors.properties" + }, + "raw": { + "sha1": "f2b9a22ddd0a77869497a64f28f07e89a7d41f48", + "size": 1274, + "url": "https://launcher.mojang.com/v1/objects/f2b9a22ddd0a77869497a64f28f07e89a7d41f48/cursors.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/cursors/invalid32x32.gif": { + "downloads": { + "raw": { + "sha1": "259edc45b4569427e8319895a444f4295d54348f", + "size": 153, + "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/cursors/motif_CopyDrop32x32.gif": { + "downloads": { + "raw": { + "sha1": "eb7620fae702172aa663a19d170a0b929d3b11d1", + "size": 158, + "url": "https://launcher.mojang.com/v1/objects/eb7620fae702172aa663a19d170a0b929d3b11d1/motif_CopyDrop32x32.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/cursors/motif_CopyNoDrop32x32.gif": { + "downloads": { + "raw": { + "sha1": "259edc45b4569427e8319895a444f4295d54348f", + "size": 153, + "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/cursors/motif_LinkDrop32x32.gif": { + "downloads": { + "raw": { + "sha1": "9699137f990c240e714481563181069c8f6c17bb", + "size": 162, + "url": "https://launcher.mojang.com/v1/objects/9699137f990c240e714481563181069c8f6c17bb/motif_LinkDrop32x32.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/cursors/motif_LinkNoDrop32x32.gif": { + "downloads": { + "raw": { + "sha1": "259edc45b4569427e8319895a444f4295d54348f", + "size": 153, + "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/cursors/motif_MoveDrop32x32.gif": { + "downloads": { + "raw": { + "sha1": "03c1617ce3c5ab8af03e46d30a8c8f31ab57fb1b", + "size": 141, + "url": "https://launcher.mojang.com/v1/objects/03c1617ce3c5ab8af03e46d30a8c8f31ab57fb1b/motif_MoveDrop32x32.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/cursors/motif_MoveNoDrop32x32.gif": { + "downloads": { + "raw": { + "sha1": "259edc45b4569427e8319895a444f4295d54348f", + "size": 153, + "url": "https://launcher.mojang.com/v1/objects/259edc45b4569427e8319895a444f4295d54348f/invalid32x32.gif" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/icons": { + "type": "directory" + }, + "lib/images/icons/sun-java.png": { + "downloads": { + "raw": { + "sha1": "d101b693aa054f51097eebdfeed8b8a6ca7b55b8", + "size": 4707, + "url": "https://launcher.mojang.com/v1/objects/d101b693aa054f51097eebdfeed8b8a6ca7b55b8/sun-java.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/icons/sun-java_HighContrast.png": { + "downloads": { + "raw": { + "sha1": "a6b1e418d6b5d03719b96f61f0c5236a60970151", + "size": 3729, + "url": "https://launcher.mojang.com/v1/objects/a6b1e418d6b5d03719b96f61f0c5236a60970151/sun-java_HighContrast.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/icons/sun-java_HighContrastInverse.png": { + "downloads": { + "raw": { + "sha1": "2dda28b9bddc9b5b018e3e8a8b062a99d9b2f887", + "size": 3777, + "url": + "https://launcher.mojang.com/v1/objects/2dda28b9bddc9b5b018e3e8a8b062a99d9b2f887/sun-java_HighContrastInverse.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/images/icons/sun-java_LowContrast.png": { + "downloads": { + "raw": { + "sha1": "7714cc4e894c3626c8da6fe742ed22b2829122d9", + "size": 4012, + "url": "https://launcher.mojang.com/v1/objects/7714cc4e894c3626c8da6fe742ed22b2829122d9/sun-java_LowContrast.png" + } + }, + "executable": false, + "type": "file" + }, + "lib/javafx.properties": { + "downloads": { + "raw": { + "sha1": "49e6b75d109e5fd3f6cbe7cc5fa9a7980796d14d", + "size": 56, + "url": "https://launcher.mojang.com/v1/objects/49e6b75d109e5fd3f6cbe7cc5fa9a7980796d14d/javafx.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/javaws.jar": { + "downloads": { + "raw": { + "sha1": "04fa5ae04ead65b91be5dee575497e49ffd49fe9", + "size": 488118, + "url": "https://launcher.mojang.com/v1/objects/04fa5ae04ead65b91be5dee575497e49ffd49fe9/javaws.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/jce.jar": { + "downloads": { + "raw": { + "sha1": "5460adee09cc5fc8829c0acfc46c34670a7d70a0", + "size": 115646, + "url": "https://launcher.mojang.com/v1/objects/5460adee09cc5fc8829c0acfc46c34670a7d70a0/jce.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/jexec": { + "downloads": { + "lzma": { + "sha1": "2d4323d4e060f8126d026ca6c03b8972aedd2fab", + "size": 3311, + "url": "https://launcher.mojang.com/v1/objects/2d4323d4e060f8126d026ca6c03b8972aedd2fab/jexec" + }, + "raw": { + "sha1": "6aa01f1d8d103974164bcfaea03c04eeeefd7d41", + "size": 13376, + "url": "https://launcher.mojang.com/v1/objects/6aa01f1d8d103974164bcfaea03c04eeeefd7d41/jexec" + } + }, + "executable": true, + "type": "file" + }, + "lib/jfr": { + "type": "directory" + }, + "lib/jfr.jar": { + "downloads": { + "lzma": { + "sha1": "5b9d615c91c72f4fe356d9b4105946679452d1e1", + "size": 137982, + "url": "https://launcher.mojang.com/v1/objects/5b9d615c91c72f4fe356d9b4105946679452d1e1/jfr.jar" + }, + "raw": { + "sha1": "0f3fd66a336703d935bdc22ad8082bc51d34e534", + "size": 560713, + "url": "https://launcher.mojang.com/v1/objects/0f3fd66a336703d935bdc22ad8082bc51d34e534/jfr.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/jfr/default.jfc": { + "downloads": { + "lzma": { + "sha1": "373ddd878146dd8ce8991c2c5115a05a82859bdb", + "size": 2207, + "url": "https://launcher.mojang.com/v1/objects/373ddd878146dd8ce8991c2c5115a05a82859bdb/default.jfc" + }, + "raw": { + "sha1": "1a64b68d0e7d43f8149faba94440be54f4f24527", + "size": 20109, + "url": "https://launcher.mojang.com/v1/objects/1a64b68d0e7d43f8149faba94440be54f4f24527/default.jfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/jfr/profile.jfc": { + "downloads": { + "lzma": { + "sha1": "3dcdc5feee3ccfb66bc8726b666944cd4bdadae3", + "size": 2199, + "url": "https://launcher.mojang.com/v1/objects/3dcdc5feee3ccfb66bc8726b666944cd4bdadae3/profile.jfc" + }, + "raw": { + "sha1": "5d7d08a595f76322c51ae43ea966fbba6b69eebe", + "size": 20065, + "url": "https://launcher.mojang.com/v1/objects/5d7d08a595f76322c51ae43ea966fbba6b69eebe/profile.jfc" + } + }, + "executable": false, + "type": "file" + }, + "lib/jfxswt.jar": { + "downloads": { + "raw": { + "sha1": "99d9a264c898d84c01e1c42565e7fe1a89dcd72d", + "size": 33932, + "url": "https://launcher.mojang.com/v1/objects/99d9a264c898d84c01e1c42565e7fe1a89dcd72d/jfxswt.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/jsse.jar": { + "downloads": { + "lzma": { + "sha1": "94a17dfbc2e76cd12c33970a15341424f875a9ce", + "size": 187549, + "url": "https://launcher.mojang.com/v1/objects/94a17dfbc2e76cd12c33970a15341424f875a9ce/jsse.jar" + }, + "raw": { + "sha1": "92c5c626e8a2d16f41272c0e404d4f992dd8310a", + "size": 675599, + "url": "https://launcher.mojang.com/v1/objects/92c5c626e8a2d16f41272c0e404d4f992dd8310a/jsse.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/jvm.hprof.txt": { + "downloads": { + "lzma": { + "sha1": "eccdb240a815b2a83a502749339b27bb8669965b", + "size": 1863, + "url": "https://launcher.mojang.com/v1/objects/eccdb240a815b2a83a502749339b27bb8669965b/jvm.hprof.txt" + }, + "raw": { + "sha1": "fbd61d52534cdd0c15df332114d469c65d001e33", + "size": 4226, + "url": "https://launcher.mojang.com/v1/objects/fbd61d52534cdd0c15df332114d469c65d001e33/jvm.hprof.txt" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale": { + "type": "directory" + }, + "lib/locale/de": { + "type": "directory" + }, + "lib/locale/de/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/de/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "3061d922907cc557208109088fc6ab81d577ff6f", + "size": 970, + "url": "https://launcher.mojang.com/v1/objects/3061d922907cc557208109088fc6ab81d577ff6f/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "5b223a3d723ac1cfce63623fb109f2868d47d1b7", + "size": 2483, + "url": "https://launcher.mojang.com/v1/objects/5b223a3d723ac1cfce63623fb109f2868d47d1b7/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/es": { + "type": "directory" + }, + "lib/locale/es/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/es/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "24338049a89b323e17182b3a3006b50565d4fa0f", + "size": 979, + "url": "https://launcher.mojang.com/v1/objects/24338049a89b323e17182b3a3006b50565d4fa0f/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "6cc63dc97f2fdb2ed799e48b1dc98c4f37cdecc1", + "size": 2477, + "url": "https://launcher.mojang.com/v1/objects/6cc63dc97f2fdb2ed799e48b1dc98c4f37cdecc1/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/fr": { + "type": "directory" + }, + "lib/locale/fr/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/fr/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "22796a48ef39f57d2d6fa70f41308e493d7f05c1", + "size": 1033, + "url": "https://launcher.mojang.com/v1/objects/22796a48ef39f57d2d6fa70f41308e493d7f05c1/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "d9d5b458db6e83fdf85c3526aeee3f57c4929840", + "size": 2746, + "url": "https://launcher.mojang.com/v1/objects/d9d5b458db6e83fdf85c3526aeee3f57c4929840/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/it": { + "type": "directory" + }, + "lib/locale/it/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/it/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "59a4cae38bfb8927745674d0efc2f284bc277987", + "size": 958, + "url": "https://launcher.mojang.com/v1/objects/59a4cae38bfb8927745674d0efc2f284bc277987/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "f6e72e3b2141ccc3dffab10ae14a754e494577ba", + "size": 2434, + "url": "https://launcher.mojang.com/v1/objects/f6e72e3b2141ccc3dffab10ae14a754e494577ba/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/ja": { + "type": "directory" + }, + "lib/locale/ja/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/ja/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "7d6aeed563e1cefcf0224cf522048468088884a9", + "size": 1036, + "url": "https://launcher.mojang.com/v1/objects/7d6aeed563e1cefcf0224cf522048468088884a9/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "378881a8cb8dd2aebb43eacd0c68519be4f258b1", + "size": 2415, + "url": "https://launcher.mojang.com/v1/objects/378881a8cb8dd2aebb43eacd0c68519be4f258b1/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/ko": { + "type": "directory" + }, + "lib/locale/ko.UTF-8": { + "type": "directory" + }, + "lib/locale/ko.UTF-8/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/ko.UTF-8/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "12ee3b21511e8497d95ea0ba9d6fe519227d0b16", + "size": 1069, + "url": "https://launcher.mojang.com/v1/objects/12ee3b21511e8497d95ea0ba9d6fe519227d0b16/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "cb19df01c59662dbe2f4050b1290d374b82fe1fa", + "size": 2753, + "url": "https://launcher.mojang.com/v1/objects/cb19df01c59662dbe2f4050b1290d374b82fe1fa/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/ko/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/ko/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "6e2e47c64c360517fd436bc79c823b5679a1efe6", + "size": 996, + "url": "https://launcher.mojang.com/v1/objects/6e2e47c64c360517fd436bc79c823b5679a1efe6/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "12c8a118d150c78f719314df6dec49a967af71e9", + "size": 2399, + "url": "https://launcher.mojang.com/v1/objects/12c8a118d150c78f719314df6dec49a967af71e9/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/pt_BR": { + "type": "directory" + }, + "lib/locale/pt_BR/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/pt_BR/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "bcaa7e7916493f071f1bf64bf58c6b038e3569c9", + "size": 940, + "url": "https://launcher.mojang.com/v1/objects/bcaa7e7916493f071f1bf64bf58c6b038e3569c9/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "a3bc0c43994c53c59bba94982cf95f6d36283dd0", + "size": 2420, + "url": "https://launcher.mojang.com/v1/objects/a3bc0c43994c53c59bba94982cf95f6d36283dd0/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/sv": { + "type": "directory" + }, + "lib/locale/sv/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/sv/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "76017835d6261fe2eedbcbe5eb08a7484c3080c5", + "size": 946, + "url": "https://launcher.mojang.com/v1/objects/76017835d6261fe2eedbcbe5eb08a7484c3080c5/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "09a47686edec4bbb34e82fbd08559f8bb6266544", + "size": 2359, + "url": "https://launcher.mojang.com/v1/objects/09a47686edec4bbb34e82fbd08559f8bb6266544/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/zh": { + "type": "directory" + }, + "lib/locale/zh.GBK": { + "type": "directory" + }, + "lib/locale/zh.GBK/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/zh.GBK/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "75fd04045bf5890b8bb822770bfdb90a2e9ea65b", + "size": 902, + "url": "https://launcher.mojang.com/v1/objects/75fd04045bf5890b8bb822770bfdb90a2e9ea65b/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "7006fe7767b8807441a1f359a90509b3e507b0d1", + "size": 2002, + "url": "https://launcher.mojang.com/v1/objects/7006fe7767b8807441a1f359a90509b3e507b0d1/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/zh/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/zh/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "75fd04045bf5890b8bb822770bfdb90a2e9ea65b", + "size": 902, + "url": "https://launcher.mojang.com/v1/objects/75fd04045bf5890b8bb822770bfdb90a2e9ea65b/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "7006fe7767b8807441a1f359a90509b3e507b0d1", + "size": 2002, + "url": "https://launcher.mojang.com/v1/objects/7006fe7767b8807441a1f359a90509b3e507b0d1/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/zh_HK.BIG5HK": { + "type": "directory" + }, + "lib/locale/zh_HK.BIG5HK/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/zh_HK.BIG5HK/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "3a1397bb1b1741697be1479232b6d9599940c851", + "size": 912, + "url": "https://launcher.mojang.com/v1/objects/3a1397bb1b1741697be1479232b6d9599940c851/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "c6023544067278c78599921f1032de353ff7da42", + "size": 2025, + "url": "https://launcher.mojang.com/v1/objects/c6023544067278c78599921f1032de353ff7da42/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/zh_TW": { + "type": "directory" + }, + "lib/locale/zh_TW.BIG5": { + "type": "directory" + }, + "lib/locale/zh_TW.BIG5/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/zh_TW.BIG5/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "3a1397bb1b1741697be1479232b6d9599940c851", + "size": 912, + "url": "https://launcher.mojang.com/v1/objects/3a1397bb1b1741697be1479232b6d9599940c851/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "c6023544067278c78599921f1032de353ff7da42", + "size": 2025, + "url": "https://launcher.mojang.com/v1/objects/c6023544067278c78599921f1032de353ff7da42/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/locale/zh_TW/LC_MESSAGES": { + "type": "directory" + }, + "lib/locale/zh_TW/LC_MESSAGES/sunw_java_plugin.mo": { + "downloads": { + "lzma": { + "sha1": "c05e610e75182f0c4e77f3e7a4d9670ed62bf63c", + "size": 897, + "url": "https://launcher.mojang.com/v1/objects/c05e610e75182f0c4e77f3e7a4d9670ed62bf63c/sunw_java_plugin.mo" + }, + "raw": { + "sha1": "f9b972dd059eae3cd337dfcef6a178e8ed8a7db6", + "size": 2025, + "url": "https://launcher.mojang.com/v1/objects/f9b972dd059eae3cd337dfcef6a178e8ed8a7db6/sunw_java_plugin.mo" + } + }, + "executable": false, + "type": "file" + }, + "lib/logging.properties": { + "downloads": { + "lzma": { + "sha1": "642202a58e5216d086ad37c0b5a633be802edc78", + "size": 896, + "url": "https://launcher.mojang.com/v1/objects/642202a58e5216d086ad37c0b5a633be802edc78/logging.properties" + }, + "raw": { + "sha1": "89da8094484891f9ec1fa40c6c8b61f94c5869d0", + "size": 2455, + "url": "https://launcher.mojang.com/v1/objects/89da8094484891f9ec1fa40c6c8b61f94c5869d0/logging.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/management": { + "type": "directory" + }, + "lib/management-agent.jar": { + "downloads": { + "lzma": { + "sha1": "3ea0bf17e14b3428296a0f4011bf4025fcbfa4bd", + "size": 243, + "url": "https://launcher.mojang.com/v1/objects/3ea0bf17e14b3428296a0f4011bf4025fcbfa4bd/management-agent.jar" + }, + "raw": { + "sha1": "9fbed36522aa3a80bac08a328942cbc5ef39ca8e", + "size": 381, + "url": "https://launcher.mojang.com/v1/objects/9fbed36522aa3a80bac08a328942cbc5ef39ca8e/management-agent.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/management/jmxremote.access": { + "downloads": { + "lzma": { + "sha1": "69042ff1b14165db19c9d728614639dec16d6a31", + "size": 1419, + "url": "https://launcher.mojang.com/v1/objects/69042ff1b14165db19c9d728614639dec16d6a31/jmxremote.access" + }, + "raw": { + "sha1": "21200eaad898ba4a2a8834a032efb6616fabb930", + "size": 3998, + "url": "https://launcher.mojang.com/v1/objects/21200eaad898ba4a2a8834a032efb6616fabb930/jmxremote.access" + } + }, + "executable": false, + "type": "file" + }, + "lib/management/jmxremote.password.template": { + "downloads": { + "lzma": { + "sha1": "556c64b1e920766f8867be3964de6e49f5b81a60", + "size": 1129, + "url": "https://launcher.mojang.com/v1/objects/556c64b1e920766f8867be3964de6e49f5b81a60/jmxremote.password.template" + }, + "raw": { + "sha1": "c1e0f01408bf20fbbb8b4810520c725f70050db5", + "size": 2856, + "url": "https://launcher.mojang.com/v1/objects/c1e0f01408bf20fbbb8b4810520c725f70050db5/jmxremote.password.template" + } + }, + "executable": false, + "type": "file" + }, + "lib/management/management.properties": { + "downloads": { + "lzma": { + "sha1": "3e52f9baa6394ca6956845424c607e5cde5d3c67", + "size": 3176, + "url": "https://launcher.mojang.com/v1/objects/3e52f9baa6394ca6956845424c607e5cde5d3c67/management.properties" + }, + "raw": { + "sha1": "e0451d8d7d9e84d7b1c39ec7d00993307a5cbbf1", + "size": 14630, + "url": "https://launcher.mojang.com/v1/objects/e0451d8d7d9e84d7b1c39ec7d00993307a5cbbf1/management.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/management/snmp.acl.template": { + "downloads": { + "lzma": { + "sha1": "9a4aa6396c3b488b0663bed5e5ecb762985669c9", + "size": 1121, + "url": "https://launcher.mojang.com/v1/objects/9a4aa6396c3b488b0663bed5e5ecb762985669c9/snmp.acl.template" + }, + "raw": { + "sha1": "2e9f9ac287274532eb1f0d1afcefd7f3e97cc794", + "size": 3376, + "url": "https://launcher.mojang.com/v1/objects/2e9f9ac287274532eb1f0d1afcefd7f3e97cc794/snmp.acl.template" + } + }, + "executable": false, + "type": "file" + }, + "lib/meta-index": { + "downloads": { + "lzma": { + "sha1": "1ac60b31362fda4725c665b591c5fbe384cbc8c1", + "size": 788, + "url": "https://launcher.mojang.com/v1/objects/1ac60b31362fda4725c665b591c5fbe384cbc8c1/meta-index" + }, + "raw": { + "sha1": "bf204f09242203e713c31785158a0792f9edb600", + "size": 2034, + "url": "https://launcher.mojang.com/v1/objects/bf204f09242203e713c31785158a0792f9edb600/meta-index" + } + }, + "executable": false, + "type": "file" + }, + "lib/net.properties": { + "downloads": { + "lzma": { + "sha1": "e9ec3981a0797bf55bb87b24d9eb651ce7e6916b", + "size": 1830, + "url": "https://launcher.mojang.com/v1/objects/e9ec3981a0797bf55bb87b24d9eb651ce7e6916b/net.properties" + }, + "raw": { + "sha1": "fd9471742eb759f4478bb1de9a0dc0527265b6ea", + "size": 5352, + "url": "https://launcher.mojang.com/v1/objects/fd9471742eb759f4478bb1de9a0dc0527265b6ea/net.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/oblique-fonts": { + "type": "directory" + }, + "lib/oblique-fonts/LucidaSansDemiOblique.ttf": { + "downloads": { + "lzma": { + "sha1": "49c8980c1b89bbdbab59d0f5bd5bebf0afcb93b2", + "size": 38580, + "url": "https://launcher.mojang.com/v1/objects/49c8980c1b89bbdbab59d0f5bd5bebf0afcb93b2/LucidaSansDemiOblique.ttf" + }, + "raw": { + "sha1": "53e4e12a675ac222469341c3dbc102464a1be4c7", + "size": 91352, + "url": "https://launcher.mojang.com/v1/objects/53e4e12a675ac222469341c3dbc102464a1be4c7/LucidaSansDemiOblique.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/oblique-fonts/LucidaSansOblique.ttf": { + "downloads": { + "lzma": { + "sha1": "553123c0edcd08035dede4ffd92b5b81c9a7538a", + "size": 116575, + "url": "https://launcher.mojang.com/v1/objects/553123c0edcd08035dede4ffd92b5b81c9a7538a/LucidaSansOblique.ttf" + }, + "raw": { + "sha1": "95a195ad4fc520b3e395c85b747fc3024d118dd9", + "size": 253724, + "url": "https://launcher.mojang.com/v1/objects/95a195ad4fc520b3e395c85b747fc3024d118dd9/LucidaSansOblique.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/oblique-fonts/LucidaTypewriterBoldOblique.ttf": { + "downloads": { + "lzma": { + "sha1": "2475b08151556ad4d89bb1d2b6494c6bee9abd82", + "size": 29954, + "url": "https://launcher.mojang.com/v1/objects/2475b08151556ad4d89bb1d2b6494c6bee9abd82/LucidaTypewriterBoldOblique.ttf" + }, + "raw": { + "sha1": "f331fc8b0cc494702bc46b690f2b8eed36469a02", + "size": 63168, + "url": "https://launcher.mojang.com/v1/objects/f331fc8b0cc494702bc46b690f2b8eed36469a02/LucidaTypewriterBoldOblique.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/oblique-fonts/LucidaTypewriterOblique.ttf": { + "downloads": { + "lzma": { + "sha1": "5b970bc3b7abb21dce1aa28ff7f03459d351e552", + "size": 60133, + "url": "https://launcher.mojang.com/v1/objects/5b970bc3b7abb21dce1aa28ff7f03459d351e552/LucidaTypewriterOblique.ttf" + }, + "raw": { + "sha1": "f8ea00db73f8a89a27674d050edc37c2280930e1", + "size": 137484, + "url": "https://launcher.mojang.com/v1/objects/f8ea00db73f8a89a27674d050edc37c2280930e1/LucidaTypewriterOblique.ttf" + } + }, + "executable": false, + "type": "file" + }, + "lib/oblique-fonts/fonts.dir": { + "downloads": { + "lzma": { + "sha1": "067528c789bd713c7c3f34e779aa6e2e8253dcf6", + "size": 188, + "url": "https://launcher.mojang.com/v1/objects/067528c789bd713c7c3f34e779aa6e2e8253dcf6/fonts.dir" + }, + "raw": { + "sha1": "5aee54ffba9e33de56fd84ef64fa496b898585bb", + "size": 2115, + "url": "https://launcher.mojang.com/v1/objects/5aee54ffba9e33de56fd84ef64fa496b898585bb/fonts.dir" + } + }, + "executable": false, + "type": "file" + }, + "lib/plugin.jar": { + "downloads": { + "raw": { + "sha1": "3f250842c79112bae5369e372025b166990820e8", + "size": 950772, + "url": "https://launcher.mojang.com/v1/objects/3f250842c79112bae5369e372025b166990820e8/plugin.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/psfont.properties.ja": { + "downloads": { + "lzma": { + "sha1": "7ca1cc244ed251cd1eb2347f1eea37d7d18c8ad4", + "size": 701, + "url": "https://launcher.mojang.com/v1/objects/7ca1cc244ed251cd1eb2347f1eea37d7d18c8ad4/psfont.properties.ja" + }, + "raw": { + "sha1": "56ed1c661eeede17b4fae8c9de7b5edbad387abc", + "size": 2796, + "url": "https://launcher.mojang.com/v1/objects/56ed1c661eeede17b4fae8c9de7b5edbad387abc/psfont.properties.ja" + } + }, + "executable": false, + "type": "file" + }, + "lib/psfontj2d.properties": { + "downloads": { + "lzma": { + "sha1": "4252fa01af8739a3545e2b705e3383892e22ab40", + "size": 2278, + "url": "https://launcher.mojang.com/v1/objects/4252fa01af8739a3545e2b705e3383892e22ab40/psfontj2d.properties" + }, + "raw": { + "sha1": "aa327a22a49967f4d74afeee6726f505f209692f", + "size": 10393, + "url": "https://launcher.mojang.com/v1/objects/aa327a22a49967f4d74afeee6726f505f209692f/psfontj2d.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/resources.jar": { + "downloads": { + "lzma": { + "sha1": "1b0e08441750dc17efe4b527aa146da6cc14e8a6", + "size": 579294, + "url": "https://launcher.mojang.com/v1/objects/1b0e08441750dc17efe4b527aa146da6cc14e8a6/resources.jar" + }, + "raw": { + "sha1": "daa021906e4648d4c37e798c11733dc2047f2da1", + "size": 3505206, + "url": "https://launcher.mojang.com/v1/objects/daa021906e4648d4c37e798c11733dc2047f2da1/resources.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/rt.jar": { + "downloads": { + "lzma": { + "sha1": "fc4a8681aeda29c2a2a3fd11bad7729543283f3d", + "size": 14378994, + "url": "https://launcher.mojang.com/v1/objects/fc4a8681aeda29c2a2a3fd11bad7729543283f3d/rt.jar" + }, + "raw": { + "sha1": "5396b0954a20f3210f1f4f1886ead30880d6ebfe", + "size": 66334986, + "url": "https://launcher.mojang.com/v1/objects/5396b0954a20f3210f1f4f1886ead30880d6ebfe/rt.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/security": { + "type": "directory" + }, + "lib/security/blacklist": { + "downloads": { + "lzma": { + "sha1": "8206fce6c1d91a39fdf78e8e79e953913994a1cd", + "size": 1969, + "url": "https://launcher.mojang.com/v1/objects/8206fce6c1d91a39fdf78e8e79e953913994a1cd/blacklist" + }, + "raw": { + "sha1": "d4ffb3857eab403955ce9d156e46d056061e6a5a", + "size": 4054, + "url": "https://launcher.mojang.com/v1/objects/d4ffb3857eab403955ce9d156e46d056061e6a5a/blacklist" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/blacklisted.certs": { + "downloads": { + "lzma": { + "sha1": "8311bead054caf6cfe678d4b7998de4caaabfa53", + "size": 806, + "url": "https://launcher.mojang.com/v1/objects/8311bead054caf6cfe678d4b7998de4caaabfa53/blacklisted.certs" + }, + "raw": { + "sha1": "c5c005c29a80493f5c31cd7eb629ac1b9c752404", + "size": 1273, + "url": "https://launcher.mojang.com/v1/objects/c5c005c29a80493f5c31cd7eb629ac1b9c752404/blacklisted.certs" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/cacerts": { + "downloads": { + "lzma": { + "sha1": "654dd94809655d5b28385cbb5eba8d6ad9f2c1aa", + "size": 67802, + "url": "https://launcher.mojang.com/v1/objects/654dd94809655d5b28385cbb5eba8d6ad9f2c1aa/cacerts" + }, + "raw": { + "sha1": "2917859c443c68e19f93abcd1315c3c2904cbef9", + "size": 104430, + "url": "https://launcher.mojang.com/v1/objects/2917859c443c68e19f93abcd1315c3c2904cbef9/cacerts" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/java.policy": { + "downloads": { + "lzma": { + "sha1": "b601c420d02ef3dbd8595453d08fdef91134e8b5", + "size": 647, + "url": "https://launcher.mojang.com/v1/objects/b601c420d02ef3dbd8595453d08fdef91134e8b5/java.policy" + }, + "raw": { + "sha1": "c0112209a567b3b523cfed7041709f9440227968", + "size": 2466, + "url": "https://launcher.mojang.com/v1/objects/c0112209a567b3b523cfed7041709f9440227968/java.policy" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/java.security": { + "downloads": { + "lzma": { + "sha1": "531620e82ca0365ce8dc97096bb0ac5a7ace5952", + "size": 10959, + "url": "https://launcher.mojang.com/v1/objects/531620e82ca0365ce8dc97096bb0ac5a7ace5952/java.security" + }, + "raw": { + "sha1": "5dcc17a168c53d0b366784e520bd4d55aa61ac18", + "size": 41528, + "url": "https://launcher.mojang.com/v1/objects/5dcc17a168c53d0b366784e520bd4d55aa61ac18/java.security" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/javaws.policy": { + "downloads": { + "raw": { + "sha1": "4384ca5e4d32f7dd86d8baddd1e690730d74e694", + "size": 98, + "url": "https://launcher.mojang.com/v1/objects/4384ca5e4d32f7dd86d8baddd1e690730d74e694/javaws.policy" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/policy": { + "type": "directory" + }, + "lib/security/policy/limited": { + "type": "directory" + }, + "lib/security/policy/limited/US_export_policy.jar": { + "downloads": { + "raw": { + "sha1": "7d69ea3b385bc067738520f1b5c549e1084be285", + "size": 3026, + "url": "https://launcher.mojang.com/v1/objects/7d69ea3b385bc067738520f1b5c549e1084be285/US_export_policy.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/policy/limited/local_policy.jar": { + "downloads": { + "raw": { + "sha1": "238b8826e110f58acb2e1959773b0a577cd4d569", + "size": 3527, + "url": "https://launcher.mojang.com/v1/objects/238b8826e110f58acb2e1959773b0a577cd4d569/local_policy.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/policy/unlimited": { + "type": "directory" + }, + "lib/security/policy/unlimited/US_export_policy.jar": { + "downloads": { + "raw": { + "sha1": "f6fb2af1e87fc622cda194a7d6b5f5f069653ff1", + "size": 3023, + "url": "https://launcher.mojang.com/v1/objects/f6fb2af1e87fc622cda194a7d6b5f5f069653ff1/US_export_policy.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/policy/unlimited/local_policy.jar": { + "downloads": { + "raw": { + "sha1": "517368ab2cbaf6b42ea0b963f98eeedd996e83e3", + "size": 3035, + "url": "https://launcher.mojang.com/v1/objects/517368ab2cbaf6b42ea0b963f98eeedd996e83e3/local_policy.jar" + } + }, + "executable": false, + "type": "file" + }, + "lib/security/trusted.libraries": { + "downloads": { + "raw": { + "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "size": 0, + "url": "https://launcher.mojang.com/v1/objects/da39a3ee5e6b4b0d3255bfef95601890afd80709/trusted.libraries" + } + }, + "executable": false, + "type": "file" + }, + "lib/sound.properties": { + "downloads": { + "lzma": { + "sha1": "3b5f7e4ec437d79048af35094290577f483b3fe1", + "size": 473, + "url": "https://launcher.mojang.com/v1/objects/3b5f7e4ec437d79048af35094290577f483b3fe1/sound.properties" + }, + "raw": { + "sha1": "9afceb218059d981d0fa9f07aad3c5097cf41b0c", + "size": 1210, + "url": "https://launcher.mojang.com/v1/objects/9afceb218059d981d0fa9f07aad3c5097cf41b0c/sound.properties" + } + }, + "executable": false, + "type": "file" + }, + "lib/tzdb.dat": { + "downloads": { + "lzma": { + "sha1": "39c69339965484afe89c14111baeeb862fdefd97", + "size": 32547, + "url": "https://launcher.mojang.com/v1/objects/39c69339965484afe89c14111baeeb862fdefd97/tzdb.dat" + }, + "raw": { + "sha1": "b59c07e3619271a3b9861e999f4b138e971baf69", + "size": 105734, + "url": "https://launcher.mojang.com/v1/objects/b59c07e3619271a3b9861e999f4b138e971baf69/tzdb.dat" + } + }, + "executable": false, + "type": "file" + }, + "man": { + "type": "directory" + }, + "man/ja": { + "target": "ja_JP.UTF-8", + "type": "link" + }, + "man/ja_JP.UTF-8": { + "type": "directory" + }, + "man/ja_JP.UTF-8/man1": { + "type": "directory" + }, + "man/ja_JP.UTF-8/man1/java.1": { + "downloads": { + "lzma": { + "sha1": "f9da09710b6c6df23c256e324a0c4df00a0d6ded", + "size": 25461, + "url": "https://launcher.mojang.com/v1/objects/f9da09710b6c6df23c256e324a0c4df00a0d6ded/java.1" + }, + "raw": { + "sha1": "b0b12a0bb66e6171771ca4b1dfca32fb759bcaec", + "size": 148688, + "url": "https://launcher.mojang.com/v1/objects/b0b12a0bb66e6171771ca4b1dfca32fb759bcaec/java.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/javaws.1": { + "downloads": { + "lzma": { + "sha1": "6188fae453ca09ccb19be5c9f4d2059926b36267", + "size": 2154, + "url": "https://launcher.mojang.com/v1/objects/6188fae453ca09ccb19be5c9f4d2059926b36267/javaws.1" + }, + "raw": { + "sha1": "8f39d928870268ace07bedfebd18db1e1d07fc37", + "size": 6641, + "url": "https://launcher.mojang.com/v1/objects/8f39d928870268ace07bedfebd18db1e1d07fc37/javaws.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/jjs.1": { + "downloads": { + "lzma": { + "sha1": "6e42b989d28b185dc1aab50c0389834e649a37d4", + "size": 3452, + "url": "https://launcher.mojang.com/v1/objects/6e42b989d28b185dc1aab50c0389834e649a37d4/jjs.1" + }, + "raw": { + "sha1": "e023322a2013912315a2bd1034e6f829a27c76e0", + "size": 11365, + "url": "https://launcher.mojang.com/v1/objects/e023322a2013912315a2bd1034e6f829a27c76e0/jjs.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/keytool.1": { + "downloads": { + "lzma": { + "sha1": "a78134a4bddd53d684a70aa677e51a215db1c9cb", + "size": 20698, + "url": "https://launcher.mojang.com/v1/objects/a78134a4bddd53d684a70aa677e51a215db1c9cb/keytool.1" + }, + "raw": { + "sha1": "148583c837eaaf6333ccfd8c9e8df08574e14b0c", + "size": 111033, + "url": "https://launcher.mojang.com/v1/objects/148583c837eaaf6333ccfd8c9e8df08574e14b0c/keytool.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/orbd.1": { + "downloads": { + "lzma": { + "sha1": "326af0dcbff173ef8aee29163dbe146d7389cc3e", + "size": 4225, + "url": "https://launcher.mojang.com/v1/objects/326af0dcbff173ef8aee29163dbe146d7389cc3e/orbd.1" + }, + "raw": { + "sha1": "95651622d33c08286858ec337edd3ea72acd93dc", + "size": 16092, + "url": "https://launcher.mojang.com/v1/objects/95651622d33c08286858ec337edd3ea72acd93dc/orbd.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/pack200.1": { + "downloads": { + "lzma": { + "sha1": "e0eedafa748c61a44e5be4355fe9d44b05048e80", + "size": 4293, + "url": "https://launcher.mojang.com/v1/objects/e0eedafa748c61a44e5be4355fe9d44b05048e80/pack200.1" + }, + "raw": { + "sha1": "aa21a0ab75707f7fc66e83c7a392e69b37ddf80e", + "size": 14482, + "url": "https://launcher.mojang.com/v1/objects/aa21a0ab75707f7fc66e83c7a392e69b37ddf80e/pack200.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/policytool.1": { + "downloads": { + "lzma": { + "sha1": "3c766ed12dab58166169d35680c392a6be1814a1", + "size": 1380, + "url": "https://launcher.mojang.com/v1/objects/3c766ed12dab58166169d35680c392a6be1814a1/policytool.1" + }, + "raw": { + "sha1": "80879c74e072a98fad6f32b3283331aaf9bd002f", + "size": 4020, + "url": "https://launcher.mojang.com/v1/objects/80879c74e072a98fad6f32b3283331aaf9bd002f/policytool.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/rmid.1": { + "downloads": { + "lzma": { + "sha1": "1e20779d990beacc32a48237777d670fcc47ca14", + "size": 4836, + "url": "https://launcher.mojang.com/v1/objects/1e20779d990beacc32a48237777d670fcc47ca14/rmid.1" + }, + "raw": { + "sha1": "7e40cb8003d098d6e36f45640b26f979ac94b5c5", + "size": 19715, + "url": "https://launcher.mojang.com/v1/objects/7e40cb8003d098d6e36f45640b26f979ac94b5c5/rmid.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/rmiregistry.1": { + "downloads": { + "lzma": { + "sha1": "aaf4ffe07e954f8696eef1ecb7a5e244628d0ad9", + "size": 1627, + "url": "https://launcher.mojang.com/v1/objects/aaf4ffe07e954f8696eef1ecb7a5e244628d0ad9/rmiregistry.1" + }, + "raw": { + "sha1": "c53c52f3ae7a011c135894c9fc51b741e729c33d", + "size": 4557, + "url": "https://launcher.mojang.com/v1/objects/c53c52f3ae7a011c135894c9fc51b741e729c33d/rmiregistry.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/servertool.1": { + "downloads": { + "lzma": { + "sha1": "3b9e624e9d1cf2959b438a35061162e2100ddecd", + "size": 2626, + "url": "https://launcher.mojang.com/v1/objects/3b9e624e9d1cf2959b438a35061162e2100ddecd/servertool.1" + }, + "raw": { + "sha1": "50ab8bcd9dd9d0b1a3d81348fbce1c8f82e7189e", + "size": 9081, + "url": "https://launcher.mojang.com/v1/objects/50ab8bcd9dd9d0b1a3d81348fbce1c8f82e7189e/servertool.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/tnameserv.1": { + "downloads": { + "lzma": { + "sha1": "bb3106ff74c60a76de3d20659b9c2128c70f3bf2", + "size": 4478, + "url": "https://launcher.mojang.com/v1/objects/bb3106ff74c60a76de3d20659b9c2128c70f3bf2/tnameserv.1" + }, + "raw": { + "sha1": "01e714671ecd1167edcb5310b16a9c59c33c3eaa", + "size": 17722, + "url": "https://launcher.mojang.com/v1/objects/01e714671ecd1167edcb5310b16a9c59c33c3eaa/tnameserv.1" + } + }, + "executable": false, + "type": "file" + }, + "man/ja_JP.UTF-8/man1/unpack200.1": { + "downloads": { + "lzma": { + "sha1": "c115a881cf800b08df294df55d9f250ae944e33c", + "size": 1973, + "url": "https://launcher.mojang.com/v1/objects/c115a881cf800b08df294df55d9f250ae944e33c/unpack200.1" + }, + "raw": { + "sha1": "7c882bba0067367a41ad84868d18793b8a7397a3", + "size": 5382, + "url": "https://launcher.mojang.com/v1/objects/7c882bba0067367a41ad84868d18793b8a7397a3/unpack200.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1": { + "type": "directory" + }, + "man/man1/java.1": { + "downloads": { + "lzma": { + "sha1": "06a6b0275c202bf698d73ca71f95618d56d81c15", + "size": 25796, + "url": "https://launcher.mojang.com/v1/objects/06a6b0275c202bf698d73ca71f95618d56d81c15/java.1" + }, + "raw": { + "sha1": "69fec7a341aa91f18dbdcdb95952dede7e1b689a", + "size": 124796, + "url": "https://launcher.mojang.com/v1/objects/69fec7a341aa91f18dbdcdb95952dede7e1b689a/java.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/javaws.1": { + "downloads": { + "lzma": { + "sha1": "4bae251c6dfb5420f56928815cf80d0b6d517a1f", + "size": 1759, + "url": "https://launcher.mojang.com/v1/objects/4bae251c6dfb5420f56928815cf80d0b6d517a1f/javaws.1" + }, + "raw": { + "sha1": "e61e44e101b1bc119c2d2d4b10320f38b36a8036", + "size": 4897, + "url": "https://launcher.mojang.com/v1/objects/e61e44e101b1bc119c2d2d4b10320f38b36a8036/javaws.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/jjs.1": { + "downloads": { + "lzma": { + "sha1": "29683cf2bd47015c9461b688749ddffd95f6671d", + "size": 1881, + "url": "https://launcher.mojang.com/v1/objects/29683cf2bd47015c9461b688749ddffd95f6671d/jjs.1" + }, + "raw": { + "sha1": "78d419bd3a7f3e0802d5220e690429194b5d1beb", + "size": 4932, + "url": "https://launcher.mojang.com/v1/objects/78d419bd3a7f3e0802d5220e690429194b5d1beb/jjs.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/keytool.1": { + "downloads": { + "lzma": { + "sha1": "b67e5126d43713ee3675706724b34061578b42db", + "size": 19690, + "url": "https://launcher.mojang.com/v1/objects/b67e5126d43713ee3675706724b34061578b42db/keytool.1" + }, + "raw": { + "sha1": "4c976f86057ab779763fcfb98f5702ebef47f629", + "size": 86925, + "url": "https://launcher.mojang.com/v1/objects/4c976f86057ab779763fcfb98f5702ebef47f629/keytool.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/orbd.1": { + "downloads": { + "lzma": { + "sha1": "147064d6f7e027002e296bb246ae572d0ce0495b", + "size": 3708, + "url": "https://launcher.mojang.com/v1/objects/147064d6f7e027002e296bb246ae572d0ce0495b/orbd.1" + }, + "raw": { + "sha1": "64201e1846fcf1dcc45c786ffeab89426d1c7742", + "size": 12180, + "url": "https://launcher.mojang.com/v1/objects/64201e1846fcf1dcc45c786ffeab89426d1c7742/orbd.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/pack200.1": { + "downloads": { + "lzma": { + "sha1": "fe17486bbe9c58cf4182fa056b9cd124e8295607", + "size": 3724, + "url": "https://launcher.mojang.com/v1/objects/fe17486bbe9c58cf4182fa056b9cd124e8295607/pack200.1" + }, + "raw": { + "sha1": "26826cf52b89924f2d2a60d6cda798891875eae6", + "size": 11623, + "url": "https://launcher.mojang.com/v1/objects/26826cf52b89924f2d2a60d6cda798891875eae6/pack200.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/policytool.1": { + "downloads": { + "lzma": { + "sha1": "bd154e7c39aca71d15b2098c588866f8d95bc743", + "size": 1122, + "url": "https://launcher.mojang.com/v1/objects/bd154e7c39aca71d15b2098c588866f8d95bc743/policytool.1" + }, + "raw": { + "sha1": "ab296625155d9a2b25ecc2b4feff2f741b3ad136", + "size": 3235, + "url": "https://launcher.mojang.com/v1/objects/ab296625155d9a2b25ecc2b4feff2f741b3ad136/policytool.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/rmid.1": { + "downloads": { + "lzma": { + "sha1": "6a7da234e7f43ebca5c4ba8cd862fda3be62fbaa", + "size": 4255, + "url": "https://launcher.mojang.com/v1/objects/6a7da234e7f43ebca5c4ba8cd862fda3be62fbaa/rmid.1" + }, + "raw": { + "sha1": "6f10e214d7950a6a8460524e41dc700f112f89e5", + "size": 15979, + "url": "https://launcher.mojang.com/v1/objects/6f10e214d7950a6a8460524e41dc700f112f89e5/rmid.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/rmiregistry.1": { + "downloads": { + "lzma": { + "sha1": "f40dd17e3a734600ad1828b0c42d3a1685c4c520", + "size": 1301, + "url": "https://launcher.mojang.com/v1/objects/f40dd17e3a734600ad1828b0c42d3a1685c4c520/rmiregistry.1" + }, + "raw": { + "sha1": "d9a3d23fab689df5bb9a792b88f462f939b49f70", + "size": 3449, + "url": "https://launcher.mojang.com/v1/objects/d9a3d23fab689df5bb9a792b88f462f939b49f70/rmiregistry.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/servertool.1": { + "downloads": { + "lzma": { + "sha1": "74f1e10712202cd3ca0ff5833de05b7ee67092e1", + "size": 2307, + "url": "https://launcher.mojang.com/v1/objects/74f1e10712202cd3ca0ff5833de05b7ee67092e1/servertool.1" + }, + "raw": { + "sha1": "e6c7b510740ac8681a9bfb5f4ee1f0306125b728", + "size": 7237, + "url": "https://launcher.mojang.com/v1/objects/e6c7b510740ac8681a9bfb5f4ee1f0306125b728/servertool.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/tnameserv.1": { + "downloads": { + "lzma": { + "sha1": "4bec7f4e070d023f124f9352a8971d7acd249a15", + "size": 3955, + "url": "https://launcher.mojang.com/v1/objects/4bec7f4e070d023f124f9352a8971d7acd249a15/tnameserv.1" + }, + "raw": { + "sha1": "a31dbbe800d49cb371fab9a4b73d22c3bf8799ad", + "size": 15747, + "url": "https://launcher.mojang.com/v1/objects/a31dbbe800d49cb371fab9a4b73d22c3bf8799ad/tnameserv.1" + } + }, + "executable": false, + "type": "file" + }, + "man/man1/unpack200.1": { + "downloads": { + "lzma": { + "sha1": "f8e73863187929debf2ea6dadefb2995ec7917e7", + "size": 1672, + "url": "https://launcher.mojang.com/v1/objects/f8e73863187929debf2ea6dadefb2995ec7917e7/unpack200.1" + }, + "raw": { + "sha1": "437f7233d738cb9b822e99003127049005663e0f", + "size": 4244, + "url": "https://launcher.mojang.com/v1/objects/437f7233d738cb9b822e99003127049005663e0f/unpack200.1" + } + }, + "executable": false, + "type": "file" + }, + "plugin": { + "type": "directory" + }, + "plugin/desktop": { + "type": "directory" + }, + "plugin/desktop/sun_java.desktop": { + "downloads": { + "lzma": { + "sha1": "49ab0ccb54c3be68281d05055bc56a88b1281d3c", + "size": 447, + "url": "https://launcher.mojang.com/v1/objects/49ab0ccb54c3be68281d05055bc56a88b1281d3c/sun_java.desktop" + }, + "raw": { + "sha1": "79120ee8160ad6f3c9b90c2641fb7edf3af96b5d", + "size": 624, + "url": "https://launcher.mojang.com/v1/objects/79120ee8160ad6f3c9b90c2641fb7edf3af96b5d/sun_java.desktop" + } + }, + "executable": false, + "type": "file" + }, + "plugin/desktop/sun_java.png": { + "downloads": { + "raw": { + "sha1": "699c41e97a35414e72a80327a54d6e14e874e951", + "size": 4351, + "url": "https://launcher.mojang.com/v1/objects/699c41e97a35414e72a80327a54d6e14e874e951/sun_java.png" + } + }, + "executable": false, + "type": "file" + }, + "release": { + "downloads": { + "raw": { + "sha1": "cb462682644c0275d94a45b759108815f3112064", + "size": 424, + "url": "https://launcher.mojang.com/v1/objects/cb462682644c0275d94a45b759108815f3112064/release" + } + }, + "executable": false, + "type": "file" + } + } +} \ No newline at end of file From 215d7dbb741de9516ab5f00acb7b699adff82cab Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 4 Aug 2023 19:41:47 +0200 Subject: [PATCH 229/398] chore: update license headers Signed-off-by: Sefa Eyeoglu --- buildconfig/BuildConfig.cpp.in | 2 +- launcher/ApplicationMessage.cpp | 2 +- launcher/BaseInstance.cpp | 2 +- launcher/BaseInstance.h | 2 +- launcher/BaseVersionList.cpp | 2 +- launcher/Commandline.cpp | 2 +- launcher/DesktopServices.cpp | 2 +- launcher/GZip.cpp | 2 +- launcher/InstanceImportTask.cpp | 2 +- launcher/InstanceImportTask.h | 2 +- launcher/InstanceList.cpp | 2 +- launcher/JavaCommon.cpp | 2 +- launcher/Json.cpp | 2 +- launcher/Json.h | 2 +- launcher/LaunchController.cpp | 2 +- launcher/LaunchController.h | 2 +- launcher/NullInstance.h | 2 +- launcher/RuntimeContext.h | 2 +- launcher/Version.h | 2 +- launcher/java/JavaChecker.cpp | 2 +- launcher/java/JavaUtils.cpp | 2 +- launcher/launch/LaunchTask.cpp | 2 +- launcher/launch/LaunchTask.h | 2 +- launcher/launch/steps/CheckJava.cpp | 2 +- launcher/launch/steps/PostLaunchCommand.cpp | 2 +- launcher/launch/steps/PreLaunchCommand.cpp | 2 +- launcher/launch/steps/QuitAfterGameStop.cpp | 2 +- launcher/launch/steps/QuitAfterGameStop.h | 2 +- launcher/main.cpp | 2 +- launcher/minecraft/AssetsUtils.cpp | 2 +- launcher/minecraft/Component.cpp | 2 +- launcher/minecraft/GradleSpecifier.h | 2 +- launcher/minecraft/LaunchProfile.cpp | 2 +- launcher/minecraft/LaunchProfile.h | 2 +- launcher/minecraft/Library.cpp | 2 +- launcher/minecraft/Library.h | 2 +- launcher/minecraft/MojangVersionFormat.cpp | 2 +- launcher/minecraft/OneSixVersionFormat.cpp | 2 +- launcher/minecraft/ProfileUtils.cpp | 2 +- launcher/minecraft/ProfileUtils.h | 2 +- launcher/minecraft/Rule.cpp | 2 +- launcher/minecraft/Rule.h | 2 +- launcher/minecraft/VersionFile.cpp | 2 +- launcher/minecraft/VersionFile.h | 2 +- launcher/minecraft/WorldList.cpp | 2 +- launcher/minecraft/auth/AccountData.cpp | 2 +- launcher/minecraft/auth/AccountData.h | 2 +- launcher/minecraft/auth/AccountList.cpp | 2 +- launcher/minecraft/auth/AccountList.h | 2 +- launcher/minecraft/auth/AccountTask.cpp | 2 +- launcher/minecraft/auth/AccountTask.h | 2 +- launcher/minecraft/auth/AuthRequest.cpp | 2 +- launcher/minecraft/auth/MinecraftAccount.cpp | 2 +- launcher/minecraft/auth/MinecraftAccount.h | 2 +- launcher/minecraft/auth/steps/MSAStep.cpp | 2 +- launcher/minecraft/auth/steps/MSAStep.h | 2 +- launcher/minecraft/launch/LauncherPartLaunch.cpp | 2 +- launcher/minecraft/launch/ModMinecraftJar.cpp | 2 +- launcher/minecraft/launch/ScanModFolders.cpp | 2 +- launcher/minecraft/launch/VerifyJavaInstall.cpp | 2 +- launcher/minecraft/launch/VerifyJavaInstall.h | 2 +- launcher/minecraft/mod/MetadataHandler.h | 2 +- launcher/minecraft/mod/Mod.cpp | 2 +- launcher/minecraft/mod/Mod.h | 2 +- launcher/minecraft/mod/ModDetails.h | 2 +- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ModFolderModel.h | 2 +- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/TexturePack.cpp | 2 +- launcher/minecraft/mod/TexturePack.h | 2 +- launcher/minecraft/mod/TexturePackFolderModel.cpp | 2 +- launcher/minecraft/mod/TexturePackFolderModel.h | 2 +- launcher/minecraft/mod/tasks/LocalModUpdateTask.h | 2 +- launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp | 2 +- launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h | 2 +- launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp | 2 +- launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h | 2 +- launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 2 +- launcher/minecraft/mod/tasks/ModFolderLoadTask.h | 2 +- launcher/minecraft/services/CapeChange.cpp | 2 +- launcher/minecraft/services/SkinDelete.cpp | 2 +- launcher/minecraft/services/SkinUpload.cpp | 2 +- launcher/minecraft/update/FoldersTask.cpp | 2 +- launcher/modplatform/ModIndex.cpp | 2 +- launcher/modplatform/ResourceAPI.h | 2 +- launcher/modplatform/atlauncher/ATLPackInstallTask.cpp | 2 +- launcher/modplatform/atlauncher/ATLPackInstallTask.h | 2 +- launcher/modplatform/atlauncher/ATLPackManifest.cpp | 2 +- launcher/modplatform/atlauncher/ATLPackManifest.h | 2 +- launcher/modplatform/atlauncher/ATLShareCode.cpp | 2 +- launcher/modplatform/atlauncher/ATLShareCode.h | 2 +- launcher/modplatform/flame/PackManifest.h | 2 +- launcher/modplatform/legacy_ftb/PackFetchTask.cpp | 2 +- launcher/modplatform/legacy_ftb/PackInstallTask.cpp | 2 +- launcher/modplatform/legacy_ftb/PrivatePackManager.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackIndex.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackIndex.h | 2 +- launcher/modplatform/modrinth/ModrinthPackManifest.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackManifest.h | 2 +- launcher/modplatform/packwiz/Packwiz.cpp | 2 +- launcher/modplatform/packwiz/Packwiz.h | 2 +- launcher/modplatform/technic/SolderPackInstallTask.cpp | 2 +- launcher/modplatform/technic/SolderPackInstallTask.h | 2 +- launcher/modplatform/technic/SolderPackManifest.cpp | 2 +- launcher/modplatform/technic/SolderPackManifest.h | 2 +- launcher/net/ChecksumValidator.h | 2 +- launcher/net/NetUtils.h | 2 +- launcher/net/Sink.h | 2 +- launcher/net/Validator.h | 2 +- launcher/news/NewsChecker.cpp | 2 +- launcher/screenshots/ImgurAlbumCreation.cpp | 2 +- launcher/screenshots/ImgurAlbumCreation.h | 2 +- launcher/screenshots/ImgurUpload.cpp | 2 +- launcher/screenshots/ImgurUpload.h | 2 +- launcher/tasks/Task.cpp | 2 +- launcher/translations/TranslationsModel.cpp | 2 +- launcher/ui/dialogs/AboutDialog.cpp | 2 +- launcher/ui/dialogs/CopyInstanceDialog.cpp | 2 +- launcher/ui/dialogs/MSALoginDialog.cpp | 2 +- launcher/ui/dialogs/NewComponentDialog.cpp | 2 +- launcher/ui/dialogs/NewInstanceDialog.cpp | 2 +- launcher/ui/dialogs/NewInstanceDialog.h | 2 +- launcher/ui/dialogs/ProfileSetupDialog.cpp | 2 +- launcher/ui/dialogs/SkinUploadDialog.cpp | 2 +- launcher/ui/instanceview/InstanceDelegate.cpp | 2 +- launcher/ui/instanceview/InstanceView.cpp | 2 +- launcher/ui/instanceview/InstanceView.h | 2 +- launcher/ui/pages/BasePage.h | 2 +- launcher/ui/pages/global/APIPage.h | 2 +- launcher/ui/pages/global/AccountListPage.cpp | 2 +- launcher/ui/pages/global/AccountListPage.h | 2 +- launcher/ui/pages/global/CustomCommandsPage.cpp | 2 +- launcher/ui/pages/global/CustomCommandsPage.h | 2 +- launcher/ui/pages/global/ExternalToolsPage.cpp | 2 +- launcher/ui/pages/global/ExternalToolsPage.h | 2 +- launcher/ui/pages/global/JavaPage.cpp | 2 +- launcher/ui/pages/global/JavaPage.h | 2 +- launcher/ui/pages/global/LanguagePage.cpp | 2 +- launcher/ui/pages/global/LanguagePage.h | 2 +- launcher/ui/pages/global/LauncherPage.h | 2 +- launcher/ui/pages/global/MinecraftPage.cpp | 2 +- launcher/ui/pages/global/MinecraftPage.h | 2 +- launcher/ui/pages/global/ProxyPage.cpp | 2 +- launcher/ui/pages/global/ProxyPage.h | 2 +- launcher/ui/pages/instance/GameOptionsPage.cpp | 2 +- launcher/ui/pages/instance/GameOptionsPage.h | 2 +- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 2 +- launcher/ui/pages/instance/InstanceSettingsPage.h | 2 +- launcher/ui/pages/instance/LogPage.h | 2 +- launcher/ui/pages/instance/NotesPage.cpp | 2 +- launcher/ui/pages/instance/NotesPage.h | 2 +- launcher/ui/pages/instance/OtherLogsPage.h | 2 +- launcher/ui/pages/instance/ScreenshotsPage.h | 2 +- launcher/ui/pages/instance/ServersPage.h | 2 +- launcher/ui/pages/instance/WorldListPage.h | 2 +- launcher/ui/pages/modplatform/CustomPage.cpp | 2 +- launcher/ui/pages/modplatform/CustomPage.h | 2 +- launcher/ui/pages/modplatform/ImportPage.cpp | 2 +- launcher/ui/pages/modplatform/ImportPage.h | 2 +- .../ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp | 2 +- launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h | 2 +- launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp | 2 +- launcher/ui/pages/modplatform/atlauncher/AtlPage.h | 2 +- .../modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp | 2 +- .../modplatform/atlauncher/AtlUserInteractionSupportImpl.h | 2 +- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 2 +- launcher/ui/pages/modplatform/flame/FlamePage.h | 2 +- launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp | 2 +- launcher/ui/pages/modplatform/legacy_ftb/Page.cpp | 2 +- launcher/ui/pages/modplatform/legacy_ftb/Page.h | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthModel.h | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthPage.h | 2 +- .../ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h | 2 +- .../ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h | 2 +- launcher/ui/pages/modplatform/technic/TechnicData.h | 2 +- launcher/ui/pages/modplatform/technic/TechnicModel.cpp | 2 +- launcher/ui/pages/modplatform/technic/TechnicModel.h | 2 +- launcher/ui/pages/modplatform/technic/TechnicPage.cpp | 2 +- launcher/ui/pages/modplatform/technic/TechnicPage.h | 2 +- launcher/ui/widgets/CustomCommands.cpp | 2 +- launcher/ui/widgets/CustomCommands.h | 2 +- launcher/ui/widgets/LabeledToolButton.cpp | 2 +- launcher/ui/widgets/LogView.cpp | 2 +- launcher/ui/widgets/VariableSizedImageObject.cpp | 2 +- launcher/ui/widgets/VariableSizedImageObject.h | 2 +- launcher/updater/ExternalUpdater.h | 2 +- launcher/updater/MacSparkleUpdater.h | 2 +- launcher/updater/MacSparkleUpdater.mm | 2 +- tests/Library_test.cpp | 2 +- tests/Packwiz_test.cpp | 2 +- tests/ResourceFolderModel_test.cpp | 2 +- tests/ResourcePackParse_test.cpp | 2 +- tests/TexturePackParse_test.cpp | 2 +- 197 files changed, 197 insertions(+), 197 deletions(-) diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index 140731fe0..d7662a7a4 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ApplicationMessage.cpp b/launcher/ApplicationMessage.cpp index 8d75ecc8f..50ac10ccc 100644 --- a/launcher/ApplicationMessage.cpp +++ b/launcher/ApplicationMessage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp index 67fc150a4..70c6da6b3 100644 --- a/launcher/BaseInstance.cpp +++ b/launcher/BaseInstance.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield * diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index 1560bd258..38dc7c4aa 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield * diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp index d817926ef..e11560d5e 100644 --- a/launcher/BaseVersionList.cpp +++ b/launcher/BaseVersionList.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/Commandline.cpp b/launcher/Commandline.cpp index 4fac024ac..8489fb745 100644 --- a/launcher/Commandline.cpp +++ b/launcher/Commandline.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/DesktopServices.cpp b/launcher/DesktopServices.cpp index 62f04f162..6b738f2cf 100644 --- a/launcher/DesktopServices.cpp +++ b/launcher/DesktopServices.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 dada513 * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/GZip.cpp b/launcher/GZip.cpp index 292fab294..1c2539e08 100644 --- a/launcher/GZip.cpp +++ b/launcher/GZip.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 2bc945d7b..3f948a336 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 flowln * diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h index 582a9ded0..4459e440c 100644 --- a/launcher/InstanceImportTask.h +++ b/launcher/InstanceImportTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index 8dc0231b8..856eee816 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/JavaCommon.cpp b/launcher/JavaCommon.cpp index 73bc96a43..e16ac9255 100644 --- a/launcher/JavaCommon.cpp +++ b/launcher/JavaCommon.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/Json.cpp b/launcher/Json.cpp index 8db44f062..f397f89c5 100644 --- a/launcher/Json.cpp +++ b/launcher/Json.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/Json.h b/launcher/Json.h index 5a8504ef9..28891f398 100644 --- a/launcher/Json.h +++ b/launcher/Json.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 720f8b91b..380489e06 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/LaunchController.h b/launcher/LaunchController.h index b4138a062..f1c88afb7 100644 --- a/launcher/LaunchController.h +++ b/launcher/LaunchController.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/NullInstance.h b/launcher/NullInstance.h index c7abfc587..ff658c431 100644 --- a/launcher/NullInstance.h +++ b/launcher/NullInstance.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/RuntimeContext.h b/launcher/RuntimeContext.h index 70e7d0d16..c57140d28 100644 --- a/launcher/RuntimeContext.h +++ b/launcher/RuntimeContext.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/Version.h b/launcher/Version.h index 31c7b2d8a..92bff9ba9 100644 --- a/launcher/Version.h +++ b/launcher/Version.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2023 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index f3207fdcf..20caba189 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index a44ebca25..3512c3079 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/launch/LaunchTask.cpp b/launcher/launch/LaunchTask.cpp index 902801a10..06a32bd28 100644 --- a/launcher/launch/LaunchTask.cpp +++ b/launcher/launch/LaunchTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/launch/LaunchTask.h b/launcher/launch/LaunchTask.h index 40a3324ba..e79c43557 100644 --- a/launcher/launch/LaunchTask.h +++ b/launcher/launch/LaunchTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index 7fd8fc331..81337a88e 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/launch/steps/PostLaunchCommand.cpp b/launcher/launch/steps/PostLaunchCommand.cpp index 2e59de630..725101224 100644 --- a/launcher/launch/steps/PostLaunchCommand.cpp +++ b/launcher/launch/steps/PostLaunchCommand.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/launch/steps/PreLaunchCommand.cpp b/launcher/launch/steps/PreLaunchCommand.cpp index a7f36086b..6d071a66e 100644 --- a/launcher/launch/steps/PreLaunchCommand.cpp +++ b/launcher/launch/steps/PreLaunchCommand.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/launch/steps/QuitAfterGameStop.cpp b/launcher/launch/steps/QuitAfterGameStop.cpp index f9eced993..389560461 100644 --- a/launcher/launch/steps/QuitAfterGameStop.cpp +++ b/launcher/launch/steps/QuitAfterGameStop.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 dada513 * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/launch/steps/QuitAfterGameStop.h b/launcher/launch/steps/QuitAfterGameStop.h index 5f5e63048..9326b2a8c 100644 --- a/launcher/launch/steps/QuitAfterGameStop.h +++ b/launcher/launch/steps/QuitAfterGameStop.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 dada513 * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/main.cpp b/launcher/main.cpp index 31551f998..35f545f52 100644 --- a/launcher/main.cpp +++ b/launcher/main.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp index 21c3007eb..4ef007075 100644 --- a/launcher/minecraft/AssetsUtils.cpp +++ b/launcher/minecraft/AssetsUtils.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/Component.cpp b/launcher/minecraft/Component.cpp index 96d67a057..79ea7a06d 100644 --- a/launcher/minecraft/Component.cpp +++ b/launcher/minecraft/Component.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/GradleSpecifier.h b/launcher/minecraft/GradleSpecifier.h index 53c31e8e0..22db7d641 100644 --- a/launcher/minecraft/GradleSpecifier.h +++ b/launcher/minecraft/GradleSpecifier.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/LaunchProfile.cpp b/launcher/minecraft/LaunchProfile.cpp index 013c78ae3..cf819b411 100644 --- a/launcher/minecraft/LaunchProfile.cpp +++ b/launcher/minecraft/LaunchProfile.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/LaunchProfile.h b/launcher/minecraft/LaunchProfile.h index 9f7bc812e..12b312383 100644 --- a/launcher/minecraft/LaunchProfile.h +++ b/launcher/minecraft/LaunchProfile.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/Library.cpp b/launcher/minecraft/Library.cpp index 0bb618b40..0e8ddf03d 100644 --- a/launcher/minecraft/Library.cpp +++ b/launcher/minecraft/Library.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/Library.h b/launcher/minecraft/Library.h index a24c11215..f8816a97b 100644 --- a/launcher/minecraft/Library.h +++ b/launcher/minecraft/Library.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/MojangVersionFormat.cpp b/launcher/minecraft/MojangVersionFormat.cpp index d7393cf4a..6ee10ec15 100644 --- a/launcher/minecraft/MojangVersionFormat.cpp +++ b/launcher/minecraft/MojangVersionFormat.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp index 91b58c96c..306c95a6a 100644 --- a/launcher/minecraft/OneSixVersionFormat.cpp +++ b/launcher/minecraft/OneSixVersionFormat.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/ProfileUtils.cpp b/launcher/minecraft/ProfileUtils.cpp index 5b2fd090e..d56ed14bd 100644 --- a/launcher/minecraft/ProfileUtils.cpp +++ b/launcher/minecraft/ProfileUtils.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/ProfileUtils.h b/launcher/minecraft/ProfileUtils.h index 93cc3da07..98a7ff739 100644 --- a/launcher/minecraft/ProfileUtils.h +++ b/launcher/minecraft/ProfileUtils.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/Rule.cpp b/launcher/minecraft/Rule.cpp index 74c12a0d2..d80aab84d 100644 --- a/launcher/minecraft/Rule.cpp +++ b/launcher/minecraft/Rule.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/Rule.h b/launcher/minecraft/Rule.h index b1bf0eac7..c6cdbc43f 100644 --- a/launcher/minecraft/Rule.h +++ b/launcher/minecraft/Rule.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/VersionFile.cpp b/launcher/minecraft/VersionFile.cpp index b8aaee90f..6632bb8bf 100644 --- a/launcher/minecraft/VersionFile.cpp +++ b/launcher/minecraft/VersionFile.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 Jamie Mansfield * diff --git a/launcher/minecraft/VersionFile.h b/launcher/minecraft/VersionFile.h index d8984a29e..280e35ee3 100644 --- a/launcher/minecraft/VersionFile.h +++ b/launcher/minecraft/VersionFile.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index cdfbef5b8..812b13c71 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp index fc870811f..474bf7c6e 100644 --- a/launcher/minecraft/auth/AccountData.cpp +++ b/launcher/minecraft/auth/AccountData.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h index 38e3c3c90..9b626c34e 100644 --- a/launcher/minecraft/auth/AccountData.h +++ b/launcher/minecraft/auth/AccountData.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 3ef6a7584..c534ea3bd 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/AccountList.h b/launcher/minecraft/auth/AccountList.h index 30926d13f..6a0b01916 100644 --- a/launcher/minecraft/auth/AccountList.h +++ b/launcher/minecraft/auth/AccountList.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/AccountTask.cpp b/launcher/minecraft/auth/AccountTask.cpp index 896607197..4c3d6ee19 100644 --- a/launcher/minecraft/auth/AccountTask.cpp +++ b/launcher/minecraft/auth/AccountTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/AccountTask.h b/launcher/minecraft/auth/AccountTask.h index 68bbfe5fa..82332c0b9 100644 --- a/launcher/minecraft/auth/AccountTask.h +++ b/launcher/minecraft/auth/AccountTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/AuthRequest.cpp b/launcher/minecraft/auth/AuthRequest.cpp index bd48a059d..189978cc0 100644 --- a/launcher/minecraft/auth/AuthRequest.cpp +++ b/launcher/minecraft/auth/AuthRequest.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index e8422a6f3..1dcea2072 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h index 395ca5498..f04f947fa 100644 --- a/launcher/minecraft/auth/MinecraftAccount.h +++ b/launcher/minecraft/auth/MinecraftAccount.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp index 66a9a0e80..1aa22765d 100644 --- a/launcher/minecraft/auth/steps/MSAStep.cpp +++ b/launcher/minecraft/auth/steps/MSAStep.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/auth/steps/MSAStep.h b/launcher/minecraft/auth/steps/MSAStep.h index fc070ff6a..b6635d4a5 100644 --- a/launcher/minecraft/auth/steps/MSAStep.h +++ b/launcher/minecraft/auth/steps/MSAStep.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp index 2980b0bd1..44e5d0a63 100644 --- a/launcher/minecraft/launch/LauncherPartLaunch.cpp +++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/launch/ModMinecraftJar.cpp b/launcher/minecraft/launch/ModMinecraftJar.cpp index f858dd740..6e73333b1 100644 --- a/launcher/minecraft/launch/ModMinecraftJar.cpp +++ b/launcher/minecraft/launch/ModMinecraftJar.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/launch/ScanModFolders.cpp b/launcher/minecraft/launch/ScanModFolders.cpp index 04d820668..7e08a4e36 100644 --- a/launcher/minecraft/launch/ScanModFolders.cpp +++ b/launcher/minecraft/launch/ScanModFolders.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/launch/VerifyJavaInstall.cpp b/launcher/minecraft/launch/VerifyJavaInstall.cpp index 03831d175..cdd1f7fd1 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.cpp +++ b/launcher/minecraft/launch/VerifyJavaInstall.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/launch/VerifyJavaInstall.h b/launcher/minecraft/launch/VerifyJavaInstall.h index edf6015a3..dabbf3b25 100644 --- a/launcher/minecraft/launch/VerifyJavaInstall.h +++ b/launcher/minecraft/launch/VerifyJavaInstall.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index ea9078e04..88e9ff2b6 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 46509cde6..ae3dea8d8 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 543648115..6dafecfc5 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index 0235fe333..a00d5a24b 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index a8451681c..280e70d7b 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index f1f40a817..06fd78149 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 7dfd09e62..f27431576 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp index fbc716c42..7d8c67137 100644 --- a/launcher/minecraft/mod/TexturePack.cpp +++ b/launcher/minecraft/mod/TexturePack.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/TexturePack.h b/launcher/minecraft/mod/TexturePack.h index 577005655..bf4b5b6b4 100644 --- a/launcher/minecraft/mod/TexturePack.h +++ b/launcher/minecraft/mod/TexturePack.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index a2cebb15f..5c5f2b7c1 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index ccc634da7..b975d8641 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h index 31f919b84..080999294 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.h +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp index 7440e6aa3..73cbf891c 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h index 58d90b3b9..5199bf3f0 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp index 817b0ea9c..887a1062e 100644 --- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h index 6b91565ad..1341590f2 100644 --- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 4a19a8eb4..9f79ba098 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h index 7ce13cfaf..4200ef6d9 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/minecraft/services/CapeChange.cpp b/launcher/minecraft/services/CapeChange.cpp index fe64e18b3..2ba38a6af 100644 --- a/launcher/minecraft/services/CapeChange.cpp +++ b/launcher/minecraft/services/CapeChange.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/services/SkinDelete.cpp b/launcher/minecraft/services/SkinDelete.cpp index 3737a5af8..9e9020692 100644 --- a/launcher/minecraft/services/SkinDelete.cpp +++ b/launcher/minecraft/services/SkinDelete.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/services/SkinUpload.cpp b/launcher/minecraft/services/SkinUpload.cpp index 299608815..163b481b1 100644 --- a/launcher/minecraft/services/SkinUpload.cpp +++ b/launcher/minecraft/services/SkinUpload.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/minecraft/update/FoldersTask.cpp b/launcher/minecraft/update/FoldersTask.cpp index 3cbc309d0..c74e8d2ef 100644 --- a/launcher/minecraft/update/FoldersTask.cpp +++ b/launcher/minecraft/update/FoldersTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index ecea0d8ce..350a9f10b 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 63d0d2f2d..a92217a06 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 1332583e5..5d1a361df 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h index b82f523fe..ffc358fbb 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/atlauncher/ATLPackManifest.cpp b/launcher/modplatform/atlauncher/ATLPackManifest.cpp index 88d728c22..9ff2f339e 100644 --- a/launcher/modplatform/atlauncher/ATLPackManifest.cpp +++ b/launcher/modplatform/atlauncher/ATLPackManifest.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/atlauncher/ATLPackManifest.h b/launcher/modplatform/atlauncher/ATLPackManifest.h index fec4bb576..8db91087d 100644 --- a/launcher/modplatform/atlauncher/ATLPackManifest.h +++ b/launcher/modplatform/atlauncher/ATLPackManifest.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/atlauncher/ATLShareCode.cpp b/launcher/modplatform/atlauncher/ATLShareCode.cpp index b49631024..800eac538 100644 --- a/launcher/modplatform/atlauncher/ATLShareCode.cpp +++ b/launcher/modplatform/atlauncher/ATLShareCode.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/atlauncher/ATLShareCode.h b/launcher/modplatform/atlauncher/ATLShareCode.h index 69a493f85..531945bce 100644 --- a/launcher/modplatform/atlauncher/ATLShareCode.h +++ b/launcher/modplatform/atlauncher/ATLShareCode.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h index a608263c6..854cdbc41 100644 --- a/launcher/modplatform/flame/PackManifest.h +++ b/launcher/modplatform/flame/PackManifest.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp index 767dbc65c..8f1a6e2ff 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index beb295dc3..761f622bb 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp b/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp index 7ab5e9d6b..2ae351329 100644 --- a/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp +++ b/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 969018a9d..85e66a91e 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h index a8d986c57..58a0f227c 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.h +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index d4565191a..0d07c6361 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.h b/launcher/modplatform/modrinth/ModrinthPackManifest.h index 1af47cbc0..effa1a84a 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.h +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 82deef8b1..71f66bf3e 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 6b13f74a9..7edc18cde 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index 6e4784f8b..c162d6253 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2021-2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/technic/SolderPackInstallTask.h b/launcher/modplatform/technic/SolderPackInstallTask.h index f2c6a83a4..2ea701e23 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.h +++ b/launcher/modplatform/technic/SolderPackInstallTask.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2021-2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/technic/SolderPackManifest.cpp b/launcher/modplatform/technic/SolderPackManifest.cpp index 3d9a2ea11..38b668f6b 100644 --- a/launcher/modplatform/technic/SolderPackManifest.cpp +++ b/launcher/modplatform/technic/SolderPackManifest.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/technic/SolderPackManifest.h b/launcher/modplatform/technic/SolderPackManifest.h index 917b4eefa..1a06d7037 100644 --- a/launcher/modplatform/technic/SolderPackManifest.h +++ b/launcher/modplatform/technic/SolderPackManifest.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/net/ChecksumValidator.h b/launcher/net/ChecksumValidator.h index a2ca2c7a4..dfee0aee5 100644 --- a/launcher/net/ChecksumValidator.h +++ b/launcher/net/ChecksumValidator.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/net/NetUtils.h b/launcher/net/NetUtils.h index afaf7b5f3..cd517bcca 100644 --- a/launcher/net/NetUtils.h +++ b/launcher/net/NetUtils.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/net/Sink.h b/launcher/net/Sink.h index 3870f29bc..fcdabf372 100644 --- a/launcher/net/Sink.h +++ b/launcher/net/Sink.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/net/Validator.h b/launcher/net/Validator.h index 7d35ec387..7eaede7b7 100644 --- a/launcher/net/Validator.h +++ b/launcher/net/Validator.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/news/NewsChecker.cpp b/launcher/news/NewsChecker.cpp index 11ba5311b..33fb7eceb 100644 --- a/launcher/news/NewsChecker.cpp +++ b/launcher/news/NewsChecker.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp index 4f087b0fd..d548c89ae 100644 --- a/launcher/screenshots/ImgurAlbumCreation.cpp +++ b/launcher/screenshots/ImgurAlbumCreation.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/screenshots/ImgurAlbumCreation.h b/launcher/screenshots/ImgurAlbumCreation.h index d47bcaa74..bb71bec2b 100644 --- a/launcher/screenshots/ImgurAlbumCreation.h +++ b/launcher/screenshots/ImgurAlbumCreation.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index 2d8c0db8c..29499a20d 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/screenshots/ImgurUpload.h b/launcher/screenshots/ImgurUpload.h index 14994d64e..542255b2d 100644 --- a/launcher/screenshots/ImgurUpload.h +++ b/launcher/screenshots/ImgurUpload.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index a8097ffd6..b17096ca7 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (c) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> * diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 97affc071..933fe2d35 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp index bac30b010..3c6f6ef16 100644 --- a/launcher/ui/dialogs/AboutDialog.cpp +++ b/launcher/ui/dialogs/AboutDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/dialogs/CopyInstanceDialog.cpp b/launcher/ui/dialogs/CopyInstanceDialog.cpp index 2c98fad16..8b2f5bb80 100644 --- a/launcher/ui/dialogs/CopyInstanceDialog.cpp +++ b/launcher/ui/dialogs/CopyInstanceDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/dialogs/MSALoginDialog.cpp b/launcher/ui/dialogs/MSALoginDialog.cpp index f8aab34d9..74fff9fd3 100644 --- a/launcher/ui/dialogs/MSALoginDialog.cpp +++ b/launcher/ui/dialogs/MSALoginDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/dialogs/NewComponentDialog.cpp b/launcher/ui/dialogs/NewComponentDialog.cpp index 0d90b02e3..b47b85ff1 100644 --- a/launcher/ui/dialogs/NewComponentDialog.cpp +++ b/launcher/ui/dialogs/NewComponentDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index fba689067..1daaa3cec 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/dialogs/NewInstanceDialog.h b/launcher/ui/dialogs/NewInstanceDialog.h index de054cf7a..b348649fe 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.h +++ b/launcher/ui/dialogs/NewInstanceDialog.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/dialogs/ProfileSetupDialog.cpp b/launcher/ui/dialogs/ProfileSetupDialog.cpp index 207733bbf..4b0c5b768 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.cpp +++ b/launcher/ui/dialogs/ProfileSetupDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/dialogs/SkinUploadDialog.cpp b/launcher/ui/dialogs/SkinUploadDialog.cpp index 9422b8d68..5b3ebfa23 100644 --- a/launcher/ui/dialogs/SkinUploadDialog.cpp +++ b/launcher/ui/dialogs/SkinUploadDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/instanceview/InstanceDelegate.cpp b/launcher/ui/instanceview/InstanceDelegate.cpp index 9427836dc..d947163bc 100644 --- a/launcher/ui/instanceview/InstanceDelegate.cpp +++ b/launcher/ui/instanceview/InstanceDelegate.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 8fb71ff6a..607f3cadb 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h index 11892b227..3d4d56208 100644 --- a/launcher/ui/instanceview/InstanceView.h +++ b/launcher/ui/instanceview/InstanceView.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/BasePage.h b/launcher/ui/pages/BasePage.h index dc2bde992..d35206a08 100644 --- a/launcher/ui/pages/BasePage.h +++ b/launcher/ui/pages/BasePage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/APIPage.h b/launcher/ui/pages/global/APIPage.h index 8d8f06454..d4ed92900 100644 --- a/launcher/ui/pages/global/APIPage.h +++ b/launcher/ui/pages/global/APIPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield * Copyright (c) 2022 Lenny McLennington diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index caaa4b069..5c6fb092b 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield * diff --git a/launcher/ui/pages/global/AccountListPage.h b/launcher/ui/pages/global/AccountListPage.h index 483d7924f..add0f4aa0 100644 --- a/launcher/ui/pages/global/AccountListPage.h +++ b/launcher/ui/pages/global/AccountListPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (c) 2022 Jamie Mansfield * diff --git a/launcher/ui/pages/global/CustomCommandsPage.cpp b/launcher/ui/pages/global/CustomCommandsPage.cpp index fad69050b..cc8518c2f 100644 --- a/launcher/ui/pages/global/CustomCommandsPage.cpp +++ b/launcher/ui/pages/global/CustomCommandsPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/global/CustomCommandsPage.h b/launcher/ui/pages/global/CustomCommandsPage.h index c69b02e5a..ec1204ffe 100644 --- a/launcher/ui/pages/global/CustomCommandsPage.h +++ b/launcher/ui/pages/global/CustomCommandsPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/ExternalToolsPage.cpp b/launcher/ui/pages/global/ExternalToolsPage.cpp index abe157f09..33e9c5388 100644 --- a/launcher/ui/pages/global/ExternalToolsPage.cpp +++ b/launcher/ui/pages/global/ExternalToolsPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/ExternalToolsPage.h b/launcher/ui/pages/global/ExternalToolsPage.h index 0b38b80f9..7248f0c99 100644 --- a/launcher/ui/pages/global/ExternalToolsPage.h +++ b/launcher/ui/pages/global/ExternalToolsPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index f28cbc5d9..45d8f0180 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/global/JavaPage.h b/launcher/ui/pages/global/JavaPage.h index 64f2a296e..1a1bd96e1 100644 --- a/launcher/ui/pages/global/JavaPage.h +++ b/launcher/ui/pages/global/JavaPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/LanguagePage.cpp b/launcher/ui/pages/global/LanguagePage.cpp index 27af91d84..af6fc1727 100644 --- a/launcher/ui/pages/global/LanguagePage.cpp +++ b/launcher/ui/pages/global/LanguagePage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/global/LanguagePage.h b/launcher/ui/pages/global/LanguagePage.h index ea358851a..ff7ce7ddc 100644 --- a/launcher/ui/pages/global/LanguagePage.h +++ b/launcher/ui/pages/global/LanguagePage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/global/LauncherPage.h b/launcher/ui/pages/global/LauncherPage.h index 238e31bb4..e733224d2 100644 --- a/launcher/ui/pages/global/LauncherPage.h +++ b/launcher/ui/pages/global/LauncherPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp index 55ad12ac8..866a4121c 100644 --- a/launcher/ui/pages/global/MinecraftPage.cpp +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2023 seth * diff --git a/launcher/ui/pages/global/MinecraftPage.h b/launcher/ui/pages/global/MinecraftPage.h index a9e2e8024..28c31b5d8 100644 --- a/launcher/ui/pages/global/MinecraftPage.h +++ b/launcher/ui/pages/global/MinecraftPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/ProxyPage.cpp b/launcher/ui/pages/global/ProxyPage.cpp index 0eae6e4b8..9caffcb37 100644 --- a/launcher/ui/pages/global/ProxyPage.cpp +++ b/launcher/ui/pages/global/ProxyPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/global/ProxyPage.h b/launcher/ui/pages/global/ProxyPage.h index 092a11d2f..26118f181 100644 --- a/launcher/ui/pages/global/ProxyPage.h +++ b/launcher/ui/pages/global/ProxyPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/instance/GameOptionsPage.cpp b/launcher/ui/pages/instance/GameOptionsPage.cpp index e90041709..8db392b1d 100644 --- a/launcher/ui/pages/instance/GameOptionsPage.cpp +++ b/launcher/ui/pages/instance/GameOptionsPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/GameOptionsPage.h b/launcher/ui/pages/instance/GameOptionsPage.h index 563bd10ae..a132843e7 100644 --- a/launcher/ui/pages/instance/GameOptionsPage.h +++ b/launcher/ui/pages/instance/GameOptionsPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 8ea24b78a..f7be91684 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 seth diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 9f1355939..21ecbaf8e 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/LogPage.h b/launcher/ui/pages/instance/LogPage.h index 33b6cc39f..6c259891d 100644 --- a/launcher/ui/pages/instance/LogPage.h +++ b/launcher/ui/pages/instance/LogPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/NotesPage.cpp b/launcher/ui/pages/instance/NotesPage.cpp index 887bad85a..a86369f87 100644 --- a/launcher/ui/pages/instance/NotesPage.cpp +++ b/launcher/ui/pages/instance/NotesPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/NotesPage.h b/launcher/ui/pages/instance/NotesPage.h index aa6083062..3351d25fc 100644 --- a/launcher/ui/pages/instance/NotesPage.h +++ b/launcher/ui/pages/instance/NotesPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/OtherLogsPage.h b/launcher/ui/pages/instance/OtherLogsPage.h index ecb896fca..4b3b122b0 100644 --- a/launcher/ui/pages/instance/OtherLogsPage.h +++ b/launcher/ui/pages/instance/OtherLogsPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/ScreenshotsPage.h b/launcher/ui/pages/instance/ScreenshotsPage.h index 0f824a056..bb127b429 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.h +++ b/launcher/ui/pages/instance/ScreenshotsPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/instance/ServersPage.h b/launcher/ui/pages/instance/ServersPage.h index 96a8dd7d4..a27d1d297 100644 --- a/launcher/ui/pages/instance/ServersPage.h +++ b/launcher/ui/pages/instance/ServersPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/instance/WorldListPage.h b/launcher/ui/pages/instance/WorldListPage.h index df8b512ff..4f83002f4 100644 --- a/launcher/ui/pages/instance/WorldListPage.h +++ b/launcher/ui/pages/instance/WorldListPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/CustomPage.cpp b/launcher/ui/pages/modplatform/CustomPage.cpp index ae5cae30f..4ac21b012 100644 --- a/launcher/ui/pages/modplatform/CustomPage.cpp +++ b/launcher/ui/pages/modplatform/CustomPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/CustomPage.h b/launcher/ui/pages/modplatform/CustomPage.h index 273a60790..c5d6d5af5 100644 --- a/launcher/ui/pages/modplatform/CustomPage.h +++ b/launcher/ui/pages/modplatform/CustomPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index 79f295997..ce2777b3b 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/modplatform/ImportPage.h b/launcher/ui/pages/modplatform/ImportPage.h index 66c452b9f..d846d566d 100644 --- a/launcher/ui/pages/modplatform/ImportPage.h +++ b/launcher/ui/pages/modplatform/ImportPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp index 868d98138..6fb867733 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h index 1adfdf036..55903003b 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp index 1e96a75df..5e3b9ecf1 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h index ac336ec10..6bc449649 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp index 9ed75bccf..0c7257859 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h index adeb53cbc..52ced2615 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 28af22e30..183e16f90 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index ad54c13a8..ff5c79750 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index f4ddf3312..356d919d9 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index d3983696f..0103bbaa2 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.h b/launcher/ui/pages/modplatform/legacy_ftb/Page.h index 32b4a8146..a12b0745d 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 7427c0473..ebc5556c6 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index 47c2d55b4..721c69f55 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index d5c089b40..41fd5003f 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index db5e1a3d6..b7054c886 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index 512eb0274..ce7475b6e 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index d7c858f88..15cd58544 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index ff809c7bb..616c1a815 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index 26037f0cd..86ba1ccb2 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/technic/TechnicData.h b/launcher/ui/pages/modplatform/technic/TechnicData.h index 81488811a..fc7fa4d39 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicData.h +++ b/launcher/ui/pages/modplatform/technic/TechnicData.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2021-2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index 5ba804db5..e8c5ac922 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2021 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index 0f1a814e2..d7a635d41 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2021 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index e87164711..54b86feba 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2021-2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index d33656ebb..91b61eaf2 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2021-2022 Jamie Mansfield * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/widgets/CustomCommands.cpp b/launcher/ui/widgets/CustomCommands.cpp index 98a1b7e86..9b98d7409 100644 --- a/launcher/ui/widgets/CustomCommands.cpp +++ b/launcher/ui/widgets/CustomCommands.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/widgets/CustomCommands.h b/launcher/ui/widgets/CustomCommands.h index 96a3fa627..5b410ae9a 100644 --- a/launcher/ui/widgets/CustomCommands.h +++ b/launcher/ui/widgets/CustomCommands.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/widgets/LabeledToolButton.cpp b/launcher/ui/widgets/LabeledToolButton.cpp index 7af48b0c9..46114e047 100644 --- a/launcher/ui/widgets/LabeledToolButton.cpp +++ b/launcher/ui/widgets/LabeledToolButton.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/widgets/LogView.cpp b/launcher/ui/widgets/LogView.cpp index 8c960ebb1..4096889d3 100644 --- a/launcher/ui/widgets/LogView.cpp +++ b/launcher/ui/widgets/LogView.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/widgets/VariableSizedImageObject.cpp b/launcher/ui/widgets/VariableSizedImageObject.cpp index c72df5a9c..f655fc38d 100644 --- a/launcher/ui/widgets/VariableSizedImageObject.cpp +++ b/launcher/ui/widgets/VariableSizedImageObject.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/widgets/VariableSizedImageObject.h b/launcher/ui/widgets/VariableSizedImageObject.h index 137487eee..ca67af0c9 100644 --- a/launcher/ui/widgets/VariableSizedImageObject.h +++ b/launcher/ui/widgets/VariableSizedImageObject.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/updater/ExternalUpdater.h b/launcher/updater/ExternalUpdater.h index 6c0803a7e..daa5b1095 100644 --- a/launcher/updater/ExternalUpdater.h +++ b/launcher/updater/ExternalUpdater.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Kenneth Chew * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/updater/MacSparkleUpdater.h b/launcher/updater/MacSparkleUpdater.h index 3f6b5f4ad..5f9b1a28c 100644 --- a/launcher/updater/MacSparkleUpdater.h +++ b/launcher/updater/MacSparkleUpdater.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Kenneth Chew * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/updater/MacSparkleUpdater.mm b/launcher/updater/MacSparkleUpdater.mm index 1c1f5cd27..b2b631593 100644 --- a/launcher/updater/MacSparkleUpdater.mm +++ b/launcher/updater/MacSparkleUpdater.mm @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Kenneth Chew * * This program is free software: you can redistribute it and/or modify diff --git a/tests/Library_test.cpp b/tests/Library_test.cpp index e8090c097..8b8d4c55c 100644 --- a/tests/Library_test.cpp +++ b/tests/Library_test.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/tests/Packwiz_test.cpp b/tests/Packwiz_test.cpp index 6f4aa5d1b..d1b274d12 100644 --- a/tests/Packwiz_test.cpp +++ b/tests/Packwiz_test.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/tests/ResourceFolderModel_test.cpp b/tests/ResourceFolderModel_test.cpp index 8012d4df0..57c2cbdff 100644 --- a/tests/ResourceFolderModel_test.cpp +++ b/tests/ResourceFolderModel_test.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify diff --git a/tests/ResourcePackParse_test.cpp b/tests/ResourcePackParse_test.cpp index 1dcce3249..e1092167d 100644 --- a/tests/ResourcePackParse_test.cpp +++ b/tests/ResourcePackParse_test.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * * This program is free software: you can redistribute it and/or modify diff --git a/tests/TexturePackParse_test.cpp b/tests/TexturePackParse_test.cpp index 558529287..85c96b57c 100644 --- a/tests/TexturePackParse_test.cpp +++ b/tests/TexturePackParse_test.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * From 9546c771139bd5708ab4096ab15ffd39a15bed18 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 15 Aug 2023 00:52:34 +0300 Subject: [PATCH 230/398] Some warnings Signed-off-by: Trial97 --- launcher/minecraft/mod/ResourceFolderModel.h | 2 +- launcher/ui/pages/modplatform/ResourceModel.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 6277028b3..80c31e456 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -99,7 +99,7 @@ class ResourceFolderModel : public QAbstractListModel { enum Columns { ACTIVE_COLUMN = 0, NAME_COLUMN, DATE_COLUMN, NUM_COLUMNS }; QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; } - [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : size(); } + [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast(size()); } [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; } [[nodiscard]] Qt::DropActions supportedDropActions() const override; diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 6533d9c6a..cc813d6e6 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -42,7 +42,10 @@ class ResourceModel : public QAbstractListModel { [[nodiscard]] virtual auto debugName() const -> QString; [[nodiscard]] virtual auto metaEntryBase() const -> QString = 0; - [[nodiscard]] inline int rowCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : m_packs.size(); } + [[nodiscard]] inline int rowCount(const QModelIndex& parent) const override + { + return parent.isValid() ? 0 : static_cast(m_packs.size()); + } [[nodiscard]] inline int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : 1; } [[nodiscard]] inline auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); } From 1939e3e6ed3d2d2d4199d90154333cc8892eafeb Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Tue, 15 Aug 2023 09:02:15 +0200 Subject: [PATCH 231/398] chore: reformat Signed-off-by: Sefa Eyeoglu --- launcher/ui/pages/instance/ServersPage.cpp | 20 ++++++++++++++++---- tests/FileSystem_test.cpp | 5 ++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index 5c31f73b2..da49f4a7d 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -354,8 +354,14 @@ class ServersModel : public QAbstractListModel { } } - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override { return parent.isValid() ? 0 : m_servers.size(); } - int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : COLUMN_COUNT; } + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override + { + return parent.isValid() ? 0 : m_servers.size(); + } + int columnCount(const QModelIndex& parent) const override + { + return parent.isValid() ? 0 : COLUMN_COUNT; + } Server* at(int index) { @@ -439,7 +445,10 @@ class ServersModel : public QAbstractListModel { qDebug() << "Changed:" << path; load(); } - void fileChanged(const QString& path) { qDebug() << "Changed:" << path; } + void fileChanged(const QString& path) + { + qDebug() << "Changed:" << path; + } private slots: void save_internal() @@ -483,7 +492,10 @@ class ServersModel : public QAbstractListModel { m_saveTimer.stop(); } - bool saveIsScheduled() const { return m_dirty; } + bool saveIsScheduled() const + { + return m_dirty; + } void updateFSObserver() { diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index 1d3cee85f..e19410423 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -353,7 +353,10 @@ class FileSystemTest : public QObject { } } - void test_getDesktop() { QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); } + void test_getDesktop() + { + QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + } void test_link() { From 6ce7e426d2e3bbca74719da073eb46d05b001439 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Tue, 15 Aug 2023 10:38:04 +0200 Subject: [PATCH 232/398] chore: reformat Signed-off-by: Sefa Eyeoglu --- launcher/ui/MainWindow.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index dd35d5d00..be9c4994b 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -155,7 +155,10 @@ class MainWindow : public QMainWindow { void deleteGroup(); void undoTrashInstance(); - inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } + inline void on_actionExportInstance_triggered() + { + on_actionExportInstanceZip_triggered(); + } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); void on_actionExportInstanceFlamePack_triggered(); From ff67fd10c33fa99423b5a43dcbd30494b4c40dc5 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 17 Jul 2023 10:57:41 +0200 Subject: [PATCH 233/398] feat: implement override for GLFW/OpenAL with split natives Fixes PrismLauncher/PrismLauncher#513 Signed-off-by: Sefa Eyeoglu --- launcher/MangoHud.cpp | 43 ++++++++++++++++++++ launcher/MangoHud.h | 4 +- launcher/minecraft/MinecraftInstance.cpp | 18 ++++++++ launcher/minecraft/launch/ExtractNatives.cpp | 10 ++--- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/launcher/MangoHud.cpp b/launcher/MangoHud.cpp index 5758da3aa..ab79f418b 100644 --- a/launcher/MangoHud.cpp +++ b/launcher/MangoHud.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -26,6 +27,15 @@ #include "Json.h" #include "MangoHud.h" +#ifdef __GLIBC__ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#define UNDEF_GNU_SOURCE +#endif +#include +#include +#endif + namespace MangoHud { QString getLibraryString() @@ -106,4 +116,37 @@ QString getLibraryString() return QString(); } + +QString findLibrary(QString libName) +{ +#ifdef __GLIBC__ + const char* library = libName.toLocal8Bit().constData(); + + void* handle = dlopen(library, RTLD_NOW); + if (!handle) { + qCritical() << "dlopen() failed:" << dlerror(); + return {}; + } + + char path[PATH_MAX]; + if (dlinfo(handle, RTLD_DI_ORIGIN, path) == -1) { + qCritical() << "dlinfo() failed:" << dlerror(); + dlclose(handle); + return {}; + } + + auto fullPath = FS::PathCombine(QString(path), libName); + + dlclose(handle); + return fullPath; +#else + qWarning() << "MangoHud::findLibrary is not implemented on this platform"; + return {}; +#endif +} } // namespace MangoHud + +#ifdef UNDEF_GNU_SOURCE +#undef _GNU_SOURCE +#undef UNDEF_GNU_SOURCE +#endif diff --git a/launcher/MangoHud.h b/launcher/MangoHud.h index 7b7c2849c..5361999b4 100644 --- a/launcher/MangoHud.h +++ b/launcher/MangoHud.h @@ -24,4 +24,6 @@ namespace MangoHud { QString getLibraryString(); -} + +QString findLibrary(QString libName); +} // namespace MangoHud diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 305bff67b..40fde6cb3 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -389,6 +389,24 @@ QStringList MinecraftInstance::extraArguments() if (loaders.has_value() && loaders.value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool()) list.append("-Dloader.disable_beacon=true"); } + +#ifdef Q_OS_LINUX + { + QString openALPath; + QString glfwPath; + + if (settings()->get("UseNativeOpenAL").toBool()) + openALPath = MangoHud::findLibrary("libopenal.so"); + if (settings()->get("UseNativeGLFW").toBool()) + glfwPath = MangoHud::findLibrary("libglfw.so"); + + if (!openALPath.isEmpty()) + list.append("-Dorg.lwjgl.openal.libname=" + openALPath); + if (!glfwPath.isEmpty()) + list.append("-Dorg.lwjgl.glfw.libname=" + glfwPath); + } +#endif + return list; } diff --git a/launcher/minecraft/launch/ExtractNatives.cpp b/launcher/minecraft/launch/ExtractNatives.cpp index cebeaedd4..1aa4dccc4 100644 --- a/launcher/minecraft/launch/ExtractNatives.cpp +++ b/launcher/minecraft/launch/ExtractNatives.cpp @@ -39,7 +39,7 @@ static QString replaceSuffix(QString target, const QString& suffix, const QStrin return target + replacement; } -static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack, bool nativeOpenAL, bool nativeGLFW) +static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack, bool nativeOpenAL) { QuaZip zip(source); if (!zip.open(QuaZip::mdUnzip)) { @@ -52,9 +52,6 @@ static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibH do { QString name = zip.getCurrentFileName(); auto lowercase = name.toLower(); - if (nativeGLFW && name.contains("glfw")) { - continue; - } if (nativeOpenAL && name.contains("openal")) { continue; } @@ -83,14 +80,15 @@ void ExtractNatives::executeTask() return; } auto settings = minecraftInstance->settings(); + + // We only need OpenAL here, as modern versions of LWJGL (3+) are handled by JVM args, while older versions (2) didn't have GLFW bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool(); - bool nativeGLFW = settings->get("UseNativeGLFW").toBool(); auto outputPath = minecraftInstance->getNativePath(); auto javaVersion = minecraftInstance->getJavaVersion(); bool jniHackEnabled = javaVersion.major() >= 8; for (const auto& source : toExtract) { - if (!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL, nativeGLFW)) { + if (!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL)) { const char* reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'"); emit logLine(QString(reason).arg(source, outputPath), MessageLevel::Fatal); emitFailed(tr(reason).arg(source, outputPath)); From 83aa0062c7d831ca42ed4d82e5f6162ac8793be8 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 2 Aug 2023 13:45:08 +0200 Subject: [PATCH 234/398] feat: add custom native library path settings Signed-off-by: Sefa Eyeoglu --- CMakeLists.txt | 12 +++++ buildconfig/BuildConfig.cpp.in | 3 ++ buildconfig/BuildConfig.h | 3 ++ launcher/Application.cpp | 13 ++++++ launcher/Application.h | 4 ++ launcher/minecraft/MinecraftInstance.cpp | 20 ++++++--- launcher/ui/pages/global/MinecraftPage.cpp | 35 ++++++++++++++- launcher/ui/pages/global/MinecraftPage.h | 3 ++ launcher/ui/pages/global/MinecraftPage.ui | 40 +++++++++++++++-- .../pages/instance/InstanceSettingsPage.cpp | 34 +++++++++++++- .../ui/pages/instance/InstanceSettingsPage.h | 3 ++ .../ui/pages/instance/InstanceSettingsPage.ui | 44 ++++++++++++++++--- 12 files changed, 196 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a2853cb5a..a8dd7a73d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,6 +216,18 @@ set(Launcher_SUBREDDIT_URL "https://prismlauncher.org/reddit" CACHE STRING "URL set(Launcher_FORCE_BUNDLED_LIBS OFF CACHE BOOL "Prevent using system libraries, if they are available as submodules") set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build against") +# Native libraries +if(UNIX AND APPLE) + set(Launcher_GLFW_LIBRARY_NAME "libglfw.dylib" CACHE STRING "Name of native glfw library") + set(Launcher_OPENAL_LIBRARY_NAME "libopenal.dylib" CACHE STRING "Name of native glfw library") +elseif(UNIX) + set(Launcher_GLFW_LIBRARY_NAME "libglfw.so" CACHE STRING "Name of native glfw library") + set(Launcher_OPENAL_LIBRARY_NAME "libopenal.so" CACHE STRING "Name of native glfw library") +elseif(WIN32) + set(Launcher_GLFW_LIBRARY_NAME "glfw.dll" CACHE STRING "Name of native glfw library") + set(Launcher_OPENAL_LIBRARY_NAME "OpenAL.dll" CACHE STRING "Name of native glfw library") +endif() + # API Keys # NOTE: These API keys are here for convenience. If you rebrand this software or intend to break the terms of service # of these platforms, please change these API keys beforehand. diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index d7662a7a4..1eb0022b8 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -110,6 +110,9 @@ Config::Config() FLAME_API_KEY = "@Launcher_CURSEFORGE_API_KEY@"; META_URL = "@Launcher_META_URL@"; + GLFW_LIBRARY_NAME = "@Launcher_GLFW_LIBRARY_NAME@"; + OPENAL_LIBRARY_NAME = "@Launcher_OPENAL_LIBRARY_NAME@"; + BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@"; TRANSLATIONS_URL = "@Launcher_TRANSLATIONS_URL@"; MATRIX_URL = "@Launcher_MATRIX_URL@"; diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 387f494f3..a5649b98f 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -134,6 +134,9 @@ class Config { */ QString META_URL; + QString GLFW_LIBRARY_NAME; + QString OPENAL_LIBRARY_NAME; + QString BUG_TRACKER_URL; QString TRANSLATIONS_URL; QString MATRIX_URL; diff --git a/launcher/Application.cpp b/launcher/Application.cpp index a13935101..6daa5a84b 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -582,7 +582,9 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // Native library workarounds m_settings->registerSetting("UseNativeOpenAL", false); + m_settings->registerSetting("CustomOpenALPath", ""); m_settings->registerSetting("UseNativeGLFW", false); + m_settings->registerSetting("CustomGLFWPath", ""); // Peformance related options m_settings->registerSetting("EnableFeralGamemode", false); @@ -842,6 +844,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) updateCapabilities(); + detectLibraries(); + if (createSetupWizard()) { return; } @@ -1412,6 +1416,15 @@ void Application::updateCapabilities() #endif } +void Application::detectLibraries() +{ +#ifdef Q_OS_LINUX + m_detectedGLFWPath = MangoHud::findLibrary(BuildConfig.GLFW_LIBRARY_NAME); + m_detectedOpenALPath = MangoHud::findLibrary(BuildConfig.OPENAL_LIBRARY_NAME); + qDebug() << m_detectedGLFWPath << m_detectedOpenALPath; +#endif +} + QString Application::getJarPath(QString jarFile) { QStringList potentialPaths = { diff --git a/launcher/Application.h b/launcher/Application.h index 6bc332749..5807107cf 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -142,6 +142,8 @@ class Application : public QApplication { void updateCapabilities(); + void detectLibraries(); + /*! * Finds and returns the full path to a jar file. * Returns a null-string if it could not be found. @@ -275,6 +277,8 @@ class Application : public QApplication { SetupWizard* m_setupWizard = nullptr; public: + QString m_detectedGLFWPath; + QString m_detectedOpenALPath; QString m_instanceIdToLaunch; QString m_serverToJoin; QString m_profileToUse; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 40fde6cb3..bfc4ad98a 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -166,7 +166,9 @@ void MinecraftInstance::loadSpecificSettings() // Native library workarounds auto nativeLibraryWorkaroundsOverride = m_settings->registerSetting("OverrideNativeWorkarounds", false); m_settings->registerOverride(global_settings->getSetting("UseNativeOpenAL"), nativeLibraryWorkaroundsOverride); + m_settings->registerOverride(global_settings->getSetting("CustomOpenALPath"), nativeLibraryWorkaroundsOverride); m_settings->registerOverride(global_settings->getSetting("UseNativeGLFW"), nativeLibraryWorkaroundsOverride); + m_settings->registerOverride(global_settings->getSetting("CustomGLFWPath"), nativeLibraryWorkaroundsOverride); // Peformance related options auto performanceOverride = m_settings->registerSetting("OverridePerformance", false); @@ -390,22 +392,28 @@ QStringList MinecraftInstance::extraArguments() list.append("-Dloader.disable_beacon=true"); } -#ifdef Q_OS_LINUX { QString openALPath; QString glfwPath; - if (settings()->get("UseNativeOpenAL").toBool()) - openALPath = MangoHud::findLibrary("libopenal.so"); - if (settings()->get("UseNativeGLFW").toBool()) - glfwPath = MangoHud::findLibrary("libglfw.so"); + if (settings()->get("UseNativeOpenAL").toBool()) { + auto customPath = settings()->get("CustomOpenALPath").toString(); + openALPath = APPLICATION->m_detectedOpenALPath; + if (!customPath.isEmpty()) + openALPath = customPath; + } + if (settings()->get("UseNativeGLFW").toBool()) { + auto customPath = settings()->get("CustomGLFWPath").toString(); + glfwPath = APPLICATION->m_detectedGLFWPath; + if (!customPath.isEmpty()) + glfwPath = customPath; + } if (!openALPath.isEmpty()) list.append("-Dorg.lwjgl.openal.libname=" + openALPath); if (!glfwPath.isEmpty()) list.append("-Dorg.lwjgl.glfw.libname=" + glfwPath); } -#endif return list; } diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp index 866a4121c..1c7747210 100644 --- a/launcher/ui/pages/global/MinecraftPage.cpp +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -35,6 +35,7 @@ */ #include "MinecraftPage.h" +#include "BuildConfig.h" #include "ui_MinecraftPage.h" #include @@ -44,9 +45,15 @@ #include "Application.h" #include "settings/SettingsObject.h" +#ifdef Q_OS_LINUX +#include "MangoHud.h" +#endif + MinecraftPage::MinecraftPage(QWidget* parent) : QWidget(parent), ui(new Ui::MinecraftPage) { ui->setupUi(this); + connect(ui->useNativeGLFWCheck, &QAbstractButton::toggled, this, &MinecraftPage::onUseNativeGLFWChanged); + connect(ui->useNativeOpenALCheck, &QAbstractButton::toggled, this, &MinecraftPage::onUseNativeOpenALChanged); loadSettings(); updateCheckboxStuff(); } @@ -74,6 +81,16 @@ void MinecraftPage::on_maximizedCheckBox_clicked(bool checked) updateCheckboxStuff(); } +void MinecraftPage::onUseNativeGLFWChanged(bool checked) +{ + ui->lineEditGLFWPath->setEnabled(checked); +} + +void MinecraftPage::onUseNativeOpenALChanged(bool checked) +{ + ui->lineEditOpenALPath->setEnabled(checked); +} + void MinecraftPage::applySettings() { auto s = APPLICATION->settings(); @@ -84,8 +101,10 @@ void MinecraftPage::applySettings() s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); // Native library workarounds - s->set("UseNativeOpenAL", ui->useNativeOpenALCheck->isChecked()); s->set("UseNativeGLFW", ui->useNativeGLFWCheck->isChecked()); + s->set("CustomGLFWPath", ui->lineEditGLFWPath->text()); + s->set("UseNativeOpenAL", ui->useNativeOpenALCheck->isChecked()); + s->set("CustomOpenALPath", ui->lineEditOpenALPath->text()); // Peformance related options s->set("EnableFeralGamemode", ui->enableFeralGamemodeCheck->isChecked()); @@ -114,8 +133,20 @@ void MinecraftPage::loadSettings() ui->windowWidthSpinBox->setValue(s->get("MinecraftWinWidth").toInt()); ui->windowHeightSpinBox->setValue(s->get("MinecraftWinHeight").toInt()); - ui->useNativeOpenALCheck->setChecked(s->get("UseNativeOpenAL").toBool()); ui->useNativeGLFWCheck->setChecked(s->get("UseNativeGLFW").toBool()); + ui->lineEditGLFWPath->setText(s->get("CustomGLFWPath").toString()); + ui->lineEditGLFWPath->setPlaceholderText(tr("Path to %1 library file").arg(BuildConfig.GLFW_LIBRARY_NAME)); +#ifdef Q_OS_LINUX + if (!APPLICATION->m_detectedGLFWPath.isEmpty()) + ui->lineEditGLFWPath->setPlaceholderText(tr("Auto detected path: %1").arg(APPLICATION->m_detectedGLFWPath)); +#endif + ui->useNativeOpenALCheck->setChecked(s->get("UseNativeOpenAL").toBool()); + ui->lineEditOpenALPath->setText(s->get("CustomOpenALPath").toString()); + ui->lineEditOpenALPath->setPlaceholderText(tr("Path to %1 library file").arg(BuildConfig.OPENAL_LIBRARY_NAME)); +#ifdef Q_OS_LINUX + if (!APPLICATION->m_detectedOpenALPath.isEmpty()) + ui->lineEditOpenALPath->setPlaceholderText(tr("Auto detected path: %1").arg(APPLICATION->m_detectedOpenALPath)); +#endif ui->enableFeralGamemodeCheck->setChecked(s->get("EnableFeralGamemode").toBool()); ui->enableMangoHud->setChecked(s->get("EnableMangoHud").toBool()); diff --git a/launcher/ui/pages/global/MinecraftPage.h b/launcher/ui/pages/global/MinecraftPage.h index 28c31b5d8..5facfbb3f 100644 --- a/launcher/ui/pages/global/MinecraftPage.h +++ b/launcher/ui/pages/global/MinecraftPage.h @@ -70,6 +70,9 @@ class MinecraftPage : public QWidget, public BasePage { private slots: void on_maximizedCheckBox_clicked(bool checked); + void onUseNativeGLFWChanged(bool checked); + void onUseNativeOpenALChanged(bool checked); + private: Ui::MinecraftPage* ui; }; diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 393b0f358..98e90e4ec 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -214,21 +214,55 @@ Native library workarounds - - + + Use system installation of &GLFW - + + + + &GLFW library path + + + lineEditGLFWPath + + + + Use system installation of &OpenAL + + + + &OpenAL library path + + + lineEditOpenALPath + + + + + + + false + + + + + + + false + + + diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index f7be91684..d603237b6 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -66,6 +66,10 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance* inst, QWidget* parent) connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); connect(ui->instanceAccountSelector, QOverload::of(&QComboBox::currentIndexChanged), this, &InstanceSettingsPage::changeInstanceAccount); + + connect(ui->useNativeGLFWCheck, &QAbstractButton::toggled, this, &InstanceSettingsPage::onUseNativeGLFWChanged); + connect(ui->useNativeOpenALCheck, &QAbstractButton::toggled, this, &InstanceSettingsPage::onUseNativeOpenALChanged); + loadSettings(); updateThresholds(); @@ -198,11 +202,15 @@ void InstanceSettingsPage::applySettings() bool workarounds = ui->nativeWorkaroundsGroupBox->isChecked(); m_settings->set("OverrideNativeWorkarounds", workarounds); if (workarounds) { - m_settings->set("UseNativeOpenAL", ui->useNativeOpenALCheck->isChecked()); m_settings->set("UseNativeGLFW", ui->useNativeGLFWCheck->isChecked()); + m_settings->set("CustomGLFWPath", ui->lineEditGLFWPath->text()); + m_settings->set("UseNativeOpenAL", ui->useNativeOpenALCheck->isChecked()); + m_settings->set("CustomOpenALPath", ui->lineEditOpenALPath->text()); } else { - m_settings->reset("UseNativeOpenAL"); m_settings->reset("UseNativeGLFW"); + m_settings->reset("CustomGLFWPath"); + m_settings->reset("UseNativeOpenAL"); + m_settings->reset("CustomOpenALPath"); } // Performance @@ -312,7 +320,19 @@ void InstanceSettingsPage::loadSettings() // Workarounds ui->nativeWorkaroundsGroupBox->setChecked(m_settings->get("OverrideNativeWorkarounds").toBool()); ui->useNativeGLFWCheck->setChecked(m_settings->get("UseNativeGLFW").toBool()); + ui->lineEditGLFWPath->setText(m_settings->get("CustomGLFWPath").toString()); +#ifdef Q_OS_LINUX + ui->lineEditGLFWPath->setPlaceholderText(APPLICATION->m_detectedGLFWPath); +#else + ui->lineEditGLFWPath->setPlaceholderText(tr("Path to %1 library file").arg(BuildConfig.GLFW_LIBRARY_NAME)); +#endif ui->useNativeOpenALCheck->setChecked(m_settings->get("UseNativeOpenAL").toBool()); + ui->lineEditOpenALPath->setText(m_settings->get("CustomOpenALPath").toString()); +#ifdef Q_OS_LINUX + ui->lineEditOpenALPath->setPlaceholderText(APPLICATION->m_detectedOpenALPath); +#else + ui->lineEditGLFWPath->setPlaceholderText(tr("Path to %1 library file").arg(BuildConfig.OPENAL_LIBRARY_NAME)); +#endif // Performance ui->perfomanceGroupBox->setChecked(m_settings->get("OverridePerformance").toBool()); @@ -408,6 +428,16 @@ void InstanceSettingsPage::on_javaTestBtn_clicked() checker->run(); } +void InstanceSettingsPage::onUseNativeGLFWChanged(bool checked) +{ + ui->lineEditGLFWPath->setEnabled(checked); +} + +void InstanceSettingsPage::onUseNativeOpenALChanged(bool checked) +{ + ui->lineEditOpenALPath->setEnabled(checked); +} + void InstanceSettingsPage::updateAccountsMenu() { ui->instanceAccountSelector->clear(); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 21ecbaf8e..8b78dcb7f 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -71,6 +71,9 @@ class InstanceSettingsPage : public QWidget, public BasePage { void on_javaBrowseBtn_clicked(); void on_maxMemSpinBox_valueChanged(int i); + void onUseNativeGLFWChanged(bool checked); + void onUseNativeOpenALChanged(bool checked); + void applySettings(); void loadSettings(); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 380d8c88c..fcc2a5d0a 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -443,18 +443,52 @@ false - - + + + + + Use system installation of OpenAL + + + + + + + &GLFW library path + + + lineEditGLFWPath + + + + Use system installation of GLFW - - + + + + false + + + + + - Use system installation of OpenAL + &OpenAL library path + + + lineEditOpenALPath + + + + + + + false From 4c446ccd500f7a0bc136b66b554fd7880c6f5168 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 2 Aug 2023 13:47:50 +0200 Subject: [PATCH 235/398] fix: remove meta OpenAL workaround LWJGL 2 doesn't have a separate zip for OpenAL. So there is no reason for this code. Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/launch/ExtractNatives.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/launcher/minecraft/launch/ExtractNatives.cpp b/launcher/minecraft/launch/ExtractNatives.cpp index 1aa4dccc4..8f3cac4d1 100644 --- a/launcher/minecraft/launch/ExtractNatives.cpp +++ b/launcher/minecraft/launch/ExtractNatives.cpp @@ -39,7 +39,7 @@ static QString replaceSuffix(QString target, const QString& suffix, const QStrin return target + replacement; } -static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack, bool nativeOpenAL) +static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack) { QuaZip zip(source); if (!zip.open(QuaZip::mdUnzip)) { @@ -52,9 +52,6 @@ static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibH do { QString name = zip.getCurrentFileName(); auto lowercase = name.toLower(); - if (nativeOpenAL && name.contains("openal")) { - continue; - } if (applyJnilibHack) { name = replaceSuffix(name, ".jnilib", ".dylib"); } @@ -81,14 +78,11 @@ void ExtractNatives::executeTask() } auto settings = minecraftInstance->settings(); - // We only need OpenAL here, as modern versions of LWJGL (3+) are handled by JVM args, while older versions (2) didn't have GLFW - bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool(); - auto outputPath = minecraftInstance->getNativePath(); auto javaVersion = minecraftInstance->getJavaVersion(); bool jniHackEnabled = javaVersion.major() >= 8; for (const auto& source : toExtract) { - if (!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL)) { + if (!unzipNatives(source, outputPath, jniHackEnabled)) { const char* reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'"); emit logLine(QString(reason).arg(source, outputPath), MessageLevel::Fatal); emitFailed(tr(reason).arg(source, outputPath)); From f1c3da6583d004273e5812a0b40977200ce330d6 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 2 Aug 2023 13:49:59 +0200 Subject: [PATCH 236/398] fix: fix typo Signed-off-by: Sefa Eyeoglu --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a8dd7a73d..638fba051 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,13 +219,13 @@ set(Launcher_QT_VERSION_MAJOR "6" CACHE STRING "Major Qt version to build agains # Native libraries if(UNIX AND APPLE) set(Launcher_GLFW_LIBRARY_NAME "libglfw.dylib" CACHE STRING "Name of native glfw library") - set(Launcher_OPENAL_LIBRARY_NAME "libopenal.dylib" CACHE STRING "Name of native glfw library") + set(Launcher_OPENAL_LIBRARY_NAME "libopenal.dylib" CACHE STRING "Name of native openal library") elseif(UNIX) set(Launcher_GLFW_LIBRARY_NAME "libglfw.so" CACHE STRING "Name of native glfw library") - set(Launcher_OPENAL_LIBRARY_NAME "libopenal.so" CACHE STRING "Name of native glfw library") + set(Launcher_OPENAL_LIBRARY_NAME "libopenal.so" CACHE STRING "Name of native openal library") elseif(WIN32) set(Launcher_GLFW_LIBRARY_NAME "glfw.dll" CACHE STRING "Name of native glfw library") - set(Launcher_OPENAL_LIBRARY_NAME "OpenAL.dll" CACHE STRING "Name of native glfw library") + set(Launcher_OPENAL_LIBRARY_NAME "OpenAL.dll" CACHE STRING "Name of native openal library") endif() # API Keys From b927e58126440d735803251caa3e03d29e4a0547 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 2 Aug 2023 13:51:13 +0200 Subject: [PATCH 237/398] fix: improve debug message Signed-off-by: Sefa Eyeoglu --- launcher/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6daa5a84b..0f25589ed 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1421,7 +1421,7 @@ void Application::detectLibraries() #ifdef Q_OS_LINUX m_detectedGLFWPath = MangoHud::findLibrary(BuildConfig.GLFW_LIBRARY_NAME); m_detectedOpenALPath = MangoHud::findLibrary(BuildConfig.OPENAL_LIBRARY_NAME); - qDebug() << m_detectedGLFWPath << m_detectedOpenALPath; + qDebug() << "Detected native libraries:" << m_detectedGLFWPath << m_detectedOpenALPath; #endif } From c2d6a137aba6d41df709c73096f4521df3779304 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 2 Aug 2023 13:56:23 +0200 Subject: [PATCH 238/398] fix: only add native library overrides if files exist Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/MinecraftInstance.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index bfc4ad98a..62d22019f 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -397,22 +397,25 @@ QStringList MinecraftInstance::extraArguments() QString glfwPath; if (settings()->get("UseNativeOpenAL").toBool()) { - auto customPath = settings()->get("CustomOpenALPath").toString(); openALPath = APPLICATION->m_detectedOpenALPath; + auto customPath = settings()->get("CustomOpenALPath").toString(); if (!customPath.isEmpty()) openALPath = customPath; } if (settings()->get("UseNativeGLFW").toBool()) { - auto customPath = settings()->get("CustomGLFWPath").toString(); glfwPath = APPLICATION->m_detectedGLFWPath; + auto customPath = settings()->get("CustomGLFWPath").toString(); if (!customPath.isEmpty()) glfwPath = customPath; } - if (!openALPath.isEmpty()) - list.append("-Dorg.lwjgl.openal.libname=" + openALPath); - if (!glfwPath.isEmpty()) - list.append("-Dorg.lwjgl.glfw.libname=" + glfwPath); + QFileInfo openALInfo(openALPath); + QFileInfo glfwInfo(glfwPath); + + if (!openALPath.isEmpty() && openALInfo.exists()) + list.append("-Dorg.lwjgl.openal.libname=" + openALInfo.absoluteFilePath()); + if (!glfwPath.isEmpty() && glfwInfo.exists()) + list.append("-Dorg.lwjgl.glfw.libname=" + glfwInfo.absoluteFilePath()); } return list; From 06aba530d7154f0cff76b2d5dc650a428ff1a54e Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 2 Aug 2023 14:22:55 +0200 Subject: [PATCH 239/398] fix: add missing header Signed-off-by: Sefa Eyeoglu --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index d603237b6..108f2c274 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -48,6 +48,7 @@ #include "ui/widgets/CustomCommands.h" #include "Application.h" +#include "BuildConfig.h" #include "JavaCommon.h" #include "minecraft/auth/AccountList.h" From 3a0aa353cc6c0c501a1a4cf1a3fa7600c798235a Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 6 Aug 2023 21:05:51 +0200 Subject: [PATCH 240/398] feat: add NeoForge to ModLoaderType Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/PackProfile.cpp | 3 ++- launcher/modplatform/ResourceAPI.h | 4 +++- launcher/modplatform/flame/FlameAPI.h | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index cf8270cd2..92988808a 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -62,7 +62,8 @@ #include "Application.h" #include "modplatform/ResourceAPI.h" -static const QMap modloaderMapping{ { "net.minecraftforge", ResourceAPI::Forge }, +static const QMap modloaderMapping{ { "net.neoforged", ResourceAPI::NeoForge }, + { "net.minecraftforge", ResourceAPI::Forge }, { "net.fabricmc.fabric-loader", ResourceAPI::Fabric }, { "org.quiltmc.quilt-loader", ResourceAPI::Quilt }, { "com.mumfrey.liteloader", ResourceAPI::LiteLoader } }; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index a92217a06..f6ccb426d 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -54,7 +54,7 @@ class ResourceAPI { public: virtual ~ResourceAPI() = default; - enum ModLoaderType { Forge = 1 << 0, Cauldron = 1 << 1, LiteLoader = 1 << 2, Fabric = 1 << 3, Quilt = 1 << 4 }; + enum ModLoaderType { NeoForge = 1 << 0, Forge = 1 << 1, Cauldron = 1 << 2, LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5 }; Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType) struct SortingMethod { @@ -164,6 +164,8 @@ class ResourceAPI { static auto getModLoaderString(ModLoaderType type) -> const QString { switch (type) { + case NeoForge: + return "neoforge"; case Forge: return "forge"; case Cauldron: diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 49bc316f2..33b1bed7c 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -46,7 +46,9 @@ class FlameAPI : public NetworkResourceAPI { return 4; // TODO: remove this once Quilt drops official Fabric support if (loaders & Quilt) // NOTE: Most if not all Fabric mods should work *currently* - return 4; // Quilt would probably be 5 + return 4; // FIXME: implement multiple loaders filter + if (loaders & NeoForge) + return 6; return 0; } From 52e5ee711108c95815ac6c711bd7296f1a25884d Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 6 Aug 2023 21:06:52 +0200 Subject: [PATCH 241/398] feat: add NeoForge to UIs Signed-off-by: Sefa Eyeoglu --- launcher/resources/multimc/multimc.qrc | 1 + .../resources/multimc/scalable/instances/neoforged.svg | 3 +++ launcher/ui/dialogs/InstallLoaderDialog.cpp | 4 +++- launcher/ui/pages/modplatform/CustomPage.cpp | 3 +++ launcher/ui/pages/modplatform/CustomPage.ui | 10 ++++++++++ 5 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 launcher/resources/multimc/scalable/instances/neoforged.svg diff --git a/launcher/resources/multimc/multimc.qrc b/launcher/resources/multimc/multimc.qrc index 8f079bb37..80981559b 100644 --- a/launcher/resources/multimc/multimc.qrc +++ b/launcher/resources/multimc/multimc.qrc @@ -350,6 +350,7 @@ scalable/instances/quiltmc.svg scalable/instances/fabricmc.svg + scalable/instances/neoforged.svg 128x128/instances/forge.png 128x128/instances/liteloader.png diff --git a/launcher/resources/multimc/scalable/instances/neoforged.svg b/launcher/resources/multimc/scalable/instances/neoforged.svg new file mode 100644 index 000000000..706d53a0e --- /dev/null +++ b/launcher/resources/multimc/scalable/instances/neoforged.svg @@ -0,0 +1,3 @@ + + +Sefa Eyeoglu <contact@scrumplex.net> diff --git a/launcher/ui/dialogs/InstallLoaderDialog.cpp b/launcher/ui/dialogs/InstallLoaderDialog.cpp index 840a328f3..541119d10 100644 --- a/launcher/ui/dialogs/InstallLoaderDialog.cpp +++ b/launcher/ui/dialogs/InstallLoaderDialog.cpp @@ -129,7 +129,9 @@ InstallLoaderDialog::InstallLoaderDialog(std::shared_ptr profile, c QList InstallLoaderDialog::getPages() { - return { // Forge + return { // NeoForge + new InstallLoaderPage("net.neoforged", "neoforged", tr("NeoForge"), {}, profile), + // Forge new InstallLoaderPage("net.minecraftforge", "forge", tr("Forge"), {}, profile), // Fabric new InstallLoaderPage("net.fabricmc.fabric-loader", "fabricmc", tr("Fabric"), Version("1.14"), profile), diff --git a/launcher/ui/pages/modplatform/CustomPage.cpp b/launcher/ui/pages/modplatform/CustomPage.cpp index 4ac21b012..068fb3a36 100644 --- a/launcher/ui/pages/modplatform/CustomPage.cpp +++ b/launcher/ui/pages/modplatform/CustomPage.cpp @@ -127,6 +127,9 @@ void CustomPage::loaderFilterChanged() ui->loaderVersionList->setEmptyString(tr("No mod loader is selected.")); ui->loaderVersionList->setEmptyMode(VersionListView::String); return; + } else if (ui->neoForgeFilter->isChecked()) { + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + m_selectedLoader = "net.neoforged"; } else if (ui->forgeFilter->isChecked()) { ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); m_selectedLoader = "net.minecraftforge"; diff --git a/launcher/ui/pages/modplatform/CustomPage.ui b/launcher/ui/pages/modplatform/CustomPage.ui index 0d89b5956..23351ccd4 100644 --- a/launcher/ui/pages/modplatform/CustomPage.ui +++ b/launcher/ui/pages/modplatform/CustomPage.ui @@ -194,6 +194,16 @@ + + + + NeoForge + + + loaderBtnGroup + + + From 01c37508353b805a4c19330e076232ede593e383 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 6 Aug 2023 21:07:24 +0200 Subject: [PATCH 242/398] feat: support NeoForge mrpack modpacks Signed-off-by: Sefa Eyeoglu --- .../modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 4 ++++ launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h | 2 +- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index cdbbd42d0..9ff6b374d 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -211,6 +211,8 @@ bool ModrinthCreationTask::createInstance() components->setComponentVersion("org.quiltmc.quilt-loader", m_quilt_version); if (!m_forge_version.isEmpty()) components->setComponentVersion("net.minecraftforge", m_forge_version); + if (!m_neoForge_version.isEmpty()) + components->setComponentVersion("net.neoforged", m_neoForge_version); if (m_instIcon != "default") { instance.setIconKey(m_instIcon); @@ -398,6 +400,8 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, m_quilt_version = Json::requireString(*it, "Quilt Loader version"); } else if (name == "forge") { m_forge_version = Json::requireString(*it, "Forge version"); + } else if (name == "neoforge") { + m_neoForge_version = Json::requireString(*it, "NeoForge version"); } else { throw JSONValidationError("Unknown dependency type: " + name); } diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h index 07e417be5..1bd5b7de9 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h @@ -39,7 +39,7 @@ class ModrinthCreationTask final : public InstanceCreationTask { private: QWidget* m_parent = nullptr; - QString m_minecraft_version, m_fabric_version, m_quilt_version, m_forge_version; + QString m_minecraft_version, m_fabric_version, m_quilt_version, m_forge_version, m_neoForge_version; QString m_managed_id, m_managed_version_id, m_managed_name; std::vector m_files; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 64c06d1ba..ad8fefac1 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -245,6 +245,7 @@ QByteArray ModrinthPackExportTask::generateIndex() const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); const ComponentPtr forge = profile->getComponent("net.minecraftforge"); + const ComponentPtr neoForge = profile->getComponent("net.neoforged"); // convert all available components to mrpack dependencies QJsonObject dependencies; @@ -256,6 +257,8 @@ QByteArray ModrinthPackExportTask::generateIndex() dependencies["fabric-loader"] = fabric->m_version; if (forge != nullptr) dependencies["forge"] = forge->m_version; + if (neoForge != nullptr) + dependencies["neoforge"] = neoForge->m_version; out["dependencies"] = dependencies; } From 62c14cea2aea28cc943e795bb0f8ea10495c926a Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 6 Aug 2023 22:14:18 +0200 Subject: [PATCH 243/398] fix: allow NeoForge in resource APIs Signed-off-by: Sefa Eyeoglu --- launcher/modplatform/flame/FlameAPI.h | 2 +- launcher/modplatform/modrinth/ModrinthAPI.h | 4 ++-- launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 33b1bed7c..af8f39482 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -23,7 +23,7 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] auto getSortingMethods() const -> QList override; - static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (Forge | Fabric | Quilt); } + static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (NeoForge | Forge | Fabric | Quilt); } private: static int getClassId(ModPlatform::ResourceType type) diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 58af14cc7..c3f6bab85 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -38,7 +38,7 @@ class ModrinthAPI : public NetworkResourceAPI { static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList { QStringList l; - for (auto loader : { Forge, Fabric, Quilt, LiteLoader }) { + for (auto loader : { NeoForge, Forge, Fabric, Quilt, LiteLoader }) { if (types & loader) { l << getModLoaderString(loader); } @@ -141,7 +141,7 @@ class ModrinthAPI : public NetworkResourceAPI { return s.isEmpty() ? QString() : s; } - static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (Forge | Fabric | Quilt | LiteLoader); } + static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (NeoForge | Forge | Fabric | Quilt | LiteLoader); } [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index a7c22832a..bff8fa2fe 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -111,8 +111,8 @@ void ModrinthCheckUpdate::executeTask() // so we may want to filter it QString loader_filter; if (m_loaders.has_value()) { - static auto flags = { ResourceAPI::ModLoaderType::Forge, ResourceAPI::ModLoaderType::Fabric, - ResourceAPI::ModLoaderType::Quilt }; + static auto flags = { ResourceAPI::ModLoaderType::NeoForge, ResourceAPI::ModLoaderType::Forge, + ResourceAPI::ModLoaderType::Fabric, ResourceAPI::ModLoaderType::Quilt }; for (auto flag : flags) { if (m_loaders.value().testFlag(flag)) { loader_filter = api.getModLoaderString(flag); From c22eec8f27e11a6517abb89075b36705d73b1983 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 15 Aug 2023 17:00:58 +0300 Subject: [PATCH 244/398] fixed crash on atlauncher pack install Signed-off-by: Trial97 --- .../atlauncher/ATLPackInstallTask.cpp | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 5d1a361df..e5771b7cd 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -1005,15 +1005,30 @@ static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& if (!vlist) return {}; - if (!vlist->isLoaded()) - vlist->load(Net::Mode::Online); + if (!vlist->isLoaded()) { + QEventLoop loadVersionLoop; + auto task = vlist->getLoadTask(); + QObject::connect(task.get(), &Task::finished, &loadVersionLoop, &QEventLoop::quit); + if (!task->isRunning()) + task->start(); + + loadVersionLoop.exec(); + } auto ver = vlist->getVersion(version); if (!ver) return {}; - if (!ver->isLoaded()) + if (!ver->isLoaded()) { + QEventLoop loadVersionLoop; ver->load(Net::Mode::Online); + auto task = ver->getCurrentTask(); + QObject::connect(task.get(), &Task::finished, &loadVersionLoop, &QEventLoop::quit); + if (!task->isRunning()) + task->start(); + + loadVersionLoop.exec(); + } return ver; } From 07f25d6ccadc1958729471f4d68155d33c072564 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 14:19:42 +0000 Subject: [PATCH 245/398] chore(deps): update korthout/backport-action action to v1.4.0 --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 77c1a8802..08cfb56dd 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -24,7 +24,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs - uses: korthout/backport-action@v1.3.1 + uses: korthout/backport-action@v1.4.0 with: # Config README: https://github.com/korthout/backport-action#backport-action pull_description: |- From 589d8b6923531a53cbccabb8b79ed9861d0fe27c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 16 Aug 2023 19:53:39 +0300 Subject: [PATCH 246/398] feat:Added remove metadata button Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 18 ++++++---- launcher/minecraft/mod/Mod.h | 2 ++ launcher/minecraft/mod/ModFolderModel.cpp | 19 +++++++++++ launcher/minecraft/mod/ModFolderModel.h | 1 + launcher/modplatform/ModIndex.h | 1 - .../pages/instance/ExternalResourcesPage.ui | 11 +++++++ launcher/ui/pages/instance/ModFolderPage.cpp | 33 +++++++++++++++++++ launcher/ui/pages/instance/ModFolderPage.h | 1 + 8 files changed, 79 insertions(+), 7 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index ae3dea8d8..c9952998c 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -132,17 +132,23 @@ auto Mod::destroy(QDir& index_dir, bool preserve_metadata, bool attempt_trash) - if (!preserve_metadata) { qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name()); - if (metadata()) { - Metadata::remove(index_dir, metadata()->slug); - } else { - auto n = name(); - Metadata::remove(index_dir, n); - } + destroyMetadata(index_dir); } return Resource::destroy(attempt_trash); } +void Mod::destroyMetadata(QDir& index_dir) +{ + if (metadata()) { + Metadata::remove(index_dir, metadata()->slug); + } else { + auto n = name(); + Metadata::remove(index_dir, n); + } + m_local_details.metadata = nullptr; +} + auto Mod::details() const -> const ModDetails& { return m_local_details; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 6dafecfc5..e97ee9d3b 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -93,6 +93,8 @@ class Mod : public Resource { // Delete all the files of this mod auto destroy(QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool; + // Delete the metadata only + void destroyMetadata(QDir& index_dir); void finishResolvingWithDetails(ModDetails&& details); diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 280e70d7b..d6ce98ed9 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -228,6 +228,25 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes) return true; } +bool ModFolderModel::deleteModsMeatadata(const QModelIndexList& indexes) +{ + if (indexes.isEmpty()) + return true; + + for (auto i : indexes) { + if (i.column() != 0) { + continue; + } + auto m = at(i.row()); + auto index_dir = indexDir(); + m->destroyMetadata(index_dir); + } + + update(); + + return true; +} + bool ModFolderModel::isValid() { return m_dir.exists() && m_dir.isReadable(); diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 06fd78149..c512c58f0 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -79,6 +79,7 @@ class ModFolderModel : public ResourceFolderModel { /// Deletes all the selected mods bool deleteMods(const QModelIndexList& indexes); + bool deleteModsMeatadata(const QModelIndexList& indexes); bool isValid(); diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index cad217034..0e18ccd17 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -128,7 +128,6 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; -QString getMetaURL(ResourceProvider provider, QVariant projectID); struct OverrideDep { QString quilt; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 3c8366917..56adce476 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -168,6 +168,17 @@ Go to mods home page + + + false + + + Remove metadata + + + Remove selected mod metadata + + diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 0f5e29cb6..146e1d973 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -92,6 +92,10 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->addAction(ui->actionVisitItemPage); connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); + ui->actionRemoveItemMetadata->setToolTip(tr("Remove mod's metadata")); + ui->actionsToolbar->insertActionAfter(ui->actionRemoveItem, ui->actionRemoveItemMetadata); + connect(ui->actionRemoveItemMetadata, &QAction::triggered, this, &ModFolderPage::deleteModMetadata); + auto check_allow_update = [this] { return ui->treeView->selectionModel()->hasSelection() || !m_model->empty(); }; connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] { @@ -104,11 +108,16 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr if (selected <= 1) { ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); + + ui->actionRemoveItemMetadata->setToolTip(tr("Remove mod's metadata")); } else { ui->actionVisitItemPage->setText(tr("Visit mods' pages")); ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); + + ui->actionRemoveItemMetadata->setToolTip(tr("Remove mods' metadata")); } ui->actionVisitItemPage->setEnabled(selected != 0); + ui->actionRemoveItemMetadata->setEnabled(selected != 0); }); connect(mods.get(), &ModFolderModel::rowsInserted, this, @@ -297,3 +306,27 @@ void ModFolderPage::visitModPages() DesktopServices::openUrl(url); } } + +void ModFolderPage::deleteModMetadata() +{ + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + QString text; + auto selectionCount = m_model->selectedMods(selection).length(); + if (selectionCount == 0) + return; + else if (selectionCount > 1) + text = tr("You are about to remove the metadata for %1 mods.\n" + "Are you sure?") + .arg(selectionCount); + else + text = tr("You are about to remove the metadata for %1.\n" + "Are you sure?") + .arg(m_model->at(selection.at(0).row())->name()); + + auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), text, QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response == QMessageBox::Yes) + m_model->deleteModsMeatadata(selection); +} diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index a23dcae18..0c654d0d1 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -61,6 +61,7 @@ class ModFolderPage : public ExternalResourcesPage { private slots: void removeItems(const QItemSelection& selection) override; + void deleteModMetadata(); void installMods(); void updateMods(); From f919d363b706e4c00317b56849702d8f95446bdb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 16 Aug 2023 20:02:32 +0300 Subject: [PATCH 247/398] made safe for vegetarians Signed-off-by: Trial97 --- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ModFolderModel.h | 2 +- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index d6ce98ed9..42ee94991 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -228,7 +228,7 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes) return true; } -bool ModFolderModel::deleteModsMeatadata(const QModelIndexList& indexes) +bool ModFolderModel::deleteModsMetadata(const QModelIndexList& indexes) { if (indexes.isEmpty()) return true; diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index c512c58f0..4d1bafaed 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -79,7 +79,7 @@ class ModFolderModel : public ResourceFolderModel { /// Deletes all the selected mods bool deleteMods(const QModelIndexList& indexes); - bool deleteModsMeatadata(const QModelIndexList& indexes); + bool deleteModsMetadata(const QModelIndexList& indexes); bool isValid(); diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 146e1d973..d4e7a25c9 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -328,5 +328,5 @@ void ModFolderPage::deleteModMetadata() ->exec(); if (response == QMessageBox::Yes) - m_model->deleteModsMeatadata(selection); + m_model->deleteModsMetadata(selection); } From 6c2c724bd99d442f7856da1a2ef4ebdd674064d1 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Wed, 16 Aug 2023 21:03:09 +0300 Subject: [PATCH 248/398] Update launcher/ui/pages/instance/ExternalResourcesPage.ui Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/pages/instance/ExternalResourcesPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 56adce476..ba703f77d 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -176,7 +176,7 @@ Remove metadata - Remove selected mod metadata + Remove mod's metadata From b0e197de38858c3fe6bc5fbb62570efd3359c802 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 16 Aug 2023 21:26:43 +0300 Subject: [PATCH 249/398] removed warning for one mod selected Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 25 +++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index d4e7a25c9..b42bbf466 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -310,23 +310,20 @@ void ModFolderPage::visitModPages() void ModFolderPage::deleteModMetadata() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - QString text; auto selectionCount = m_model->selectedMods(selection).length(); if (selectionCount == 0) return; - else if (selectionCount > 1) - text = tr("You are about to remove the metadata for %1 mods.\n" - "Are you sure?") - .arg(selectionCount); - else - text = tr("You are about to remove the metadata for %1.\n" - "Are you sure?") - .arg(m_model->at(selection.at(0).row())->name()); + if (selectionCount > 1) { + auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), + tr("You are about to remove the metadata for %1 mods.\n" + "Are you sure?") + .arg(selectionCount), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); - auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), text, QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::No, QMessageBox::No) - ->exec(); + if (response != QMessageBox::Yes) + return; + } - if (response == QMessageBox::Yes) - m_model->deleteModsMetadata(selection); + m_model->deleteModsMetadata(selection); } From f0da16a758e4d3c2d41813f723b21390281e4a4e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 17 Aug 2023 00:13:12 +0300 Subject: [PATCH 250/398] removed line Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ImportPage.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index ee8757f85..3e3c36b7b 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -114,7 +114,6 @@ void ImportPage::updateState() bool isMRPack = fi.suffix() == "mrpack"; if (fi.exists() && (isZip || isMRPack)) { - QFileInfo fi(url.fileName()); auto extra_info = QMap(m_extra_info); qDebug() << "Pack Extra Info" << extra_info << m_extra_info; dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this, std::move(extra_info))); From bad44ea264eab5ce896f51a981cf1659f2755716 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 17 Aug 2023 00:14:49 +0300 Subject: [PATCH 251/398] feat:added flame install mod metadata Signed-off-by: Trial97 --- launcher/minecraft/mod/ModFolderModel.cpp | 49 +++++++++++++++++++++++ launcher/minecraft/mod/ModFolderModel.h | 2 + launcher/ui/MainWindow.cpp | 31 +++++++------- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 280e70d7b..eed35615c 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -51,8 +51,13 @@ #include "Application.h" +#include "Json.h" #include "minecraft/mod/tasks/LocalModParseTask.h" +#include "minecraft/mod/tasks/LocalModUpdateTask.h" #include "minecraft/mod/tasks/ModFolderLoadTask.h" +#include "modplatform/ModIndex.h" +#include "modplatform/flame/FlameAPI.h" +#include "modplatform/flame/FlameModIndex.h" ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) @@ -309,3 +314,47 @@ void ModFolderModel::onParseSucceeded(int ticket, QString mod_id) emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); } + +static const FlameAPI flameAPI; +bool ModFolderModel::installMod(QString file_path, ModPlatform::IndexedVersion& vers) +{ + if (vers.addonId.isValid()) { + ModPlatform::IndexedPack pack{ + vers.addonId, + ModPlatform::ResourceProvider::FLAME, + }; + + QEventLoop loop; + + auto response = std::make_shared(); + auto job = flameAPI.getProject(vers.addonId.toString(), response); + + QObject::connect(job.get(), &Task::failed, [&loop] { loop.quit(); }); + QObject::connect(job.get(), &Task::aborted, &loop, &QEventLoop::quit); + QObject::connect(job.get(), &Task::succeeded, [response, this, &vers, &loop, &pack] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qDebug() << *response; + return; + } + try { + auto obj = Json::requireObject(Json::requireObject(doc), "data"); + FlameMod::loadIndexedPack(pack, obj); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading mod info: " << e.cause(); + } + LocalModUpdateTask update_metadata(indexDir(), pack, vers); + QObject::connect(&update_metadata, &Task::finished, &loop, &QEventLoop::quit); + update_metadata.start(); + }); + + job->start(); + + loop.exec(); + } + return ResourceFolderModel::installResource(file_path); +} diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 06fd78149..f1890e87e 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -48,6 +48,7 @@ #include "minecraft/mod/tasks/LocalModParseTask.h" #include "minecraft/mod/tasks/ModFolderLoadTask.h" +#include "modplatform/ModIndex.h" class LegacyInstance; class BaseInstance; @@ -75,6 +76,7 @@ class ModFolderModel : public ResourceFolderModel { [[nodiscard]] Task* createParseTask(Resource&) override; bool installMod(QString file_path) { return ResourceFolderModel::installResource(file_path); } + bool installMod(QString file_path, ModPlatform::IndexedVersion& vers); bool uninstallMod(const QString& filename, bool preserve_metadata = false); /// Deletes all the selected mods diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 7d4148775..6736e912c 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -43,6 +43,8 @@ #include "FileSystem.h" #include "MainWindow.h" +#include "modplatform/ModIndex.h" +#include "modplatform/flame/FlameModIndex.h" #include "ui/dialogs/ExportToModListDialog.h" #include "ui_MainWindow.h" @@ -980,11 +982,12 @@ void MainWindow::processURLs(QList urls) if (url.scheme().isEmpty()) url.setScheme("file"); + ModPlatform::IndexedVersion version; QMap extra_info; QUrl local_url; if (!url.isLocalFile()) { // download the remote resource and identify QUrl dl_url; - if(url.scheme() == "curseforge") { + if (url.scheme() == "curseforge") { // need to find the download link for the modpack / resource // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE QUrlQuery query(url); @@ -1000,20 +1003,19 @@ void MainWindow::processURLs(QList urls) auto api = FlameAPI(); auto job = api.getFile(addonId, fileId, array); - QString resource_name; - connect(job.get(), &Task::failed, this, [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(job.get(), &Task::succeeded, this, [this, array, addonId, fileId, &dl_url, &resource_name] { + connect(job.get(), &Task::succeeded, this, [this, array, addonId, fileId, &dl_url, &version] { qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); auto doc = Json::requireDocument(*array); auto data = Json::ensureObject(Json::ensureObject(doc.object()), "data"); // No way to find out if it's a mod or a modpack before here // And also we need to check if it ends with .zip, instead of any better way - auto fileName = Json::ensureString(data, "fileName"); + version = FlameMod::loadIndexedPackVersion(data); + auto fileName = version.fileName; // Have to use ensureString then use QUrl to get proper url encoding - dl_url = QUrl(Json::ensureString(data, "downloadUrl", "", "downloadUrl")); + dl_url = QUrl(version.downloadUrl); if (!dl_url.isValid()) { CustomMessageBox::selectable( this, tr("Error"), @@ -1024,22 +1026,20 @@ void MainWindow::processURLs(QList urls) } QFileInfo dl_file(dl_url.fileName()); - resource_name = Json::ensureString(data, "displayName", dl_file.completeBaseName(), "displayName"); }); - { // drop stack + { // drop stack ProgressDialog dlUrlDialod(this); dlUrlDialod.setSkipButton(true, tr("Abort")); dlUrlDialod.execWithTask(job.get()); } - } else { dl_url = url; } if (!dl_url.isValid()) { - continue; // no valid url to download this resource + continue; // no valid url to download this resource } const QString path = dl_url.host() + '/' + dl_url.path(); @@ -1050,17 +1050,18 @@ void MainWindow::processURLs(QList urls) auto archivePath = entry->getFullPath(); bool dl_success = false; - connect(dl_job.get(), &Task::failed, this, [this](QString reason){CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(dl_job.get(), &Task::succeeded, this, [&dl_success]{dl_success = true;}); + connect(dl_job.get(), &Task::failed, this, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); + connect(dl_job.get(), &Task::succeeded, this, [&dl_success] { dl_success = true; }); - { // drop stack + { // drop stack ProgressDialog dlUrlDialod(this); dlUrlDialod.setSkipButton(true, tr("Abort")); dlUrlDialod.execWithTask(dl_job.get()); } if (!dl_success) { - continue; // no local file to identify + continue; // no local file to identify } local_url = QUrl::fromLocalFile(archivePath); @@ -1099,7 +1100,7 @@ void MainWindow::processURLs(QList urls) qWarning() << "Importing of Data Packs not supported at this time. Ignoring" << localFileName; break; case PackedResourceType::Mod: - minecraftInst->loaderModList()->installMod(localFileName); + minecraftInst->loaderModList()->installMod(localFileName, version); break; case PackedResourceType::ShaderPack: minecraftInst->shaderPackList()->installResource(localFileName); From 5e2d1ffdfbb3f673c063029c9a6c55071cba160a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 17 Aug 2023 00:23:53 +0300 Subject: [PATCH 252/398] removed line Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.cpp | 2 +- launcher/ui/MainWindow.cpp | 16 ++++++++-------- launcher/ui/pages/modplatform/ImportPage.cpp | 1 - 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 4a04e583d..74d7db975 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -204,7 +204,7 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, std::shared_ptrresponse) const +Task::Ptr FlameAPI::getFile(const QString& addonId, const QString& fileId, std::shared_ptr response) const { auto netJob = makeShared(QString("Flame::GetFile"), APPLICATION->network()); netJob->addNetAction( diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 7d4148775..067108f2d 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -984,7 +984,7 @@ void MainWindow::processURLs(QList urls) QUrl local_url; if (!url.isLocalFile()) { // download the remote resource and identify QUrl dl_url; - if(url.scheme() == "curseforge") { + if (url.scheme() == "curseforge") { // need to find the download link for the modpack / resource // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE QUrlQuery query(url); @@ -1027,19 +1027,18 @@ void MainWindow::processURLs(QList urls) resource_name = Json::ensureString(data, "displayName", dl_file.completeBaseName(), "displayName"); }); - { // drop stack + { // drop stack ProgressDialog dlUrlDialod(this); dlUrlDialod.setSkipButton(true, tr("Abort")); dlUrlDialod.execWithTask(job.get()); } - } else { dl_url = url; } if (!dl_url.isValid()) { - continue; // no valid url to download this resource + continue; // no valid url to download this resource } const QString path = dl_url.host() + '/' + dl_url.path(); @@ -1050,17 +1049,18 @@ void MainWindow::processURLs(QList urls) auto archivePath = entry->getFullPath(); bool dl_success = false; - connect(dl_job.get(), &Task::failed, this, [this](QString reason){CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(dl_job.get(), &Task::succeeded, this, [&dl_success]{dl_success = true;}); + connect(dl_job.get(), &Task::failed, this, + [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); + connect(dl_job.get(), &Task::succeeded, this, [&dl_success] { dl_success = true; }); - { // drop stack + { // drop stack ProgressDialog dlUrlDialod(this); dlUrlDialod.setSkipButton(true, tr("Abort")); dlUrlDialod.execWithTask(dl_job.get()); } if (!dl_success) { - continue; // no local file to identify + continue; // no local file to identify } local_url = QUrl::fromLocalFile(archivePath); diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index ee8757f85..3e3c36b7b 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -114,7 +114,6 @@ void ImportPage::updateState() bool isMRPack = fi.suffix() == "mrpack"; if (fi.exists() && (isZip || isMRPack)) { - QFileInfo fi(url.fileName()); auto extra_info = QMap(m_extra_info); qDebug() << "Pack Extra Info" << extra_info << m_extra_info; dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url, this, std::move(extra_info))); From 6da2e7d3f6f06916e9d92578546b5d80474aaa5f Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 17 Aug 2023 10:12:38 +0100 Subject: [PATCH 253/398] I was forced /j Co-authored-by: Sefa Eyeoglu Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index babf92989..d930d6811 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -272,10 +272,7 @@ void MinecraftInstance::populateLaunchMenu(QMenu* menu) profilerAction->setChecked(settings()->get("Profiler").toString() == profiler.key()); QString error; - if (profiler.value()->check(&error)) - profilerAction->setIcon(APPLICATION->getThemedIcon("status-good")); - else - profilerAction->setIcon(APPLICATION->getThemedIcon("status-bad")); + profilerAction->setEnabled(profiler.value()->check(&error)); } } From ffd8ed550f05e1336afc6ddc424b6733256ecf02 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 17 Aug 2023 10:16:52 +0100 Subject: [PATCH 254/398] Reformat Signed-off-by: TheKodeToad --- launcher/Application.cpp | 15 +++++---------- launcher/Application.h | 2 +- launcher/ui/InstanceWindow.h | 2 +- launcher/ui/MainWindow.cpp | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index c1bf7e5ef..4da7629ce 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1104,18 +1104,13 @@ bool Application::launch(InstancePtr instance, MinecraftServerTargetPtr serverToJoin, MinecraftAccountPtr accountToUse) { - if(m_updateRunning) - { + if (m_updateRunning) { qDebug() << "Cannot launch instances while an update is running. Please try again when updates are completed."; - } - else if(instance->canLaunch()) - { - auto & extras = m_instanceExtras[instance->id()]; + } else if (instance->canLaunch()) { + auto& extras = m_instanceExtras[instance->id()]; auto window = extras.window; - if(window) - { - if(!window->saveAll()) - { + if (window) { + if (!window->saveAll()) { return false; } } diff --git a/launcher/Application.h b/launcher/Application.h index a09f46b57..8a85fd952 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -187,7 +187,7 @@ class Application : public QApplication { void clickedOnDock(); #endif -public slots: + public slots: bool launch(InstancePtr instance, bool online = true, bool demo = false, diff --git a/launcher/ui/InstanceWindow.h b/launcher/ui/InstanceWindow.h index a8a7559fd..e5bc24d44 100644 --- a/launcher/ui/InstanceWindow.h +++ b/launcher/ui/InstanceWindow.h @@ -52,7 +52,7 @@ class PageContainer; class InstanceWindow : public QMainWindow, public BasePageContainer { Q_OBJECT -public: + public: explicit InstanceWindow(InstancePtr proc, QWidget* parent = 0); virtual ~InstanceWindow() = default; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 48feea099..36a6e379b 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -551,7 +551,7 @@ void MainWindow::updateMainToolBar() void MainWindow::updateLaunchButton() { - QMenu *launchMenu = ui->actionLaunchInstance->menu(); + QMenu* launchMenu = ui->actionLaunchInstance->menu(); if (launchMenu) launchMenu->clear(); else From aac734d174cc61d0a72c677e82c6ca2539c09633 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 17 Aug 2023 22:20:43 +0200 Subject: [PATCH 255/398] fix: add theoretical support for NeoForge in FTB modpacks Signed-off-by: Sefa Eyeoglu --- launcher/modplatform/import_ftb/PackHelpers.cpp | 6 +++++- launcher/modplatform/import_ftb/PackInstallTask.cpp | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/import_ftb/PackHelpers.cpp b/launcher/modplatform/import_ftb/PackHelpers.cpp index 4a1bbef96..118bdd157 100644 --- a/launcher/modplatform/import_ftb/PackHelpers.cpp +++ b/launcher/modplatform/import_ftb/PackHelpers.cpp @@ -59,7 +59,11 @@ Modpack parseDirectory(QString path) auto obj = Json::requireObject(target, "target"); auto name = Json::requireString(obj, "name", "name"); auto version = Json::requireString(obj, "version", "version"); - if (name == "forge") { + if (name == "neoforge") { + modpack.loaderType = ResourceAPI::NeoForge; + modpack.version = version; + break; + } else if (name == "forge") { modpack.loaderType = ResourceAPI::Forge; modpack.version = version; break; diff --git a/launcher/modplatform/import_ftb/PackInstallTask.cpp b/launcher/modplatform/import_ftb/PackInstallTask.cpp index b5e424d12..9e4decb0c 100644 --- a/launcher/modplatform/import_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/import_ftb/PackInstallTask.cpp @@ -68,6 +68,10 @@ void PackInstallTask::copySettings() auto modloader = m_pack.loaderType; if (modloader.has_value()) switch (modloader.value()) { + case ResourceAPI::NeoForge: { + components->setComponentVersion("net.neoforged", m_pack.version, true); + break; + } case ResourceAPI::Forge: { components->setComponentVersion("net.minecraftforge", m_pack.version, true); break; From 7ab391904aca58c09bead083c41b7bf4108361d1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 15 Aug 2023 14:13:29 +0300 Subject: [PATCH 256/398] Flame support for neoforge Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 8 ++++++-- launcher/modplatform/flame/FlamePackExportTask.cpp | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 9fe8d4865..45b4e2125 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -284,7 +284,7 @@ QString FlameCreationTask::getVersionForLoader(QString uid, QString loaderType, // filter by minecraft version, if the loader depends on a certain version. // not all mod loaders depend on a given Minecraft version, so we won't do this // filtering for those loaders. - if (loaderType == "forge") { + if (loaderType == "forge" || loaderType == "neoforge") { auto iter = std::find_if(reqs.begin(), reqs.end(), [mcVersion](const Meta::Require& req) { return req.uid == "net.minecraft" && req.equalsVersion == mcVersion; }); @@ -350,7 +350,11 @@ bool FlameCreationTask::createInstance() for (auto& loader : m_pack.minecraft.modLoaders) { auto id = loader.id; - if (id.startsWith("forge-")) { + if (id.startsWith("neoforge-")) { + id.remove("neoforge-"); + loaderType = "neoforge"; + loaderUid = "net.neoforged"; + } else if (id.startsWith("forge-")) { id.remove("forge-"); loaderType = "forge"; loaderUid = "net.minecraftforge"; diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index f5f3af372..0863f0b2b 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -381,6 +381,7 @@ QByteArray FlamePackExportTask::generateIndex() const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); const ComponentPtr forge = profile->getComponent("net.minecraftforge"); + const ComponentPtr neoforge = profile->getComponent("net.neoforged"); // convert all available components to mrpack dependencies if (minecraft != nullptr) @@ -392,6 +393,8 @@ QByteArray FlamePackExportTask::generateIndex() id = "fabric-" + fabric->getVersion(); else if (forge != nullptr) id = "forge-" + forge->getVersion(); + else if (neoforge != nullptr) + id = "neoforge-" + neoforge->getVersion(); version["modLoaders"] = QJsonArray(); if (!id.isEmpty()) { QJsonObject loader; From be2888d6fbf28e515206d8677f8f6c8fce8b6e89 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 17 Aug 2023 22:23:50 +0200 Subject: [PATCH 257/398] chore: reformat Signed-off-by: Sefa Eyeoglu --- launcher/modplatform/modrinth/ModrinthAPI.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index c3f6bab85..0f150e97a 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -141,7 +141,10 @@ class ModrinthAPI : public NetworkResourceAPI { return s.isEmpty() ? QString() : s; } - static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (NeoForge | Forge | Fabric | Quilt | LiteLoader); } + static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool + { + return loaders & (NeoForge | Forge | Fabric | Quilt | LiteLoader); + } [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { From f4ebeedc21c97df41168901c618a3b57357c7b7a Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 18 Aug 2023 09:01:57 +0200 Subject: [PATCH 258/398] fix: fix browse button size in skin upload dialog Signed-off-by: Sefa Eyeoglu --- launcher/ui/dialogs/SkinUploadDialog.ui | 6 ------ 1 file changed, 6 deletions(-) diff --git a/launcher/ui/dialogs/SkinUploadDialog.ui b/launcher/ui/dialogs/SkinUploadDialog.ui index 2c81a7fed..c6df92df3 100644 --- a/launcher/ui/dialogs/SkinUploadDialog.ui +++ b/launcher/ui/dialogs/SkinUploadDialog.ui @@ -35,12 +35,6 @@ 0 - - - 28 - 16777215 - - Browse From 6d1c67663dd5388b2209d162d517d6d9baa37d83 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 12:24:28 +0300 Subject: [PATCH 259/398] feat:added option to show playtime in hours Signed-off-by: Trial97 --- launcher/Application.cpp | 1 + launcher/MMCTime.cpp | 7 ++++--- launcher/MMCTime.h | 2 +- launcher/minecraft/MinecraftInstance.cpp | 11 +++++++---- launcher/ui/MainWindow.cpp | 4 +++- launcher/ui/pages/global/MinecraftPage.cpp | 2 ++ launcher/ui/pages/global/MinecraftPage.ui | 7 +++++++ 7 files changed, 25 insertions(+), 9 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 78de87470..442970158 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -598,6 +598,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("ShowGameTime", true); m_settings->registerSetting("ShowGlobalGameTime", true); m_settings->registerSetting("RecordGameTime", true); + m_settings->registerSetting("ShowGameTimeWithoutDays", false); // Minecraft mods m_settings->registerSetting("ModMetadataDisabled", false); diff --git a/launcher/MMCTime.cpp b/launcher/MMCTime.cpp index 3972dbd53..1765fd844 100644 --- a/launcher/MMCTime.cpp +++ b/launcher/MMCTime.cpp @@ -16,19 +16,20 @@ */ #include +#include #include #include #include -QString Time::prettifyDuration(int64_t duration) +QString Time::prettifyDuration(int64_t duration, bool noDays) { int seconds = (int)(duration % 60); duration /= 60; int minutes = (int)(duration % 60); duration /= 60; - int hours = (int)(duration % 24); - int days = (int)(duration / 24); + int hours = (int)(noDays ? duration : (duration % 24)); + int days = (int)(noDays ? 0 : (duration / 24)); if ((hours == 0) && (days == 0)) { return QObject::tr("%1min %2s").arg(minutes).arg(seconds); } diff --git a/launcher/MMCTime.h b/launcher/MMCTime.h index b7d34b5d8..ea6d37e7e 100644 --- a/launcher/MMCTime.h +++ b/launcher/MMCTime.h @@ -20,7 +20,7 @@ namespace Time { -QString prettifyDuration(int64_t duration); +QString prettifyDuration(int64_t duration, bool noDays = false); /** * @brief Returns a string with short form time duration ie. `2days 1h3m4s56.0ms`. diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 62d22019f..c90d43623 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -897,13 +897,16 @@ QString MinecraftInstance::getStatusbarDescription() if (m_settings->get("ShowGameTime").toBool()) { if (lastTimePlayed() > 0) { QDateTime lastLaunchTime = QDateTime::fromMSecsSinceEpoch(lastLaunch()); - description.append(tr(", last played on %1 for %2") - .arg(QLocale().toString(lastLaunchTime, QLocale::ShortFormat)) - .arg(Time::prettifyDuration(lastTimePlayed()))); + description.append( + tr(", last played on %1 for %2") + .arg(QLocale().toString(lastLaunchTime, QLocale::ShortFormat)) + .arg(Time::prettifyDuration(lastTimePlayed(), APPLICATION->settings()->get("ShowGameTimeWithoutDays").toBool()))); } if (totalTimePlayed() > 0) { - description.append(tr(", total played for %1").arg(Time::prettifyDuration(totalTimePlayed()))); + description.append( + tr(", total played for %1") + .arg(Time::prettifyDuration(totalTimePlayed(), APPLICATION->settings()->get("ShowGameTimeWithoutDays").toBool()))); } } if (hasCrashed()) { diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 067108f2d..de2b96345 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1810,7 +1810,9 @@ void MainWindow::updateStatusCenter() int timePlayed = APPLICATION->instances()->getTotalPlayTime(); if (timePlayed > 0) { - m_statusCenter->setText(tr("Total playtime: %1").arg(Time::prettifyDuration(timePlayed))); + m_statusCenter->setText( + tr("Total playtime: %1") + .arg(Time::prettifyDuration(timePlayed, APPLICATION->settings()->get("ShowGameTimeWithoutDays").toBool()))); } } // "Instance actions" are actions that require an instance to be selected (i.e. "new instance" is not here) diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp index 1c7747210..9beaa433e 100644 --- a/launcher/ui/pages/global/MinecraftPage.cpp +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -115,6 +115,7 @@ void MinecraftPage::applySettings() s->set("ShowGameTime", ui->showGameTime->isChecked()); s->set("ShowGlobalGameTime", ui->showGlobalGameTime->isChecked()); s->set("RecordGameTime", ui->recordGameTime->isChecked()); + s->set("ShowGameTimeWithoutDays", ui->showGameTimeWithoutDays->isChecked()); // Miscellaneous s->set("CloseAfterLaunch", ui->closeAfterLaunchCheck->isChecked()); @@ -169,6 +170,7 @@ void MinecraftPage::loadSettings() ui->showGameTime->setChecked(s->get("ShowGameTime").toBool()); ui->showGlobalGameTime->setChecked(s->get("ShowGlobalGameTime").toBool()); ui->recordGameTime->setChecked(s->get("RecordGameTime").toBool()); + ui->showGameTimeWithoutDays->setChecked(s->get("ShowGameTimeWithoutDays").toBool()); ui->closeAfterLaunchCheck->setChecked(s->get("CloseAfterLaunch").toBool()); ui->quitAfterGameStopCheck->setChecked(s->get("QuitAfterGameStop").toBool()); diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 98e90e4ec..89bef9491 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -138,6 +138,13 @@ + + + + Show time spent playing without days + + + From 28ffa8bf44f220e541d00204b52a45573fba645a Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Fri, 18 Aug 2023 12:57:08 +0300 Subject: [PATCH 260/398] Update launcher/ui/pages/global/MinecraftPage.ui Co-authored-by: Sefa Eyeoglu Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/pages/global/MinecraftPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 89bef9491..6fb21da42 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -141,7 +141,7 @@ - Show time spent playing without days + Show time spent playing in hours From d3acac16e664b5b36d5f7eb0c857bb400fdbdac8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 13:10:13 +0300 Subject: [PATCH 261/398] added -Wno-gnu-zero-variadic-macro-arguments and fixed more warnings Signed-off-by: Trial97 --- cmake/CompilerWarnings.cmake | 4 ++++ launcher/java/JavaInstall.h | 6 +++--- launcher/minecraft/mod/ResourceFolderModel.h | 3 ++- launcher/ui/widgets/VersionSelectWidget.h | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index 635e54289..0ded8fd60 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -90,6 +90,10 @@ function( -Wdouble-promotion # warn if float is implicit promoted to double -Wformat=2 # warn on security issues around functions that format output (ie printf) -Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation + # -Wgnu-zero-variadic-macro-arguments (part of -pedantic) is triggered by every qCDebug() call and therefore results + # in a lot of noise. This warning is only notifying us that clang is emulating the GCC behaviour + # instead of the exact standard wording so we can safely ignore it + -Wno-gnu-zero-variadic-macro-arguments ) endif() diff --git a/launcher/java/JavaInstall.h b/launcher/java/JavaInstall.h index 30815b5a8..49e9ed06e 100644 --- a/launcher/java/JavaInstall.h +++ b/launcher/java/JavaInstall.h @@ -24,11 +24,11 @@ struct JavaInstall : public BaseVersion { JavaInstall() {} JavaInstall(QString id, QString arch, QString path) : id(id), arch(arch), path(path) {} - virtual QString descriptor() { return id.toString(); } + virtual QString descriptor() override { return id.toString(); } - virtual QString name() { return id.toString(); } + virtual QString name() override { return id.toString(); } - virtual QString typeString() const { return arch; } + virtual QString typeString() const override { return arch; } virtual bool operator<(BaseVersion& a) override; virtual bool operator>(BaseVersion& a) override; diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 80c31e456..60b8879c0 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -330,7 +330,8 @@ void ResourceFolderModel::applyUpdates(QSet& current_set, QSet // When you have a Qt build with assertions turned on, proceeding here will abort the application if (added_set.size() > 0) { - beginInsertRows(QModelIndex(), m_resources.size(), m_resources.size() + added_set.size() - 1); + beginInsertRows(QModelIndex(), static_cast(m_resources.size()), + static_cast(m_resources.size() + added_set.size() - 1)); for (auto& added : added_set) { auto res = new_resources[added]; diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index 99729fbdf..d5ef1cc9f 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -82,7 +82,7 @@ class VersionSelectWidget : public QWidget { void selectedVersionChanged(BaseVersion::Ptr version); protected: - virtual void closeEvent(QCloseEvent*); + virtual void closeEvent(QCloseEvent*) override; private slots: void onTaskSucceeded(); From fecc1e087aefd276a18d7941d123f1f261a6d0d2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 13:35:50 +0300 Subject: [PATCH 262/398] Add Trial97 to contribuitors list Signed-off-by: Trial97 --- launcher/ui/dialogs/AboutDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp index 3c6f6ef16..f5eaff7a1 100644 --- a/launcher/ui/dialogs/AboutDialog.cpp +++ b/launcher/ui/dialogs/AboutDialog.cpp @@ -85,6 +85,7 @@ QString getCreditsHtml() stream << QString("

TayouVR %1

\n").arg(getGitHub("TayouVR")); stream << QString("

TheKodeToad %1

\n").arg(getGitHub("TheKodeToad")); stream << QString("

getchoo %1

\n").arg(getGitHub("getchoo")); + stream << QString("

Alexandru Tripon (Trial97) %1

\n").arg(getGitHub("Trial97")); stream << "
\n"; // TODO: possibly retrieve from git history at build time? From 44ff247f5f71ebeb95423ca37bf82d9913073522 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 20:03:02 +0300 Subject: [PATCH 263/398] feat:refactored modpack ux Signed-off-by: Trial97 --- launcher/modplatform/ResourceAPI.h | 2 + .../helpers/NetworkResourceAPI.cpp | 3 +- .../ui/pages/modplatform/ResourceModel.cpp | 57 ++++++++++ launcher/ui/pages/modplatform/ResourceModel.h | 1 + .../ui/pages/modplatform/ResourcePage.cpp | 3 - .../modplatform/atlauncher/AtlFilterModel.cpp | 3 +- .../modplatform/atlauncher/AtlListModel.cpp | 56 +++++++--- .../pages/modplatform/atlauncher/AtlPage.cpp | 4 +- .../pages/modplatform/atlauncher/AtlPage.ui | 93 +++++++++------- .../ui/pages/modplatform/flame/FlameModel.cpp | 55 +++++++-- .../ui/pages/modplatform/flame/FlameModel.h | 5 +- .../ui/pages/modplatform/flame/FlamePage.cpp | 10 ++ .../ui/pages/modplatform/flame/FlamePage.h | 5 +- .../modplatform/import_ftb/ImportFTBPage.cpp | 29 ++++- .../modplatform/import_ftb/ImportFTBPage.h | 3 + .../modplatform/import_ftb/ImportFTBPage.ui | 52 ++++++++- .../modplatform/import_ftb/ListModel.cpp | 105 ++++++++++++++++-- .../pages/modplatform/import_ftb/ListModel.h | 22 ++++ .../modplatform/legacy_ftb/ListModel.cpp | 90 ++++++++++----- .../pages/modplatform/legacy_ftb/ListModel.h | 2 + .../ui/pages/modplatform/legacy_ftb/Page.cpp | 13 +++ .../ui/pages/modplatform/legacy_ftb/Page.h | 5 +- .../ui/pages/modplatform/legacy_ftb/Page.ui | 49 +++++--- .../modplatform/modrinth/ModrinthModel.cpp | 62 +++++++++-- .../modplatform/modrinth/ModrinthModel.h | 5 +- .../modplatform/modrinth/ModrinthPage.cpp | 10 ++ .../pages/modplatform/modrinth/ModrinthPage.h | 4 + .../modplatform/technic/TechnicModel.cpp | 72 ++++++++---- .../pages/modplatform/technic/TechnicModel.h | 2 + .../pages/modplatform/technic/TechnicPage.cpp | 13 +++ .../pages/modplatform/technic/TechnicPage.h | 5 +- launcher/ui/widgets/ProjectItem.cpp | 2 +- 32 files changed, 679 insertions(+), 163 deletions(-) diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index a92217a06..bd0d2824f 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -109,6 +109,8 @@ class ResourceAPI { }; struct ProjectInfoCallbacks { std::function on_succeed; + std::function on_fail; + std::function on_abort; }; struct DependencySearchArgs { diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index 46b966620..506eb187e 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -72,7 +72,8 @@ Task::Ptr NetworkResourceAPI::getProjectInfo(ProjectInfoArgs&& args, ProjectInfo callbacks.on_succeed(doc, args.pack); }); - + QObject::connect(job.get(), &NetJob::failed, [callbacks](QString reason) { callbacks.on_fail(reason); }); + QObject::connect(job.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); }); return job; } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 0a7edb7b7..96803531b 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -132,6 +132,36 @@ void ResourceModel::search() if (hasActiveSearchJob()) return; + if (m_search_term.startsWith("#")) { + auto projectId = m_search_term.removeFirst(); + if (!projectId.isEmpty()) { + ResourceAPI::ProjectInfoCallbacks callbacks; + + // Use defaults if no callbacks are set + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestFailed(reason, -1); + }; + if (!callbacks.on_abort) + callbacks.on_abort = [this] { + if (!s_running_models.constFind(this).value()) + return; + searchRequestAborted(); + }; + + if (!callbacks.on_succeed) + callbacks.on_succeed = [this](auto& doc, auto pack) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestForOneSucceeded(doc); + }; + if (auto job = m_api->getProjectInfo({ projectId }, std::move(callbacks)); job) + runSearchJob(job); + return; + } + } auto args{ createSearchArguments() }; auto callbacks{ createSearchCallbacks() }; @@ -194,6 +224,12 @@ void ResourceModel::loadEntry(QModelIndex& entry) return; infoRequestSucceeded(doc, pack, entry); }; + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { + if (!s_running_models.constFind(this).value()) + return; + QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load project info:%1").arg(reason)); + }; if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job) runInfoJob(job); @@ -372,6 +408,27 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) endInsertRows(); } +void ResourceModel::searchRequestForOneSucceeded(QJsonDocument& doc) +{ + ModPlatform::IndexedPack::Ptr pack = std::make_shared(); + + try { + auto obj = Json::requireObject(doc); + if (obj.contains("data")) + obj = Json::requireObject(obj, "data"); + loadIndexedPack(*pack, obj); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause(); + } + + m_search_state = SearchState::Finished; + + beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + 1); + m_packs.append(pack); + endInsertRows(); +} + void ResourceModel::searchRequestFailed([[maybe_unused]] QString reason, int network_error_code) { switch (network_error_code) { diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index cc813d6e6..ecf4f8f79 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -149,6 +149,7 @@ class ResourceModel : public QAbstractListModel { private: /* Default search request callbacks */ void searchRequestSucceeded(QJsonDocument&); + void searchRequestForOneSucceeded(QJsonDocument&); void searchRequestFailed(QString reason, int network_error_code); void searchRequestAborted(); diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index c087e2be3..fc7d64a48 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -44,9 +44,6 @@ #include #include "Markdown.h" -#include "ResourceDownloadTask.h" - -#include "minecraft/MinecraftInstance.h" #include "ui/dialogs/ResourceDownloadDialog.h" #include "ui/pages/modplatform/ResourceModel.h" diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp index 9cd5eed53..dee3784e5 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlFilterModel.cpp @@ -67,9 +67,10 @@ bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParen if (searchTerm.isEmpty()) { return true; } - QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); ATLauncher::IndexedPack pack = sourceModel()->data(index, Qt::UserRole).value(); + if (searchTerm.startsWith("#")) + return QString::number(pack.id) == searchTerm.mid(1); return pack.name.contains(searchTerm, Qt::CaseInsensitive); } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 39f4f346a..b6fb71535 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -21,6 +21,7 @@ #include #include "net/ApiDownload.h" +#include "ui/widgets/ProjectItem.h" namespace Atl { @@ -46,27 +47,50 @@ QVariant ListModel::data(const QModelIndex& index, int role) const } ATLauncher::IndexedPack pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name; - } else if (role == Qt::ToolTipRole) { - return pack.name; - } else if (role == Qt::DecorationRole) { - if (m_logoMap.contains(pack.safeName)) { - return (m_logoMap.value(pack.safeName)); + switch (role) { + case Qt::ToolTipRole: { + if (pack.description.length() > 100) { + // some magic to prevent to long tooltips and replace html linebreaks + QString edit = pack.description.left(97); + edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); + return edit; + } + return pack.description; } - auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); + case Qt::DecorationRole: { + if (m_logoMap.contains(pack.safeName)) { + return (m_logoMap.value(pack.safeName)); + } + auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); - auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower()); - ((ListModel*)this)->requestLogo(pack.safeName, url); + auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower()); + ((ListModel*)this)->requestLogo(pack.safeName, url); - return icon; - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; + return icon; + } + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return pack.description; + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; } - return QVariant(); + return {}; } void ListModel::request() diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp index 5e3b9ecf1..c7e800278 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp @@ -35,11 +35,11 @@ */ #include "AtlPage.h" +#include "ui/widgets/ProjectItem.h" #include "ui_AtlPage.h" #include "BuildConfig.h" -#include "AtlOptionalModDialog.h" #include "AtlUserInteractionSupportImpl.h" #include "modplatform/atlauncher/ATLPackInstallTask.h" #include "ui/dialogs/NewInstanceDialog.h" @@ -71,6 +71,8 @@ AtlPage::AtlPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &AtlPage::onSortingSelectionChanged); connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &AtlPage::onSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &AtlPage::onVersionSelectionChanged); + + ui->packView->setItemDelegate(new ProjectItemDelegate(this)); } AtlPage::~AtlPage() diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui b/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui index 746aa6d1c..8b6747331 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.ui @@ -11,44 +11,7 @@ - - - - - - true - - - - 96 - 48 - - - - - - - - true - - - true - - - - - - - Warning: This is still a work in progress. If you run into issues with the imported modpack, it may be a bug. - - - true - - - - - - + @@ -68,7 +31,34 @@ - + + + + + + true + + + true + + + + + + + true + + + + 96 + 48 + + + + + + + Search and filter... @@ -78,6 +68,31 @@ + + + + Search + + + + + + + + true + + + + Warning: This is still a work in progress. If you run into issues with the imported modpack, it may be a bug. + + + Qt::AlignCenter + + + true + + + diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index ff21d0109..e488f0787 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -1,6 +1,8 @@ #include "FlameModel.h" #include #include "Application.h" +#include "modplatform/ResourceAPI.h" +#include "modplatform/flame/FlameAPI.h" #include "ui/widgets/ProjectItem.h" #include "net/ApiDownload.h" @@ -161,6 +163,25 @@ void ListModel::fetchMore(const QModelIndex& parent) void ListModel::performPaginatedSearch() { + if (currentSearchTerm.startsWith("#")) { + auto projectId = currentSearchTerm.removeFirst(); + if (!projectId.isEmpty()) { + ResourceAPI::ProjectInfoCallbacks callbacks; + + // Use defaults if no callbacks are set + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + + if (!callbacks.on_succeed) + callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + static const FlameAPI api; + if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { + jobPtr = job; + jobPtr->start(); + } + return; + } + } auto netJob = makeShared("Flame::Search", APPLICATION->network()); auto searchUrl = QString( "https://api.curseforge.com/v1/mods/search?" @@ -189,23 +210,24 @@ void ListModel::searchWithTerm(const QString& term, int sort) } currentSearchTerm = term; currentSort = sort; - if (jobPtr) { + if (hasActiveSearchJob()) { jobPtr->abort(); searchState = ResetRequested; return; - } else { - beginResetModel(); - modpacks.clear(); - endResetModel(); - searchState = None; } + beginResetModel(); + modpacks.clear(); + endResetModel(); + searchState = None; + nextSearchOffset = 0; performPaginatedSearch(); } void Flame::ListModel::searchRequestFinished() { - jobPtr.reset(); + if (hasActiveSearchJob()) + return; QJsonParseError parse_error; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); @@ -246,6 +268,25 @@ void Flame::ListModel::searchRequestFinished() endInsertRows(); } +void Flame::ListModel::searchRequestForOneSucceeded(QJsonDocument& doc) +{ + jobPtr.reset(); + + auto packObj = Json::ensureObject(doc.object(), "data"); + + Flame::IndexedPack pack; + try { + Flame::loadIndexedPack(pack, packObj); + } catch (const JSONValidationError& e) { + qWarning() << "Error while loading pack from CurseForge: " << e.cause(); + return; + } + + beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + 1); + modpacks.append({ pack }); + endInsertRows(); +} + void Flame::ListModel::searchRequestFailed(QString reason) { jobPtr.reset(); diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h index b3bc96b8c..cd73fce30 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ b/launcher/ui/pages/modplatform/flame/FlameModel.h @@ -40,6 +40,8 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); void searchWithTerm(const QString& term, const int sort); + [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + private slots: void performPaginatedSearch(); @@ -48,6 +50,7 @@ class ListModel : public QAbstractListModel { void searchRequestFinished(); void searchRequestFailed(QString reason); + void searchRequestForOneSucceeded(QJsonDocument&); private: void requestLogo(QString file, QString url); @@ -63,7 +66,7 @@ class ListModel : public QAbstractListModel { int currentSort = 0; int nextSearchOffset = 0; enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None; - NetJob::Ptr jobPtr; + Task::Ptr jobPtr; std::shared_ptr response = std::make_shared(); }; diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 183e16f90..79fcc8211 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -61,6 +61,11 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(paren ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); + m_search_timer.setSingleShot(true); + + connect(&m_search_timer, &QTimer::timeout, this, &FlamePage::triggerSearch); + // index is used to set the sorting with the curseforge api ui->sortByBox->addItem(tr("Sort by Featured")); ui->sortByBox->addItem(tr("Sort by Popularity")); @@ -90,6 +95,11 @@ bool FlamePage::eventFilter(QObject* watched, QEvent* event) triggerSearch(); keyEvent->accept(); return true; + } else { + if (m_search_timer.isActive()) + m_search_timer.stop(); + + m_search_timer.start(350); } } return QWidget::eventFilter(watched, event); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index ff5c79750..a45c9e404 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -39,7 +39,7 @@ #include #include -#include "tasks/Task.h" +#include #include "ui/pages/BasePage.h" namespace Ui { @@ -86,4 +86,7 @@ class FlamePage : public QWidget, public BasePage { Flame::IndexedPack current; int m_selected_version_index = -1; + + // Used to do instant searching with a delay to cache quick changes + QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp index 5c9ff63b2..d3ead0837 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp @@ -17,6 +17,7 @@ */ #include "ImportFTBPage.h" +#include "ui/widgets/ProjectItem.h" #include "ui_ImportFTBPage.h" #include @@ -32,17 +33,30 @@ ImportFTBPage::ImportFTBPage(NewInstanceDialog* dialog, QWidget* parent) : QWidg ui->setupUi(this); { + currentModel = new FilterModel(this); listModel = new ListModel(this); + currentModel->setSourceModel(listModel); - ui->modpackList->setModel(listModel); + ui->modpackList->setModel(currentModel); ui->modpackList->setSortingEnabled(true); ui->modpackList->header()->hide(); ui->modpackList->setIndentation(0); ui->modpackList->setIconSize(QSize(42, 42)); + + for (int i = 0; i < currentModel->getAvailableSortings().size(); i++) { + ui->sortByBox->addItem(currentModel->getAvailableSortings().keys().at(i)); + } + + ui->sortByBox->setCurrentText(currentModel->translateCurrentSorting()); } connect(ui->modpackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &ImportFTBPage::onPublicPackSelectionChanged); + connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &ImportFTBPage::onSortingSelectionChanged); + + connect(ui->searchEdit, &QLineEdit::textChanged, this, &ImportFTBPage::triggerSearch); + + ui->modpackList->setItemDelegate(new ProjectItemDelegate(this)); ui->modpackList->selectionModel()->reset(); } @@ -86,7 +100,7 @@ void ImportFTBPage::onPublicPackSelectionChanged(QModelIndex now, QModelIndex pr onPackSelectionChanged(); return; } - Modpack selectedPack = listModel->data(now, Qt::UserRole).value(); + Modpack selectedPack = currentModel->data(now, Qt::UserRole).value(); onPackSelectionChanged(&selectedPack); } @@ -101,4 +115,15 @@ void ImportFTBPage::onPackSelectionChanged(Modpack* pack) dialog->setSuggestedPack(); } +void ImportFTBPage::onSortingSelectionChanged(QString sort) +{ + FilterModel::Sorting toSet = currentModel->getAvailableSortings().value(sort); + currentModel->setSorting(toSet); +} + +void ImportFTBPage::triggerSearch() +{ + currentModel->setSearchTerm(ui->searchEdit->text()); +} + } // namespace FTBImportAPP diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h index 54c49f7b7..8e9661272 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.h @@ -53,12 +53,15 @@ class ImportFTBPage : public QWidget, public BasePage { void suggestCurrent(); void onPackSelectionChanged(Modpack* pack = nullptr); private slots: + void onSortingSelectionChanged(QString data); void onPublicPackSelectionChanged(QModelIndex first, QModelIndex second); + void triggerSearch(); private: bool initialized = false; Modpack selected; ListModel* listModel = nullptr; + FilterModel* currentModel = nullptr; NewInstanceDialog* dialog = nullptr; Ui::ImportFTBPage* ui = nullptr; diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui index 32d548b0d..5e09fb6d1 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.ui @@ -10,8 +10,8 @@ 1011 - - + + @@ -21,6 +21,54 @@ + + + + + + Search and filter... + + + true + + + + + + + Search + + + + + + + + + + + + 265 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp index dc78f451c..134bdc0c3 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ListModel.cpp @@ -23,7 +23,9 @@ #include #include #include "FileSystem.h" +#include "StringUtils.h" #include "modplatform/import_ftb/PackHelpers.h" +#include "ui/widgets/ProjectItem.h" namespace FTBImportAPP { @@ -71,18 +73,99 @@ QVariant ListModel::data(const QModelIndex& index, int role) const } auto pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name; - } else if (role == Qt::DecorationRole) { - return pack.icon; - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; - } else if (role == Qt::ToolTipRole) { - return tr("Minecraft %1").arg(pack.mcVersion); + if (role == Qt::ToolTipRole) { } - return QVariant(); + switch (role) { + case Qt::ToolTipRole: + return tr("Minecraft %1").arg(pack.mcVersion); + case Qt::DecorationRole: + return pack.icon; + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return tr("Minecraft %1").arg(pack.mcVersion); + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; + } + + return {}; +} + +FilterModel::FilterModel(QObject* parent) : QSortFilterProxyModel(parent) +{ + currentSorting = Sorting::ByGameVersion; + sortings.insert(tr("Sort by Name"), Sorting::ByName); + sortings.insert(tr("Sort by Game Version"), Sorting::ByGameVersion); +} + +bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const +{ + Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value(); + Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value(); + + if (currentSorting == Sorting::ByGameVersion) { + Version lv(leftPack.mcVersion); + Version rv(rightPack.mcVersion); + return lv < rv; + + } else if (currentSorting == Sorting::ByName) { + return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0; + } + + // UHM, some inavlid value set?! + qWarning() << "Invalid sorting set!"; + return true; +} + +bool FilterModel::filterAcceptsRow([[maybe_unused]] int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const +{ + if (searchTerm.isEmpty()) { + return true; + } + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + Modpack pack = sourceModel()->data(index, Qt::UserRole).value(); + return pack.name.contains(searchTerm, Qt::CaseInsensitive); +} + +void FilterModel::setSearchTerm(const QString term) +{ + searchTerm = term.trimmed(); + invalidate(); +} + +const QMap FilterModel::getAvailableSortings() +{ + return sortings; +} + +QString FilterModel::translateCurrentSorting() +{ + return sortings.key(currentSorting); +} + +void FilterModel::setSorting(Sorting s) +{ + currentSorting = s; + invalidate(); +} + +FilterModel::Sorting FilterModel::getCurrentSorting() +{ + return currentSorting; } } // namespace FTBImportAPP \ No newline at end of file diff --git a/launcher/ui/pages/modplatform/import_ftb/ListModel.h b/launcher/ui/pages/modplatform/import_ftb/ListModel.h index c67aa8963..111928276 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ListModel.h +++ b/launcher/ui/pages/modplatform/import_ftb/ListModel.h @@ -20,11 +20,33 @@ #include #include +#include #include #include "modplatform/import_ftb/PackHelpers.h" namespace FTBImportAPP { +class FilterModel : public QSortFilterProxyModel { + Q_OBJECT + public: + FilterModel(QObject* parent = Q_NULLPTR); + enum Sorting { ByName, ByGameVersion }; + const QMap getAvailableSortings(); + QString translateCurrentSorting(); + void setSorting(Sorting sorting); + Sorting getCurrentSorting(); + void setSearchTerm(QString term); + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; + + private: + QMap sortings; + Sorting currentSorting; + QString searchTerm; +}; + class ListModel : public QAbstractListModel { Q_OBJECT diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 356d919d9..49666cf6e 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -41,6 +41,7 @@ #include #include "StringUtils.h" +#include "ui/widgets/ProjectItem.h" #include #include @@ -79,7 +80,20 @@ bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) co bool FilterModel::filterAcceptsRow([[maybe_unused]] int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const { - return true; + if (searchTerm.isEmpty()) { + return true; + } + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + Modpack pack = sourceModel()->data(index, Qt::UserRole).value(); + if (searchTerm.startsWith("#")) + return pack.packCode == searchTerm.mid(1); + return pack.name.contains(searchTerm, Qt::CaseInsensitive); +} + +void FilterModel::setSearchTerm(const QString term) +{ + searchTerm = term.trimmed(); + invalidate(); } const QMap FilterModel::getAvailableSortings() @@ -139,39 +153,57 @@ QVariant ListModel::data(const QModelIndex& index, int role) const } Modpack pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name + "\n" + translatePackType(pack.type); - } else if (role == Qt::ToolTipRole) { - if (pack.description.length() > 100) { - // some magic to prevent to long tooltips and replace html linebreaks - QString edit = pack.description.left(97); - edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); - return edit; + switch (role) { + case Qt::ToolTipRole: { + if (pack.description.length() > 100) { + // some magic to prevent to long tooltips and replace html linebreaks + QString edit = pack.description.left(97); + edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); + return edit; + } + return pack.description; } - return pack.description; - } else if (role == Qt::DecorationRole) { - if (m_logoMap.contains(pack.logo)) { - return (m_logoMap.value(pack.logo)); + case Qt::DecorationRole: { + if (m_logoMap.contains(pack.logo)) { + return (m_logoMap.value(pack.logo)); + } + QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + ((ListModel*)this)->requestLogo(pack.logo); + return icon; } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ListModel*)this)->requestLogo(pack.logo); - return icon; - } else if (role == Qt::ForegroundRole) { - if (pack.broken) { - // FIXME: Hardcoded color - return QColor(255, 0, 50); - } else if (pack.bugged) { - // FIXME: Hardcoded color - // bugged pack, currently only indicates bugged xml - return QColor(244, 229, 66); + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; } - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; + case Qt::ForegroundRole: { + if (pack.broken) { + // FIXME: Hardcoded color + return QColor(255, 0, 50); + } else if (pack.bugged) { + // FIXME: Hardcoded color + // bugged pack, currently only indicates bugged xml + return QColor(244, 229, 66); + } + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return pack.description; + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; } - return QVariant(); + return {}; } void ListModel::fill(ModpackList modpacks_) diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h index 51a58d991..c802a4b56 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.h @@ -25,6 +25,7 @@ class FilterModel : public QSortFilterProxyModel { QString translateCurrentSorting(); void setSorting(Sorting sorting); Sorting getCurrentSorting(); + void setSearchTerm(QString term); protected: bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; @@ -33,6 +34,7 @@ class FilterModel : public QSortFilterProxyModel { private: QMap sortings; Sorting currentSorting; + QString searchTerm; }; class ListModel : public QAbstractListModel { diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index 0103bbaa2..4104f1391 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -35,6 +35,7 @@ */ #include "Page.h" +#include "ui/widgets/ProjectItem.h" #include "ui_Page.h" #include @@ -110,6 +111,8 @@ Page::Page(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &Page::onSortingSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &Page::onVersionSelectionItemChanged); + connect(ui->searchEdit, &QLineEdit::textChanged, this, &Page::triggerSearch); + connect(ui->publicPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPublicPackSelectionChanged); connect(ui->thirdPartyPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onThirdPartyPackSelectionChanged); connect(ui->privatePackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPrivatePackSelectionChanged); @@ -125,6 +128,9 @@ Page::Page(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog ui->thirdPartyPackList->selectionModel()->reset(); ui->privatePackList->selectionModel()->reset(); + ui->publicPackList->setItemDelegate(new ProjectItemDelegate(this)); + ui->thirdPartyPackList->setItemDelegate(new ProjectItemDelegate(this)); + ui->privatePackList->setItemDelegate(new ProjectItemDelegate(this)); onTabChanged(ui->tabWidget->currentIndex()); } @@ -319,6 +325,8 @@ void Page::onTabChanged(int tab) currentModpackInfo = ui->publicPackDescription; } + triggerSearch(); + currentList->selectionModel()->reset(); QModelIndex idx = currentList->currentIndex(); if (idx.isValid()) { @@ -358,4 +366,9 @@ void Page::onRemovePackClicked() onPackSelectionChanged(); } +void Page::triggerSearch() +{ + currentModel->setSearchTerm(ui->searchEdit->text()); +} + } // namespace LegacyFTB diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.h b/launcher/ui/pages/modplatform/legacy_ftb/Page.h index a12b0745d..4d317b7c0 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.h +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.h @@ -43,7 +43,6 @@ #include "QObjectPtr.h" #include "modplatform/legacy_ftb/PackFetchTask.h" #include "modplatform/legacy_ftb/PackHelpers.h" -#include "tasks/Task.h" #include "ui/pages/BasePage.h" class NewInstanceDialog; @@ -56,8 +55,6 @@ class Page; class ListModel; class FilterModel; -class PrivatePackListModel; -class PrivatePackFilterModel; class PrivatePackManager; class Page : public QWidget, public BasePage { @@ -98,6 +95,8 @@ class Page : public QWidget, public BasePage { void onAddPackClicked(); void onRemovePackClicked(); + void triggerSearch(); + private: FilterModel* currentModel = nullptr; QTreeView* currentList = nullptr; diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.ui b/launcher/ui/pages/modplatform/legacy_ftb/Page.ui index ad08dc255..56cba7485 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.ui +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.ui @@ -10,8 +10,29 @@ 602 - - + + + + + + + Search and filter... + + + true + + + + + + + Search + + + + + + 0 @@ -36,9 +57,9 @@ - - true - + + true + @@ -50,10 +71,10 @@ - - true - - + + true + + @@ -104,16 +125,16 @@ - - true - - + + true + + - + diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index ebc5556c6..16949ebae 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -38,8 +38,8 @@ #include "BuildConfig.h" #include "Json.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" +#include "modplatform/modrinth/ModrinthAPI.h" +#include "net/NetJob.h" #include "ui/widgets/ProjectItem.h" #include "net/ApiDownload.h" @@ -130,7 +130,28 @@ bool ModpackListModel::setData(const QModelIndex& index, const QVariant& value, void ModpackListModel::performPaginatedSearch() { - // TODO: Move to standalone API + if (hasActiveSearchJob()) + return; + + if (currentSearchTerm.startsWith("#")) { + auto projectId = currentSearchTerm.removeFirst(); + if (!projectId.isEmpty()) { + ResourceAPI::ProjectInfoCallbacks callbacks; + + // Use defaults if no callbacks are set + if (!callbacks.on_fail) + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + + if (!callbacks.on_succeed) + callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + static const ModrinthAPI api; + if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { + jobPtr = job; + jobPtr->start(); + } + return; + } + } // TODO: Move to standalone API auto netJob = makeShared("Modrinth::SearchModpack", APPLICATION->network()); auto searchAllUrl = QString(BuildConfig.MODRINTH_PROD_URL + "/search?" @@ -167,16 +188,17 @@ void ModpackListModel::performPaginatedSearch() void ModpackListModel::refresh() { - if (jobPtr) { + if (hasActiveSearchJob()) { jobPtr->abort(); searchState = ResetRequested; return; - } else { - beginResetModel(); - modpacks.clear(); - endResetModel(); - searchState = None; } + + beginResetModel(); + modpacks.clear(); + endResetModel(); + searchState = None; + nextSearchOffset = 0; performPaginatedSearch(); } @@ -307,9 +329,29 @@ void ModpackListModel::searchRequestFinished(QJsonDocument& doc_all) endInsertRows(); } +void ModpackListModel::searchRequestForOneSucceeded(QJsonDocument& doc) +{ + jobPtr.reset(); + + auto packObj = doc.object(); + + Modrinth::Modpack pack; + try { + Modrinth::loadIndexedPack(pack, packObj); + pack.id = Json::ensureString(packObj, "id", pack.id); + } catch (const JSONValidationError& e) { + qWarning() << "Error while loading mod from " << m_parent->debugName() << ": " << e.cause(); + return; + } + + beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + 1); + modpacks.append({ pack }); + endInsertRows(); +} + void ModpackListModel::searchRequestFailed(QString reason) { - auto failed_action = jobPtr->getFailedActions().at(0); + auto failed_action = dynamic_cast(jobPtr.get())->getFailedActions().at(0); if (!failed_action->m_reply) { // Network error QMessageBox::critical(nullptr, tr("Error"), tr("A network error occurred. Could not load modpacks.")); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index 721c69f55..f5e686a80 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -73,6 +73,8 @@ class ModpackListModel : public QAbstractListModel { void refresh(); void searchWithTerm(const QString& term, const int sort); + [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); inline auto canFetchMore(const QModelIndex& parent) const -> bool override @@ -83,6 +85,7 @@ class ModpackListModel : public QAbstractListModel { public slots: void searchRequestFinished(QJsonDocument& doc_all); void searchRequestFailed(QString reason); + void searchRequestForOneSucceeded(QJsonDocument&); protected slots: @@ -111,7 +114,7 @@ class ModpackListModel : public QAbstractListModel { int nextSearchOffset = 0; enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None; - NetJob::Ptr jobPtr; + Task::Ptr jobPtr; std::shared_ptr m_all_response = std::make_shared(); QByteArray m_specific_response; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 41fd5003f..72c9da358 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -64,6 +64,11 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); + m_search_timer.setSingleShot(true); + + connect(&m_search_timer, &QTimer::timeout, this, &ModrinthPage::triggerSearch); + ui->sortByBox->addItem(tr("Sort by Relevance")); ui->sortByBox->addItem(tr("Sort by Total Downloads")); ui->sortByBox->addItem(tr("Sort by Follows")); @@ -102,6 +107,11 @@ bool ModrinthPage::eventFilter(QObject* watched, QEvent* event) this->triggerSearch(); keyEvent->accept(); return true; + } else { + if (m_search_timer.isActive()) + m_search_timer.stop(); + + m_search_timer.start(350); } } return QObject::eventFilter(watched, event); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index b7054c886..0705ca99b 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -42,6 +42,7 @@ #include "modplatform/modrinth/ModrinthPackManifest.h" +#include #include namespace Ui { @@ -88,4 +89,7 @@ class ModrinthPage : public QWidget, public BasePage { Modrinth::Modpack current; QString selectedVersion; + + // Used to do instant searching with a delay to cache quick changes + QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index e8c5ac922..3cd1d9a2d 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -39,6 +39,7 @@ #include "Json.h" #include "net/ApiDownload.h" +#include "ui/widgets/ProjectItem.h" #include @@ -54,21 +55,47 @@ QVariant Technic::ListModel::data(const QModelIndex& index, int role) const } Modpack pack = modpacks.at(pos); - if (role == Qt::DisplayRole) { - return pack.name; - } else if (role == Qt::DecorationRole) { - if (m_logoMap.contains(pack.logoName)) { - return (m_logoMap.value(pack.logoName)); + switch (role) { + case Qt::ToolTipRole: { + if (pack.description.length() > 100) { + // some magic to prevent to long tooltips and replace html linebreaks + QString edit = pack.description.left(97); + edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); + return edit; + } + return pack.description; } - QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl); - return icon; - } else if (role == Qt::UserRole) { - QVariant v; - v.setValue(pack); - return v; + case Qt::DecorationRole: { + if (m_logoMap.contains(pack.logoName)) { + return (m_logoMap.value(pack.logoName)); + } + QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); + ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl); + return icon; + } + case Qt::UserRole: { + QVariant v; + v.setValue(pack); + return v; + } + case Qt::DisplayRole: + return pack.name; + case Qt::SizeHintRole: + return QSize(0, 58); + // Custom data + case UserDataTypes::TITLE: + return pack.name; + case UserDataTypes::DESCRIPTION: + return pack.description; + case UserDataTypes::SELECTED: + return false; + case UserDataTypes::INSTALLED: + return false; + default: + break; } - return QVariant(); + + return {}; } int Technic::ListModel::columnCount(const QModelIndex& parent) const @@ -87,21 +114,25 @@ void Technic::ListModel::searchWithTerm(const QString& term) return; } currentSearchTerm = term; - if (jobPtr) { + if (hasActiveSearchJob()) { jobPtr->abort(); searchState = ResetRequested; return; - } else { - beginResetModel(); - modpacks.clear(); - endResetModel(); - searchState = None; } + + beginResetModel(); + modpacks.clear(); + endResetModel(); + searchState = None; + performSearch(); } void Technic::ListModel::performSearch() { + if (hasActiveSearchJob()) + return; + auto netJob = makeShared("Technic::Search", APPLICATION->network()); QString searchUrl = ""; if (currentSearchTerm.isEmpty()) { @@ -113,6 +144,9 @@ void Technic::ListModel::performSearch() } else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) { searchUrl = QString("%1?build=%2").arg(currentSearchTerm, BuildConfig.TECHNIC_API_BUILD); searchMode = Single; + } else if (currentSearchTerm.startsWith("#")) { + searchUrl = QString("https://api.technicpack.net/modpack/%1?build=%2").arg(currentSearchTerm.mid(1), BuildConfig.TECHNIC_API_BUILD); + searchMode = Single; } else { searchUrl = QString("%1search?build=%2&q=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm); diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index d7a635d41..c0d13ae82 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -58,6 +58,8 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); void searchWithTerm(const QString& term); + [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + private slots: void searchRequestFinished(); void searchRequestFailed(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 54b86feba..518d049e8 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -34,6 +34,7 @@ */ #include "TechnicPage.h" +#include "ui/widgets/ProjectItem.h" #include "ui_TechnicPage.h" #include @@ -59,8 +60,15 @@ TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(p model = new Technic::ListModel(this); ui->packView->setModel(model); + m_search_timer.setTimerType(Qt::TimerType::CoarseTimer); + m_search_timer.setSingleShot(true); + + connect(&m_search_timer, &QTimer::timeout, this, &TechnicPage::triggerSearch); + connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &TechnicPage::onSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &TechnicPage::onVersionSelectionChanged); + + ui->packView->setItemDelegate(new ProjectItemDelegate(this)); } bool TechnicPage::eventFilter(QObject* watched, QEvent* event) @@ -71,6 +79,11 @@ bool TechnicPage::eventFilter(QObject* watched, QEvent* event) triggerSearch(); keyEvent->accept(); return true; + } else { + if (m_search_timer.isActive()) + m_search_timer.stop(); + + m_search_timer.start(350); } } return QWidget::eventFilter(watched, event); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index 91b61eaf2..1e36fbd31 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -35,12 +35,12 @@ #pragma once +#include #include #include #include "TechnicData.h" #include "net/NetJob.h" -#include "tasks/Task.h" #include "ui/pages/BasePage.h" namespace Ui { @@ -91,4 +91,7 @@ class TechnicPage : public QWidget, public BasePage { NetJob::Ptr jobPtr; std::shared_ptr response = std::make_shared(); + + // Used to do instant searching with a delay to cache quick changes + QTimer m_search_timer; }; diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index 1481c1b6b..60b92b28b 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -34,8 +34,8 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o icon_width = icon_size.width(); icon_height = icon_size.height(); - icon_x_margin = (rect.height() - icon_width) / 2; icon_y_margin = (rect.height() - icon_height) / 2; + icon_x_margin = icon_y_margin; // use same margins for consistency } // Centralize icon with a margin to separate from the other elements From 4c52b18bdd3112b5e92de61860fd8eff8ecdde9b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 20:19:51 +0300 Subject: [PATCH 264/398] replaced removeFirst with mid Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourceModel.cpp | 2 +- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 96803531b..74c1d2171 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -133,7 +133,7 @@ void ResourceModel::search() return; if (m_search_term.startsWith("#")) { - auto projectId = m_search_term.removeFirst(); + auto projectId = m_search_term.mid(1); if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index e488f0787..e4388c246 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -164,7 +164,7 @@ void ListModel::fetchMore(const QModelIndex& parent) void ListModel::performPaginatedSearch() { if (currentSearchTerm.startsWith("#")) { - auto projectId = currentSearchTerm.removeFirst(); + auto projectId = currentSearchTerm.mid(1); if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 16949ebae..36a1c47a9 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -134,7 +134,7 @@ void ModpackListModel::performPaginatedSearch() return; if (currentSearchTerm.startsWith("#")) { - auto projectId = currentSearchTerm.removeFirst(); + auto projectId = currentSearchTerm.mid(1); if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; From 58efd3e9e27e09d55dac1d185f8de81cf2121f23 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 21:43:57 +0300 Subject: [PATCH 265/398] fixed code scaning Signed-off-by: Trial97 --- launcher/modplatform/ResourceAPI.h | 2 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index bd0d2824f..8af5ebd14 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -108,7 +108,7 @@ class ResourceAPI { void operator=(ProjectInfoArgs other) { pack = other.pack; } }; struct ProjectInfoCallbacks { - std::function on_succeed; + std::function on_succeed; std::function on_fail; std::function on_abort; }; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 74c1d2171..018721f94 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -152,7 +152,7 @@ void ResourceModel::search() }; if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto pack) { + callbacks.on_succeed = [this](auto& doc, auto& pack) { if (!s_running_models.constFind(this).value()) return; searchRequestForOneSucceeded(doc); @@ -219,9 +219,10 @@ void ResourceModel::loadEntry(QModelIndex& entry) // Use default if no callbacks are set if (!callbacks.on_succeed) - callbacks.on_succeed = [this, entry](auto& doc, auto pack) { + callbacks.on_succeed = [this, entry](auto& doc, auto& newpack) { if (!s_running_models.constFind(this).value()) return; + auto pack = newpack; infoRequestSucceeded(doc, pack, entry); }; if (!callbacks.on_fail) From 05094b7382aafc0a9dcda17c13d5294dbaa89c36 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 18 Aug 2023 22:24:30 +0300 Subject: [PATCH 266/398] more fixes Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 2 +- launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index e4388c246..17875a604 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -173,7 +173,7 @@ void ListModel::performPaginatedSearch() callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const FlameAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 36a1c47a9..efb1fe44e 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -143,7 +143,7 @@ void ModpackListModel::performPaginatedSearch() callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const ModrinthAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; From 0138cd65cb259966fa9902732bb03e3e7888cc64 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 19 Aug 2023 09:00:59 +0300 Subject: [PATCH 267/398] feat:neoforge can download forge mods Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.h | 7 ++++--- launcher/modplatform/modrinth/ModrinthAPI.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index a1256e175..e423189a8 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -47,9 +47,10 @@ class FlameAPI : public NetworkResourceAPI { return 4; // TODO: remove this once Quilt drops official Fabric support if (loaders & Quilt) // NOTE: Most if not all Fabric mods should work *currently* - return 4; // FIXME: implement multiple loaders filter - if (loaders & NeoForge) - return 6; + return 4; // FIXME: implement multiple loaders filter (this should be 5) + // TODO: remove this once NeoForge drops official Forge support + if (loaders & NeoForge) // NOTE: Most if not all Forge mods should work *currently* + return 1; // FIXME: implement multiple loaders filter (this should be 6) return 0; } diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 0f150e97a..fb42c532c 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -43,6 +43,8 @@ class ModrinthAPI : public NetworkResourceAPI { l << getModLoaderString(loader); } } + if ((types & NeoForge) && (~types & Forge)) // Add Forge if NeoForge is in use, if Forge isn't already there + l << getModLoaderString(Forge); if ((types & Quilt) && (~types & Fabric)) // Add Fabric if Quilt is in use, if Fabric isn't already there l << getModLoaderString(Fabric); return l; From acf586ef82e13e5bb8c2eeace37085970d9917e4 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sat, 19 Aug 2023 10:21:46 +0200 Subject: [PATCH 268/398] chore: add fixme about UI code in Minecraftinstance Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/MinecraftInstance.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index d930d6811..7e7b3554b 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -233,6 +233,7 @@ QSet MinecraftInstance::traits() const return profile->getTraits(); } +// FIXME: move UI code out of MinecraftInstance void MinecraftInstance::populateLaunchMenu(QMenu* menu) { QAction* normalLaunch = menu->addAction(tr("&Launch")); From d25e89a4c1304092f99b3516e91a5b989a110212 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 20 Aug 2023 00:48:46 +0300 Subject: [PATCH 269/398] refactor packwiz file write Signed-off-by: Trial97 --- .../minecraft/mod/tasks/ModFolderLoadTask.cpp | 2 +- launcher/modplatform/packwiz/Packwiz.cpp | 43 +++++++++++-------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 9f79ba098..2094df4fc 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -122,7 +122,7 @@ void ModFolderLoadTask::getFromMetadata() auto metadata = Metadata::get(m_index_dir, entry); if (!metadata.isValid()) { - return; + continue; } auto* mod = new Mod(m_mods_dir, metadata); diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 71f66bf3e..381476697 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "FileSystem.h" #include "StringUtils.h" @@ -161,31 +163,36 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) // Put TOML data into the file QTextStream in_stream(&index_file); - auto addToStream = [&in_stream](QString&& key, QString value) { in_stream << QString("%1 = \"%2\"\n").arg(key, value); }; - { - addToStream("name", mod.name); - addToStream("filename", mod.filename); - addToStream("side", mod.side); - - in_stream << QString("\n[download]\n"); - addToStream("mode", mod.mode); - addToStream("url", mod.url.toString()); - addToStream("hash-format", mod.hash_format); - addToStream("hash", mod.hash); - - in_stream << QString("\n[update]\n"); - in_stream << QString("[update.%1]\n").arg(ProviderCaps.name(mod.provider)); + toml::table update; switch (mod.provider) { case (ModPlatform::ResourceProvider::FLAME): - in_stream << QString("file-id = %1\n").arg(mod.file_id.toString()); - in_stream << QString("project-id = %1\n").arg(mod.project_id.toString()); + update = toml::table{ + { "file-id", mod.file_id.toInt() }, + { "project-id", mod.project_id.toInt() }, + }; break; case (ModPlatform::ResourceProvider::MODRINTH): - addToStream("mod-id", mod.mod_id().toString()); - addToStream("version", mod.version().toString()); + update = toml::table{ + { "mod-id", mod.mod_id().toString().toStdString() }, + { "version", mod.version().toString().toStdString() }, + }; break; } + auto tbl = toml::table{ { "name", mod.name.toStdString() }, + { "filename", mod.filename.toStdString() }, + { "side", mod.side.toStdString() }, + { "download", + toml::table{ + { "mode", mod.mode.toStdString() }, + { "url", mod.url.toString().toStdString() }, + { "hash-format", mod.hash_format.toStdString() }, + { "hash", mod.hash.toStdString() }, + } }, + { "update", toml::table{ { ProviderCaps.name(mod.provider), update } } } }; + std::stringstream ss; + ss << tbl; + in_stream << QString::fromStdString(ss.str()); } index_file.flush(); From d3c7850f53a87d5d6b5f7aab3c6c56f3808c7071 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 20 Aug 2023 00:16:56 +0000 Subject: [PATCH 270/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/f0451844bbdf545f696f029d1448de4906c7f753' (2023-08-12) → 'github:nixos/nixpkgs/ca3c9ac9f4cdd4bea19f592b32bb59b74ab7d783' (2023-08-19) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/c5ac3aa3324bd8aebe8622a3fc92eeb3975d317a' (2023-08-11) → 'github:cachix/pre-commit-hooks.nix/7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa' (2023-08-17) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index bfe151758..28ef60f30 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1691853136, - "narHash": "sha256-wTzDsRV4HN8A2Sl0SVQY0q8ILs90CD43Ha//7gNZE+E=", + "lastModified": 1692463654, + "narHash": "sha256-F8hZmsQINI+S6UROM4jyxAMbQLtzE44pI8Nk6NtMdao=", "owner": "nixos", "repo": "nixpkgs", - "rev": "f0451844bbdf545f696f029d1448de4906c7f753", + "rev": "ca3c9ac9f4cdd4bea19f592b32bb59b74ab7d783", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1691747570, - "narHash": "sha256-J3fnIwJtHVQ0tK2JMBv4oAmII+1mCdXdpeCxtIsrL2A=", + "lastModified": 1692274144, + "narHash": "sha256-BxTQuRUANQ81u8DJznQyPmRsg63t4Yc+0kcyq6OLz8s=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "c5ac3aa3324bd8aebe8622a3fc92eeb3975d317a", + "rev": "7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa", "type": "github" }, "original": { From 963627fe9855c8903926f4e2809727169c1742e9 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 20 Aug 2023 13:16:02 +0200 Subject: [PATCH 271/398] Revert "chore: better explain quilt loader beacon" This reverts commit a2a09ffe01fe8eb6cd1f557b0feb98ed0271151e. Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/MinecraftInstance.cpp | 2 +- launcher/ui/pages/global/MinecraftPage.ui | 5 +---- launcher/ui/pages/instance/InstanceSettingsPage.ui | 5 +---- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 699aaffaf..c74ac7ae6 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -3,7 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 Jamie Mansfield - * Copyright (C) 2023 TheKodeToad + * Copyright (C) 2023 TheKodeToad \ * Copyright (c) 2023 seth * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 98e90e4ec..f8ac4896a 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -199,10 +199,7 @@ - Disable Quilt Loader Beacon - - - Disable Quilt loader's beacon for counting monthly active users + Disable Quilt's Beacon diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index fcc2a5d0a..1b443f54c 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -598,10 +598,7 @@ - Disable Quilt Loader Beacon - - - Disable Quilt loader's beacon for counting monthly active users + Disable Quilt's Beacon From 5b4dcae7d948cd3516bc691f6e696f0951041721 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sun, 20 Aug 2023 13:17:17 +0200 Subject: [PATCH 272/398] Revert "feat: add toggle for quilt beacon" This reverts commit 89aaedc06c3eb7a035d8be593a7bbe417cb2f712. Signed-off-by: Sefa Eyeoglu --- launcher/Application.cpp | 4 ---- launcher/minecraft/MinecraftInstance.cpp | 13 +---------- launcher/ui/pages/global/MinecraftPage.cpp | 6 ----- launcher/ui/pages/global/MinecraftPage.ui | 16 -------------- .../pages/instance/InstanceSettingsPage.cpp | 13 ----------- .../ui/pages/instance/InstanceSettingsPage.ui | 22 ------------------- 6 files changed, 1 insertion(+), 73 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 5a952c74f..000104656 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -9,7 +9,6 @@ * Copyright (C) 2022 Tayou * Copyright (C) 2023 TheKodeToad * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> - * Copyright (C) 2023 seth * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -580,9 +579,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("IgnoreJavaCompatibility", false); m_settings->registerSetting("IgnoreJavaWizard", false); - // Mod loader settings - m_settings->registerSetting("DisableQuiltBeacon", false); - // Native library workarounds m_settings->registerSetting("UseNativeOpenAL", false); m_settings->registerSetting("CustomOpenALPath", ""); diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index c74ac7ae6..0da97c146 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -3,8 +3,7 @@ * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 Jamie Mansfield - * Copyright (C) 2023 TheKodeToad \ - * Copyright (c) 2023 seth + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -185,10 +184,6 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerOverride(global_settings->getSetting("CloseAfterLaunch"), miscellaneousOverride); m_settings->registerOverride(global_settings->getSetting("QuitAfterGameStop"), miscellaneousOverride); - // Mod loader specific options - auto modLoaderSettings = m_settings->registerSetting("OverrideModLoaderSettings", false); - m_settings->registerOverride(global_settings->getSetting("DisableQuiltBeacon"), modLoaderSettings); - m_settings->set("InstanceType", "OneSix"); } @@ -434,12 +429,6 @@ QStringList MinecraftInstance::extraArguments() list.append("-javaagent:" + jar[0] + (agent->argument().isEmpty() ? "" : "=" + agent->argument())); } - { - const auto loaders = version->getModLoaders(); - if (loaders.has_value() && loaders.value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool()) - list.append("-Dloader.disable_beacon=true"); - } - { QString openALPath; QString glfwPath; diff --git a/launcher/ui/pages/global/MinecraftPage.cpp b/launcher/ui/pages/global/MinecraftPage.cpp index 1c7747210..f0d50b638 100644 --- a/launcher/ui/pages/global/MinecraftPage.cpp +++ b/launcher/ui/pages/global/MinecraftPage.cpp @@ -2,7 +2,6 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield - * Copyright (C) 2023 seth * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -119,9 +118,6 @@ void MinecraftPage::applySettings() // Miscellaneous s->set("CloseAfterLaunch", ui->closeAfterLaunchCheck->isChecked()); s->set("QuitAfterGameStop", ui->quitAfterGameStopCheck->isChecked()); - - // Mod loader settings - s->set("DisableQuiltBeacon", ui->disableQuiltBeaconCheckBox->isChecked()); } void MinecraftPage::loadSettings() @@ -172,8 +168,6 @@ void MinecraftPage::loadSettings() ui->closeAfterLaunchCheck->setChecked(s->get("CloseAfterLaunch").toBool()); ui->quitAfterGameStopCheck->setChecked(s->get("QuitAfterGameStop").toBool()); - - ui->disableQuiltBeaconCheckBox->setChecked(s->get("DisableQuiltBeacon").toBool()); } void MinecraftPage::retranslate() diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index f8ac4896a..ef4a22874 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -190,22 +190,6 @@ Tweaks - - - - Mod loader settings - - - - - - Disable Quilt's Beacon - - - - - - diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 108f2c274..d5dbb80b8 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -3,7 +3,6 @@ * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2023 seth * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -254,14 +253,6 @@ void InstanceSettingsPage::applySettings() m_settings->reset("InstanceAccountId"); } - bool overrideModLoaderSettings = ui->modLoaderSettingsGroupBox->isChecked(); - m_settings->set("OverrideModLoaderSettings", overrideModLoaderSettings); - if (overrideModLoaderSettings) { - m_settings->set("DisableQuiltBeacon", ui->disableQuiltBeaconCheckBox->isChecked()); - } else { - m_settings->reset("DisableQuiltBeacon"); - } - // FIXME: This should probably be called by a signal instead m_instance->updateRuntimeContext(); } @@ -365,10 +356,6 @@ void InstanceSettingsPage::loadSettings() ui->instanceAccountGroupBox->setChecked(m_settings->get("UseAccountForInstance").toBool()); updateAccountsMenu(); - - // Mod loader specific settings - ui->modLoaderSettingsGroupBox->setChecked(m_settings->get("OverrideModLoaderSettings").toBool()); - ui->disableQuiltBeaconCheckBox->setChecked(m_settings->get("DisableQuiltBeacon").toBool()); } void InstanceSettingsPage::on_javaDetectBtn_clicked() diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 1b443f54c..81cf7093e 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -583,28 +583,6 @@ Miscellaneous - - - - true - - - false - - - Mod loader settings - - - - - - Disable Quilt's Beacon - - - - - - From 254444470f020b086648ac496ebfffb7d3e9ce05 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 20 Aug 2023 16:40:58 +0300 Subject: [PATCH 273/398] renamed enum type Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.cpp | 40 +++++++++------------ launcher/modplatform/ModIndex.h | 29 ++++++++------- launcher/modplatform/flame/FlamePackIndex.h | 2 -- 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 04fd42a7a..17edcdb5d 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -24,30 +24,32 @@ namespace ModPlatform { -static const QMap s_indexed_version_type_names = { { "release", IndexedVersionType::Enum::Release }, - { "beta", IndexedVersionType::Enum::Beta }, - { "alpha", IndexedVersionType::Enum::Alpha } }; +static const QMap s_indexed_version_type_names = { + { "release", IndexedVersionType::VersionType::Release }, + { "beta", IndexedVersionType::VersionType::Beta }, + { "alpha", IndexedVersionType::VersionType::Alpha } +}; IndexedVersionType::IndexedVersionType(const QString& type) : IndexedVersionType(enumFromString(type)) {} -IndexedVersionType::IndexedVersionType(int type) +IndexedVersionType::IndexedVersionType(int flame_type) { - switch (type) { + switch (flame_type) { case 1: - m_type = IndexedVersionType::Enum::Release; + m_type = IndexedVersionType::VersionType::Release; break; case 2: - m_type = IndexedVersionType::Enum::Beta; + m_type = IndexedVersionType::VersionType::Beta; break; case 3: - m_type = IndexedVersionType::Enum::Alpha; + m_type = IndexedVersionType::VersionType::Alpha; break; default: - m_type = IndexedVersionType::Enum::UNKNOWN; + m_type = IndexedVersionType::VersionType::Unknown; } } -IndexedVersionType::IndexedVersionType(const IndexedVersionType::Enum& type) +IndexedVersionType::IndexedVersionType(const IndexedVersionType::VersionType& type) { m_type = type; } @@ -63,24 +65,14 @@ IndexedVersionType& IndexedVersionType::operator=(const IndexedVersionType& othe return *this; } -const QString IndexedVersionType::toString(const IndexedVersionType::Enum& type) +const QString IndexedVersionType::toString(const IndexedVersionType::VersionType& type) { - switch (type) { - case IndexedVersionType::Enum::Release: - return "release"; - case IndexedVersionType::Enum::Beta: - return "beta"; - case IndexedVersionType::Enum::Alpha: - return "alpha"; - case IndexedVersionType::Enum::UNKNOWN: - default: - return "unknown"; - } + return s_indexed_version_type_names.key(type, "unknown"); } -IndexedVersionType::Enum IndexedVersionType::enumFromString(const QString& type) +IndexedVersionType::VersionType IndexedVersionType::enumFromString(const QString& type) { - return s_indexed_version_type_names.value(type, IndexedVersionType::Enum::UNKNOWN); + return s_indexed_version_type_names.value(type, IndexedVersionType::VersionType::Unknown); } auto ProviderCapabilities::name(ResourceProvider p) -> const char* diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index e430f2b00..e56c282a2 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -57,32 +57,32 @@ struct DonationData { }; struct IndexedVersionType { - enum class Enum { Release = 1, Beta, Alpha, UNKNOWN }; + enum class VersionType { Release = 1, Beta, Alpha, Unknown }; IndexedVersionType(const QString& type); - IndexedVersionType(int type); - IndexedVersionType(const IndexedVersionType::Enum& type); + IndexedVersionType(int flame_type); + IndexedVersionType(const IndexedVersionType::VersionType& type); IndexedVersionType(const IndexedVersionType& type); - IndexedVersionType() : IndexedVersionType(IndexedVersionType::Enum::UNKNOWN) {} - static const QString toString(const IndexedVersionType::Enum& type); - static IndexedVersionType::Enum enumFromString(const QString& type); - bool isValid() const { return m_type != IndexedVersionType::Enum::UNKNOWN; } + IndexedVersionType() : IndexedVersionType(IndexedVersionType::VersionType::Unknown) {} + static const QString toString(const IndexedVersionType::VersionType& type); + static IndexedVersionType::VersionType enumFromString(const QString& type); + bool isValid() const { return m_type != IndexedVersionType::VersionType::Unknown; } IndexedVersionType& operator=(const IndexedVersionType& other); bool operator==(const IndexedVersionType& other) const { return m_type == other.m_type; } - bool operator==(const IndexedVersionType::Enum& type) const { return m_type == type; } + bool operator==(const IndexedVersionType::VersionType& type) const { return m_type == type; } bool operator!=(const IndexedVersionType& other) const { return m_type != other.m_type; } - bool operator!=(const IndexedVersionType::Enum& type) const { return m_type != type; } + bool operator!=(const IndexedVersionType::VersionType& type) const { return m_type != type; } bool operator<(const IndexedVersionType& other) const { return m_type < other.m_type; } - bool operator<(const IndexedVersionType::Enum& type) const { return m_type < type; } + bool operator<(const IndexedVersionType::VersionType& type) const { return m_type < type; } bool operator<=(const IndexedVersionType& other) const { return m_type <= other.m_type; } - bool operator<=(const IndexedVersionType::Enum& type) const { return m_type <= type; } + bool operator<=(const IndexedVersionType::VersionType& type) const { return m_type <= type; } bool operator>(const IndexedVersionType& other) const { return m_type > other.m_type; } - bool operator>(const IndexedVersionType::Enum& type) const { return m_type > type; } + bool operator>(const IndexedVersionType::VersionType& type) const { return m_type > type; } bool operator>=(const IndexedVersionType& other) const { return m_type >= other.m_type; } - bool operator>=(const IndexedVersionType::Enum& type) const { return m_type >= type; } + bool operator>=(const IndexedVersionType::VersionType& type) const { return m_type >= type; } QString toString() const { return toString(m_type); } - IndexedVersionType::Enum m_type; + IndexedVersionType::VersionType m_type; }; struct Dependency { @@ -159,7 +159,6 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; -QString getMetaURL(ResourceProvider provider, QVariant projectID); struct OverrideDep { QString quilt; diff --git a/launcher/modplatform/flame/FlamePackIndex.h b/launcher/modplatform/flame/FlamePackIndex.h index 5f642aceb..b2a12a67f 100644 --- a/launcher/modplatform/flame/FlamePackIndex.h +++ b/launcher/modplatform/flame/FlamePackIndex.h @@ -6,8 +6,6 @@ #include #include "modplatform/ModIndex.h" -#include "modplatform/ModIndex.h" - namespace Flame { struct ModpackAuthor { From 19316e22b40b47cf88856592b9ff528e860aa4a5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 20 Aug 2023 22:46:44 +0300 Subject: [PATCH 274/398] fixed status label after instance remove Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 73b8dbe5e..9228928fc 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -560,7 +560,8 @@ void MainWindow::updateLaunchButton() launchMenu->clear(); else launchMenu = new QMenu(this); - m_selectedInstance->populateLaunchMenu(launchMenu); + if (m_selectedInstance) + m_selectedInstance->populateLaunchMenu(launchMenu); ui->actionLaunchInstance->setMenu(launchMenu); } @@ -1351,10 +1352,11 @@ void MainWindow::on_actionDeleteInstance_triggered() if (APPLICATION->instances()->trashInstance(id)) { ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); - return; + } else { + APPLICATION->instances()->deleteInstance(id); } - - APPLICATION->instances()->deleteInstance(id); + APPLICATION->settings()->set("SelectedInstance", QString()); + selectionBad(); } void MainWindow::on_actionExportInstanceZip_triggered() @@ -1652,10 +1654,6 @@ void MainWindow::instanceChanged(const QModelIndex& current, [[maybe_unused]] co connect(m_selectedInstance.get(), &BaseInstance::runningStatusChanged, this, &MainWindow::refreshCurrentInstance); connect(m_selectedInstance.get(), &BaseInstance::profilerChanged, this, &MainWindow::refreshCurrentInstance); } else { - ui->instanceToolBar->setEnabled(false); - setInstanceActionsEnabled(false); - ui->actionLaunchInstance->setEnabled(false); - ui->actionKillInstance->setEnabled(false); APPLICATION->settings()->set("SelectedInstance", QString()); selectionBad(); return; @@ -1680,6 +1678,7 @@ void MainWindow::selectionBad() { // start by reseting everything... m_selectedInstance = nullptr; + m_statusLeft->setText(tr("No instance selected")); statusBar()->clearMessage(); ui->instanceToolBar->setEnabled(false); From 8e5be6f4203f777ba10d61608c2d5b80c05cc0d4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 00:09:46 +0300 Subject: [PATCH 275/398] added suport for atlauncher browser download Signed-off-by: Trial97 --- .../atlauncher/ATLPackInstallTask.cpp | 98 ++++++++++++++++--- launcher/ui/dialogs/BlockedModsDialog.cpp | 6 +- launcher/ui/dialogs/BlockedModsDialog.h | 3 +- 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index e5771b7cd..a3f26e1f7 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -37,6 +37,7 @@ #include "ATLPackInstallTask.h" #include +#include #include @@ -50,6 +51,7 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/OneSixVersionFormat.h" #include "minecraft/PackProfile.h" +#include "modplatform/atlauncher/ATLPackManifest.h" #include "net/ChecksumValidator.h" #include "settings/INISettingsObject.h" @@ -57,6 +59,7 @@ #include "Application.h" #include "BuildConfig.h" +#include "ui/dialogs/BlockedModsDialog.h" namespace ATLauncher { @@ -717,6 +720,8 @@ void PackInstallTask::downloadMods() jarmods.clear(); jobPtr.reset(new NetJob(tr("Mod download"), APPLICATION->network())); + + QList blocked_mods; for (const auto& mod : m_version.mods) { // skip non-client mods if (!mod.client) @@ -731,9 +736,10 @@ void PackInstallTask::downloadMods() case DownloadType::Server: url = BuildConfig.ATL_DOWNLOAD_SERVER_URL + mod.url; break; - case DownloadType::Browser: - emitFailed(tr("Unsupported download type: %1").arg(mod.download_raw)); - return; + case DownloadType::Browser: { + blocked_mods.append(mod); + continue; + } case DownloadType::Direct: url = mod.url; break; @@ -805,24 +811,86 @@ void PackInstallTask::downloadMods() modsToCopy[entry->getFullPath()] = path; } } + if (!blocked_mods.isEmpty()) { + QList mods; + + for (auto mod : blocked_mods) { + BlockedMod blocked_mod; + blocked_mod.name = mod.file; + blocked_mod.websiteUrl = mod.url; + blocked_mod.hash = mod.md5; + blocked_mod.matched = false; + blocked_mod.localPath = ""; + + mods.append(blocked_mod); + } + + qWarning() << "Blocked mods found, displaying mod list"; + + BlockedModsDialog message_dialog(nullptr, tr("Blocked mods found"), + tr("The following files are not available for download in third party launchers.
" + "You will need to manually download them and add them to the instance."), + mods, "md5"); + + message_dialog.setModal(true); + + if (message_dialog.exec()) { + qDebug() << "Post dialog blocked mods list: " << mods; + for (auto blocked : mods) { + if (!blocked.matched) { + qDebug() << blocked.name << "was not matched to a local file, skipping copy"; + continue; + } + auto modIter = std::find_if(blocked_mods.begin(), blocked_mods.end(), + [blocked](VersionMod mod) { return mod.url == blocked.websiteUrl; }); + if (modIter == blocked_mods.end()) + continue; + auto mod = *modIter; + if (mod.type == ModType::Extract || mod.type == ModType::TexturePackExtract || mod.type == ModType::ResourcePackExtract) { + modsToExtract.insert(blocked.localPath, mod); + } else if (mod.type == ModType::Decomp) { + modsToDecomp.insert(blocked.localPath, mod); + } else { + auto relpath = getDirForModType(mod.type, mod.type_raw); + if (relpath == Q_NULLPTR) + continue; + + auto path = FS::PathCombine(m_stagingPath, "minecraft", relpath, mod.file); + + if (mod.type == ModType::Forge) { + auto ver = getComponentVersion("net.minecraftforge", mod.version); + if (ver) { + componentsToInstall.insert("net.minecraftforge", ver); + continue; + } + + qDebug() << "Jarmod: " + path; + jarmods.push_back(path); + } + + if (mod.type == ModType::Jar) { + qDebug() << "Jarmod: " + path; + jarmods.push_back(path); + } + + modsToCopy[blocked.localPath] = path; + } + } + } else { + emitFailed(tr("Unknown download type: %1").arg("browser")); + return; + } + } connect(jobPtr.get(), &NetJob::succeeded, this, &PackInstallTask::onModsDownloaded); - connect(jobPtr.get(), &NetJob::failed, [&](QString reason) { - abortable = false; - jobPtr.reset(); - emitFailed(reason); - }); - connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) { + connect(jobPtr.get(), &NetJob::progress, [this](qint64 current, qint64 total) { setDetails(tr("%1 out of %2 complete").arg(current).arg(total)); abortable = true; setProgress(current, total); }); connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress); - connect(jobPtr.get(), &NetJob::aborted, [&] { - abortable = false; - jobPtr.reset(); - emitAborted(); - }); + connect(jobPtr.get(), &NetJob::aborted, &PackInstallTask::emitAborted); + connect(jobPtr.get(), &NetJob::failed, &PackInstallTask::emitFailed); jobPtr->start(); } @@ -843,7 +911,7 @@ void PackInstallTask::onModsDownloaded() QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy); #endif connect(&m_modExtractFutureWatcher, &QFutureWatcher::finished, this, &PackInstallTask::onModsExtracted); - connect(&m_modExtractFutureWatcher, &QFutureWatcher::canceled, this, [&]() { emitAborted(); }); + connect(&m_modExtractFutureWatcher, &QFutureWatcher::canceled, this, &PackInstallTask::emitAborted); m_modExtractFutureWatcher.setFuture(m_modExtractFuture); } else { install(); diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index 727c06148..f105b4b5f 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -41,8 +41,8 @@ #include #include -BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods) - : QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods) +BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods, QString hash_type) + : QDialog(parent), ui(new Ui::BlockedModsDialog), m_mods(mods), m_hash_type(hash_type) { m_hashing_task = shared_qobject_ptr(new ConcurrentTask(this, "MakeHashesTask", 10)); connect(m_hashing_task.get(), &Task::finished, this, &BlockedModsDialog::hashTaskFinished); @@ -254,7 +254,7 @@ void BlockedModsDialog::addHashTask(QString path) /// @param path the path to the local file being hashed void BlockedModsDialog::buildHashTask(QString path) { - auto hash_task = Hashing::createBlockedModHasher(path, ModPlatform::ResourceProvider::FLAME, "sha1"); + auto hash_task = Hashing::createBlockedModHasher(path, ModPlatform::ResourceProvider::FLAME, m_hash_type); qDebug() << "[Blocked Mods Dialog] Creating Hash task for path: " << path; diff --git a/launcher/ui/dialogs/BlockedModsDialog.h b/launcher/ui/dialogs/BlockedModsDialog.h index e3b7c9756..09722bce9 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.h +++ b/launcher/ui/dialogs/BlockedModsDialog.h @@ -54,7 +54,7 @@ class BlockedModsDialog : public QDialog { Q_OBJECT public: - BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods); + BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods, QString hash_type = "sha1"); ~BlockedModsDialog() override; @@ -73,6 +73,7 @@ class BlockedModsDialog : public QDialog { QSet m_pending_hash_paths; bool m_rehash_pending; QPushButton* m_openMissingButton; + QString m_hash_type; void openAll(bool missingOnly); void addDownloadFolder(); From 8092c321a943ab64faab2c15ee5c44b83b56289d Mon Sep 17 00:00:00 2001 From: Danny Dorazio Date: Sun, 20 Aug 2023 23:00:25 -0400 Subject: [PATCH 276/398] =?UTF-8?q?Replace=20instances=20of=20=E2=80=9CMin?= =?UTF-8?q?ecraft=20account=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- launcher/ui/MainWindow.cpp | 2 +- launcher/ui/pages/instance/VersionPage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 73b8dbe5e..780147ef8 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -870,7 +870,7 @@ void MainWindow::finalizeInstance(InstancePtr inst) } else { CustomMessageBox::selectable(this, tr("Error"), tr("The launcher cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Mojang or Minecraft account."), + "one account added.\nPlease add your Microsoft or Mojang account."), QMessageBox::Warning) ->show(); } diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index ef029d1d9..fa5064311 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -408,7 +408,7 @@ void VersionPage::on_actionDownload_All_triggered() if (!APPLICATION->accounts()->anyAccountIsValid()) { CustomMessageBox::selectable(this, tr("Error"), tr("Cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Mojang or Minecraft account."), + "one account added.\nPlease add your Microsoft or Mojang account."), QMessageBox::Warning) ->show(); return; From 3638fc0a7db049e83e7e4ffab0d2100b9e2e7c58 Mon Sep 17 00:00:00 2001 From: Danny Dorazio Date: Sun, 20 Aug 2023 23:00:50 -0400 Subject: [PATCH 277/398] =?UTF-8?q?Update=20=E2=80=9CWelcome=E2=80=9D=20me?= =?UTF-8?q?ssage=20on=20account=20list=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- launcher/ui/pages/global/AccountListPage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index 5c6fb092b..c0bd1607d 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -64,7 +64,8 @@ AccountListPage::AccountListPage(QWidget* parent) : QMainWindow(parent), ui(new ui->setupUi(this); ui->listView->setEmptyString( tr("Welcome!\n" - "If you're new here, you can click the \"Add\" button to add your Mojang or Minecraft account.")); + "If you're new here, you can select the \"Add Microsoft\" or \"Add Mojang\" buttons to link your Microsoft and/or Mojang " + "accounts.")); ui->listView->setEmptyMode(VersionListView::String); ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); From 02264f67f35b47a6074ea7cdb925e94ea8ac590d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 14:15:51 +0300 Subject: [PATCH 280/398] Fixed codeql Signed-off-by: Trial97 --- launcher/modplatform/atlauncher/ATLPackInstallTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index a3f26e1f7..8ae8145de 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -842,7 +842,7 @@ void PackInstallTask::downloadMods() continue; } auto modIter = std::find_if(blocked_mods.begin(), blocked_mods.end(), - [blocked](VersionMod mod) { return mod.url == blocked.websiteUrl; }); + [blocked](const VersionMod& mod) { return mod.url == blocked.websiteUrl; }); if (modIter == blocked_mods.end()) continue; auto mod = *modIter; From 492bf373c65123ad3b3f8b1508cb8fb97628053d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 15:00:11 +0300 Subject: [PATCH 281/398] updated memory allocation on quick setup Signed-off-by: Trial97 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 42279a663..4129e3af6 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -186,12 +187,12 @@ QString JavaSettingsWidget::javaPath() const int JavaSettingsWidget::maxHeapSize() const { - return m_maxMemSpinBox->value(); + return std::max(m_minMemSpinBox->value(), m_maxMemSpinBox->value()); } int JavaSettingsWidget::minHeapSize() const { - return m_minMemSpinBox->value(); + return std::min(m_minMemSpinBox->value(), m_maxMemSpinBox->value()); } bool JavaSettingsWidget::permGenEnabled() const @@ -214,17 +215,9 @@ void JavaSettingsWidget::memoryValueChanged(int) if (obj == m_minMemSpinBox && min != observedMinMemory) { observedMinMemory = min; actuallyChanged = true; - if (min > max) { - observedMaxMemory = min; - m_maxMemSpinBox->setValue(min); - } } else if (obj == m_maxMemSpinBox && max != observedMaxMemory) { observedMaxMemory = max; actuallyChanged = true; - if (min > max) { - observedMinMemory = max; - m_minMemSpinBox->setValue(max); - } } else if (obj == m_permGenSpinBox && permgen != observedPermGenMemory) { observedPermGenMemory = permgen; actuallyChanged = true; From 1eb75b685280c056e5e9a43685e6356c8fab2e2a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 15:34:45 +0300 Subject: [PATCH 282/398] fixed build Signed-off-by: Trial97 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 4129e3af6..ec33d991e 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include @@ -187,12 +186,20 @@ QString JavaSettingsWidget::javaPath() const int JavaSettingsWidget::maxHeapSize() const { - return std::max(m_minMemSpinBox->value(), m_maxMemSpinBox->value()); + auto min = m_minMemSpinBox->value(); + auto max = m_maxMemSpinBox->value(); + if (max < min) + max = min; + return max; } int JavaSettingsWidget::minHeapSize() const { - return std::min(m_minMemSpinBox->value(), m_maxMemSpinBox->value()); + auto min = m_minMemSpinBox->value(); + auto max = m_maxMemSpinBox->value(); + if (min > max) + min = max; + return min; } bool JavaSettingsWidget::permGenEnabled() const From d7dadabfbf61a46996d13894ed591d057bb8c1b3 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 21 Aug 2023 13:55:28 +0100 Subject: [PATCH 283/398] List fixes Double-click to toggle profile components. Restore double-click to toggle resources. Fix clicking on checkbox to select account. Double-click to select account. Signed-off-by: TheKodeToad --- launcher/minecraft/auth/AccountList.cpp | 5 +++-- launcher/ui/pages/global/AccountListPage.cpp | 2 ++ launcher/ui/pages/instance/ExternalResourcesPage.cpp | 1 + launcher/ui/pages/instance/VersionPage.cpp | 7 +++++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index c534ea3bd..84dbd8416 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -415,7 +415,7 @@ Qt::ItemFlags AccountList::flags(const QModelIndex& index) const bool AccountList::setData(const QModelIndex& idx, const QVariant& value, int role) { - if (idx.row() < 0 || idx.row() >= rowCount(idx) || !idx.isValid()) { + if (idx.row() < 0 || idx.row() >= rowCount(idx.parent()) || !idx.isValid()) { return false; } @@ -423,7 +423,8 @@ bool AccountList::setData(const QModelIndex& idx, const QVariant& value, int rol if (value == Qt::Checked) { MinecraftAccountPtr account = at(idx.row()); setDefaultAccount(account); - } + } else if (m_defaultAccount == at(idx.row())) + setDefaultAccount(nullptr); } emit dataChanged(idx, index(idx.row(), columnCount(QModelIndex()) - 1)); diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index 5c6fb092b..a92e3dd95 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -85,6 +85,8 @@ AccountListPage::AccountListPage(QWidget* parent) : QMainWindow(parent), ui(new connect(selectionModel, &QItemSelectionModel::selectionChanged, [this]([[maybe_unused]] const QItemSelection& sel, [[maybe_unused]] const QItemSelection& dsel) { updateButtonStates(); }); connect(ui->listView, &VersionListView::customContextMenuRequested, this, &AccountListPage::ShowContextMenu); + connect(ui->listView, &VersionListView::activated, this, + [this](const QModelIndex& index) { m_accounts->setDefaultAccount(m_accounts->at(index.row())); }); connect(m_accounts.get(), &AccountList::listChanged, this, &AccountListPage::listChanged); connect(m_accounts.get(), &AccountList::listActivityChanged, this, &AccountListPage::listChanged); diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 719db8799..1a8fafa9b 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -152,6 +152,7 @@ void ExternalResourcesPage::retranslate() void ExternalResourcesPage::itemActivated(const QModelIndex&) { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); + m_model->setResourceEnabled(selection.indexes(), EnableAction::TOGGLE); } void ExternalResourcesPage::filterTextChanged(const QString& newContents) diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index ef029d1d9..b1060704b 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -166,14 +166,17 @@ VersionPage::VersionPage(MinecraftInstance* inst, QWidget* parent) : QMainWindow ui->packageView->setSelectionMode(QAbstractItemView::SingleSelection); ui->packageView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->packageView->selectionModel(), &QItemSelectionModel::currentChanged, this, &VersionPage::versionCurrent); auto smodel = ui->packageView->selectionModel(); + connect(smodel, &QItemSelectionModel::currentChanged, this, &VersionPage::versionCurrent); connect(smodel, &QItemSelectionModel::currentChanged, this, &VersionPage::packageCurrent); - connect(m_profile.get(), &PackProfile::minecraftChanged, this, &VersionPage::updateVersionControls); updateVersionControls(); preselect(0); connect(ui->packageView, &ModListView::customContextMenuRequested, this, &VersionPage::showContextMenu); + connect(ui->packageView, &QAbstractItemView::activated, this, [this](const QModelIndex& index) { + auto component = m_profile->getComponent(index.row()); + component->setEnabled(!component->isEnabled()); + }); connect(ui->filterEdit, &QLineEdit::textChanged, this, &VersionPage::onFilterTextChanged); } From 45dad27a6d945e3d6257d76ff0652307ad42788a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 17:46:50 +0300 Subject: [PATCH 284/398] fixed check Signed-off-by: Trial97 --- launcher/ui/widgets/JavaSettingsWidget.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index ec33d991e..4ffa3b168 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -361,8 +361,8 @@ void JavaSettingsWidget::checkJavaPath(const QString& path) setJavaStatus(JavaStatus::Pending); m_checker.reset(new JavaChecker()); m_checker->m_path = path; - m_checker->m_minMem = m_minMemSpinBox->value(); - m_checker->m_maxMem = m_maxMemSpinBox->value(); + m_checker->m_minMem = minHeapSize(); + m_checker->m_maxMem = maxHeapSize(); if (m_permGenSpinBox->isVisible()) { m_checker->m_permGen = m_permGenSpinBox->value(); } @@ -415,6 +415,9 @@ void JavaSettingsWidget::updateThresholds() } else if (observedMaxMemory > (m_availableMemory * 0.9)) { iconName = "status-yellow"; m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); + } else if (observedMaxMemory < observedMinMemory) { + iconName = "status-yellow"; + m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller that the minimum value")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); From 7acfe36a625e2f0c4fb5ba9c11a15be45484a4f6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 21:30:44 +0300 Subject: [PATCH 285/398] fixed httpmetacache load Signed-off-by: Trial97 --- launcher/net/HttpMetaCache.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp index 7809d40fc..f37bc0bf8 100644 --- a/launcher/net/HttpMetaCache.cpp +++ b/launcher/net/HttpMetaCache.cpp @@ -218,9 +218,24 @@ void HttpMetaCache::Load() if (!index.open(QIODevice::ReadOnly)) return; - QJsonDocument json = QJsonDocument::fromJson(index.readAll()); + QJsonParseError parseError; + QJsonDocument json = QJsonDocument::fromJson(index.readAll(), &parseError); - auto root = Json::requireObject(json, "HttpMetaCache root"); + // Fail if the JSON is invalid. + if (parseError.error != QJsonParseError::NoError) { + qCritical() << QString("Failed to parse HttpMetaCache file: %1 at offset %2") + .arg(parseError.errorString(), QString::number(parseError.offset)) + .toUtf8(); + return; + } + + // Make sure the root is an object. + if (!json.isObject()) { + qCritical() << "HttpMetaCache root should be an object."; + return; + } + + auto root = json.object(); // check file version first auto version_val = Json::ensureString(root, "version"); From c3d03f0c3392051a845be5afeef246d386e0ca18 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 21 Aug 2023 22:20:33 +0300 Subject: [PATCH 286/398] added check for valid query items in curse url install Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 780147ef8..cbfd4b9a4 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -932,6 +932,11 @@ void MainWindow::processURLs(QList urls) // format of url curseforge://install?addonId=IDHERE&fileId=IDHERE QUrlQuery query(url); + if (query.allQueryItemValues("addonId").isEmpty() || query.allQueryItemValues("fileId").isEmpty()) { + qDebug() << "Invalid curseforge link:" << url; + continue; + } + auto addonId = query.allQueryItemValues("addonId")[0]; auto fileId = query.allQueryItemValues("fileId")[0]; From 09aca7a0b573047df567d349ba9b792d2ffbc16e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 22 Aug 2023 10:52:35 +0300 Subject: [PATCH 287/398] Added warning to settings page Signed-off-by: Trial97 --- launcher/ui/pages/global/JavaPage.cpp | 4 ++++ launcher/ui/pages/instance/InstanceSettingsPage.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 45d8f0180..d36fca99d 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -185,6 +185,7 @@ void JavaPage::updateThresholds() { auto sysMiB = Sys::getSystemRam() / Sys::mebibyte; unsigned int maxMem = ui->maxMemSpinBox->value(); + unsigned int minMem = ui->minMemSpinBox->value(); QString iconName; @@ -194,6 +195,9 @@ void JavaPage::updateThresholds() } else if (maxMem > (sysMiB * 0.9)) { iconName = "status-yellow"; ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); + } else if (maxMem < minMem) { + iconName = "status-yellow"; + ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller that the minimum value")); } else { iconName = "status-good"; ui->labelMaxMemIcon->setToolTip(""); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index d5dbb80b8..7fa18674f 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -478,6 +478,7 @@ void InstanceSettingsPage::updateThresholds() { auto sysMiB = Sys::getSystemRam() / Sys::mebibyte; unsigned int maxMem = ui->maxMemSpinBox->value(); + unsigned int minMem = ui->minMemSpinBox->value(); QString iconName; @@ -487,6 +488,9 @@ void InstanceSettingsPage::updateThresholds() } else if (maxMem > (sysMiB * 0.9)) { iconName = "status-yellow"; ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); + } else if (maxMem < minMem) { + iconName = "status-yellow"; + ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller that the minimum value")); } else { iconName = "status-good"; ui->labelMaxMemIcon->setToolTip(""); From 3574d89e0f6ea9d507e5c4844d07a2aeac9ade97 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 22 Aug 2023 16:16:50 +0300 Subject: [PATCH 288/398] Update launcher/ui/pages/global/JavaPage.cpp Co-authored-by: Tayou <31988415+TayouVR@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/pages/global/JavaPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index d36fca99d..ac50319ec 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -197,7 +197,7 @@ void JavaPage::updateThresholds() ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); } else if (maxMem < minMem) { iconName = "status-yellow"; - ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller that the minimum value")); + ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else { iconName = "status-good"; ui->labelMaxMemIcon->setToolTip(""); From 06dbd381f8e0ed2222193424812d7e83a4db1adf Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 22 Aug 2023 16:16:57 +0300 Subject: [PATCH 289/398] Update launcher/ui/pages/instance/InstanceSettingsPage.cpp Co-authored-by: Tayou <31988415+TayouVR@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 7fa18674f..7aa6bd322 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -490,7 +490,7 @@ void InstanceSettingsPage::updateThresholds() ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); } else if (maxMem < minMem) { iconName = "status-yellow"; - ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller that the minimum value")); + ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else { iconName = "status-good"; ui->labelMaxMemIcon->setToolTip(""); From eed7e996da260db2c3bc7e062953bee7bb04b8e7 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Tue, 22 Aug 2023 16:17:05 +0300 Subject: [PATCH 290/398] Update launcher/ui/widgets/JavaSettingsWidget.cpp Co-authored-by: Tayou <31988415+TayouVR@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/widgets/JavaSettingsWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 4ffa3b168..d2d921918 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -417,7 +417,7 @@ void JavaSettingsWidget::updateThresholds() m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); } else if (observedMaxMemory < observedMinMemory) { iconName = "status-yellow"; - m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller that the minimum value")); + m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); From 4704c522e002e0da2c9ce49f71456fce684ab3a1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 23 Aug 2023 10:26:57 +0300 Subject: [PATCH 291/398] moved modloaderTypes to ModPlatform Signed-off-by: Trial97 --- launcher/minecraft/PackProfile.cpp | 16 +++++----- launcher/minecraft/PackProfile.h | 2 +- .../mod/tasks/GetModDependenciesTask.cpp | 6 ++-- .../mod/tasks/GetModDependenciesTask.h | 2 +- launcher/modplatform/CheckUpdateTask.h | 4 +-- launcher/modplatform/ModIndex.cpp | 21 +++++++++++++ launcher/modplatform/ModIndex.h | 6 +++- launcher/modplatform/ResourceAPI.h | 30 ++----------------- launcher/modplatform/flame/FlameAPI.h | 23 +++++++------- launcher/modplatform/flame/FlameCheckUpdate.h | 2 +- .../modplatform/import_ftb/PackHelpers.cpp | 8 ++--- launcher/modplatform/import_ftb/PackHelpers.h | 2 +- .../import_ftb/PackInstallTask.cpp | 12 ++++---- launcher/modplatform/modrinth/ModrinthAPI.cpp | 4 +-- launcher/modplatform/modrinth/ModrinthAPI.h | 24 ++++++++------- .../modrinth/ModrinthCheckUpdate.cpp | 6 ++-- .../modrinth/ModrinthCheckUpdate.h | 2 +- launcher/ui/dialogs/ModUpdateDialog.cpp | 2 +- launcher/ui/pages/modplatform/ModPage.h | 2 +- .../modplatform/flame/FlameResourcePages.cpp | 2 +- .../modplatform/flame/FlameResourcePages.h | 2 +- .../modrinth/ModrinthResourcePages.cpp | 2 +- .../modrinth/ModrinthResourcePages.h | 2 +- 23 files changed, 94 insertions(+), 88 deletions(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 92988808a..dd7364851 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -62,11 +62,11 @@ #include "Application.h" #include "modplatform/ResourceAPI.h" -static const QMap modloaderMapping{ { "net.neoforged", ResourceAPI::NeoForge }, - { "net.minecraftforge", ResourceAPI::Forge }, - { "net.fabricmc.fabric-loader", ResourceAPI::Fabric }, - { "org.quiltmc.quilt-loader", ResourceAPI::Quilt }, - { "com.mumfrey.liteloader", ResourceAPI::LiteLoader } }; +static const QMap modloaderMapping{ { "net.neoforged", ModPlatform::NeoForge }, + { "net.minecraftforge", ModPlatform::Forge }, + { "net.fabricmc.fabric-loader", ModPlatform::Fabric }, + { "org.quiltmc.quilt-loader", ModPlatform::Quilt }, + { "com.mumfrey.liteloader", ModPlatform::LiteLoader } }; PackProfile::PackProfile(MinecraftInstance* instance) : QAbstractListModel() { @@ -990,12 +990,12 @@ void PackProfile::disableInteraction(bool disable) } } -std::optional PackProfile::getModLoaders() +std::optional PackProfile::getModLoaders() { - ResourceAPI::ModLoaderTypes result; + ModPlatform::ModLoaderTypes result; bool has_any_loader = false; - QMapIterator i(modloaderMapping); + QMapIterator i(modloaderMapping); while (i.hasNext()) { i.next(); diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h index ce44fa588..4b93d654c 100644 --- a/launcher/minecraft/PackProfile.h +++ b/launcher/minecraft/PackProfile.h @@ -146,7 +146,7 @@ class PackProfile : public QAbstractListModel { // todo(merged): is this the best approach void appendComponent(ComponentPtr component); - std::optional getModLoaders(); + std::optional getModLoaders(); private: void scheduleSave(); diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 0a0f57bf3..46b489ce0 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -39,7 +39,7 @@ static Version mcVersion(BaseInstance* inst) return static_cast(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion(); } -static ResourceAPI::ModLoaderTypes mcLoaders(BaseInstance* inst) +static ModPlatform::ModLoaderTypes mcLoaders(BaseInstance* inst) { return static_cast(inst)->getPackProfile()->getModLoaders().value(); } @@ -75,7 +75,7 @@ void GetModDependenciesTask::prepare() ModPlatform::Dependency GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep, const ModPlatform::ResourceProvider providerName) { - if (auto isQuilt = m_loaderType & ResourceAPI::Quilt; isQuilt || m_loaderType & ResourceAPI::Fabric) { + if (auto isQuilt = m_loaderType & ModPlatform::Quilt; isQuilt || m_loaderType & ModPlatform::Fabric) { auto overide = ModPlatform::getOverrideDeps(); auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, providerName, isQuilt](auto o) { return o.provider == providerName && dep.addonId == (isQuilt ? o.fabric : o.quilt); @@ -191,7 +191,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } pDep->version = provider.mod->loadDependencyVersions(dep, arr); if (!pDep->version.addonId.isValid()) { - if (m_loaderType & ResourceAPI::Quilt) { // falback for quilt + if (m_loaderType & ModPlatform::Quilt) { // falback for quilt auto overide = ModPlatform::getOverrideDeps(); auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, provider](auto o) { return o.provider == provider.name && dep.addonId == o.quilt; }); diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 50eba6afc..a8b9953d3 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -80,5 +80,5 @@ class GetModDependenciesTask : public SequentialTask { Provider m_modrinth_provider; Version m_version; - ResourceAPI::ModLoaderTypes m_loaderType; + ModPlatform::ModLoaderTypes m_loaderType; }; diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index 6d968ea48..d125a5879 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -14,7 +14,7 @@ class CheckUpdateTask : public Task { public: CheckUpdateTask(QList& mods, std::list& mcVersions, - std::optional loaders, + std::optional loaders, std::shared_ptr mods_folder) : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){}; @@ -53,7 +53,7 @@ class CheckUpdateTask : public Task { protected: QList& m_mods; std::list& m_game_versions; - std::optional m_loaders; + std::optional m_loaders; std::shared_ptr m_mods_folder; std::vector m_updatable; diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 350a9f10b..e8e4a38dd 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -83,4 +83,25 @@ QString getMetaURL(ResourceProvider provider, QVariant projectID) projectID.toString(); } +auto getModLoaderString(ModLoaderType type) -> const QString +{ + switch (type) { + case NeoForge: + return "neoforge"; + case Forge: + return "forge"; + case Cauldron: + return "cauldron"; + case LiteLoader: + return "liteloader"; + case Fabric: + return "fabric"; + case Quilt: + return "quilt"; + default: + break; + } + return ""; +} + } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index cad217034..2178422f0 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -30,6 +30,9 @@ class QIODevice; namespace ModPlatform { +enum ModLoaderType { NeoForge = 1 << 0, Forge = 1 << 1, Cauldron = 1 << 2, LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5 }; +Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType) + enum class ResourceProvider { MODRINTH, FLAME }; enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK }; @@ -128,7 +131,6 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; -QString getMetaURL(ResourceProvider provider, QVariant projectID); struct OverrideDep { QString quilt; @@ -148,6 +150,8 @@ inline auto getOverrideDeps() -> QList QString getMetaURL(ResourceProvider provider, QVariant projectID); +auto getModLoaderString(ModLoaderType type) -> const QString; + } // namespace ModPlatform Q_DECLARE_METATYPE(ModPlatform::IndexedPack) diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index f6ccb426d..7965d0f53 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -54,9 +54,6 @@ class ResourceAPI { public: virtual ~ResourceAPI() = default; - enum ModLoaderType { NeoForge = 1 << 0, Forge = 1 << 1, Cauldron = 1 << 2, LiteLoader = 1 << 3, Fabric = 1 << 4, Quilt = 1 << 5 }; - Q_DECLARE_FLAGS(ModLoaderTypes, ModLoaderType) - struct SortingMethod { // The index of the sorting method. Used to allow for arbitrary ordering in the list of methods. // Used by Flame in the API request. @@ -74,7 +71,7 @@ class ResourceAPI { std::optional search; std::optional sorting; - std::optional loaders; + std::optional loaders; std::optional > versions; }; struct SearchCallbacks { @@ -87,7 +84,7 @@ class ResourceAPI { ModPlatform::IndexedPack pack; std::optional > mcVersions; - std::optional loaders; + std::optional loaders; VersionSearchArgs(VersionSearchArgs const&) = default; void operator=(VersionSearchArgs other) @@ -114,7 +111,7 @@ class ResourceAPI { struct DependencySearchArgs { ModPlatform::Dependency dependency; Version mcVersion; - ModLoaderTypes loader; + ModPlatform::ModLoaderTypes loader; }; struct DependencySearchCallbacks { @@ -161,27 +158,6 @@ class ResourceAPI { return nullptr; } - static auto getModLoaderString(ModLoaderType type) -> const QString - { - switch (type) { - case NeoForge: - return "neoforge"; - case Forge: - return "forge"; - case Cauldron: - return "cauldron"; - case LiteLoader: - return "liteloader"; - case Fabric: - return "fabric"; - case Quilt: - return "quilt"; - default: - break; - } - return ""; - } - protected: [[nodiscard]] inline QString debugName() const { return "External resource API"; } diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index e423189a8..a36b99a47 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -24,7 +24,10 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] auto getSortingMethods() const -> QList override; - static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (NeoForge | Forge | Fabric | Quilt); } + static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool + { + return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt); + } private: static int getClassId(ModPlatform::ResourceType type) @@ -38,19 +41,19 @@ class FlameAPI : public NetworkResourceAPI { } } - static int getMappedModLoader(ModLoaderTypes loaders) + static int getMappedModLoader(ModPlatform::ModLoaderTypes loaders) { // https://docs.curseforge.com/?http#tocS_ModLoaderType - if (loaders & Forge) + if (loaders & ModPlatform::Forge) return 1; - if (loaders & Fabric) + if (loaders & ModPlatform::Fabric) return 4; // TODO: remove this once Quilt drops official Fabric support - if (loaders & Quilt) // NOTE: Most if not all Fabric mods should work *currently* - return 4; // FIXME: implement multiple loaders filter (this should be 5) + if (loaders & ModPlatform::Quilt) // NOTE: Most if not all Fabric mods should work *currently* + return 4; // FIXME: implement multiple loaders filter (this should be 5) // TODO: remove this once NeoForge drops official Forge support - if (loaders & NeoForge) // NOTE: Most if not all Forge mods should work *currently* - return 1; // FIXME: implement multiple loaders filter (this should be 6) + if (loaders & ModPlatform::NeoForge) // NOTE: Most if not all Forge mods should work *currently* + return 1; // FIXME: implement multiple loaders filter (this should be 6) return 0; } @@ -93,7 +96,7 @@ class FlameAPI : public NetworkResourceAPI { if (args.loaders.has_value()) { int mappedModLoader = getMappedModLoader(args.loaders.value()); - if (args.loaders.value() & Quilt) { + if (args.loaders.value() & ModPlatform::Quilt) { auto overide = ModPlatform::getOverrideDeps(); auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; @@ -113,7 +116,7 @@ class FlameAPI : public NetworkResourceAPI { { auto mappedModLoader = getMappedModLoader(args.loader); auto addonId = args.dependency.addonId.toString(); - if (args.loader & Quilt) { + if (args.loader & ModPlatform::Quilt) { auto overide = ModPlatform::getOverrideDeps(); auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.h b/launcher/modplatform/flame/FlameCheckUpdate.h index e3465d7e2..05c619a70 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.h +++ b/launcher/modplatform/flame/FlameCheckUpdate.h @@ -10,7 +10,7 @@ class FlameCheckUpdate : public CheckUpdateTask { public: FlameCheckUpdate(QList& mods, std::list& mcVersions, - std::optional loaders, + std::optional loaders, std::shared_ptr mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) {} diff --git a/launcher/modplatform/import_ftb/PackHelpers.cpp b/launcher/modplatform/import_ftb/PackHelpers.cpp index 118bdd157..ecf973452 100644 --- a/launcher/modplatform/import_ftb/PackHelpers.cpp +++ b/launcher/modplatform/import_ftb/PackHelpers.cpp @@ -60,19 +60,19 @@ Modpack parseDirectory(QString path) auto name = Json::requireString(obj, "name", "name"); auto version = Json::requireString(obj, "version", "version"); if (name == "neoforge") { - modpack.loaderType = ResourceAPI::NeoForge; + modpack.loaderType = ModPlatform::NeoForge; modpack.version = version; break; } else if (name == "forge") { - modpack.loaderType = ResourceAPI::Forge; + modpack.loaderType = ModPlatform::Forge; modpack.version = version; break; } else if (name == "fabric") { - modpack.loaderType = ResourceAPI::Fabric; + modpack.loaderType = ModPlatform::Fabric; modpack.version = version; break; } else if (name == "quilt") { - modpack.loaderType = ResourceAPI::Quilt; + modpack.loaderType = ModPlatform::Quilt; modpack.version = version; break; } diff --git a/launcher/modplatform/import_ftb/PackHelpers.h b/launcher/modplatform/import_ftb/PackHelpers.h index 8ea4f3faf..5400252b6 100644 --- a/launcher/modplatform/import_ftb/PackHelpers.h +++ b/launcher/modplatform/import_ftb/PackHelpers.h @@ -39,7 +39,7 @@ struct Modpack { // not needed for instance creation QVariant jvmArgs; - std::optional loaderType; + std::optional loaderType; QString loaderVersion; QIcon icon; diff --git a/launcher/modplatform/import_ftb/PackInstallTask.cpp b/launcher/modplatform/import_ftb/PackInstallTask.cpp index 9e4decb0c..9a3b2595b 100644 --- a/launcher/modplatform/import_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/import_ftb/PackInstallTask.cpp @@ -68,25 +68,25 @@ void PackInstallTask::copySettings() auto modloader = m_pack.loaderType; if (modloader.has_value()) switch (modloader.value()) { - case ResourceAPI::NeoForge: { + case ModPlatform::NeoForge: { components->setComponentVersion("net.neoforged", m_pack.version, true); break; } - case ResourceAPI::Forge: { + case ModPlatform::Forge: { components->setComponentVersion("net.minecraftforge", m_pack.version, true); break; } - case ResourceAPI::Fabric: { + case ModPlatform::Fabric: { components->setComponentVersion("net.fabricmc.fabric-loader", m_pack.version, true); break; } - case ResourceAPI::Quilt: { + case ModPlatform::Quilt: { components->setComponentVersion("org.quiltmc.quilt-loader", m_pack.version, true); break; } - case ResourceAPI::Cauldron: + case ModPlatform::Cauldron: break; - case ResourceAPI::LiteLoader: + case ModPlatform::LiteLoader: break; } components->saveNow(); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp index 466c5b102..f453f5cb9 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.cpp +++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp @@ -41,7 +41,7 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f Task::Ptr ModrinthAPI::latestVersion(QString hash, QString hash_format, std::optional> mcVersions, - std::optional loaders, + std::optional loaders, std::shared_ptr response) { auto netJob = makeShared(QString("Modrinth::GetLatestVersion"), APPLICATION->network()); @@ -71,7 +71,7 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash, Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes, QString hash_format, std::optional> mcVersions, - std::optional loaders, + std::optional loaders, std::shared_ptr response) { auto netJob = makeShared(QString("Modrinth::GetLatestVersions"), APPLICATION->network()); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index fb42c532c..6ff8f7bcd 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -19,13 +19,13 @@ class ModrinthAPI : public NetworkResourceAPI { auto latestVersion(QString hash, QString hash_format, std::optional> mcVersions, - std::optional loaders, + std::optional loaders, std::shared_ptr response) -> Task::Ptr; auto latestVersions(const QStringList& hashes, QString hash_format, std::optional> mcVersions, - std::optional loaders, + std::optional loaders, std::shared_ptr response) -> Task::Ptr; Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const override; @@ -35,22 +35,24 @@ class ModrinthAPI : public NetworkResourceAPI { inline auto getAuthorURL(const QString& name) const -> QString { return "https://modrinth.com/user/" + name; }; - static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList + static auto getModLoaderStrings(const ModPlatform::ModLoaderTypes types) -> const QStringList { QStringList l; - for (auto loader : { NeoForge, Forge, Fabric, Quilt, LiteLoader }) { + for (auto loader : + { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt, ModPlatform::LiteLoader }) { if (types & loader) { l << getModLoaderString(loader); } } - if ((types & NeoForge) && (~types & Forge)) // Add Forge if NeoForge is in use, if Forge isn't already there - l << getModLoaderString(Forge); - if ((types & Quilt) && (~types & Fabric)) // Add Fabric if Quilt is in use, if Fabric isn't already there - l << getModLoaderString(Fabric); + if ((types & ModPlatform::NeoForge) && + (~types & ModPlatform::Forge)) // Add Forge if NeoForge is in use, if Forge isn't already there + l << getModLoaderString(ModPlatform::Forge); + if ((types & ModPlatform::Quilt) && (~types & ModPlatform::Fabric)) // Add Fabric if Quilt is in use, if Fabric isn't already there + l << getModLoaderString(ModPlatform::Fabric); return l; } - static auto getModLoaderFilters(ModLoaderTypes types) -> const QString + static auto getModLoaderFilters(ModPlatform::ModLoaderTypes types) -> const QString { QStringList l; for (auto loader : getModLoaderStrings(types)) { @@ -143,9 +145,9 @@ class ModrinthAPI : public NetworkResourceAPI { return s.isEmpty() ? QString() : s; } - static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool + static inline auto validateModLoaders(ModPlatform::ModLoaderTypes loaders) -> bool { - return loaders & (NeoForge | Forge | Fabric | Quilt | LiteLoader); + return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt | ModPlatform::LiteLoader); } [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index bff8fa2fe..ba3aad844 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -111,11 +111,11 @@ void ModrinthCheckUpdate::executeTask() // so we may want to filter it QString loader_filter; if (m_loaders.has_value()) { - static auto flags = { ResourceAPI::ModLoaderType::NeoForge, ResourceAPI::ModLoaderType::Forge, - ResourceAPI::ModLoaderType::Fabric, ResourceAPI::ModLoaderType::Quilt }; + static auto flags = { ModPlatform::ModLoaderType::NeoForge, ModPlatform::ModLoaderType::Forge, + ModPlatform::ModLoaderType::Fabric, ModPlatform::ModLoaderType::Quilt }; for (auto flag : flags) { if (m_loaders.value().testFlag(flag)) { - loader_filter = api.getModLoaderString(flag); + loader_filter = ModPlatform::getModLoaderString(flag); break; } } diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h index 4583dd6ce..f2f2c7e92 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h @@ -10,7 +10,7 @@ class ModrinthCheckUpdate : public CheckUpdateTask { public: ModrinthCheckUpdate(QList& mods, std::list& mcVersions, - std::optional loaders, + std::optional loaders, std::shared_ptr mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) {} diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 0af1ec59b..3e18b224e 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -30,7 +30,7 @@ static std::list mcVersions(BaseInstance* inst) return { static_cast(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion() }; } -static std::optional mcLoaders(BaseInstance* inst) +static std::optional mcLoaders(BaseInstance* inst) { return { static_cast(inst)->getPackProfile()->getModLoaders() }; } diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 5510c1911..5a43e49a6 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -55,7 +55,7 @@ class ModPage : public ResourcePage { virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, - std::optional loaders = {}) const -> bool = 0; + std::optional loaders = {}) const -> bool = 0; [[nodiscard]] bool supportsFiltering() const override { return true; }; auto getFilter() const -> const std::shared_ptr { return m_filter; } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index dc17e705a..5650fb95d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -68,7 +68,7 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, - std::optional loaders) const -> bool + std::optional loaders) const -> bool { Q_UNUSED(loaders); return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty(); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index c6ebc1eac..035da2d5f 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -95,7 +95,7 @@ class FlameModPage : public ModPage { bool validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, - std::optional loaders = {}) const override; + std::optional loaders = {}) const override; bool optedOut(ModPlatform::IndexedVersion& ver) const override; void openUrl(const QUrl& url) override; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index 616c1a815..e944a2a98 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -65,7 +65,7 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, - std::optional loaders) const -> bool + std::optional loaders) const -> bool { auto loaderCompatible = !loaders.has_value(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h index 86ba1ccb2..311bcfe32 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.h @@ -93,7 +93,7 @@ class ModrinthModPage : public ModPage { [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } - auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const + auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const -> bool override; }; From f8f9ffa1182c76cd22c2c181820bdd9516d7958f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 23 Aug 2023 11:33:45 +0300 Subject: [PATCH 292/398] added loaders for flame version Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/flame/FileResolvingTask.cpp | 3 ++- launcher/modplatform/flame/FlameModIndex.cpp | 13 +++++++++++++ .../modplatform/modrinth/ModrinthPackIndex.cpp | 13 ++++++++++++- launcher/ui/pages/modplatform/ModPage.cpp | 1 - launcher/ui/pages/modplatform/ShaderPackPage.cpp | 3 ++- .../pages/modplatform/flame/FlameResourcePages.cpp | 3 +-- .../modplatform/modrinth/ModrinthResourcePages.cpp | 14 +------------- 8 files changed, 32 insertions(+), 20 deletions(-) diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 2178422f0..780f68b4d 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -73,7 +73,7 @@ struct IndexedVersion { QString downloadUrl; QString date; QString fileName; - QStringList loaders = {}; + ModLoaderTypes loaders = {}; QString hash_type; QString hash; bool is_preferred = true; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 860d7340f..07a3ae632 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -1,5 +1,6 @@ #include "FileResolvingTask.h" +#include #include "Json.h" #include "net/ApiDownload.h" #include "net/ApiUpload.h" @@ -153,7 +154,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() // If there's more than one mod loader for this version, we can't know for sure // which file is relative to each loader, so it's best to not use any one and // let the user download it manually. - if (file.loaders.size() <= 1) { + if (std::bitset<8>(file.loaders.toInt()).count() <= 1) { out->url = file.downloadUrl; qDebug() << "Found alternative on modrinth " << out->fileName; } else { diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 19803cf6d..8924913bc 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -115,6 +115,19 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> if (str.contains('.')) file.mcVersion.append(str); + auto loader = str.toLower(); + if (loader == "neoforge") + file.loaders |= ModPlatform::NeoForge; + if (loader == "forge") + file.loaders |= ModPlatform::Forge; + if (loader == "cauldron") + file.loaders |= ModPlatform::Cauldron; + if (loader == "liteloader") + file.loaders |= ModPlatform::LiteLoader; + if (loader == "fabric") + file.loaders |= ModPlatform::Fabric; + if (loader == "quilt") + file.loaders |= ModPlatform::Quilt; } file.addonId = Json::requireInteger(obj, "modId"); diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 85e66a91e..1ff5a4b9e 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -134,7 +134,18 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t } auto loaders = Json::requireArray(obj, "loaders"); for (auto loader : loaders) { - file.loaders.append(loader.toString()); + if (loader == "neoforge") + file.loaders |= ModPlatform::NeoForge; + if (loader == "forge") + file.loaders |= ModPlatform::Forge; + if (loader == "cauldron") + file.loaders |= ModPlatform::Cauldron; + if (loader == "liteloader") + file.loaders |= ModPlatform::LiteLoader; + if (loader == "fabric") + file.loaders |= ModPlatform::Fabric; + if (loader == "quilt") + file.loaders |= ModPlatform::Quilt; } file.version = Json::requireString(obj, "name"); file.version_number = Json::requireString(obj, "version_number"); diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 60a43128a..c9270d399 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -124,7 +124,6 @@ void ModPage::updateVersionList() auto version = current_pack->versions[i]; bool valid = false; for (auto& mcVer : m_filter->versions) { - // NOTE: Flame doesn't care about loader, so passing it changes nothing. if (validateVersion(version, mcVer.toString(), packProfile->getModLoaders())) { valid = true; break; diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index fbf94e844..586dffc55 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: GPL-3.0-only #include "ShaderPackPage.h" +#include "modplatform/ModIndex.h" #include "ui_ResourcePage.h" #include "ShaderPackModel.h" @@ -48,7 +49,7 @@ void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pac const std::shared_ptr base_model) { QString custom_target_folder; - if (version.loaders.contains(QStringLiteral("canvas"))) + if (version.loaders & ModPlatform::Cauldron) custom_target_folder = QStringLiteral("resourcepacks"); m_model->addPack(pack, version, base_model, false, custom_target_folder); } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index 5650fb95d..222ceedc6 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -70,8 +70,7 @@ auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders) const -> bool { - Q_UNUSED(loaders); - return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty(); + return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty() && (!loaders.has_value() || loaders.value() & ver.loaders); } bool FlameModPage::optedOut(ModPlatform::IndexedVersion& ver) const diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index e944a2a98..bcd0a4cf4 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -67,19 +67,7 @@ auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders) const -> bool { - auto loaderCompatible = !loaders.has_value(); - - if (!loaderCompatible) { - auto loaderStrings = ModrinthAPI::getModLoaderStrings(loaders.value()); - for (auto remoteLoader : ver.loaders) { - if (loaderStrings.contains(remoteLoader)) { - loaderCompatible = true; - break; - } - } - } - - return ver.mcVersion.contains(mineVer) && loaderCompatible; + return ver.mcVersion.contains(mineVer) && (!loaders.has_value() || loaders.value() & ver.loaders); } ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) From b93cd88292c152175abcd79a6de1d276301de003 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 23 Aug 2023 11:52:31 +0200 Subject: [PATCH 293/398] fix(nix): add canonicalize-jars-hook See https://github.com/NixOS/nixpkgs/pull/250757 Signed-off-by: Sefa Eyeoglu --- nix/package.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nix/package.nix b/nix/package.nix index 1dbadd405..074214c4b 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -1,6 +1,7 @@ { lib, stdenv, + canonicalize-jars-hook, cmake, cmark, Cocoa, @@ -26,7 +27,7 @@ assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is on src = lib.cleanSource self; - nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja]; + nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja canonicalize-jars-hook]; buildInputs = [ qtbase From e6ba2f4970abe69f2203bb5b85503e4cf3177016 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 23 Aug 2023 12:52:51 +0300 Subject: [PATCH 294/398] Added loaders check on versions load Signed-off-by: Trial97 --- launcher/minecraft/ComponentUpdateTask.cpp | 4 +- launcher/minecraft/PackProfile.cpp | 20 +++++++-- launcher/minecraft/PackProfile.h | 8 ++-- .../mod/tasks/GetModDependenciesTask.cpp | 3 +- launcher/modplatform/flame/FlameAPI.cpp | 11 +---- launcher/modplatform/flame/FlameAPI.h | 45 +++++++++---------- .../modplatform/flame/FlameCheckUpdate.cpp | 2 - launcher/modplatform/flame/FlameModIndex.cpp | 12 +++-- launcher/modplatform/flame/FlameModIndex.h | 2 +- launcher/modplatform/modrinth/ModrinthAPI.h | 5 --- .../modrinth/ModrinthCheckUpdate.cpp | 1 - .../modrinth/ModrinthPackIndex.cpp | 23 ++++++---- .../modplatform/modrinth/ModrinthPackIndex.h | 7 +-- launcher/ui/MainWindow.cpp | 11 +++-- launcher/ui/dialogs/ModUpdateDialog.cpp | 4 +- .../ui/dialogs/ResourceDownloadDialog.cpp | 2 +- launcher/ui/pages/modplatform/ModModel.cpp | 4 +- launcher/ui/pages/modplatform/ModPage.cpp | 2 +- .../modplatform/flame/FlameResourceModels.cpp | 2 +- .../modrinth/ModrinthResourceModels.cpp | 10 ++--- 20 files changed, 89 insertions(+), 89 deletions(-) diff --git a/launcher/minecraft/ComponentUpdateTask.cpp b/launcher/minecraft/ComponentUpdateTask.cpp index 0b85b81aa..bb838043a 100644 --- a/launcher/minecraft/ComponentUpdateTask.cpp +++ b/launcher/minecraft/ComponentUpdateTask.cpp @@ -2,14 +2,14 @@ #include "Component.h" #include "ComponentUpdateTask_p.h" -#include "OneSixVersionFormat.h" #include "PackProfile.h" #include "PackProfile_p.h" #include "Version.h" #include "cassert" #include "meta/Index.h" #include "meta/Version.h" -#include "meta/VersionList.h" +#include "minecraft/OneSixVersionFormat.h" +#include "minecraft/ProfileUtils.h" #include "net/Mode.h" #include "Application.h" diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index dd7364851..9e42c5dd6 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -58,9 +58,8 @@ #include "ComponentUpdateTask.h" #include "PackProfile.h" #include "PackProfile_p.h" - -#include "Application.h" -#include "modplatform/ResourceAPI.h" +#include "minecraft/mod/Mod.h" +#include "modplatform/ModIndex.h" static const QMap modloaderMapping{ { "net.neoforged", ModPlatform::NeoForge }, { "net.minecraftforge", ModPlatform::Forge }, @@ -1009,3 +1008,18 @@ std::optional PackProfile::getModLoaders() return {}; return result; } + +std::optional PackProfile::getSupportedModLoaders() +{ + auto loadersOpt = getModLoaders(); + if (!loadersOpt.has_value()) + return loadersOpt; + auto loaders = loadersOpt.value(); + // TODO: remove this or add version condition once Quilt drops official Fabric support + if (loaders & ModPlatform::Quilt) + loaders |= ModPlatform::Fabric; + // TODO: remove this or add version condition once NeoForge drops official Forge support + if (loaders & ModPlatform::NeoForge) + loaders |= ModPlatform::Forge; + return loaders; +} diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h index 4b93d654c..c41601fb2 100644 --- a/launcher/minecraft/PackProfile.h +++ b/launcher/minecraft/PackProfile.h @@ -45,13 +45,9 @@ #include #include -#include "BaseVersion.h" #include "Component.h" #include "LaunchProfile.h" -#include "Library.h" -#include "MojangDownloadInfo.h" -#include "ProfileUtils.h" -#include "modplatform/ResourceAPI.h" +#include "modplatform/ModIndex.h" #include "net/Mode.h" class MinecraftInstance; @@ -147,6 +143,8 @@ class PackProfile : public QAbstractListModel { void appendComponent(ComponentPtr component); std::optional getModLoaders(); + // this returns aditional loaders(Quilt supports fabric and NeoForge supports Forge) + std::optional getSupportedModLoaders(); private: void scheduleSave(); diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 46b489ce0..93e1b2ed9 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -41,7 +41,8 @@ static Version mcVersion(BaseInstance* inst) static ModPlatform::ModLoaderTypes mcLoaders(BaseInstance* inst) { - return static_cast(inst)->getPackProfile()->getModLoaders().value(); + return static_cast(inst)->getPackProfile()->getSupportedModLoaders().value_or( + ModPlatform::ModLoaderTypes::fromInt(0)); } GetModDependenciesTask::GetModDependenciesTask(QObject* parent, diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 74d7db975..8d01f779d 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -6,7 +6,6 @@ #include "FlameModIndex.h" #include "Application.h" -#include "BuildConfig.h" #include "Json.h" #include "net/ApiDownload.h" #include "net/ApiUpload.h" @@ -131,19 +130,13 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe auto obj = Json::requireObject(doc); auto arr = Json::requireArray(obj, "data"); - QJsonObject latest_file_obj; - ModPlatform::IndexedVersion ver_tmp; - for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - if (file_tmp.date > ver_tmp.date) { - ver_tmp = file_tmp; - latest_file_obj = file_obj; - } + if (file_tmp.date > ver.date && (!args.loaders.has_value() || args.loaders.value() & file_tmp.loaders)) + ver = file_tmp; } - ver = FlameMod::loadIndexedPackVersion(latest_file_obj); } catch (Json::JsonException& e) { qCritical() << "Failed to parse response from a version request."; qCritical() << e.what(); diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index a36b99a47..12cccb6f9 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -48,15 +48,29 @@ class FlameAPI : public NetworkResourceAPI { return 1; if (loaders & ModPlatform::Fabric) return 4; - // TODO: remove this once Quilt drops official Fabric support - if (loaders & ModPlatform::Quilt) // NOTE: Most if not all Fabric mods should work *currently* - return 4; // FIXME: implement multiple loaders filter (this should be 5) - // TODO: remove this once NeoForge drops official Forge support - if (loaders & ModPlatform::NeoForge) // NOTE: Most if not all Forge mods should work *currently* - return 1; // FIXME: implement multiple loaders filter (this should be 6) + if (loaders & ModPlatform::Quilt) + return 5; + if (loaders & ModPlatform::NeoForge) + return 6; return 0; } + static auto getModLoaderStrings(const ModPlatform::ModLoaderTypes types) -> const QStringList + { + QStringList l; + for (auto loader : { ModPlatform::NeoForge, ModPlatform::Forge, ModPlatform::Fabric, ModPlatform::Quilt }) { + if (types & loader) { + l << QString::number(getMappedModLoader(loader)); + } + } + return l; + } + + static auto getModLoaderFilters(ModPlatform::ModLoaderTypes types) -> const QString + { + return "[" + getModLoaderStrings(types).join(',') + "]"; + } + private: [[nodiscard]] std::optional getSearchURL(SearchArgs const& args) const override { @@ -73,7 +87,7 @@ class FlameAPI : public NetworkResourceAPI { get_arguments.append(QString("sortField=%1").arg(args.sorting.value().index)); get_arguments.append("sortOrder=desc"); if (args.loaders.has_value()) - get_arguments.append(QString("modLoaderType=%1").arg(getMappedModLoader(args.loaders.value()))); + get_arguments.append(QString("modLoaderTypes=%1").arg(getModLoaderFilters(args.loaders.value()))); get_arguments.append(gameVersionStr); return "https://api.curseforge.com/v1/mods/search?gameId=432&" + get_arguments.join('&'); @@ -92,23 +106,6 @@ class FlameAPI : public NetworkResourceAPI { QStringList get_parameters; if (args.mcVersions.has_value()) get_parameters.append(QString("gameVersion=%1").arg(args.mcVersions.value().front().toString())); - - if (args.loaders.has_value()) { - int mappedModLoader = getMappedModLoader(args.loaders.value()); - - if (args.loaders.value() & ModPlatform::Quilt) { - auto overide = ModPlatform::getOverrideDeps(); - auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { - return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; - }); - if (over != overide.cend()) { - mappedModLoader = 5; - } - } - - get_parameters.append(QString("modLoaderType=%1").arg(mappedModLoader)); - } - return url + get_parameters.join('&'); }; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index e10fedc3c..476a4667a 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -5,13 +5,11 @@ #include #include -#include "FileSystem.h" #include "Json.h" #include "ResourceDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" -#include "minecraft/mod/ResourceFolderModel.h" #include "net/ApiDownload.h" diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 8924913bc..67e3468f9 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -81,6 +81,7 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QVector unsortedVersions; auto profile = (dynamic_cast(inst))->getPackProfile(); QString mcVersion = profile->getComponentVersion("net.minecraft"); + auto loaders = profile->getSupportedModLoaders(); for (auto versionIter : arr) { auto obj = versionIter.toObject(); @@ -89,7 +90,8 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, if (!file.addonId.isValid()) file.addonId = pack.addonId; - if (file.fileId.isValid()) // Heuristic to check if the returned value is valid + if (file.fileId.isValid() && + (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid unsortedVersions.append(file); } @@ -186,8 +188,11 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> return file; } -ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) +ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) { + auto profile = (dynamic_cast(inst))->getPackProfile(); + QString mcVersion = profile->getComponentVersion("net.minecraft"); + auto loaders = profile->getSupportedModLoaders(); QVector versions; for (auto versionIter : arr) { auto obj = versionIter.toObject(); @@ -196,7 +201,8 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform:: if (!file.addonId.isValid()) file.addonId = m.addonId; - if (file.fileId.isValid()) // Heuristic to check if the returned value is valid + if (file.fileId.isValid() && + (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid versions.append(file); } diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h index aa0d6f812..1bcaa44ba 100644 --- a/launcher/modplatform/flame/FlameModIndex.h +++ b/launcher/modplatform/flame/FlameModIndex.h @@ -19,5 +19,5 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, const shared_qobject_ptr& network, const BaseInstance* inst); auto loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false) -> ModPlatform::IndexedVersion; -auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion; +auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) -> ModPlatform::IndexedVersion; } // namespace FlameMod \ No newline at end of file diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 6ff8f7bcd..d0f0811b2 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -44,11 +44,6 @@ class ModrinthAPI : public NetworkResourceAPI { l << getModLoaderString(loader); } } - if ((types & ModPlatform::NeoForge) && - (~types & ModPlatform::Forge)) // Add Forge if NeoForge is in use, if Forge isn't already there - l << getModLoaderString(ModPlatform::Forge); - if ((types & ModPlatform::Quilt) && (~types & ModPlatform::Fabric)) // Add Fabric if Quilt is in use, if Fabric isn't already there - l << getModLoaderString(ModPlatform::Fabric); return l; } diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index ba3aad844..c65f4fa80 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -11,7 +11,6 @@ #include "tasks/ConcurrentTask.h" #include "minecraft/mod/ModFolderModel.h" -#include "minecraft/mod/ResourceFolderModel.h" static ModrinthAPI api; static ModPlatform::ProviderCapabilities ProviderCaps; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 1ff5a4b9e..d857e82a8 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -93,19 +93,19 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob pack.extraDataLoaded = true; } -void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, - QJsonArray& arr, - [[maybe_unused]] const shared_qobject_ptr& network, - const BaseInstance* inst) +void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const BaseInstance* inst) { QVector unsortedVersions; - QString mcVersion = (static_cast(inst))->getPackProfile()->getComponentVersion("net.minecraft"); + auto profile = (dynamic_cast(inst))->getPackProfile(); + QString mcVersion = profile->getComponentVersion("net.minecraft"); + auto loaders = profile->getSupportedModLoaders(); for (auto versionIter : arr) { auto obj = versionIter.toObject(); auto file = loadIndexedPackVersion(obj); - if (file.fileId.isValid()) // Heuristic to check if the returned value is valid + if (file.fileId.isValid() && + (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { @@ -229,15 +229,20 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t return {}; } -auto Modrinth::loadDependencyVersions([[maybe_unused]] const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto Modrinth::loadDependencyVersions([[maybe_unused]] const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) + -> ModPlatform::IndexedVersion { - QVector versions; + auto profile = (dynamic_cast(inst))->getPackProfile(); + QString mcVersion = profile->getComponentVersion("net.minecraft"); + auto loaders = profile->getSupportedModLoaders(); + QVector versions; for (auto versionIter : arr) { auto obj = versionIter.toObject(); auto file = loadIndexedPackVersion(obj); - if (file.fileId.isValid()) // Heuristic to check if the returned value is valid + if (file.fileId.isValid() && + (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid versions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h index 58a0f227c..93f91eec2 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.h +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h @@ -26,11 +26,8 @@ namespace Modrinth { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj); void loadExtraPackData(ModPlatform::IndexedPack& m, QJsonObject& obj); -void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, - QJsonArray& arr, - const shared_qobject_ptr& network, - const BaseInstance* inst); +void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const BaseInstance* inst); auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion; -auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion; +auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr, const BaseInstance* inst) -> ModPlatform::IndexedVersion; } // namespace Modrinth diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index b3b60714a..7900e6c45 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -43,7 +43,6 @@ #include "FileSystem.h" #include "MainWindow.h" -#include "ui/dialogs/ExportToModListDialog.h" #include "ui_MainWindow.h" #include @@ -90,17 +89,14 @@ #include #include #include -#include "InstancePageProvider.h" #include "InstanceWindow.h" -#include "JavaCommon.h" -#include "LaunchController.h" #include "ui/dialogs/AboutDialog.h" #include "ui/dialogs/CopyInstanceDialog.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/dialogs/EditAccountDialog.h" #include "ui/dialogs/ExportInstanceDialog.h" #include "ui/dialogs/ExportPackDialog.h" +#include "ui/dialogs/ExportToModListDialog.h" #include "ui/dialogs/IconPickerDialog.h" #include "ui/dialogs/ImportResourceDialog.h" #include "ui/dialogs/NewInstanceDialog.h" @@ -113,9 +109,13 @@ #include "ui/themes/ThemeManager.h" #include "ui/widgets/LabeledToolButton.h" +#include "minecraft/PackProfile.h" +#include "minecraft/VersionFile.h" #include "minecraft/WorldList.h" #include "minecraft/mod/ModFolderModel.h" +#include "minecraft/mod/ResourcePackFolderModel.h" #include "minecraft/mod/ShaderPackFolderModel.h" +#include "minecraft/mod/TexturePackFolderModel.h" #include "minecraft/mod/tasks/LocalResourceParse.h" #include "modplatform/flame/FlameAPI.h" @@ -123,7 +123,6 @@ #include "KonamiCode.h" #include "InstanceCopyTask.h" -#include "InstanceImportTask.h" #include "Json.h" diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 3e18b224e..1f0fa7cd2 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -5,8 +5,6 @@ #include "ScrollMessageBox.h" #include "ui_ReviewMessageBox.h" -#include "FileSystem.h" -#include "Json.h" #include "Markdown.h" #include "tasks/ConcurrentTask.h" @@ -32,7 +30,7 @@ static std::list mcVersions(BaseInstance* inst) static std::optional mcLoaders(BaseInstance* inst) { - return { static_cast(inst)->getPackProfile()->getModLoaders() }; + return { static_cast(inst)->getPackProfile()->getSupportedModLoaders() }; } ModUpdateDialog::ModUpdateDialog(QWidget* parent, diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 4b82c0c5c..9e121bb61 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -279,7 +279,7 @@ QList ModDownloadDialog::getPages() { QList pages; - auto loaders = static_cast(m_instance)->getPackProfile()->getModLoaders().value(); + auto loaders = static_cast(m_instance)->getPackProfile()->getSupportedModLoaders().value(); if (ModrinthAPI::validateModLoaders(loaders)) pages.append(ModrinthModPage::create(this, *m_instance)); diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index b75378905..c628f74ac 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -33,7 +33,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() auto sort = getCurrentSortingMethodByIndex(); - return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, profile->getModLoaders(), versions }; + return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, profile->getSupportedModLoaders(), versions }; } ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry) @@ -48,7 +48,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en if (!m_filter->versions.empty()) versions = m_filter->versions; - return { pack, versions, profile->getModLoaders() }; + return { pack, versions, profile->getSupportedModLoaders() }; } ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index c9270d399..7eb08f6a2 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -124,7 +124,7 @@ void ModPage::updateVersionList() auto version = current_pack->versions[i]; bool valid = false; for (auto& mcVer : m_filter->versions) { - if (validateVersion(version, mcVer.toString(), packProfile->getModLoaders())) { + if (validateVersion(version, mcVer.toString(), packProfile->getSupportedModLoaders())) { valid = true; break; } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index 2b020c48d..c80e4f999 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -31,7 +31,7 @@ void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonAr auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { - return FlameMod::loadDependencyVersions(m, arr); + return FlameMod::loadDependencyVersions(m, arr, &m_base_instance); } auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index ce7475b6e..856018294 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -39,12 +39,12 @@ void ModrinthModModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObjec void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) { - ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); + ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance); } auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { - return ::Modrinth::loadDependencyVersions(m, arr); + return ::Modrinth::loadDependencyVersions(m, arr, &m_base_instance); } auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray @@ -66,7 +66,7 @@ void ModrinthResourcePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, Q void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) { - ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); + ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance); } auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray @@ -88,7 +88,7 @@ void ModrinthTexturePackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJ void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) { - ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); + ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance); } auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray @@ -110,7 +110,7 @@ void ModrinthShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJs void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) { - ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); + ::Modrinth::loadIndexedPackVersions(m, arr, &m_base_instance); } auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray From aa065f2b5173dc56614ac45649ada06b74681a53 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 23 Aug 2023 13:28:23 +0300 Subject: [PATCH 295/398] Updated dependency resolution Signed-off-by: Trial97 --- .../modplatform/flame/FileResolvingTask.cpp | 4 ++-- launcher/modplatform/flame/FlameAPI.h | 22 ++++--------------- .../helpers/NetworkResourceAPI.cpp | 2 +- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 07a3ae632..b13274a6b 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -103,7 +103,7 @@ void Flame::FileResolvingTask::netJobFinished() auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); auto output = std::make_shared(); auto dl = Net::ApiDownload::makeByteArray(QUrl(url), output); - QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; }); + QObject::connect(dl.get(), &Net::ApiDownload::succeeded, [&out]() { out.resolved = true; }); m_checkJob->addNetAction(dl); blockedProjects.insert(&out, output); @@ -176,7 +176,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); auto dl = Net::ApiDownload::makeByteArray(url, output); qDebug() << "Fetching url slug for file:" << mod->fileName; - QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { + QObject::connect(dl.get(), &Net::ApiDownload::succeeded, [block, index, output]() { auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done auto json = QJsonDocument::fromJson(*output); auto base = diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 12cccb6f9..e0386991d 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -101,30 +101,16 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] std::optional getVersionsURL(VersionSearchArgs const& args) const override { auto addonId = args.pack.addonId.toString(); - QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(addonId) }; + QString url = QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000").arg(addonId); - QStringList get_parameters; if (args.mcVersions.has_value()) - get_parameters.append(QString("gameVersion=%1").arg(args.mcVersions.value().front().toString())); - return url + get_parameters.join('&'); + url += QString("&gameVersion=%1").arg(args.mcVersions.value().front().toString()); + return url; }; [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { - auto mappedModLoader = getMappedModLoader(args.loader); auto addonId = args.dependency.addonId.toString(); - if (args.loader & ModPlatform::Quilt) { - auto overide = ModPlatform::getOverrideDeps(); - auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { - return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; - }); - if (over != overide.cend()) { - mappedModLoader = 5; - } - } - return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%3") - .arg(addonId) - .arg(args.mcVersion.toString()) - .arg(mappedModLoader); + return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2").arg(addonId, args.mcVersion.toString()); }; }; diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index 46b966620..78b39fffa 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -131,7 +131,7 @@ Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args, auto netJob = makeShared(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network()); auto response = std::make_shared(); - netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); + netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response)); QObject::connect(netJob.get(), &NetJob::succeeded, [=] { QJsonParseError parse_error{}; From 6178e5a975d7e967df0d3d45e402ac0fcfb4b43a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 23 Aug 2023 13:36:31 +0300 Subject: [PATCH 296/398] reverted change for optional Signed-off-by: Trial97 --- launcher/minecraft/PackProfile.h | 1 + launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 3 +-- launcher/modplatform/flame/FileResolvingTask.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/minecraft/PackProfile.h b/launcher/minecraft/PackProfile.h index c41601fb2..e72b6ebfe 100644 --- a/launcher/minecraft/PackProfile.h +++ b/launcher/minecraft/PackProfile.h @@ -44,6 +44,7 @@ #include #include #include +#include #include "Component.h" #include "LaunchProfile.h" diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 93e1b2ed9..b273d70d7 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -41,8 +41,7 @@ static Version mcVersion(BaseInstance* inst) static ModPlatform::ModLoaderTypes mcLoaders(BaseInstance* inst) { - return static_cast(inst)->getPackProfile()->getSupportedModLoaders().value_or( - ModPlatform::ModLoaderTypes::fromInt(0)); + return static_cast(inst)->getPackProfile()->getSupportedModLoaders().value(); } GetModDependenciesTask::GetModDependenciesTask(QObject* parent, diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index b13274a6b..463014b6e 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -154,7 +154,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() // If there's more than one mod loader for this version, we can't know for sure // which file is relative to each loader, so it's best to not use any one and // let the user download it manually. - if (std::bitset<8>(file.loaders.toInt()).count() <= 1) { + if (std::bitset<8>(file.loaders).count() <= 1) { out->url = file.downloadUrl; qDebug() << "Found alternative on modrinth " << out->fileName; } else { From 095de5ed4ba373a44211ae3eb616139c69a0151a Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 23 Aug 2023 13:46:04 +0200 Subject: [PATCH 297/398] chore(nix): update clang-format to clang-tools 16 Signed-off-by: Sefa Eyeoglu --- nix/dev.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nix/dev.nix b/nix/dev.nix index c39e15653..6699cac6a 100644 --- a/nix/dev.nix +++ b/nix/dev.nix @@ -23,6 +23,8 @@ types_or = ["c" "c++" "java" "json" "objective-c"]; }; }; + + tools.clang-tools = pkgs.clang-tools_16; }; }; From 85c23b26de7d8161729abfa3bc94915645192087 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 23 Aug 2023 13:46:23 +0200 Subject: [PATCH 298/398] chore: reformat Signed-off-by: Sefa Eyeoglu --- launcher/Version.h | 20 ++++---------------- launcher/launch/LogModel.h | 2 +- launcher/ui/MainWindow.h | 5 +---- launcher/ui/pages/instance/ServersPage.cpp | 20 ++++---------------- libraries/LocalPeer/src/LocalPeer.cpp | 2 +- tests/FileSystem_test.cpp | 5 +---- 6 files changed, 12 insertions(+), 42 deletions(-) diff --git a/launcher/Version.h b/launcher/Version.h index 92bff9ba9..9c043b013 100644 --- a/launcher/Version.h +++ b/launcher/Version.h @@ -103,14 +103,8 @@ class Version { QString m_fullString; - [[nodiscard]] inline bool isAppendix() const - { - return m_stringPart.startsWith('+'); - } - [[nodiscard]] inline bool isPreRelease() const - { - return m_stringPart.startsWith('-') && m_stringPart.length() > 1; - } + [[nodiscard]] inline bool isAppendix() const { return m_stringPart.startsWith('+'); } + [[nodiscard]] inline bool isPreRelease() const { return m_stringPart.startsWith('-') && m_stringPart.length() > 1; } inline bool operator==(const Section& other) const { @@ -156,14 +150,8 @@ class Version { return m_fullString < other.m_fullString; } - inline bool operator!=(const Section& other) const - { - return !(*this == other); - } - inline bool operator>(const Section& other) const - { - return !(*this < other || *this == other); - } + inline bool operator!=(const Section& other) const { return !(*this == other); } + inline bool operator>(const Section& other) const { return !(*this < other || *this == other); } }; private: diff --git a/launcher/launch/LogModel.h b/launcher/launch/LogModel.h index ba2e4054a..18e51d7e3 100644 --- a/launcher/launch/LogModel.h +++ b/launcher/launch/LogModel.h @@ -30,7 +30,7 @@ class LogModel : public QAbstractListModel { enum Roles { LevelRole = Qt::UserRole }; - private /* types */: + private /* types */: struct entry { MessageLevel::Enum level; QString line; diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index b6f45da2e..0b6144522 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -151,10 +151,7 @@ class MainWindow : public QMainWindow { void deleteGroup(); void undoTrashInstance(); - inline void on_actionExportInstance_triggered() - { - on_actionExportInstanceZip_triggered(); - } + inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); void on_actionExportInstanceFlamePack_triggered(); diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index 6bf802e63..2142e6c9f 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -354,14 +354,8 @@ class ServersModel : public QAbstractListModel { } } - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override - { - return parent.isValid() ? 0 : m_servers.size(); - } - int columnCount(const QModelIndex& parent) const override - { - return parent.isValid() ? 0 : COLUMN_COUNT; - } + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override { return parent.isValid() ? 0 : m_servers.size(); } + int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : COLUMN_COUNT; } Server* at(int index) { @@ -445,10 +439,7 @@ class ServersModel : public QAbstractListModel { qDebug() << "Changed:" << path; load(); } - void fileChanged(const QString& path) - { - qDebug() << "Changed:" << path; - } + void fileChanged(const QString& path) { qDebug() << "Changed:" << path; } private slots: void save_internal() @@ -492,10 +483,7 @@ class ServersModel : public QAbstractListModel { m_saveTimer.stop(); } - bool saveIsScheduled() const - { - return m_dirty; - } + bool saveIsScheduled() const { return m_dirty; } void updateFSObserver() { diff --git a/libraries/LocalPeer/src/LocalPeer.cpp b/libraries/LocalPeer/src/LocalPeer.cpp index ab528c2a1..bd407042f 100644 --- a/libraries/LocalPeer/src/LocalPeer.cpp +++ b/libraries/LocalPeer/src/LocalPeer.cpp @@ -220,5 +220,5 @@ void LocalPeer::receiveConnection() socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; - emit messageReceived(uMsg); //### (might take a long time to return) + emit messageReceived(uMsg); // ### (might take a long time to return) } diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index e19410423..1d3cee85f 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -353,10 +353,7 @@ class FileSystemTest : public QObject { } } - void test_getDesktop() - { - QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); - } + void test_getDesktop() { QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); } void test_link() { From d7b6450613b7c106dcc06c6e160ba124990e4e93 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 23 Aug 2023 13:47:04 +0200 Subject: [PATCH 299/398] fix(nix): reload direnv if parts change Signed-off-by: Sefa Eyeoglu --- .envrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.envrc b/.envrc index 3550a30f2..190b5b2b3 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ use flake +watch_file nix/*.nix From 41bd008f5d8d5872e1ab2646c78908e27eae7b73 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 23 Aug 2023 13:49:09 +0200 Subject: [PATCH 300/398] chore(nix): remove pre-commit tools from shell use `pre-commit` CLI instead! Signed-off-by: Sefa Eyeoglu --- nix/dev.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/nix/dev.nix b/nix/dev.nix index 6699cac6a..a9c1dc65d 100644 --- a/nix/dev.nix +++ b/nix/dev.nix @@ -30,13 +30,6 @@ devShells.default = pkgs.mkShell { inherit (self.checks.${system}.pre-commit-check) shellHook; - packages = with pkgs; [ - nodePackages.markdownlint-cli - alejandra - deadnix - clang-tools - nil - ]; inputsFrom = [self.packages.${system}.prismlauncher-unwrapped]; buildInputs = with pkgs; [ccache ninja]; From 1515607060d23bd3467a77e2f6045681daa94998 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 23 Aug 2023 20:16:51 +0300 Subject: [PATCH 301/398] updated getMappedModLoader Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index e0386991d..0008643dd 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -41,18 +41,23 @@ class FlameAPI : public NetworkResourceAPI { } } - static int getMappedModLoader(ModPlatform::ModLoaderTypes loaders) + static int getMappedModLoader(ModPlatform::ModLoaderType loaders) { // https://docs.curseforge.com/?http#tocS_ModLoaderType - if (loaders & ModPlatform::Forge) - return 1; - if (loaders & ModPlatform::Fabric) - return 4; - if (loaders & ModPlatform::Quilt) - return 5; - if (loaders & ModPlatform::NeoForge) - return 6; - return 0; + switch (loaders) { + case ModPlatform::Forge: + return 1; + case ModPlatform::Cauldron: + return 2; + case ModPlatform::LiteLoader: + return 3; + case ModPlatform::Fabric: + return 4; + case ModPlatform::Quilt: + return 5; + case ModPlatform::NeoForge: + return 6; + } } static auto getModLoaderStrings(const ModPlatform::ModLoaderTypes types) -> const QStringList From 6c0492c0d174f45262f072d6900c2fcf098d209b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 23 Aug 2023 21:09:32 +0300 Subject: [PATCH 302/398] return 0 for any Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.h | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 0008643dd..745f889d5 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -58,6 +58,7 @@ class FlameAPI : public NetworkResourceAPI { case ModPlatform::NeoForge: return 6; } + return 0; } static auto getModLoaderStrings(const ModPlatform::ModLoaderTypes types) -> const QStringList From 783af2c06a2d11391e32f1f938ad3ad3da606f38 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 04:32:25 +0000 Subject: [PATCH 303/398] chore(deps): update determinatesystems/update-flake-lock action to v20 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 6bad57030..ad4016ff4 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v3 - uses: cachix/install-nix-action@v22 - - uses: DeterminateSystems/update-flake-lock@v19 + - uses: DeterminateSystems/update-flake-lock@v20 with: commit-msg: "chore(nix): update lockfile" pr-title: "chore(nix): update lockfile" From ea384d59fbff194f26f4fc678ce2388f01b2f484 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 24 Aug 2023 12:41:37 +0300 Subject: [PATCH 304/398] use qt separtor for file path Signed-off-by: Trial97 --- launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 9ff6b374d..47a0de5fe 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -322,7 +322,7 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, bool had_optional = false; for (const auto& modInfo : jsonFiles) { Modrinth::File file; - file.path = Json::requireString(modInfo, "path"); + file.path = Json::requireString(modInfo, "path").replace("\\", "/"); auto env = Json::ensureObject(modInfo, "env"); // 'env' field is optional From 2990c5d0c9ef9e36daa0ed7315521852164fe59e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 24 Aug 2023 12:44:11 +0300 Subject: [PATCH 305/398] Added optional mods dialog Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 4 + .../flame/FlameInstanceCreationTask.cpp | 29 +++- launcher/modplatform/flame/PackManifest.h | 2 +- .../modrinth/ModrinthInstanceCreationTask.cpp | 40 +++-- .../modrinth/ModrinthPackManifest.h | 1 + .../pages/modplatform/OptionalModDialog.cpp | 143 ++++++++++++++++++ .../ui/pages/modplatform/OptionalModDialog.h | 76 ++++++++++ .../ui/pages/modplatform/OptionalModDialog.ui | 105 +++++++++++++ .../atlauncher/AtlOptionalModDialog.h | 2 +- 9 files changed, 382 insertions(+), 20 deletions(-) create mode 100644 launcher/ui/pages/modplatform/OptionalModDialog.cpp create mode 100644 launcher/ui/pages/modplatform/OptionalModDialog.h create mode 100644 launcher/ui/pages/modplatform/OptionalModDialog.ui diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 18e0acab1..c73d89ec3 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -916,6 +916,9 @@ SET(LAUNCHER_SOURCES ui/pages/modplatform/ImportPage.cpp ui/pages/modplatform/ImportPage.h + ui/pages/modplatform/OptionalModDialog.cpp + ui/pages/modplatform/OptionalModDialog.h + ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp ui/pages/modplatform/modrinth/ModrinthResourceModels.h ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -1080,6 +1083,7 @@ qt_wrap_ui(LAUNCHER_UI ui/pages/modplatform/legacy_ftb/Page.ui ui/pages/modplatform/import_ftb/ImportFTBPage.ui ui/pages/modplatform/ImportPage.ui + ui/pages/modplatform/OptionalModDialog.ui ui/pages/modplatform/modrinth/ModrinthPage.ui ui/pages/modplatform/technic/TechnicPage.ui ui/widgets/InstanceCardWidget.ui diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 45b4e2125..ead5b464e 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -62,6 +62,7 @@ #include "minecraft/World.h" #include "minecraft/mod/tasks/LocalResourceParse.h" #include "net/ApiDownload.h" +#include "ui/pages/modplatform/OptionalModDialog.h" static const FlameAPI api; @@ -509,13 +510,33 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) void FlameCreationTask::setupDownloadJob(QEventLoop& loop) { m_files_job.reset(new NetJob(tr("Mod Download Flame"), APPLICATION->network())); - for (const auto& result : m_mod_id_resolver->getResults().files) { - QString filename = result.fileName; + auto results = m_mod_id_resolver->getResults().files; + + QStringList optionalFiles; + for (auto& result : results) { if (!result.required) { - filename += ".disabled"; + optionalFiles << FS::PathCombine(result.targetFolder, result.fileName); + } + } + + QStringList selectedOptionalMods; + if (!optionalFiles.empty()) { + OptionalModDialog optionalModDialog(m_parent, optionalFiles); + if (optionalModDialog.exec() == QDialog::Rejected) { + emitAborted(); + loop.quit(); + return; } - auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename); + selectedOptionalMods = optionalModDialog.getResult(); + } + for (const auto& result : results) { + auto relpath = FS::PathCombine(result.targetFolder, result.fileName); + if (!result.required && !selectedOptionalMods.contains(relpath)) { + relpath += ".disabled"; + } + + relpath = FS::PathCombine("minecraft", relpath); auto path = FS::PathCombine(m_stagingPath, relpath); switch (result.type) { diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h index 854cdbc41..4417c2430 100644 --- a/launcher/modplatform/flame/PackManifest.h +++ b/launcher/modplatform/flame/PackManifest.h @@ -48,7 +48,7 @@ struct File { int projectId = 0; int fileId = 0; - // NOTE: the opposite to 'optional'. This is at the time of writing unused. + // NOTE: the opposite to 'optional' bool required = true; QString hash; // NOTE: only set on blocked files ! Empty otherwise. diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 47a0de5fe..1be58c2b8 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -9,6 +9,7 @@ #include "modplatform/helpers/OverrideUtils.h" +#include "modplatform/modrinth/ModrinthPackManifest.h" #include "net/ChecksumValidator.h" #include "net/ApiDownload.h" @@ -16,8 +17,10 @@ #include "settings/INISettingsObject.h" #include "ui/dialogs/CustomMessageBox.h" +#include "ui/pages/modplatform/OptionalModDialog.h" #include +#include bool ModrinthCreationTask::abort() { @@ -319,7 +322,7 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, } auto jsonFiles = Json::requireIsArrayOf(obj, "files", "modrinth.index.json"); - bool had_optional = false; + std::vector optionalFiles; for (const auto& modInfo : jsonFiles) { Modrinth::File file; file.path = Json::requireString(modInfo, "path").replace("\\", "/"); @@ -331,18 +334,7 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, if (support == "unsupported") { continue; } else if (support == "optional") { - // TODO: Make a review dialog for choosing which ones the user wants! - if (!had_optional && show_optional_dialog) { - had_optional = true; - auto info = CustomMessageBox::selectable( - m_parent, tr("Optional mod detected!"), - tr("One or more mods from this modpack are optional. They will be downloaded, but disabled by default!"), - QMessageBox::Information); - info->exec(); - } - - if (file.path.endsWith(".jar")) - file.path += ".disabled"; + file.required = false; } } @@ -385,9 +377,29 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, } } - files.push_back(file); + (file.required ? files : optionalFiles).push_back(file); } + if (!optionalFiles.empty()) { + QStringList oFiles; + for (auto file : optionalFiles) + oFiles.push_back(file.path); + OptionalModDialog optionalModDialog(m_parent, oFiles); + if (optionalModDialog.exec() == QDialog::Rejected) { + emitAborted(); + return false; + } + + auto selectedMods = optionalModDialog.getResult(); + for (auto file : optionalFiles) { + if (selectedMods.contains(file.path)) { + file.required = true; + } else if (file.path.endsWith(".jar")) { + file.path += ".disabled"; + } + files.push_back(file); + } + } if (set_internal_data) { auto dependencies = Json::requireObject(obj, "dependencies", "modrinth.index.json"); for (auto it = dependencies.begin(), end = dependencies.end(); it != end; ++it) { diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.h b/launcher/modplatform/modrinth/ModrinthPackManifest.h index effa1a84a..93ae69697 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.h +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.h @@ -55,6 +55,7 @@ struct File { QCryptographicHash::Algorithm hashAlgorithm; QByteArray hash; QQueue downloads; + bool required = true; }; struct DonationData { diff --git a/launcher/ui/pages/modplatform/OptionalModDialog.cpp b/launcher/ui/pages/modplatform/OptionalModDialog.cpp new file mode 100644 index 000000000..620de4f74 --- /dev/null +++ b/launcher/ui/pages/modplatform/OptionalModDialog.cpp @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "OptionalModDialog.h" +#include "ui_OptionalModDialog.h" + +OptionalModListModel::OptionalModListModel(QWidget* parent, QStringList mods) : QAbstractListModel(parent), m_mods(mods) {} + +QStringList OptionalModListModel::getResult() +{ + QStringList result; + for (const auto& mod : m_mods) { + if (m_selected.value(mod, false)) { + result << mod; + } + } + return result; +} + +int OptionalModListModel::rowCount(const QModelIndex& parent) const +{ + return parent.isValid() ? 0 : m_mods.size(); +} + +int OptionalModListModel::columnCount(const QModelIndex& parent) const +{ + // Enabled, Name + return parent.isValid() ? 0 : 2; +} + +QVariant OptionalModListModel::data(const QModelIndex& index, int role) const +{ + auto row = index.row(); + auto mod = m_mods.at(row); + + if (role == Qt::DisplayRole && index.column() == NameColumn) { + return mod; + } else if (role == Qt::CheckStateRole && index.column() == EnabledColumn) { + return m_selected.value(mod, false) ? Qt::Checked : Qt::Unchecked; + } + + return {}; +} + +bool OptionalModListModel::setData(const QModelIndex& index, [[maybe_unused]] const QVariant& value, int role) +{ + if (role == Qt::CheckStateRole) { + auto row = index.row(); + auto mod = m_mods.at(row); + + toggleMod(mod, row); + return true; + } + + return false; +} + +QVariant OptionalModListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + switch (section) { + case EnabledColumn: + return QString(); + case NameColumn: + return QString("Name"); + } + } + + return {}; +} + +Qt::ItemFlags OptionalModListModel::flags(const QModelIndex& index) const +{ + auto flags = QAbstractListModel::flags(index); + if (index.isValid() && index.column() == EnabledColumn) { + flags |= Qt::ItemIsUserCheckable; + } + return flags; +} + +void OptionalModListModel::toggleAll(bool enabled) +{ + for (const auto& mod : m_mods) { + m_selected[mod] = enabled; + } + + emit dataChanged(OptionalModListModel::index(0, EnabledColumn), OptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); +} + +void OptionalModListModel::toggleMod(QString mod, int index) +{ + auto enable = !m_selected.value(mod, false); + + setMod(mod, index, enable); +} + +void OptionalModListModel::setMod(QString mod, int index, bool enable, bool shouldEmit) +{ + if (m_selected.value(mod, false) == enable) + return; + + m_selected[mod] = enable; + + if (shouldEmit) { + emit dataChanged(OptionalModListModel::index(index, EnabledColumn), OptionalModListModel::index(index, EnabledColumn)); + } +} + +OptionalModDialog::OptionalModDialog(QWidget* parent, QStringList mods) : QDialog(parent), ui(new Ui::OptionalModDialog) +{ + ui->setupUi(this); + + listModel = new OptionalModListModel(this, mods); + ui->treeView->setModel(listModel); + + ui->treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + ui->treeView->header()->setSectionResizeMode(OptionalModListModel::NameColumn, QHeaderView::Stretch); + + connect(ui->selectAllButton, &QPushButton::clicked, listModel, &OptionalModListModel::selectAll); + connect(ui->clearAllButton, &QPushButton::clicked, listModel, &OptionalModListModel::clearAll); + connect(ui->installButton, &QPushButton::clicked, this, &QDialog::accept); + connect(ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); +} + +OptionalModDialog::~OptionalModDialog() +{ + delete ui; +} diff --git a/launcher/ui/pages/modplatform/OptionalModDialog.h b/launcher/ui/pages/modplatform/OptionalModDialog.h new file mode 100644 index 000000000..4e22d0e46 --- /dev/null +++ b/launcher/ui/pages/modplatform/OptionalModDialog.h @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include + +namespace Ui { +class OptionalModDialog; +} + +class OptionalModListModel : public QAbstractListModel { + Q_OBJECT + public: + enum Columns { + EnabledColumn = 0, + NameColumn, + }; + + OptionalModListModel(QWidget* parent, QStringList mods); + + QStringList getResult(); + + int rowCount(const QModelIndex& parent) const override; + int columnCount(const QModelIndex& parent) const override; + + QVariant data(const QModelIndex& index, int role) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + public slots: + void selectAll() { toggleAll(true); } + void clearAll() { toggleAll(false); }; + void toggleAll(bool enabled); + + private: + void toggleMod(QString mod, int index); + void setMod(QString mod, int index, bool enable, bool shouldEmit = true); + + private: + QStringList m_mods; + QHash m_selected; +}; + +class OptionalModDialog : public QDialog { + Q_OBJECT + + public: + OptionalModDialog(QWidget* parent, QStringList mods); + ~OptionalModDialog() override; + + QStringList getResult() { return listModel->getResult(); } + + private: + Ui::OptionalModDialog* ui; + + OptionalModListModel* listModel; +}; diff --git a/launcher/ui/pages/modplatform/OptionalModDialog.ui b/launcher/ui/pages/modplatform/OptionalModDialog.ui new file mode 100644 index 000000000..76d1da89d --- /dev/null +++ b/launcher/ui/pages/modplatform/OptionalModDialog.ui @@ -0,0 +1,105 @@ + + + OptionalModDialog + + + + 0 + 0 + 550 + 310 + + + + Select Mods To Install + + + + + + + + + 11 + 75 + true + + + + Select optional mods to install. + + + Qt::AlignCenter + + + + + + + + true + + + + Note: All files will be downloaded but the unselected mods will be disabled. + + + Qt::AlignCenter + + + + + + + + + + + + + + true + + + Cancel + + + + + + + Clear All + + + + + + + Select All + + + + + + + Install + + + true + + + + + + + + + + ModListView + QTreeView +
ui/widgets/ModListView.h
+
+
+ + +
diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h index 55903003b..767d277d9 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h @@ -38,7 +38,7 @@ #include #include -#include "modplatform/atlauncher/ATLPackIndex.h" +#include "modplatform/atlauncher/ATLPackManifest.h" #include "net/NetJob.h" namespace Ui { From bb4b89470d2c6f051d4c75de4a29c8dc1d836122 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 24 Aug 2023 12:46:23 +0300 Subject: [PATCH 306/398] fixed icon importing Signed-off-by: Trial97 --- launcher/modplatform/atlauncher/ATLPackIndex.cpp | 2 +- launcher/modplatform/flame/FlamePackIndex.cpp | 4 +++- launcher/modplatform/modrinth/ModrinthPackManifest.cpp | 3 ++- launcher/ui/dialogs/NewInstanceDialog.cpp | 3 +-- launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp | 2 +- launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp | 2 +- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 3 +-- launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp | 2 +- launcher/ui/pages/modplatform/legacy_ftb/Page.cpp | 2 -- launcher/ui/pages/modplatform/technic/TechnicModel.cpp | 5 +++-- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/launcher/modplatform/atlauncher/ATLPackIndex.cpp b/launcher/modplatform/atlauncher/ATLPackIndex.cpp index 3be169739..84b0cc9e2 100644 --- a/launcher/modplatform/atlauncher/ATLPackIndex.cpp +++ b/launcher/modplatform/atlauncher/ATLPackIndex.cpp @@ -43,5 +43,5 @@ void ATLauncher::loadIndexedPack(ATLauncher::IndexedPack& m, QJsonObject& obj) m.system = Json::ensureBoolean(obj, QString("system"), false); m.description = Json::ensureString(obj, "description", ""); - m.safeName = Json::requireString(obj, "name").replace(QRegularExpression("[^A-Za-z0-9]"), ""); + m.safeName = "atl_" + Json::requireString(obj, "name").replace(QRegularExpression("[^A-Za-z0-9]"), "").toLower() + ".png"; } diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp index 21835a543..1b8534cee 100644 --- a/launcher/modplatform/flame/FlamePackIndex.cpp +++ b/launcher/modplatform/flame/FlamePackIndex.cpp @@ -1,4 +1,6 @@ #include "FlamePackIndex.h" +#include +#include #include "Json.h" @@ -9,8 +11,8 @@ void Flame::loadIndexedPack(Flame::IndexedPack& pack, QJsonObject& obj) pack.description = Json::ensureString(obj, "summary", ""); auto logo = Json::requireObject(obj, "logo"); - pack.logoName = Json::requireString(logo, "title"); pack.logoUrl = Json::requireString(logo, "thumbnailUrl"); + pack.logoName = Json::requireString(obj, "slug") + "." + QFileInfo(QUrl(pack.logoUrl).fileName()).suffix(); auto authors = Json::requireArray(obj, "authors"); for (auto authorIter : authors) { diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index 0d07c6361..4565e585f 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -35,6 +35,7 @@ */ #include "ModrinthPackManifest.h" +#include #include "Json.h" #include "modplatform/modrinth/ModrinthAPI.h" @@ -56,8 +57,8 @@ void loadIndexedPack(Modpack& pack, QJsonObject& obj) pack.description = Json::ensureString(obj, "description"); auto temp_author_name = Json::ensureString(obj, "author"); pack.author = std::make_tuple(temp_author_name, api.getAuthorURL(temp_author_name)); - pack.iconName = QString("modrinth_%1").arg(Json::ensureString(obj, "slug")); pack.iconUrl = Json::ensureString(obj, "icon_url"); + pack.iconName = QString("modrinth_%1.%2").arg(Json::ensureString(obj, "slug"), QFileInfo(pack.iconUrl.fileName()).suffix()); } void loadIndexedInfo(Modpack& pack, QJsonObject& obj) diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 9613c6b00..4c8708bc7 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -237,8 +237,7 @@ void NewInstanceDialog::setSuggestedIcon(const QString& key) InstanceTask* NewInstanceDialog::extractTask() { - InstanceTask* extracted = creationTask.get(); - creationTask.release(); + InstanceTask* extracted = creationTask.release(); InstanceName inst_name(ui->instNameTextBox->placeholderText().trimmed(), importVersion); inst_name.setName(ui->instNameTextBox->text().trimmed()); diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 39f4f346a..5fc9ce06f 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -56,7 +56,7 @@ QVariant ListModel::data(const QModelIndex& index, int role) const } auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); - auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower()); + auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1").arg(pack.safeName); ((ListModel*)this)->requestLogo(pack.safeName, url); return icon; diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp index 5e3b9ecf1..61512df5e 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp @@ -113,7 +113,7 @@ void AtlPage::suggestCurrent() dialog->setSuggestedPack(selected.name, selectedVersion, new ATLauncher::PackInstallTask(uiSupport, selected.name, selectedVersion)); auto editedLogoName = selected.safeName; - auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(selected.safeName.toLower()); + auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1").arg(selected.safeName); listModel->getLogo(selected.safeName, url, [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 183e16f90..6891882cd 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -209,8 +209,7 @@ void FlamePage::suggestCurrent() extra_info.insert("pack_version_id", QString::number(version.fileId)); dialog->setSuggestedPack(current.name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info))); - QString editedLogoName; - editedLogoName = "curseforge_" + current.logoName; + QString editedLogoName = "curseforge_" + current.logoName; listModel->getLogo(current.logoName, current.logoUrl, [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); } diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp index 5c9ff63b2..b3b18e2ca 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp @@ -76,7 +76,7 @@ void ImportFTBPage::suggestCurrent() } dialog->setSuggestedPack(selected.name, new PackInstallTask(selected)); - QString editedLogoName = QString("ftb_%1").arg(selected.id); + QString editedLogoName = QString("ftb_%1.jpg").arg(selected.id); dialog->setSuggestedIconFromFile(FS::PathCombine(selected.path, "folder.jpg"), editedLogoName); } diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index 0103bbaa2..243c90dcd 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -180,8 +180,6 @@ void Page::suggestCurrent() editedLogoName = "ftb_" + selected.logo; } - editedLogoName = editedLogoName.left(editedLogoName.lastIndexOf(".png")); - if (selected.type == PackType::Public) { publicListModel->getLogo(selected.logo, [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index e8c5ac922..6fbfd7624 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -34,6 +34,7 @@ */ #include "TechnicModel.h" +#include #include "Application.h" #include "BuildConfig.h" #include "Json.h" @@ -159,7 +160,7 @@ void Technic::ListModel::searchRequestFinished() pack.logoName = "null"; } else { pack.logoUrl = rawURL; - pack.logoName = rawURL.section(QLatin1Char('/'), -1); + pack.logoName = QUrl(rawURL).fileName(); } pack.broken = false; newList.append(pack); @@ -181,7 +182,7 @@ void Technic::ListModel::searchRequestFinished() auto iconUrl = Json::requireString(iconObj, "url"); pack.logoUrl = iconUrl; - pack.logoName = iconUrl.section(QLatin1Char('/'), -1); + pack.logoName = QUrl(iconUrl).fileName(); } else { pack.logoUrl = "null"; pack.logoName = "null"; From f897b14e3e8ae658a6e63ffd9f61b7ad8a4259bf Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 24 Aug 2023 13:05:27 +0300 Subject: [PATCH 307/398] changed technic icon name retrival Signed-off-by: Trial97 --- .../ui/pages/modplatform/import_ftb/ImportFTBPage.cpp | 2 +- launcher/ui/pages/modplatform/legacy_ftb/Page.cpp | 8 +++----- launcher/ui/pages/modplatform/technic/TechnicModel.cpp | 7 ++++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp index b3b18e2ca..e54a487c6 100644 --- a/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp +++ b/launcher/ui/pages/modplatform/import_ftb/ImportFTBPage.cpp @@ -76,7 +76,7 @@ void ImportFTBPage::suggestCurrent() } dialog->setSuggestedPack(selected.name, new PackInstallTask(selected)); - QString editedLogoName = QString("ftb_%1.jpg").arg(selected.id); + QString editedLogoName = QString("ftb_%1_%2,jpg").arg(selected.name, selected.id); dialog->setSuggestedIconFromFile(FS::PathCombine(selected.path, "folder.jpg"), editedLogoName); } diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index 243c90dcd..9ba70da05 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -173,11 +173,9 @@ void Page::suggestCurrent() } dialog->setSuggestedPack(selected.name, selectedVersion, new PackInstallTask(APPLICATION->network(), selected, selectedVersion)); - QString editedLogoName; - if (selected.logo.toLower().startsWith("ftb")) { - editedLogoName = selected.logo; - } else { - editedLogoName = "ftb_" + selected.logo; + QString editedLogoName = selected.logo; + if (!selected.logo.toLower().startsWith("ftb")) { + editedLogoName = "ftb_" + editedLogoName; } if (selected.type == PackType::Public) { diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index 6fbfd7624..9675534e1 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -34,14 +34,15 @@ */ #include "TechnicModel.h" -#include #include "Application.h" #include "BuildConfig.h" #include "Json.h" #include "net/ApiDownload.h" +#include #include +#include Technic::ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {} @@ -160,7 +161,7 @@ void Technic::ListModel::searchRequestFinished() pack.logoName = "null"; } else { pack.logoUrl = rawURL; - pack.logoName = QUrl(rawURL).fileName(); + pack.logoName = pack.slug + "." + QFileInfo(QUrl(rawURL).fileName()).suffix(); } pack.broken = false; newList.append(pack); @@ -182,7 +183,7 @@ void Technic::ListModel::searchRequestFinished() auto iconUrl = Json::requireString(iconObj, "url"); pack.logoUrl = iconUrl; - pack.logoName = QUrl(iconUrl).fileName(); + pack.logoName = pack.slug + "." + QFileInfo(QUrl(iconUrl).fileName()).suffix(); } else { pack.logoUrl = "null"; pack.logoName = "null"; From 5f3e9672cd378b8f04afe469fda4e7d4b7fc64fc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 24 Aug 2023 13:31:57 +0300 Subject: [PATCH 308/398] made the loaders check more generic Signed-off-by: Trial97 --- launcher/modplatform/flame/FileResolvingTask.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 463014b6e..259d41cc1 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -1,7 +1,8 @@ #include "FileResolvingTask.h" -#include +#include #include "Json.h" +#include "modplatform/ModIndex.h" #include "net/ApiDownload.h" #include "net/ApiUpload.h" #include "net/Upload.h" @@ -135,6 +136,11 @@ void Flame::FileResolvingTask::netJobFinished() m_checkJob->start(); } +constexpr bool has_single_bit(int x) noexcept +{ + return x && !(x & (x - 1)); +} + void Flame::FileResolvingTask::modrinthCheckFinished() { setProgress(2, 3); @@ -154,7 +160,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() // If there's more than one mod loader for this version, we can't know for sure // which file is relative to each loader, so it's best to not use any one and // let the user download it manually. - if (std::bitset<8>(file.loaders).count() <= 1) { + if (!file.loaders || has_single_bit(file.loaders)) { out->url = file.downloadUrl; qDebug() << "Found alternative on modrinth " << out->fileName; } else { From 172680abf89e3d6312f48f0e1a6949ed4fc260be Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 24 Aug 2023 13:42:36 +0300 Subject: [PATCH 309/398] removed aditional header Signed-off-by: Trial97 --- launcher/modplatform/flame/FileResolvingTask.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 259d41cc1..6fc3a21c5 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -1,6 +1,5 @@ #include "FileResolvingTask.h" -#include #include "Json.h" #include "modplatform/ModIndex.h" #include "net/ApiDownload.h" From c54fecf5d9dd21dbc2b55f9a7d721f61fde034b3 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 25 Aug 2023 09:05:04 +0300 Subject: [PATCH 310/398] added condition for empty loader type Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.cpp | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 4 ++-- launcher/modplatform/modrinth/ModrinthPackIndex.cpp | 4 ++-- launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp | 3 ++- .../ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 8d01f779d..e99ce3a56 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -133,7 +133,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - if (file_tmp.date > ver.date && (!args.loaders.has_value() || args.loaders.value() & file_tmp.loaders)) + if (file_tmp.date > ver.date && (!args.loaders.has_value() || !file_tmp.loaders || args.loaders.value() & file_tmp.loaders)) ver = file_tmp; } diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 67e3468f9..a63bdc996 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -91,7 +91,7 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, file.addonId = pack.addonId; if (file.fileId.isValid() && - (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid + (!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid unsortedVersions.append(file); } @@ -202,7 +202,7 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform:: file.addonId = m.addonId; if (file.fileId.isValid() && - (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid + (!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid versions.append(file); } diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index d857e82a8..107b99006 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -105,7 +105,7 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArra auto file = loadIndexedPackVersion(obj); if (file.fileId.isValid() && - (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid + (!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { @@ -242,7 +242,7 @@ auto Modrinth::loadDependencyVersions([[maybe_unused]] const ModPlatform::Depend auto file = loadIndexedPackVersion(obj); if (file.fileId.isValid() && - (!loaders.has_value() || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid + (!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid versions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index 222ceedc6..1403e98f9 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -70,7 +70,8 @@ auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders) const -> bool { - return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty() && (!loaders.has_value() || loaders.value() & ver.loaders); + return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty() && + (!loaders.has_value() || !ver.loaders || loaders.value() & ver.loaders); } bool FlameModPage::optedOut(ModPlatform::IndexedVersion& ver) const diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index bcd0a4cf4..a4197b225 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -67,7 +67,7 @@ auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders) const -> bool { - return ver.mcVersion.contains(mineVer) && (!loaders.has_value() || loaders.value() & ver.loaders); + return ver.mcVersion.contains(mineVer) && (!loaders.has_value() || !ver.loaders || loaders.value() & ver.loaders); } ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) From abfd1a42053eb6393394fee1ac23a2b608499d47 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 25 Aug 2023 18:35:25 +0300 Subject: [PATCH 311/398] minor dependency crash fix Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 1 + launcher/modplatform/flame/FlameModIndex.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index b273d70d7..ee84b1f5e 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -201,6 +201,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } } + removePack(dep.addonId); qWarning() << "Error while reading mod version empty "; qDebug() << doc; return; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index a63bdc996..494dc2a7e 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -211,5 +211,7 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform:: return a.date > b.date; }; std::sort(versions.begin(), versions.end(), orderSortPredicate); - return versions.front(); + if (versions.size() != 0) + return versions.front(); + return {}; } From 288d0d1fd4562e4020c964955918a5681b547705 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 26 Aug 2023 22:26:01 +0300 Subject: [PATCH 312/398] Added back api loader filtering if just one is selected Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.h | 6 ++++++ launcher/modplatform/flame/FileResolvingTask.cpp | 7 +------ launcher/modplatform/flame/FlameAPI.h | 13 ++++++++++++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 780f68b4d..7d144176d 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -152,6 +152,12 @@ QString getMetaURL(ResourceProvider provider, QVariant projectID); auto getModLoaderString(ModLoaderType type) -> const QString; +constexpr bool hasSingleModLoaderSelected(ModLoaderTypes l) noexcept +{ + auto x = static_cast(l); + return x && !(x & (x - 1)); +} + } // namespace ModPlatform Q_DECLARE_METATYPE(ModPlatform::IndexedPack) diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 6fc3a21c5..5865bee91 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -135,11 +135,6 @@ void Flame::FileResolvingTask::netJobFinished() m_checkJob->start(); } -constexpr bool has_single_bit(int x) noexcept -{ - return x && !(x & (x - 1)); -} - void Flame::FileResolvingTask::modrinthCheckFinished() { setProgress(2, 3); @@ -159,7 +154,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() // If there's more than one mod loader for this version, we can't know for sure // which file is relative to each loader, so it's best to not use any one and // let the user download it manually. - if (!file.loaders || has_single_bit(file.loaders)) { + if (!file.loaders || hasSingleModLoaderSelected(file.loaders)) { out->url = file.downloadUrl; qDebug() << "Found alternative on modrinth " << out->fileName; } else { diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 745f889d5..47350c33e 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -111,12 +111,23 @@ class FlameAPI : public NetworkResourceAPI { if (args.mcVersions.has_value()) url += QString("&gameVersion=%1").arg(args.mcVersions.value().front().toString()); + + if (args.loaders.has_value() && ModPlatform::hasSingleModLoaderSelected(args.loaders.value())) { + int mappedModLoader = getMappedModLoader(static_cast(static_cast(args.loaders.value()))); + url += QString("&modLoaderType=%1").arg(mappedModLoader); + } return url; }; [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { auto addonId = args.dependency.addonId.toString(); - return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2").arg(addonId, args.mcVersion.toString()); + auto url = + QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2").arg(addonId, args.mcVersion.toString()); + if (args.loader && ModPlatform::hasSingleModLoaderSelected(args.loader)) { + int mappedModLoader = getMappedModLoader(static_cast(static_cast(args.loader))); + url += QString("&modLoaderType=%1").arg(mappedModLoader); + } + return url; }; }; From a2d44744fe71af431420f93b178a074a48b9232d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 26 Aug 2023 23:36:46 +0300 Subject: [PATCH 313/398] do not update the metadata if mod is invalid Signed-off-by: Trial97 --- launcher/modplatform/packwiz/Packwiz.cpp | 41 +++++++++++++++--------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 381476697..1757da3e0 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -156,29 +156,38 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) FS::ensureFilePathExists(index_file.fileName()); } + toml::table update; + switch (mod.provider) { + case (ModPlatform::ResourceProvider::FLAME): + if (mod.file_id.toInt() == 0 || mod.project_id.toInt() == 0) { + qCritical() << QString("Did not write file %1 because missing information!").arg(normalized_fname); + return; + } + update = toml::table{ + { "file-id", mod.file_id.toInt() }, + { "project-id", mod.project_id.toInt() }, + }; + break; + case (ModPlatform::ResourceProvider::MODRINTH): + if (mod.mod_id().toString().isEmpty() || mod.version().toString().isEmpty()) { + qCritical() << QString("Did not write file %1 because missing information!").arg(normalized_fname); + return; + } + update = toml::table{ + { "mod-id", mod.mod_id().toString().toStdString() }, + { "version", mod.version().toString().toStdString() }, + }; + break; + } + if (!index_file.open(QIODevice::ReadWrite)) { - qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name)); + qCritical() << QString("Could not open file %1!").arg(normalized_fname); return; } // Put TOML data into the file QTextStream in_stream(&index_file); { - toml::table update; - switch (mod.provider) { - case (ModPlatform::ResourceProvider::FLAME): - update = toml::table{ - { "file-id", mod.file_id.toInt() }, - { "project-id", mod.project_id.toInt() }, - }; - break; - case (ModPlatform::ResourceProvider::MODRINTH): - update = toml::table{ - { "mod-id", mod.mod_id().toString().toStdString() }, - { "version", mod.version().toString().toStdString() }, - }; - break; - } auto tbl = toml::table{ { "name", mod.name.toStdString() }, { "filename", mod.filename.toStdString() }, { "side", mod.side.toStdString() }, From 479335dfe08466ce77f769e550c7f68a10b522a5 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 27 Aug 2023 00:49:21 +0100 Subject: [PATCH 314/398] Rewrite optional mod dialog Signed-off-by: TheKodeToad --- .../pages/modplatform/OptionalModDialog.cpp | 146 ++++------------- .../ui/pages/modplatform/OptionalModDialog.h | 41 +---- .../ui/pages/modplatform/OptionalModDialog.ui | 148 +++++++++--------- 3 files changed, 113 insertions(+), 222 deletions(-) diff --git a/launcher/ui/pages/modplatform/OptionalModDialog.cpp b/launcher/ui/pages/modplatform/OptionalModDialog.cpp index 620de4f74..fc1c8b3cb 100644 --- a/launcher/ui/pages/modplatform/OptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/OptionalModDialog.cpp @@ -19,125 +19,45 @@ #include "OptionalModDialog.h" #include "ui_OptionalModDialog.h" -OptionalModListModel::OptionalModListModel(QWidget* parent, QStringList mods) : QAbstractListModel(parent), m_mods(mods) {} - -QStringList OptionalModListModel::getResult() -{ - QStringList result; - for (const auto& mod : m_mods) { - if (m_selected.value(mod, false)) { - result << mod; - } - } - return result; -} - -int OptionalModListModel::rowCount(const QModelIndex& parent) const -{ - return parent.isValid() ? 0 : m_mods.size(); -} - -int OptionalModListModel::columnCount(const QModelIndex& parent) const -{ - // Enabled, Name - return parent.isValid() ? 0 : 2; -} - -QVariant OptionalModListModel::data(const QModelIndex& index, int role) const -{ - auto row = index.row(); - auto mod = m_mods.at(row); - - if (role == Qt::DisplayRole && index.column() == NameColumn) { - return mod; - } else if (role == Qt::CheckStateRole && index.column() == EnabledColumn) { - return m_selected.value(mod, false) ? Qt::Checked : Qt::Unchecked; - } - - return {}; -} - -bool OptionalModListModel::setData(const QModelIndex& index, [[maybe_unused]] const QVariant& value, int role) -{ - if (role == Qt::CheckStateRole) { - auto row = index.row(); - auto mod = m_mods.at(row); - - toggleMod(mod, row); - return true; - } - - return false; -} - -QVariant OptionalModListModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { - switch (section) { - case EnabledColumn: - return QString(); - case NameColumn: - return QString("Name"); - } - } - - return {}; -} - -Qt::ItemFlags OptionalModListModel::flags(const QModelIndex& index) const -{ - auto flags = QAbstractListModel::flags(index); - if (index.isValid() && index.column() == EnabledColumn) { - flags |= Qt::ItemIsUserCheckable; - } - return flags; -} - -void OptionalModListModel::toggleAll(bool enabled) -{ - for (const auto& mod : m_mods) { - m_selected[mod] = enabled; - } - - emit dataChanged(OptionalModListModel::index(0, EnabledColumn), OptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); -} - -void OptionalModListModel::toggleMod(QString mod, int index) -{ - auto enable = !m_selected.value(mod, false); - - setMod(mod, index, enable); -} - -void OptionalModListModel::setMod(QString mod, int index, bool enable, bool shouldEmit) -{ - if (m_selected.value(mod, false) == enable) - return; - - m_selected[mod] = enable; - - if (shouldEmit) { - emit dataChanged(OptionalModListModel::index(index, EnabledColumn), OptionalModListModel::index(index, EnabledColumn)); - } -} - -OptionalModDialog::OptionalModDialog(QWidget* parent, QStringList mods) : QDialog(parent), ui(new Ui::OptionalModDialog) +OptionalModDialog::OptionalModDialog(QWidget* parent, const QStringList& mods) : QDialog(parent), ui(new Ui::OptionalModDialog) { ui->setupUi(this); + for (const QString& mod : mods) { + auto item = new QListWidgetItem(mod, ui->list); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(Qt::Unchecked); + item->setData(Qt::UserRole, mod); + } - listModel = new OptionalModListModel(this, mods); - ui->treeView->setModel(listModel); - - ui->treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - ui->treeView->header()->setSectionResizeMode(OptionalModListModel::NameColumn, QHeaderView::Stretch); - - connect(ui->selectAllButton, &QPushButton::clicked, listModel, &OptionalModListModel::selectAll); - connect(ui->clearAllButton, &QPushButton::clicked, listModel, &OptionalModListModel::clearAll); - connect(ui->installButton, &QPushButton::clicked, this, &QDialog::accept); - connect(ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(ui->selectAllButton, &QPushButton::clicked, ui->list, [this] { + for (int i = 0; i < ui->list->count(); i++) + ui->list->item(i)->setCheckState(Qt::Checked); + }); + connect(ui->clearAllButton, &QPushButton::clicked, ui->list, [this] { + for (int i = 0; i < ui->list->count(); i++) + ui->list->item(i)->setCheckState(Qt::Unchecked); + }); + connect(ui->list, &QListWidget::itemActivated, [](QListWidgetItem* item) { + if (item->checkState() == Qt::Checked) + item->setCheckState(Qt::Unchecked); + else + item->setCheckState(Qt::Checked); + }); } OptionalModDialog::~OptionalModDialog() { delete ui; } + +QStringList OptionalModDialog::getResult() +{ + QStringList result; + result.reserve(ui->list->count()); + for (int i = 0; i < ui->list->count(); i++) { + auto item = ui->list->item(i); + if (item->checkState() == Qt::Checked) + result.append(item->data(Qt::UserRole).toString()); + } + return result; +} diff --git a/launcher/ui/pages/modplatform/OptionalModDialog.h b/launcher/ui/pages/modplatform/OptionalModDialog.h index 4e22d0e46..1897c1fca 100644 --- a/launcher/ui/pages/modplatform/OptionalModDialog.h +++ b/launcher/ui/pages/modplatform/OptionalModDialog.h @@ -25,52 +25,15 @@ namespace Ui { class OptionalModDialog; } -class OptionalModListModel : public QAbstractListModel { - Q_OBJECT - public: - enum Columns { - EnabledColumn = 0, - NameColumn, - }; - - OptionalModListModel(QWidget* parent, QStringList mods); - - QStringList getResult(); - - int rowCount(const QModelIndex& parent) const override; - int columnCount(const QModelIndex& parent) const override; - - QVariant data(const QModelIndex& index, int role) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role) override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - - Qt::ItemFlags flags(const QModelIndex& index) const override; - - public slots: - void selectAll() { toggleAll(true); } - void clearAll() { toggleAll(false); }; - void toggleAll(bool enabled); - - private: - void toggleMod(QString mod, int index); - void setMod(QString mod, int index, bool enable, bool shouldEmit = true); - - private: - QStringList m_mods; - QHash m_selected; -}; - class OptionalModDialog : public QDialog { Q_OBJECT public: - OptionalModDialog(QWidget* parent, QStringList mods); + OptionalModDialog(QWidget* parent, const QStringList& mods); ~OptionalModDialog() override; - QStringList getResult() { return listModel->getResult(); } + QStringList getResult(); private: Ui::OptionalModDialog* ui; - - OptionalModListModel* listModel; }; diff --git a/launcher/ui/pages/modplatform/OptionalModDialog.ui b/launcher/ui/pages/modplatform/OptionalModDialog.ui index 76d1da89d..0b809d2cb 100644 --- a/launcher/ui/pages/modplatform/OptionalModDialog.ui +++ b/launcher/ui/pages/modplatform/OptionalModDialog.ui @@ -11,81 +11,63 @@
- Select Mods To Install + Select Optional Mods - - - - 11 - 75 - true - + + + Qt::IgnoreAction - - Select optional mods to install. - - - Qt::AlignCenter - - - - - - - - true - - - - Note: All files will be downloaded but the unselected mods will be disabled. - - - Qt::AlignCenter - - - - - - - - - - - - - + true - - Cancel - - - - Clear All - - + + + + + Select All + + + + + + + Deselect All + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Unchecked mods will be disabled. + + + + - - - Select All - - - - - - - Install - - - true + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -93,13 +75,39 @@
- - - ModListView - QTreeView -
ui/widgets/ModListView.h
-
-
- + + + buttonBox + accepted() + OptionalModDialog + accept() + + + 274 + 284 + + + 274 + 154 + + + + + buttonBox + rejected() + OptionalModDialog + reject() + + + 274 + 284 + + + 274 + 154 + + + + From 9735e46a7eb4aa02eec5e08dbf784005d43d37d5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 27 Aug 2023 00:17:22 +0000 Subject: [PATCH 315/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/ca3c9ac9f4cdd4bea19f592b32bb59b74ab7d783' (2023-08-19) → 'github:nixos/nixpkgs/c66ccfa00c643751da2fd9290e096ceaa30493fc' (2023-08-26) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 28ef60f30..5599efe16 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1692463654, - "narHash": "sha256-F8hZmsQINI+S6UROM4jyxAMbQLtzE44pI8Nk6NtMdao=", + "lastModified": 1693060755, + "narHash": "sha256-KNsbfqewEziFJEpPR0qvVz4rx0x6QXxw1CcunRhlFdk=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ca3c9ac9f4cdd4bea19f592b32bb59b74ab7d783", + "rev": "c66ccfa00c643751da2fd9290e096ceaa30493fc", "type": "github" }, "original": { From 4036cecfc02142c403a45e18474ad7aab6fc8834 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 27 Aug 2023 15:04:42 +0300 Subject: [PATCH 316/398] Added progress widget to some modpack providers Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/flame/FlameModel.h | 1 + launcher/ui/pages/modplatform/flame/FlamePage.cpp | 10 +++++++++- launcher/ui/pages/modplatform/flame/FlamePage.h | 3 +++ launcher/ui/pages/modplatform/flame/FlamePage.ui | 4 ++-- launcher/ui/pages/modplatform/modrinth/ModrinthModel.h | 1 + .../ui/pages/modplatform/modrinth/ModrinthPage.cpp | 10 +++++++++- launcher/ui/pages/modplatform/modrinth/ModrinthPage.h | 3 +++ launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui | 10 +++++----- launcher/ui/pages/modplatform/technic/TechnicModel.h | 1 + launcher/ui/pages/modplatform/technic/TechnicPage.cpp | 10 +++++++++- launcher/ui/pages/modplatform/technic/TechnicPage.h | 3 +++ launcher/ui/pages/modplatform/technic/TechnicPage.ui | 4 ++-- 12 files changed, 48 insertions(+), 12 deletions(-) diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h index cd73fce30..fd8496dfb 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ b/launcher/ui/pages/modplatform/flame/FlameModel.h @@ -41,6 +41,7 @@ class ListModel : public QAbstractListModel { void searchWithTerm(const QString& term, const int sort); [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } private slots: void performPaginatedSearch(); diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 79fcc8211..50656f427 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -50,7 +50,8 @@ static FlameAPI api; -FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog) +FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) + : QWidget(parent), ui(new Ui::FlamePage), dialog(dialog), m_fetch_progress(this, false) { ui->setupUi(this); connect(ui->searchButton, &QPushButton::clicked, this, &FlamePage::triggerSearch); @@ -66,6 +67,12 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(paren connect(&m_search_timer, &QTimer::timeout, this, &FlamePage::triggerSearch); + m_fetch_progress.hideIfInactive(true); + m_fetch_progress.setFixedHeight(24); + m_fetch_progress.progressFormat(""); + + ui->gridLayout->addWidget(&m_fetch_progress, 2, 0, 1, ui->gridLayout->columnCount()); + // index is used to set the sorting with the curseforge api ui->sortByBox->addItem(tr("Sort by Featured")); ui->sortByBox->addItem(tr("Sort by Popularity")); @@ -124,6 +131,7 @@ void FlamePage::openedImpl() void FlamePage::triggerSearch() { listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); + m_fetch_progress.watch(listModel->activeSearchJob().get()); } void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev) diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.h b/launcher/ui/pages/modplatform/flame/FlamePage.h index a45c9e404..d35858fbc 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.h +++ b/launcher/ui/pages/modplatform/flame/FlamePage.h @@ -41,6 +41,7 @@ #include #include #include "ui/pages/BasePage.h" +#include "ui/widgets/ProgressWidget.h" namespace Ui { class FlamePage; @@ -87,6 +88,8 @@ class FlamePage : public QWidget, public BasePage { int m_selected_version_index = -1; + ProgressWidget m_fetch_progress; + // Used to do instant searching with a delay to cache quick changes QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.ui b/launcher/ui/pages/modplatform/flame/FlamePage.ui index 71d195135..f9e1fe67f 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.ui +++ b/launcher/ui/pages/modplatform/flame/FlamePage.ui @@ -47,7 +47,7 @@
- + @@ -77,7 +77,7 @@ - + diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index f5e686a80..2a9d62261 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -74,6 +74,7 @@ class ModpackListModel : public QAbstractListModel { void searchWithTerm(const QString& term, const int sort); [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 72c9da358..f7fa8fd78 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -52,7 +52,8 @@ #include #include -ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog) +ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) + : QWidget(parent), ui(new Ui::ModrinthPage), dialog(dialog), m_fetch_progress(this, false) { ui->setupUi(this); @@ -69,6 +70,12 @@ ModrinthPage::ModrinthPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget connect(&m_search_timer, &QTimer::timeout, this, &ModrinthPage::triggerSearch); + m_fetch_progress.hideIfInactive(true); + m_fetch_progress.setFixedHeight(24); + m_fetch_progress.progressFormat(""); + + ui->gridLayout->addWidget(&m_fetch_progress, 2, 0, 1, ui->gridLayout->columnCount()); + ui->sortByBox->addItem(tr("Sort by Relevance")); ui->sortByBox->addItem(tr("Sort by Total Downloads")); ui->sortByBox->addItem(tr("Sort by Follows")); @@ -319,6 +326,7 @@ void ModrinthPage::suggestCurrent() void ModrinthPage::triggerSearch() { m_model->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); + m_fetch_progress.watch(m_model->activeSearchJob().get()); } void ModrinthPage::onVersionSelectionChanged(QString version) diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h index 0705ca99b..4240dcafb 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.h @@ -41,6 +41,7 @@ #include "ui/pages/BasePage.h" #include "modplatform/modrinth/ModrinthPackManifest.h" +#include "ui/widgets/ProgressWidget.h" #include #include @@ -90,6 +91,8 @@ class ModrinthPage : public QWidget, public BasePage { Modrinth::Modpack current; QString selectedVersion; + ProgressWidget m_fetch_progress; + // Used to do instant searching with a delay to cache quick changes QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui index 6d8b2b675..78a25feae 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui @@ -10,8 +10,8 @@ 600 - - + + @@ -29,7 +29,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -77,7 +77,7 @@ - + diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index c0d13ae82..aeb4f3084 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -59,6 +59,7 @@ class ListModel : public QAbstractListModel { void searchWithTerm(const QString& term); [[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); } + [[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } private slots: void searchRequestFinished(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 518d049e8..190b7c68f 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -52,7 +52,8 @@ #include "net/ApiDownload.h" -TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog) +TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) + : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog), m_fetch_progress(this, false) { ui->setupUi(this); connect(ui->searchButton, &QPushButton::clicked, this, &TechnicPage::triggerSearch); @@ -65,6 +66,12 @@ TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(p connect(&m_search_timer, &QTimer::timeout, this, &TechnicPage::triggerSearch); + m_fetch_progress.hideIfInactive(true); + m_fetch_progress.setFixedHeight(24); + m_fetch_progress.progressFormat(""); + + ui->gridLayout->addWidget(&m_fetch_progress, 2, 0, 1, ui->gridLayout->columnCount()); + connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &TechnicPage::onSelectionChanged); connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &TechnicPage::onVersionSelectionChanged); @@ -113,6 +120,7 @@ void TechnicPage::openedImpl() void TechnicPage::triggerSearch() { model->searchWithTerm(ui->searchEdit->text()); + m_fetch_progress.watch(model->activeSearchJob().get()); } void TechnicPage::onSelectionChanged(QModelIndex first, [[maybe_unused]] QModelIndex second) diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index 1e36fbd31..01439337d 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -42,6 +42,7 @@ #include "TechnicData.h" #include "net/NetJob.h" #include "ui/pages/BasePage.h" +#include "ui/widgets/ProgressWidget.h" namespace Ui { class TechnicPage; @@ -92,6 +93,8 @@ class TechnicPage : public QWidget, public BasePage { NetJob::Ptr jobPtr; std::shared_ptr response = std::make_shared(); + ProgressWidget m_fetch_progress; + // Used to do instant searching with a delay to cache quick changes QTimer m_search_timer; }; diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.ui b/launcher/ui/pages/modplatform/technic/TechnicPage.ui index 15bf645fb..b988eda2b 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.ui +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.ui @@ -11,7 +11,7 @@ - + @@ -44,7 +44,7 @@ - + From 8c607ae7348206c29a8a8ce5e2db421138bd89ff Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 27 Aug 2023 20:02:12 +0300 Subject: [PATCH 317/398] removed extra if Signed-off-by: Trial97 --- .../ui/pages/modplatform/ResourceModel.cpp | 34 ++++++++----------- .../ui/pages/modplatform/flame/FlameModel.cpp | 8 ++--- .../modplatform/modrinth/ModrinthModel.cpp | 8 ++--- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 018721f94..cb8f1920f 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -137,26 +137,22 @@ void ResourceModel::search() if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; - // Use defaults if no callbacks are set - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason) { - if (!s_running_models.constFind(this).value()) - return; - searchRequestFailed(reason, -1); - }; - if (!callbacks.on_abort) - callbacks.on_abort = [this] { - if (!s_running_models.constFind(this).value()) - return; - searchRequestAborted(); - }; + callbacks.on_fail = [this](QString reason) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestFailed(reason, -1); + }; + callbacks.on_abort = [this] { + if (!s_running_models.constFind(this).value()) + return; + searchRequestAborted(); + }; - if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto& pack) { - if (!s_running_models.constFind(this).value()) - return; - searchRequestForOneSucceeded(doc); - }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { + if (!s_running_models.constFind(this).value()) + return; + searchRequestForOneSucceeded(doc); + }; if (auto job = m_api->getProjectInfo({ projectId }, std::move(callbacks)); job) runSearchJob(job); return; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 17875a604..8875a9452 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -168,12 +168,8 @@ void ListModel::performPaginatedSearch() if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; - // Use defaults if no callbacks are set - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; - - if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const FlameAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index efb1fe44e..f691a185d 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -138,12 +138,8 @@ void ModpackListModel::performPaginatedSearch() if (!projectId.isEmpty()) { ResourceAPI::ProjectInfoCallbacks callbacks; - // Use defaults if no callbacks are set - if (!callbacks.on_fail) - callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; - - if (!callbacks.on_succeed) - callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; + callbacks.on_fail = [this](QString reason) { searchRequestFailed(reason); }; + callbacks.on_succeed = [this](auto& doc, auto& pack) { searchRequestForOneSucceeded(doc); }; static const ModrinthAPI api; if (auto job = api.getProjectInfo({ projectId }, std::move(callbacks)); job) { jobPtr = job; From 07d8598638247d8dfb2fcd2e38c4498e90570f6e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 27 Aug 2023 23:40:32 +0300 Subject: [PATCH 318/398] added catpacks tests Signed-off-by: Trial97 --- launcher/ui/themes/CatPack.cpp | 10 +++-- launcher/ui/themes/CatPack.h | 9 ++-- tests/CMakeLists.txt | 3 ++ tests/CatPack_test.cpp | 77 ++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 tests/CatPack_test.cpp diff --git a/launcher/ui/themes/CatPack.cpp b/launcher/ui/themes/CatPack.cpp index f0d8ddd55..bbcb58bc8 100644 --- a/launcher/ui/themes/CatPack.cpp +++ b/launcher/ui/themes/CatPack.cpp @@ -99,18 +99,22 @@ QDate ensureDay(int year, int month, int day) QString JsonCatPack::path() { - const QDate now = QDate::currentDate(); + return path(QDate::currentDate()); +} + +QString JsonCatPack::path(QDate now) +{ for (auto var : m_variants) { QDate startDate = ensureDay(now.year(), var.startTime.month, var.startTime.day); QDate endDate = ensureDay(now.year(), var.endTime.month, var.endTime.day); if (startDate > endDate) { // it's spans over multiple years - if (endDate <= now) // end date is in the past so jump one year into the future for endDate + if (endDate < now) // end date is in the past so jump one year into the future for endDate endDate = endDate.addYears(1); else // end date is in the future so jump one year into the past for startDate startDate = startDate.addYears(-1); } - if (startDate >= now && now >= endDate) + if (startDate <= now && now <= endDate) return var.path; } return m_defaultPath; diff --git a/launcher/ui/themes/CatPack.h b/launcher/ui/themes/CatPack.h index fdd117a7f..1d310e796 100644 --- a/launcher/ui/themes/CatPack.h +++ b/launcher/ui/themes/CatPack.h @@ -52,9 +52,9 @@ class BasicCatPack : public CatPack { public: BasicCatPack(QString id, QString name) : m_id(id), m_name(name) {} BasicCatPack(QString id) : BasicCatPack(id, id) {} - virtual QString id() { return m_id; } - virtual QString name() { return m_name; } - virtual QString path(); + virtual QString id() override { return m_id; } + virtual QString name() override { return m_name; } + virtual QString path() override; protected: QString m_id; @@ -83,7 +83,8 @@ class JsonCatPack : public BasicCatPack { PartialDate endTime; }; JsonCatPack(QFileInfo& manifestInfo); - virtual QString path(); + virtual QString path() override; + QString path(QDate now); private: QString m_defaultPath; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a26a49fec..1a49fd700 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,3 +56,6 @@ ecm_add_test(Index_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}: ecm_add_test(Version_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test TEST_NAME Version) + +ecm_add_test(CatPack_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test + TEST_NAME CatPack) \ No newline at end of file diff --git a/tests/CatPack_test.cpp b/tests/CatPack_test.cpp new file mode 100644 index 000000000..a84ba6511 --- /dev/null +++ b/tests/CatPack_test.cpp @@ -0,0 +1,77 @@ +#include + +#include +#include +#include +#include +#include "FileSystem.h" +#include "ui/themes/CatPack.h" + +class CatPackTest : public QObject { + Q_OBJECT + private slots: + void test_catPack() + { + QString fileContent = R"({ + "name": "My Cute Cat", + "default": "maxwell.png", + "variants": [ + { + "startTime": { "day": 12, "month": 4 }, + "endTime": { "day": 12, "month": 4 }, + "path": "oneDay.png" + }, + { + "startTime": { "day": 20, "month": 12 }, + "endTime": { "day": 28, "month": 12 }, + "path": "christmas.png" + }, + { + "startTime": { "day": 30, "month": 12 }, + "endTime": { "day": 1, "month": 1 }, + "path": "newyear2.png" + }, + { + "startTime": { "day": 28, "month": 12 }, + "endTime": { "day": 3, "month": 1 }, + "path": "newyear.png" + } + ] +})"; +#if defined(Q_OS_WIN) + QString fileName = "test_SaveAlreadyExistingFile.ini"; + QFile file(fileName); + QCOMPARE(file.open(QFile::WriteOnly | QFile::Text), true); +#else + QTemporaryFile file; + QCOMPARE(file.open(), true); + QCOMPARE(file.fileName().isEmpty(), false); + QString fileName = file.fileName(); +#endif + QTextStream stream(&file); + stream << fileContent; + file.close(); + auto fileinfo = QFileInfo(fileName); + try { + auto cat = JsonCatPack(fileinfo); + QCOMPARE(cat.path(QDate(2023, 4, 12)), FS::PathCombine(fileinfo.path(), "oneDay.png")); + QCOMPARE(cat.path(QDate(2023, 4, 11)), FS::PathCombine(fileinfo.path(), "maxwell.png")); + QCOMPARE(cat.path(QDate(2023, 4, 13)), FS::PathCombine(fileinfo.path(), "maxwell.png")); + QCOMPARE(cat.path(QDate(2023, 12, 21)), FS::PathCombine(fileinfo.path(), "christmas.png")); + QCOMPARE(cat.path(QDate(2023, 12, 28)), FS::PathCombine(fileinfo.path(), "christmas.png")); + QCOMPARE(cat.path(QDate(2023, 12, 29)), FS::PathCombine(fileinfo.path(), "newyear.png")); + QCOMPARE(cat.path(QDate(2023, 12, 30)), FS::PathCombine(fileinfo.path(), "newyear2.png")); + QCOMPARE(cat.path(QDate(2023, 12, 31)), FS::PathCombine(fileinfo.path(), "newyear2.png")); + QCOMPARE(cat.path(QDate(2024, 1, 1)), FS::PathCombine(fileinfo.path(), "newyear2.png")); + QCOMPARE(cat.path(QDate(2024, 1, 2)), FS::PathCombine(fileinfo.path(), "newyear.png")); + QCOMPARE(cat.path(QDate(2024, 1, 3)), FS::PathCombine(fileinfo.path(), "newyear.png")); + QCOMPARE(cat.path(QDate(2024, 1, 4)), FS::PathCombine(fileinfo.path(), "maxwell.png")); + } catch (const Exception& e) { + QFAIL(e.cause().toLatin1()); + } + } +}; + +QTEST_GUILESS_MAIN(CatPackTest) + +#include "CatPack_test.moc" From 66cbbfec0c992408e3d507496ccf73e25171891f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 00:23:14 +0000 Subject: [PATCH 319/398] chore(deps): lock file maintenance --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 5599efe16..f27ca5207 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693060755, - "narHash": "sha256-KNsbfqewEziFJEpPR0qvVz4rx0x6QXxw1CcunRhlFdk=", + "lastModified": 1693145325, + "narHash": "sha256-Gat9xskErH1zOcLjYMhSDBo0JTBZKfGS0xJlIRnj6Rc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c66ccfa00c643751da2fd9290e096ceaa30493fc", + "rev": "cddebdb60de376c1bdb7a4e6ee3d98355453fe56", "type": "github" }, "original": { From 5d70f4dbca4405704e03e8428a7829b6a7cc32eb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 28 Aug 2023 08:50:10 +0300 Subject: [PATCH 320/398] removed if Signed-off-by: Trial97 --- launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index 1be58c2b8..e732ad39c 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -394,7 +394,7 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, for (auto file : optionalFiles) { if (selectedMods.contains(file.path)) { file.required = true; - } else if (file.path.endsWith(".jar")) { + } else { file.path += ".disabled"; } files.push_back(file); From 97d932db620b478742583cbd151f875e89999100 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 28 Aug 2023 10:13:44 +0200 Subject: [PATCH 321/398] Revert "chore(deps): enable nix lockfile maintenance for renovate" This reverts commit 5d14724e66a1911b04dd5091e520751fd7f5ee90. Signed-off-by: Sefa Eyeoglu --- renovate.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/renovate.json b/renovate.json index 71581e3b0..f9c2c3270 100644 --- a/renovate.json +++ b/renovate.json @@ -2,11 +2,5 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:base" - ], - "nix": { - "enabled": true - }, - "lockFileMaintenance": { - "enabled": true - } + ] } From 311e36b5d6dfaed449a3bbdada3d2e5b87f2b6d9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 28 Aug 2023 11:52:26 +0300 Subject: [PATCH 322/398] added new line Signed-off-by: Trial97 --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1a49fd700..59e0e3144 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -58,4 +58,4 @@ ecm_add_test(Version_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR TEST_NAME Version) ecm_add_test(CatPack_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test - TEST_NAME CatPack) \ No newline at end of file + TEST_NAME CatPack) From bdc2fca711d3ad110d7ef2a2c1ae99537144a00e Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 28 Aug 2023 10:26:03 +0200 Subject: [PATCH 323/398] refactor(nix): don't instantiate nixpkgs See https://zimbatm.com/notes/1000-instances-of-nixpkgs Signed-off-by: Sefa Eyeoglu --- flake.nix | 14 ++++- nix/default.nix | 31 ---------- nix/distribution.nix | 36 ++++++------ nix/{package.nix => pkg/default.nix} | 0 nix/pkg/wrapper.nix | 86 ++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 49 deletions(-) delete mode 100644 nix/default.nix rename nix/{package.nix => pkg/default.nix} (100%) create mode 100644 nix/pkg/wrapper.nix diff --git a/flake.nix b/flake.nix index c3148fe03..8f31ccec5 100644 --- a/flake.nix +++ b/flake.nix @@ -23,5 +23,17 @@ outputs = inputs: inputs.flake-parts.lib.mkFlake {inherit inputs;} - {imports = [./nix];}; + { + imports = [ + ./nix/dev.nix + ./nix/distribution.nix + ]; + + systems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + }; } diff --git a/nix/default.nix b/nix/default.nix deleted file mode 100644 index 71c95c2cf..000000000 --- a/nix/default.nix +++ /dev/null @@ -1,31 +0,0 @@ -{ - inputs, - self, - ... -}: { - imports = [ - ./dev.nix - ./distribution.nix - ]; - - _module.args = { - # User-friendly version number. - version = builtins.substring 0 8 self.lastModifiedDate; - }; - - perSystem = {system, ...}: { - # Nixpkgs instantiated for supported systems with our overlay. - _module.args.pkgs = import inputs.nixpkgs { - inherit system; - overlays = [self.overlays.default]; - }; - }; - - # Supported systems. - systems = [ - "x86_64-linux" - "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; -} diff --git a/nix/distribution.nix b/nix/distribution.nix index d0904d41d..0dde1e4f0 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -1,30 +1,32 @@ { inputs, self, - version, ... }: { perSystem = {pkgs, ...}: { - packages = { - inherit (pkgs) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher; - default = pkgs.prismlauncher; + packages = let + ourPackages = self.overlays.default pkgs null; + in { + inherit (ourPackages) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher; + default = ourPackages.prismlauncher; }; }; flake = { - overlays.default = final: prev: let - # Helper function to build prism against different versions of Qt. - mkPrism = qt: - qt.callPackage ./package.nix { - inherit (inputs) libnbtplusplus; - inherit (prev.darwin.apple_sdk.frameworks) Cocoa; - inherit self version; - }; - in { - prismlauncher-qt5-unwrapped = mkPrism final.libsForQt5; - prismlauncher-qt5 = prev.prismlauncher-qt5.override {prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped;}; - prismlauncher-unwrapped = mkPrism final.qt6Packages; - prismlauncher = prev.prismlauncher.override {inherit (final) prismlauncher-unwrapped;}; + overlays.default = final: _: let + version = builtins.substring 0 8 self.lastModifiedDate; + + # common args for prismlauncher evaluations + unwrappedArgs = { + inherit (inputs) libnbtplusplus; + inherit (final.darwin.apple_sdk.frameworks) Cocoa; + inherit self version; + }; + in rec { + prismlauncher-qt5-unwrapped = final.libsForQt5.callPackage ./pkg unwrappedArgs; + prismlauncher-qt5 = final.libsForQt5.callPackage ./pkg/wrapper.nix {prismlauncher-unwrapped = prismlauncher-qt5-unwrapped;}; + prismlauncher-unwrapped = final.qt6Packages.callPackage ./pkg unwrappedArgs; + prismlauncher = final.qt6Packages.callPackage ./pkg/wrapper.nix {inherit prismlauncher-unwrapped;}; }; }; } diff --git a/nix/package.nix b/nix/pkg/default.nix similarity index 100% rename from nix/package.nix rename to nix/pkg/default.nix diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix new file mode 100644 index 000000000..3bf5b3f85 --- /dev/null +++ b/nix/pkg/wrapper.nix @@ -0,0 +1,86 @@ +{ + lib, + stdenv, + symlinkJoin, + prismlauncher-unwrapped, + wrapQtAppsHook, + qtbase, # needed for wrapQtAppsHook + qtsvg, + qtwayland, + xorg, + libpulseaudio, + libGL, + glfw, + openal, + jdk8, + jdk17, + gamemode, + flite, + mesa-demos, + msaClientID ? null, + gamemodeSupport ? stdenv.isLinux, + textToSpeechSupport ? stdenv.isLinux, + jdks ? [jdk17 jdk8], + additionalLibs ? [], + additionalPrograms ? [], +}: let + prismlauncherFinal = prismlauncher-unwrapped.override { + inherit msaClientID gamemodeSupport; + }; +in + symlinkJoin { + name = "prismlauncher-${prismlauncherFinal.version}"; + + paths = [prismlauncherFinal]; + + nativeBuildInputs = [ + wrapQtAppsHook + ]; + + buildInputs = + [ + qtbase + qtsvg + ] + ++ lib.optional (lib.versionAtLeast qtbase.version "6" && stdenv.isLinux) qtwayland; + + postBuild = '' + wrapQtAppsHook + ''; + + qtWrapperArgs = let + runtimeLibs = + (with xorg; [ + libX11 + libXext + libXcursor + libXrandr + libXxf86vm + ]) + ++ [ + libpulseaudio + libGL + glfw + openal + stdenv.cc.cc.lib + ] + ++ lib.optional gamemodeSupport gamemode.lib + ++ lib.optional textToSpeechSupport flite + ++ additionalLibs; + + runtimePrograms = + [ + xorg.xrandr + mesa-demos # need glxinfo + ] + ++ additionalPrograms; + in + ["--prefix PRISMLAUNCHER_JAVA_PATHS : ${lib.makeSearchPath "bin/java" jdks}"] + ++ lib.optionals stdenv.isLinux [ + "--set LD_LIBRARY_PATH /run/opengl-driver/lib:${lib.makeLibraryPath runtimeLibs}" + # xorg.xrandr needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 + "--prefix PATH : ${lib.makeBinPath runtimePrograms}" + ]; + + inherit (prismlauncherFinal) meta; + } From e98bca47493f53b324d0ac7fd9eac9386c30be23 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 28 Aug 2023 17:09:40 +0100 Subject: [PATCH 324/398] Fix cancelling pack save Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportPackDialog.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index 0a97ee13c..b0558df7d 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -120,18 +120,19 @@ void ExportPackDialog::done(int result) if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(name), FS::PathCombine(QDir::homePath(), filename + ".mrpack"), "Modrinth pack (*.mrpack *.zip)", nullptr); + if (output.isEmpty()) + return; if (!(output.endsWith(".zip") || output.endsWith(".mrpack"))) output.append(".mrpack"); } else { output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(name), FS::PathCombine(QDir::homePath(), filename + ".zip"), "CurseForge pack (*.zip)", nullptr); + if (output.isEmpty()) + return; if (!output.endsWith(".zip")) output.append(".zip"); } - if (output.isEmpty()) - return; - Task* task; if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { task = new ModrinthPackExportTask(name, ui->version->text(), ui->summary->text(), ui->optionalFiles->isChecked(), instance, From 0e67686295e25a3dda587e4955837e6201ae23e8 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 28 Aug 2023 17:25:07 +0100 Subject: [PATCH 325/398] Hide index folder in pack export dialog Signed-off-by: TheKodeToad --- launcher/FileIgnoreProxy.cpp | 5 +---- launcher/ui/dialogs/ExportPackDialog.cpp | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index 4c8c64c72..df06c3c75 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -267,10 +267,7 @@ bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceP bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const { - auto fileName = fileInfo.fileName(); - auto path = relPath(fileInfo.absoluteFilePath()); - return std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || - m_ignoreFilePaths.covers(path); + return m_ignoreFiles.contains(fileInfo.fileName()) || m_ignoreFilePaths.covers(relPath(fileInfo.absoluteFilePath())); } bool FileIgnoreProxy::filterFile(const QString& fileName) const diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index b0558df7d..5af24b1b7 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -81,10 +81,9 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla MinecraftInstance* mcInstance = dynamic_cast(instance.get()); if (mcInstance) { - mcInstance->loaderModList()->update(); const QDir index = mcInstance->loaderModList()->indexDir(); if (index.exists()) - proxy->blockedPaths().insert(root.relativeFilePath(index.absolutePath())); + proxy->ignoreFilesWithPath().insert(root.relativeFilePath(index.absolutePath())); } ui->files->setModel(proxy); From 8c30cb370676970f62a56e9f5615b22f646eb2e3 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 29 Aug 2023 13:27:06 +0100 Subject: [PATCH 326/398] Fix CI Signed-off-by: TheKodeToad --- launcher/InstanceList.cpp | 1 - launcher/InstanceList.h | 2 +- launcher/ui/MainWindow.cpp | 5 +++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp index ef3707ec9..756ff93dd 100644 --- a/launcher/InstanceList.cpp +++ b/launcher/InstanceList.cpp @@ -645,7 +645,6 @@ InstancePtr InstanceList::loadInstance(const InstanceId& id) return inst; } - void InstanceList::increaseGroupCount(const QString& group) { if (group.isEmpty()) diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h index 26aea6556..6b0bcd810 100644 --- a/launcher/InstanceList.h +++ b/launcher/InstanceList.h @@ -106,7 +106,7 @@ class InstanceList : public QAbstractListModel { bool isGroupCollapsed(const QString& groupName); GroupId getInstanceGroup(const InstanceId& id) const; - void setInstanceGroup(const InstanceId& id, const GroupId& name); + void setInstanceGroup(const InstanceId& id, GroupId name); void deleteGroup(const GroupId& name); void renameGroup(const GroupId& src, const GroupId& dst); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index eabfe7a49..3f0e4fb2a 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1149,12 +1149,13 @@ void MainWindow::deleteGroup(QString group) Q_ASSERT(!group.isEmpty()); const int reply = QMessageBox::question(this, tr("Delete group"), tr("Are you sure you want to delete the group '%1'?").arg(group), - QMessageBox::Yes | QMessageBox::No); + QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) APPLICATION->instances()->deleteGroup(group); } -void MainWindow::renameGroup(QString group) { +void MainWindow::renameGroup(QString group) +{ Q_ASSERT(!group.isEmpty()); QString name = QInputDialog::getText(this, tr("Rename group"), tr("Enter a new group name."), QLineEdit::Normal, group); From f23a8e4b4b80cff4b2e15fa1783dbf046d2dfc18 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 29 Aug 2023 23:30:10 +0100 Subject: [PATCH 327/398] Enable antialiasing for mod and pack icons Signed-off-by: TheKodeToad --- launcher/minecraft/mod/Mod.cpp | 5 +++-- launcher/minecraft/mod/ResourcePack.cpp | 5 +++-- launcher/minecraft/mod/TexturePack.cpp | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index ae3dea8d8..b59c6d37c 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -246,7 +246,8 @@ void Mod::setIcon(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = + QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; @@ -259,7 +260,7 @@ QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size, mode); + return cached_image.scaled(size, mode, Qt::SmoothTransformation); } // No valid image we can get diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index dab0f6d67..2bb51dc5b 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -50,7 +50,8 @@ void ResourcePack::setImage(QImage new_image) const PixmapCache::instance().remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = + QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap); m_pack_image_cache_key.was_ever_used = true; @@ -68,7 +69,7 @@ QPixmap ResourcePack::image(QSize size, Qt::AspectRatioMode mode) const if (PixmapCache::instance().find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size, mode); + return cached_image.scaled(size, mode, Qt::SmoothTransformation); } // No valid image we can get diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp index 7d8c67137..04cc36310 100644 --- a/launcher/minecraft/mod/TexturePack.cpp +++ b/launcher/minecraft/mod/TexturePack.cpp @@ -44,7 +44,8 @@ void TexturePack::setImage(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = + QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; @@ -56,7 +57,7 @@ QPixmap TexturePack::image(QSize size, Qt::AspectRatioMode mode) const if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size, mode); + return cached_image.scaled(size, mode, Qt::SmoothTransformation); } // No valid image we can get From 584e800279351cdd592d1012ca885dd86b9f26f2 Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 30 Aug 2023 11:13:39 -0400 Subject: [PATCH 328/398] fix: remove -Wextra-semi this flag is unavailable on gcc versions < 8. we could detect the version of the compiler here, but i don't think we lose much in this flags removal and this is a simpler option Signed-off-by: seth --- cmake/CompilerWarnings.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index 635e54289..69e57b4d5 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -75,7 +75,6 @@ function( set(CLANG_WARNINGS -Wall -Wextra # reasonable and standard - -Wextra-semi # Warn about semicolon after in-class function definition. -Wshadow # warn the user if a variable declaration shadows one from a parent context -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps # catch hard to track down memory errors From 707da5a25a11a8ae6c60f619f37b9fdcb7970082 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 30 Aug 2023 21:59:41 +0200 Subject: [PATCH 329/398] fix(nix): include udev dependency See https://github.com/NixOS/nixpkgs/pull/252425 Signed-off-by: Sefa Eyeoglu --- nix/pkg/wrapper.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix index 3bf5b3f85..8d160143d 100644 --- a/nix/pkg/wrapper.nix +++ b/nix/pkg/wrapper.nix @@ -17,6 +17,7 @@ gamemode, flite, mesa-demos, + udev, msaClientID ? null, gamemodeSupport ? stdenv.isLinux, textToSpeechSupport ? stdenv.isLinux, @@ -58,11 +59,15 @@ in libXxf86vm ]) ++ [ + # lwjgl libpulseaudio libGL glfw openal stdenv.cc.cc.lib + + # oshi + udev ] ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional textToSpeechSupport flite From 6cfe2dbc50d0dbe53c59012375fcd0cf3a8558a9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 31 Aug 2023 17:34:05 +0300 Subject: [PATCH 330/398] moved catpack data to testdata Signed-off-by: Trial97 --- tests/CatPack_test.cpp | 41 ++---------------------------- tests/testdata/CatPacks/index.json | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 39 deletions(-) create mode 100644 tests/testdata/CatPacks/index.json diff --git a/tests/CatPack_test.cpp b/tests/CatPack_test.cpp index a84ba6511..330d1a814 100644 --- a/tests/CatPack_test.cpp +++ b/tests/CatPack_test.cpp @@ -12,45 +12,8 @@ class CatPackTest : public QObject { private slots: void test_catPack() { - QString fileContent = R"({ - "name": "My Cute Cat", - "default": "maxwell.png", - "variants": [ - { - "startTime": { "day": 12, "month": 4 }, - "endTime": { "day": 12, "month": 4 }, - "path": "oneDay.png" - }, - { - "startTime": { "day": 20, "month": 12 }, - "endTime": { "day": 28, "month": 12 }, - "path": "christmas.png" - }, - { - "startTime": { "day": 30, "month": 12 }, - "endTime": { "day": 1, "month": 1 }, - "path": "newyear2.png" - }, - { - "startTime": { "day": 28, "month": 12 }, - "endTime": { "day": 3, "month": 1 }, - "path": "newyear.png" - } - ] -})"; -#if defined(Q_OS_WIN) - QString fileName = "test_SaveAlreadyExistingFile.ini"; - QFile file(fileName); - QCOMPARE(file.open(QFile::WriteOnly | QFile::Text), true); -#else - QTemporaryFile file; - QCOMPARE(file.open(), true); - QCOMPARE(file.fileName().isEmpty(), false); - QString fileName = file.fileName(); -#endif - QTextStream stream(&file); - stream << fileContent; - file.close(); + auto dataDir = QDir(QFINDTESTDATA("testdata/CatPacks")).absolutePath(); + auto fileName = FS::PathCombine(dataDir, "index.json"); auto fileinfo = QFileInfo(fileName); try { auto cat = JsonCatPack(fileinfo); diff --git a/tests/testdata/CatPacks/index.json b/tests/testdata/CatPacks/index.json new file mode 100644 index 000000000..c55813dbb --- /dev/null +++ b/tests/testdata/CatPacks/index.json @@ -0,0 +1,26 @@ +{ + "name": "My Cute Cat", + "default": "maxwell.png", + "variants": [ + { + "startTime": { "day": 12, "month": 4 }, + "endTime": { "day": 12, "month": 4 }, + "path": "oneDay.png" + }, + { + "startTime": { "day": 20, "month": 12 }, + "endTime": { "day": 28, "month": 12 }, + "path": "christmas.png" + }, + { + "startTime": { "day": 30, "month": 12 }, + "endTime": { "day": 1, "month": 1 }, + "path": "newyear2.png" + }, + { + "startTime": { "day": 28, "month": 12 }, + "endTime": { "day": 3, "month": 1 }, + "path": "newyear.png" + } + ] +} From 7e65aea2ef790d8f2e424e618d9ab9acd476f045 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 31 Aug 2023 19:04:41 +0300 Subject: [PATCH 331/398] format json Signed-off-by: Trial97 --- tests/testdata/CatPacks/index.json | 72 ++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/tests/testdata/CatPacks/index.json b/tests/testdata/CatPacks/index.json index c55813dbb..b5401d230 100644 --- a/tests/testdata/CatPacks/index.json +++ b/tests/testdata/CatPacks/index.json @@ -1,26 +1,50 @@ { - "name": "My Cute Cat", - "default": "maxwell.png", - "variants": [ - { - "startTime": { "day": 12, "month": 4 }, - "endTime": { "day": 12, "month": 4 }, - "path": "oneDay.png" - }, - { - "startTime": { "day": 20, "month": 12 }, - "endTime": { "day": 28, "month": 12 }, - "path": "christmas.png" - }, - { - "startTime": { "day": 30, "month": 12 }, - "endTime": { "day": 1, "month": 1 }, - "path": "newyear2.png" - }, - { - "startTime": { "day": 28, "month": 12 }, - "endTime": { "day": 3, "month": 1 }, - "path": "newyear.png" - } - ] + "name": "My Cute Cat", + "default": "maxwell.png", + "variants": [ + { + "startTime": { + "day": 12, + "month": 4 + }, + "endTime": { + "day": 12, + "month": 4 + }, + "path": "oneDay.png" + }, + { + "startTime": { + "day": 20, + "month": 12 + }, + "endTime": { + "day": 28, + "month": 12 + }, + "path": "christmas.png" + }, + { + "startTime": { + "day": 30, + "month": 12 + }, + "endTime": { + "day": 1, + "month": 1 + }, + "path": "newyear2.png" + }, + { + "startTime": { + "day": 28, + "month": 12 + }, + "endTime": { + "day": 3, + "month": 1 + }, + "path": "newyear.png" + } + ] } From 30ff417074a6a5f2200df9bac92a537425417103 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 1 Sep 2023 16:25:49 +0300 Subject: [PATCH 332/398] fix: make cached instead of file for ftb pack import Signed-off-by: Trial97 --- launcher/modplatform/legacy_ftb/PackInstallTask.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp index 761f622bb..091296751 100644 --- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp @@ -70,16 +70,18 @@ void PackInstallTask::downloadPack() setProgress(1, 4); setAbortable(false); - archivePath = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file); - + auto path = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file); + auto entry = APPLICATION->metacache()->resolveEntry("FTBPacks", path); + entry->setStale(true); + archivePath = entry->getFullPath(); netJobContainer.reset(new NetJob("Download FTB Pack", m_network)); QString url; if (m_pack.type == PackType::Private) { - url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "privatepacks/%1").arg(archivePath); + url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "privatepacks/%1").arg(path); } else { - url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(archivePath); + url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(path); } - netJobContainer->addNetAction(Net::ApiDownload::makeFile(url, archivePath)); + netJobContainer->addNetAction(Net::ApiDownload::makeCached(url, entry)); connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::unzip); connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::emitFailed); From eb66e37b8311fb830727e2632c6a00301b36b1f1 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:29:16 -0400 Subject: [PATCH 333/398] fix opening files from curseforge: links on linux Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> --- program_info/org.prismlauncher.PrismLauncher.desktop.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index 816c00595..98ac92fe5 100644 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -4,7 +4,7 @@ Name=Prism Launcher Comment=A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. Type=Application Terminal=false -Exec=@Launcher_APP_BINARY_NAME@ +Exec=@Launcher_APP_BINARY_NAME@ %u StartupNotify=true Icon=org.prismlauncher.PrismLauncher Categories=Game;ActionGame;AdventureGame;Simulation; From 984e870bca6ac4e8264ba7221bd99b54c0bb0fc9 Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:32:35 -0400 Subject: [PATCH 334/398] actually it can handle multiple files just fine Signed-off-by: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> --- program_info/org.prismlauncher.PrismLauncher.desktop.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program_info/org.prismlauncher.PrismLauncher.desktop.in b/program_info/org.prismlauncher.PrismLauncher.desktop.in index 98ac92fe5..76f4b19c0 100644 --- a/program_info/org.prismlauncher.PrismLauncher.desktop.in +++ b/program_info/org.prismlauncher.PrismLauncher.desktop.in @@ -4,7 +4,7 @@ Name=Prism Launcher Comment=A custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. Type=Application Terminal=false -Exec=@Launcher_APP_BINARY_NAME@ %u +Exec=@Launcher_APP_BINARY_NAME@ %U StartupNotify=true Icon=org.prismlauncher.PrismLauncher Categories=Game;ActionGame;AdventureGame;Simulation; From 17f696bffcf83ff9d40964137c9743b590161e77 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 1 Sep 2023 22:25:15 +0300 Subject: [PATCH 335/398] small tweaks to atl icons Signed-off-by: Trial97 --- launcher/modplatform/atlauncher/ATLPackIndex.cpp | 2 +- launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/modplatform/atlauncher/ATLPackIndex.cpp b/launcher/modplatform/atlauncher/ATLPackIndex.cpp index 84b0cc9e2..678db63cc 100644 --- a/launcher/modplatform/atlauncher/ATLPackIndex.cpp +++ b/launcher/modplatform/atlauncher/ATLPackIndex.cpp @@ -43,5 +43,5 @@ void ATLauncher::loadIndexedPack(ATLauncher::IndexedPack& m, QJsonObject& obj) m.system = Json::ensureBoolean(obj, QString("system"), false); m.description = Json::ensureString(obj, "description", ""); - m.safeName = "atl_" + Json::requireString(obj, "name").replace(QRegularExpression("[^A-Za-z0-9]"), "").toLower() + ".png"; + m.safeName = Json::requireString(obj, "name").replace(QRegularExpression("[^A-Za-z0-9]"), "").toLower() + ".png"; } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp index 6298cd0b4..e492830c6 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlPage.cpp @@ -114,7 +114,7 @@ void AtlPage::suggestCurrent() auto uiSupport = new AtlUserInteractionSupportImpl(this); dialog->setSuggestedPack(selected.name, selectedVersion, new ATLauncher::PackInstallTask(uiSupport, selected.name, selectedVersion)); - auto editedLogoName = selected.safeName; + auto editedLogoName = "atl_" + selected.safeName; auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1").arg(selected.safeName); listModel->getLogo(selected.safeName, url, [this, editedLogoName](QString logo) { dialog->setSuggestedIconFromFile(logo, editedLogoName); }); From 347228a24613f5ec7ce63341a929a8a88bb2a6b4 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 2 Sep 2023 22:29:26 +0100 Subject: [PATCH 336/398] Legacy settings override default -> false Signed-off-by: TheKodeToad --- launcher/minecraft/MinecraftInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index bc8d2db58..52416fe15 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -185,7 +185,7 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerOverride(global_settings->getSetting("QuitAfterGameStop"), miscellaneousOverride); // Legacy-related options - auto legacySettings = m_settings->registerSetting("OverrideLegacySettings", true); + auto legacySettings = m_settings->registerSetting("OverrideLegacySettings", false); m_settings->registerOverride(global_settings->getSetting("OnlineFixes"), legacySettings); m_settings->set("InstanceType", "OneSix"); From 19b5a5e00badad2630e2e4ae431d792a06bfe6b6 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 2 Sep 2023 22:38:14 +0100 Subject: [PATCH 337/398] Remove final conflict - kept by mistake Signed-off-by: TheKodeToad --- .../legacy/org/prismlauncher/legacy/LegacyLauncher.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java index 90244e1ae..02f77e039 100644 --- a/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java +++ b/libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java @@ -122,7 +122,6 @@ final class LegacyLauncher extends AbstractLauncher { MethodHandle method = ReflectionUtils.findMainMethod(main); method.invokeExact(gameArgs.toArray(new String[0])); } -<<<<<<< HEAD:libraries/launcher/legacy/org/prismlauncher/legacy/LegacyLauncher.java private static Applet createAppletClass(String clazz) throws Throwable { Class appletClass = ClassLoader.getSystemClassLoader().loadClass(clazz); @@ -153,7 +152,4 @@ final class LegacyLauncher extends AbstractLauncher { return null; } - -======= ->>>>>>> upstream/develop:libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java } From 88f3e19f815e67f6cb38c2b9df2dbf6008d4d60a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 3 Sep 2023 00:17:45 +0000 Subject: [PATCH 338/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-parts': 'github:hercules-ci/flake-parts/59cf3f1447cfc75087e7273b04b31e689a8599fb' (2023-08-01) → 'github:hercules-ci/flake-parts/7f53fdb7bdc5bb237da7fefef12d099e4fd611ca' (2023-09-01) • Updated input 'flake-parts/nixpkgs-lib': 'github:NixOS/nixpkgs/9e1960bc196baf6881340d53dccb203a951745a2?dir=lib' (2023-08-01) → 'github:NixOS/nixpkgs/3e52e76b70d5508f3cec70b882a29199f4d1ee85?dir=lib' (2023-08-31) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/cddebdb60de376c1bdb7a4e6ee3d98355453fe56' (2023-08-27) → 'github:nixos/nixpkgs/bfb7dfec93f3b5d7274db109f2990bc889861caf' (2023-09-02) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index f27ca5207..b1486ea69 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1690933134, - "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "lastModified": 1693611461, + "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", "type": "github" }, "original": { @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693145325, - "narHash": "sha256-Gat9xskErH1zOcLjYMhSDBo0JTBZKfGS0xJlIRnj6Rc=", + "lastModified": 1693626178, + "narHash": "sha256-Rpiy6lIOu4zny8tfGuIeN1ji9eSz9nPmm9yBhh/4IOM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "cddebdb60de376c1bdb7a4e6ee3d98355453fe56", + "rev": "bfb7dfec93f3b5d7274db109f2990bc889861caf", "type": "github" }, "original": { @@ -108,11 +108,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1690881714, - "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "lastModified": 1693471703, + "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", "type": "github" }, "original": { From bbf4e3b04d98eac840134b1687aba63ec180ead0 Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 3 Sep 2023 18:11:23 -0400 Subject: [PATCH 339/398] refactor(nix): use fixed points over rec Signed-off-by: seth --- nix/distribution.nix | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/nix/distribution.nix b/nix/distribution.nix index 0dde1e4f0..6b93d355f 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -3,18 +3,28 @@ self, ... }: { - perSystem = {pkgs, ...}: { + perSystem = { + lib, + pkgs, + ... + }: { packages = let - ourPackages = self.overlays.default pkgs null; + ourPackages = lib.fix (final: self.overlays.default ({inherit (pkgs) darwin;} // final) pkgs); in { - inherit (ourPackages) prismlauncher-qt5-unwrapped prismlauncher-qt5 prismlauncher-unwrapped prismlauncher; + inherit + (ourPackages) + prismlauncher-qt5-unwrapped + prismlauncher-qt5 + prismlauncher-unwrapped + prismlauncher + ; default = ourPackages.prismlauncher; }; }; flake = { - overlays.default = final: _: let - version = builtins.substring 0 8 self.lastModifiedDate; + overlays.default = final: prev: let + version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; # common args for prismlauncher evaluations unwrappedArgs = { @@ -22,11 +32,13 @@ inherit (final.darwin.apple_sdk.frameworks) Cocoa; inherit self version; }; - in rec { - prismlauncher-qt5-unwrapped = final.libsForQt5.callPackage ./pkg unwrappedArgs; - prismlauncher-qt5 = final.libsForQt5.callPackage ./pkg/wrapper.nix {prismlauncher-unwrapped = prismlauncher-qt5-unwrapped;}; - prismlauncher-unwrapped = final.qt6Packages.callPackage ./pkg unwrappedArgs; - prismlauncher = final.qt6Packages.callPackage ./pkg/wrapper.nix {inherit prismlauncher-unwrapped;}; + in { + prismlauncher-qt5-unwrapped = prev.libsForQt5.callPackage ./pkg unwrappedArgs; + prismlauncher-qt5 = prev.libsForQt5.callPackage ./pkg/wrapper.nix { + prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped; + }; + prismlauncher-unwrapped = prev.qt6Packages.callPackage ./pkg unwrappedArgs; + prismlauncher = prev.qt6Packages.callPackage ./pkg/wrapper.nix {inherit (final) prismlauncher-unwrapped;}; }; }; } From 2918d61b16934980ed43fa52ead291e37a66732c Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Mon, 4 Sep 2023 08:52:56 +0200 Subject: [PATCH 340/398] refactor(nix): use pre-commit flake module Signed-off-by: Sefa Eyeoglu --- flake.nix | 2 ++ nix/dev.nix | 38 +++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/flake.nix b/flake.nix index 8f31ccec5..d45282aa6 100644 --- a/flake.nix +++ b/flake.nix @@ -25,6 +25,8 @@ {inherit inputs;} { imports = [ + inputs.pre-commit-hooks.flakeModule + ./nix/dev.nix ./nix/distribution.nix ]; diff --git a/nix/dev.nix b/nix/dev.nix index a9c1dc65d..c476ed10f 100644 --- a/nix/dev.nix +++ b/nix/dev.nix @@ -1,37 +1,33 @@ { - inputs, - self, - ... -}: { perSystem = { - system, + config, + lib, pkgs, ... }: { - checks = { - pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run { - src = self; - hooks = { - markdownlint.enable = true; + pre-commit.settings = { + hooks = { + markdownlint.enable = true; - alejandra.enable = true; - deadnix.enable = true; - nil.enable = true; + alejandra.enable = true; + deadnix.enable = true; + nil.enable = true; - clang-format = { - enable = true; - types_or = ["c" "c++" "java" "json" "objective-c"]; - }; + clang-format = { + enable = true; + types_or = ["c" "c++" "java" "json" "objective-c"]; }; - - tools.clang-tools = pkgs.clang-tools_16; }; + + tools.clang-tools = lib.mkForce pkgs.clang-tools_16; }; devShells.default = pkgs.mkShell { - inherit (self.checks.${system}.pre-commit-check) shellHook; + shellHook = '' + ${config.pre-commit.installationScript} + ''; - inputsFrom = [self.packages.${system}.prismlauncher-unwrapped]; + inputsFrom = [config.packages.prismlauncher-unwrapped]; buildInputs = with pkgs; [ccache ninja]; }; From e1558446717c83f14c575e0b8759f6a370633477 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 10:22:11 +0000 Subject: [PATCH 341/398] chore(deps): update cachix/install-nix-action action to v23 --- .github/workflows/update-flake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index ad4016ff4..16dbd7240 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 - uses: DeterminateSystems/update-flake-lock@v20 with: From 94c1cd6bcfbc7a66286c18bf1d1c3854f49deb64 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 4 Sep 2023 14:13:44 +0100 Subject: [PATCH 342/398] CurseForge shader downloading Signed-off-by: TheKodeToad --- launcher/modplatform/flame/FlameAPI.h | 2 + .../ui/dialogs/ResourceDownloadDialog.cpp | 2 + .../modplatform/flame/FlameResourceModels.cpp | 23 ++++++++++ .../modplatform/flame/FlameResourceModels.h | 17 ++++++++ .../modplatform/flame/FlameResourcePages.cpp | 43 +++++++++++++++++++ .../modplatform/flame/FlameResourcePages.h | 28 ++++++++++++ 6 files changed, 115 insertions(+) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 47350c33e..e22d8f0d8 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -38,6 +38,8 @@ class FlameAPI : public NetworkResourceAPI { return 6; case ModPlatform::ResourceType::RESOURCE_PACK: return 12; + case ModPlatform::ResourceType::SHADER_PACK: + return 6552; } } diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 9e121bb61..bf76b01e3 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -370,6 +370,8 @@ QList ShaderPackDownloadDialog::getPages() { QList pages; pages.append(ModrinthShaderPackPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame) + pages.append(FlameShaderPackPage::create(this, *m_instance)); return pages; } diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index c80e4f999..7d18e72a6 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -121,4 +121,27 @@ auto FlameTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonAr return Json::ensureArray(obj.object(), "data"); } +FlameShaderPackModel::FlameShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new FlameAPI) {} + +void FlameShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadIndexedPack(m, obj); +} + +// We already deal with the URLs when initializing the pack, due to the API response's structure +void FlameShaderPackModel::loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) +{ + FlameMod::loadBody(m, obj); +} + +void FlameShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) +{ + FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); +} + +auto FlameShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray +{ + return Json::ensureArray(obj.object(), "data"); +} + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 6cfd6a6f8..76dbd7b3d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -68,4 +68,21 @@ class FlameTexturePackModel : public TexturePackResourceModel { auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; +class FlameShaderPackModel : public ShaderPackResourceModel { + Q_OBJECT + + public: + FlameShaderPackModel(const BaseInstance&); + ~FlameShaderPackModel() override = default; + + private: + [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } + [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } + + void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; + void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index 1403e98f9..23373ec9d 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -173,6 +173,45 @@ void FlameTexturePackPage::openUrl(const QUrl& url) TexturePackResourcePage::openUrl(url); } +FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) + : ShaderPackResourcePage(dialog, instance) +{ + m_model = new FlameShaderPackModel(instance); + m_ui->packView->setModel(m_model); + + addSortings(); + + // sometimes Qt just ignores virtual slots and doesn't work as intended it seems, + // so it's best not to connect them in the parent's constructor... + connect(m_ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch())); + connect(m_ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameShaderPackPage::onSelectionChanged); + connect(m_ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameShaderPackPage::onVersionSelectionChanged); + connect(m_ui->resourceSelectionButton, &QPushButton::clicked, this, &FlameShaderPackPage::onResourceSelected); + + m_ui->packDescription->setMetaEntry(metaEntryBase()); +} + +bool FlameShaderPackPage::optedOut(ModPlatform::IndexedVersion& ver) const +{ + return isOptedOut(ver); +} + +void FlameShaderPackPage::openUrl(const QUrl& url) +{ + if (url.scheme().isEmpty()) { + QString query = url.query(QUrl::FullyDecoded); + + if (query.startsWith("remoteUrl=")) { + // attempt to resolve url from warning page + query.remove(0, 10); + ShaderPackResourcePage::openUrl({ QUrl::fromPercentEncoding(query.toUtf8()) }); // double decoding is necessary + return; + } + } + + ShaderPackResourcePage::openUrl(url); +} + // I don't know why, but doing this on the parent class makes it so that // other mod providers start loading before being selected, at least with // my Qt, so we need to implement this in every derived class... @@ -188,5 +227,9 @@ auto FlameTexturePackPage::shouldDisplay() const -> bool { return true; } +auto FlameShaderPackPage::shouldDisplay() const -> bool +{ + return true; +} } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h index 035da2d5f..f2f5cecad 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.h @@ -44,6 +44,7 @@ #include "ui/pages/modplatform/ModPage.h" #include "ui/pages/modplatform/ResourcePackPage.h" +#include "ui/pages/modplatform/ShaderPackPage.h" #include "ui/pages/modplatform/TexturePackPage.h" namespace ResourceDownload { @@ -155,4 +156,31 @@ class FlameTexturePackPage : public TexturePackResourcePage { void openUrl(const QUrl& url) override; }; +class FlameShaderPackPage : public ShaderPackResourcePage { + Q_OBJECT + + public: + static FlameShaderPackPage* create(ShaderPackDownloadDialog* dialog, BaseInstance& instance) + { + return ShaderPackResourcePage::create(dialog, instance); + } + + FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseInstance& instance); + ~FlameShaderPackPage() override = default; + + [[nodiscard]] bool shouldDisplay() const override; + + [[nodiscard]] inline auto displayName() const -> QString override { return Flame::displayName(); } + [[nodiscard]] inline auto icon() const -> QIcon override { return Flame::icon(); } + [[nodiscard]] inline auto id() const -> QString override { return Flame::id(); } + [[nodiscard]] inline auto debugName() const -> QString override { return Flame::debugName(); } + [[nodiscard]] inline auto metaEntryBase() const -> QString override { return Flame::metaEntryBase(); } + + [[nodiscard]] inline auto helpPage() const -> QString override { return ""; } + + bool optedOut(ModPlatform::IndexedVersion& ver) const override; + + void openUrl(const QUrl& url) override; +}; + } // namespace ResourceDownload From 7dd2530027fb17997283e1ec812f036328057d39 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 15:02:01 +0000 Subject: [PATCH 343/398] chore(deps): update actions/checkout action to v4 --- .github/workflows/backport.yml | 2 +- .github/workflows/build.yml | 4 ++-- .github/workflows/codeql.yml | 2 +- .github/workflows/trigger_release.yml | 2 +- .github/workflows/update-flake.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 08cfb56dd..c705ff7b0 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -20,7 +20,7 @@ jobs: if: github.repository_owner == 'PrismLauncher' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d044f4faf..e0434ce68 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -125,7 +125,7 @@ jobs: # PREPARE ## - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: 'true' @@ -620,7 +620,7 @@ jobs: options: --privileged steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 if: inputs.build_type == 'Debug' with: submodules: 'true' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0cd1f6e40..a77b4ae1e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,7 +8,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: 'true' diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index 2a46ff5e7..bda75e354 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -26,7 +26,7 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: 'true' path: 'PrismLauncher-source' diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 16dbd7240..6a16b0369 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 - uses: DeterminateSystems/update-flake-lock@v20 From e7d6be531f1e4101aa808818159cfeb0db394a67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:22:12 +0000 Subject: [PATCH 344/398] chore(deps): update actions/cache action to v3.3.2 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e0434ce68..059795a11 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -164,7 +164,7 @@ jobs: - name: Retrieve ccache cache (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug' - uses: actions/cache@v3.3.1 + uses: actions/cache@v3.3.2 with: path: '${{ github.workspace }}\.ccache' key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }} From 89e434bd5bedcd92bfa99102011607027be20060 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 9 Sep 2023 14:32:50 -0400 Subject: [PATCH 345/398] refactor(nix): don't concat final attr in fixed point Signed-off-by: seth --- nix/distribution.nix | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/nix/distribution.nix b/nix/distribution.nix index 6b93d355f..c8fa01c59 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -9,7 +9,7 @@ ... }: { packages = let - ourPackages = lib.fix (final: self.overlays.default ({inherit (pkgs) darwin;} // final) pkgs); + ourPackages = lib.fix (final: self.overlays.default final pkgs); in { inherit (ourPackages) @@ -29,16 +29,21 @@ # common args for prismlauncher evaluations unwrappedArgs = { inherit (inputs) libnbtplusplus; - inherit (final.darwin.apple_sdk.frameworks) Cocoa; + inherit ((final.darwin or prev.darwin).apple_sdk.frameworks) Cocoa; inherit self version; }; in { prismlauncher-qt5-unwrapped = prev.libsForQt5.callPackage ./pkg unwrappedArgs; + prismlauncher-qt5 = prev.libsForQt5.callPackage ./pkg/wrapper.nix { prismlauncher-unwrapped = final.prismlauncher-qt5-unwrapped; }; + prismlauncher-unwrapped = prev.qt6Packages.callPackage ./pkg unwrappedArgs; - prismlauncher = prev.qt6Packages.callPackage ./pkg/wrapper.nix {inherit (final) prismlauncher-unwrapped;}; + + prismlauncher = prev.qt6Packages.callPackage ./pkg/wrapper.nix { + inherit (final) prismlauncher-unwrapped; + }; }; }; } From 6aa821df9c5cb2cd79e03ddad043ab49acfdd5a3 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 9 Sep 2023 14:34:38 -0400 Subject: [PATCH 346/398] refactor(nix): match inputs value in flake Signed-off-by: seth --- flake.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index d45282aa6..a58d66fb9 100644 --- a/flake.nix +++ b/flake.nix @@ -20,12 +20,14 @@ }; }; - outputs = inputs: - inputs.flake-parts.lib.mkFlake - {inherit inputs;} - { + outputs = { + flake-parts, + pre-commit-hooks, + ... + } @ inputs: + flake-parts.lib.mkFlake {inherit inputs;} { imports = [ - inputs.pre-commit-hooks.flakeModule + pre-commit-hooks.flakeModule ./nix/dev.nix ./nix/distribution.nix From 10192c540b85999c9a5cd075d695d1a4298ff9e5 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 9 Sep 2023 15:10:15 -0400 Subject: [PATCH 347/398] feat(nix): add source filtering this - along with garnix - should mostly eliminate unneeded (re)builds Signed-off-by: seth --- flake.lock | 16 ++++++++++++++++ flake.nix | 1 + nix/distribution.nix | 18 +++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index b1486ea69..df6039cf4 100644 --- a/flake.lock +++ b/flake.lock @@ -89,6 +89,21 @@ "type": "github" } }, + "nix-filter": { + "locked": { + "lastModified": 1693833173, + "narHash": "sha256-hlMABKrGbEiJD5dwUSfnw1CQ3bG7KKwDV+Nx3bEZd7U=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "ac030bd9ba98e318e1f4c4328d60766ade8ebe8b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1693626178, @@ -156,6 +171,7 @@ "flake-compat": "flake-compat", "flake-parts": "flake-parts", "libnbtplusplus": "libnbtplusplus", + "nix-filter": "nix-filter", "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks" } diff --git a/flake.nix b/flake.nix index a58d66fb9..afb0ec63a 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,7 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-parts.url = "github:hercules-ci/flake-parts"; + nix-filter.url = "github:numtide/nix-filter"; pre-commit-hooks = { url = "github:cachix/pre-commit-hooks.nix"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/nix/distribution.nix b/nix/distribution.nix index c8fa01c59..ca9999dcb 100644 --- a/nix/distribution.nix +++ b/nix/distribution.nix @@ -26,11 +26,27 @@ overlays.default = final: prev: let version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; + filteredSelf = inputs.nix-filter.lib.filter { + root = ../.; + include = [ + "buildconfig" + "cmake" + "launcher" + "libraries" + "program_info" + "tests" + ../COPYING.md + ../CMakeLists.txt + ]; + }; + # common args for prismlauncher evaluations unwrappedArgs = { + self = filteredSelf; + inherit (inputs) libnbtplusplus; inherit ((final.darwin or prev.darwin).apple_sdk.frameworks) Cocoa; - inherit self version; + inherit version; }; in { prismlauncher-qt5-unwrapped = prev.libsForQt5.callPackage ./pkg unwrappedArgs; From 82a0a5bca12851afb276851569af8716e85e66c1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 10 Sep 2023 00:17:57 +0000 Subject: [PATCH 348/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/bfb7dfec93f3b5d7274db109f2990bc889861caf' (2023-09-02) → 'github:nixos/nixpkgs/b200e0df08f80c32974a6108ce431d8a8a5e6547' (2023-09-07) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index b1486ea69..9290736b3 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693626178, - "narHash": "sha256-Rpiy6lIOu4zny8tfGuIeN1ji9eSz9nPmm9yBhh/4IOM=", + "lastModified": 1694062546, + "narHash": "sha256-PiGI4f2BGnZcedP6slLjCLGLRLXPa9+ogGGgVPfGxys=", "owner": "nixos", "repo": "nixpkgs", - "rev": "bfb7dfec93f3b5d7274db109f2990bc889861caf", + "rev": "b200e0df08f80c32974a6108ce431d8a8a5e6547", "type": "github" }, "original": { From 47d1f23568a6ea72d16b95ea6481996c64e0a9fe Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 10 Sep 2023 16:22:57 +0300 Subject: [PATCH 349/398] added side for modrinth mods Signed-off-by: Trial97 --- launcher/minecraft/mod/MetadataHandler.h | 1 + launcher/modplatform/ModIndex.h | 2 +- .../modrinth/ModrinthPackExportTask.cpp | 25 ++++++++++++---- .../modrinth/ModrinthPackExportTask.h | 1 + .../modrinth/ModrinthPackIndex.cpp | 16 ++++++++++ launcher/modplatform/packwiz/Packwiz.cpp | 29 +++++++++++++++++-- launcher/modplatform/packwiz/Packwiz.h | 7 +++-- tests/Packwiz_test.cpp | 4 +-- 8 files changed, 73 insertions(+), 12 deletions(-) diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index 88e9ff2b6..3496da2a0 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -31,6 +31,7 @@ class Mod; class Metadata { public: using ModStruct = Packwiz::V1::Mod; + using ModSide = Packwiz::V1::Side; static auto create(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> ModStruct { diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index cad217034..7036241db 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -104,6 +104,7 @@ struct IndexedPack { QString logoName; QString logoUrl; QString websiteUrl; + QString side; bool versionsLoaded = false; QVector versions; @@ -128,7 +129,6 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; -QString getMetaURL(ResourceProvider provider, QVariant projectID); struct OverrideDep { QString quilt; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index ad8fefac1..72f0bd6c4 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -25,6 +25,7 @@ #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/MetadataHandler.h" #include "minecraft/mod/ModFolderModel.h" const QStringList ModrinthPackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); @@ -127,7 +128,8 @@ void ModrinthPackExportTask::collectHashes() QCryptographicHash sha1(QCryptographicHash::Algorithm::Sha1); sha1.addData(data); - ResolvedFile resolvedFile{ sha1.result().toHex(), sha512.result().toHex(), url.toEncoded(), openFile.size() }; + ResolvedFile resolvedFile{ sha1.result().toHex(), sha512.result().toHex(), url.toEncoded(), openFile.size(), + mod->metadata()->side }; resolvedFiles[relative] = resolvedFile; // nice! we've managed to resolve based on local metadata! @@ -272,18 +274,31 @@ QByteArray ModrinthPackExportTask::generateIndex() // detect disabled mod const QFileInfo pathInfo(path); + + QJsonObject env; if (pathInfo.suffix() == "disabled") { // rename it path = pathInfo.dir().filePath(pathInfo.completeBaseName()); - // ...and make it optional - QJsonObject env; env["client"] = "optional"; env["server"] = "optional"; - fileOut["env"] = env; + } else { + env["client"] = "required"; + env["server"] = "required"; } + switch (iterator->side) { + case Metadata::ModSide::ClientSide: + env["server"] = "unsupported"; + break; + case Metadata::ModSide::ServerSide: + env["client"] = "unsupported"; + break; + case Metadata::ModSide::UniversalSide: + break; + } + fileOut["env"] = env; fileOut["path"] = path; - fileOut["downloads"] = QJsonArray{ iterator.value().url }; + fileOut["downloads"] = QJsonArray{ iterator->url }; QJsonObject hashes; hashes["sha1"] = value.sha1; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 1f9e0eb77..388b733e5 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -43,6 +43,7 @@ class ModrinthPackExportTask : public Task { struct ResolvedFile { QString sha1, sha512, url; qint64 size; + Metadata::ModSide side; }; static const QStringList PREFIXES; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 85e66a91e..9cc59ac39 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -27,6 +27,11 @@ static ModrinthAPI api; static ModPlatform::ProviderCapabilities ProviderCaps; +bool shouldDownloadOnSide(QString side) +{ + return side == "required" || side == "optional"; +} + // https://docs.modrinth.com/api-spec/#tag/projects/operation/getProject void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) { @@ -53,6 +58,17 @@ void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj) modAuthor.url = api.getAuthorURL(modAuthor.name); pack.authors.append(modAuthor); + auto client = shouldDownloadOnSide(Json::ensureString(obj, "client_side")); + auto server = shouldDownloadOnSide(Json::ensureString(obj, "server_side")); + + if (server && client) { + pack.side = "both"; + } else if (server) { + pack.side = "server"; + } else if (client) { + pack.side = "client"; + } + // Modrinth can have more data than what's provided by the basic search :) pack.extraDataLoaded = false; } diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 1757da3e0..e35567f24 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -113,6 +113,7 @@ auto V1::createModFormat([[maybe_unused]] QDir& index_dir, ModPlatform::IndexedP mod.provider = mod_pack.provider; mod.file_id = mod_version.fileId; mod.project_id = mod_pack.addonId; + mod.side = stringToSide(mod_pack.side); return mod; } @@ -190,7 +191,7 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod) { auto tbl = toml::table{ { "name", mod.name.toStdString() }, { "filename", mod.filename.toStdString() }, - { "side", mod.side.toStdString() }, + { "side", sideToString(mod.side).toStdString() }, { "download", toml::table{ { "mode", mod.mode.toStdString() }, @@ -274,7 +275,7 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod { // Basic info mod.name = stringEntry(table, "name"); mod.filename = stringEntry(table, "filename"); - mod.side = stringEntry(table, "side"); + mod.side = stringToSide(stringEntry(table, "side")); } { // [download] info @@ -329,4 +330,28 @@ auto V1::getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod return {}; } +auto V1::sideToString(Side side) -> QString +{ + switch (side) { + case Side::ClientSide: + return "client"; + case Side::ServerSide: + return "server"; + case Side::UniversalSide: + return "both"; + } + return {}; +} + +auto V1::stringToSide(QString side) -> Side +{ + if (side == "client") + return Side::ClientSide; + if (side == "server") + return Side::ServerSide; + if (side == "both") + return Side::UniversalSide; + return Side::UniversalSide; +} + } // namespace Packwiz diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 7edc18cde..dce198b0e 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -35,12 +35,12 @@ auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool shoul class V1 { public: + enum class Side { ClientSide = 1 << 0, ServerSide = 1 << 1, UniversalSide = ClientSide | ServerSide }; struct Mod { QString slug{}; QString name{}; QString filename{}; - // FIXME: make side an enum - QString side{ "both" }; + Side side{ Side::UniversalSide }; // [download] QString mode{}; @@ -93,6 +93,9 @@ class V1 { * If the mod doesn't have a metadata, it simply returns an empty Mod object. * */ static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod; + + static auto sideToString(Side side) -> QString; + static auto stringToSide(QString side) -> Side; }; } // namespace Packwiz diff --git a/tests/Packwiz_test.cpp b/tests/Packwiz_test.cpp index d1b274d12..e4abda9f9 100644 --- a/tests/Packwiz_test.cpp +++ b/tests/Packwiz_test.cpp @@ -42,7 +42,7 @@ class PackwizTest : public QObject { QCOMPARE(metadata.name, "Borderless Mining"); QCOMPARE(metadata.filename, "borderless-mining-1.1.1+1.18.jar"); - QCOMPARE(metadata.side, "client"); + QCOMPARE(metadata.side, Packwiz::V1::Side::ClientSide); QCOMPARE(metadata.url, QUrl("https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar")); QCOMPARE(metadata.hash_format, "sha512"); @@ -72,7 +72,7 @@ class PackwizTest : public QObject { QCOMPARE(metadata.name, "Screenshot to Clipboard (Fabric)"); QCOMPARE(metadata.filename, "screenshot-to-clipboard-1.0.7-fabric.jar"); - QCOMPARE(metadata.side, "both"); + QCOMPARE(metadata.side, Packwiz::V1::Side::UniversalSide); QCOMPARE(metadata.url, QUrl("https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar")); QCOMPARE(metadata.hash_format, "murmur2"); From 9afe80b0e00d9520abe4d91a3075b019e85c80d7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 17 Sep 2023 00:18:04 +0000 Subject: [PATCH 350/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/b200e0df08f80c32974a6108ce431d8a8a5e6547' (2023-09-07) → 'github:nixos/nixpkgs/46688f8eb5cd6f1298d873d4d2b9cf245e09e88e' (2023-09-15) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa' (2023-08-17) → 'github:cachix/pre-commit-hooks.nix/4f883a76282bc28eb952570afc3d8a1bf6f481d7' (2023-09-10) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 9290736b3..6fbcf0526 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694062546, - "narHash": "sha256-PiGI4f2BGnZcedP6slLjCLGLRLXPa9+ogGGgVPfGxys=", + "lastModified": 1694760568, + "narHash": "sha256-3G07BiXrp2YQKxdcdms22MUx6spc6A++MSePtatCYuI=", "owner": "nixos", "repo": "nixpkgs", - "rev": "b200e0df08f80c32974a6108ce431d8a8a5e6547", + "rev": "46688f8eb5cd6f1298d873d4d2b9cf245e09e88e", "type": "github" }, "original": { @@ -138,11 +138,11 @@ ] }, "locked": { - "lastModified": 1692274144, - "narHash": "sha256-BxTQuRUANQ81u8DJznQyPmRsg63t4Yc+0kcyq6OLz8s=", + "lastModified": 1694364351, + "narHash": "sha256-oadhSCqopYXxURwIA6/Anpe5IAG11q2LhvTJNP5zE6o=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa", + "rev": "4f883a76282bc28eb952570afc3d8a1bf6f481d7", "type": "github" }, "original": { From a49851cb40a0156edf6011b7318c632fa7483612 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 19 Sep 2023 15:48:12 +0300 Subject: [PATCH 351/398] updated blocked mods with empty hash Signed-off-by: Trial97 --- launcher/ui/dialogs/BlockedModsDialog.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index f105b4b5f..790d545b6 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -334,6 +334,13 @@ bool BlockedModsDialog::checkValidPath(QString path) for (auto& mod : m_mods) { if (compare(filename, mod.name)) { + // if the mod is not yet matched and doesn't have a hash then + // just match it with the file that has the exact same name + if (!mod.matched && mod.hash.isEmpty()) { + mod.matched = true; + mod.localPath = path; + return false; + } qDebug() << "[Blocked Mods Dialog] Name match found:" << mod.name << "| From path:" << path; return true; } From 97ced1f459664949943b3f0ef424ea792be1c716 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 19 Sep 2023 13:45:12 -0400 Subject: [PATCH 352/398] fix(nix): include libusb1 as a runtime dependency Signed-off-by: seth --- nix/pkg/wrapper.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix index 8d160143d..8bc255e71 100644 --- a/nix/pkg/wrapper.nix +++ b/nix/pkg/wrapper.nix @@ -18,9 +18,11 @@ flite, mesa-demos, udev, + libusb1, msaClientID ? null, gamemodeSupport ? stdenv.isLinux, textToSpeechSupport ? stdenv.isLinux, + controllerSupport ? stdenv.isLinux, jdks ? [jdk17 jdk8], additionalLibs ? [], additionalPrograms ? [], @@ -71,6 +73,7 @@ in ] ++ lib.optional gamemodeSupport gamemode.lib ++ lib.optional textToSpeechSupport flite + ++ lib.optional controllerSupport libusb1 ++ additionalLibs; runtimePrograms = From 97da8892b9fcb285f7023a671090b4a3becdf2d8 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 19 Sep 2023 13:45:52 -0400 Subject: [PATCH 353/398] chore(nix): add meta.mainProgram attribute Signed-off-by: seth --- nix/pkg/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/pkg/default.nix b/nix/pkg/default.nix index 074214c4b..fd19a0b3d 100644 --- a/nix/pkg/default.nix +++ b/nix/pkg/default.nix @@ -58,6 +58,7 @@ assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is on dontWrapQtApps = true; meta = with lib; { + mainProgram = "prismlauncher"; homepage = "https://prismlauncher.org/"; description = "A free, open source launcher for Minecraft"; longDescription = '' From 81a3ba18bc9740d543fe9aa569f74f37ec46c2cc Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Wed, 20 Sep 2023 18:45:23 +0300 Subject: [PATCH 354/398] Update launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 874391735..bd1fe9401 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -256,7 +256,7 @@ QHash GetModDependenciesTask::getRequiredBy() { QHash rby; auto fullList = m_selected + m_pack_dependencies; - for (auto mod : fullList) { + for (auto& mod : fullList) { auto addonId = mod->pack->addonId; auto provider = mod->pack->provider; auto version = mod->version.fileId; From f3c089792a5342eeff93f032dca134fe371db4b3 Mon Sep 17 00:00:00 2001 From: bolli24 <4827765-bolli24@users.noreply.gitlab.com> Date: Fri, 22 Sep 2023 21:10:27 +0200 Subject: [PATCH 355/398] Skip folders when updating mods. Previously the mod updater would fail, reporting "The mod updater was aborted!", when trying to update a folder. Signed-off-by: bolli24 <4827765-bolli24@users.noreply.gitlab.com> --- launcher/ui/dialogs/ModUpdateDialog.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 1f0fa7cd2..cd115bd3b 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -236,6 +236,11 @@ auto ModUpdateDialog::ensureMetadata() -> bool if (skip_rest) continue; + if (candidate->type() == ResourceType::FOLDER) { + m_failed_metadata.append({ candidate, tr("This is a folder.") }); + continue; + } + if (confirm_rest) { addToTmp(candidate, provider_rest); should_try_others.insert(candidate->internal_id(), try_others_rest); From fa65ac3ff71c27a17c5e1a6b1d75842b1c6e62ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 24 Sep 2023 00:18:03 +0000 Subject: [PATCH 356/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nix-filter': 'github:numtide/nix-filter/ac030bd9ba98e318e1f4c4328d60766ade8ebe8b' (2023-09-04) → 'github:numtide/nix-filter/41fd48e00c22b4ced525af521ead8792402de0ea' (2023-09-16) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/46688f8eb5cd6f1298d873d4d2b9cf245e09e88e' (2023-09-15) → 'github:nixos/nixpkgs/e12483116b3b51a185a33a272bf351e357ba9a99' (2023-09-21) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 8096fcebc..f96336551 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nix-filter": { "locked": { - "lastModified": 1693833173, - "narHash": "sha256-hlMABKrGbEiJD5dwUSfnw1CQ3bG7KKwDV+Nx3bEZd7U=", + "lastModified": 1694857738, + "narHash": "sha256-bxxNyLHjhu0N8T3REINXQ2ZkJco0ABFPn6PIe2QUfqo=", "owner": "numtide", "repo": "nix-filter", - "rev": "ac030bd9ba98e318e1f4c4328d60766ade8ebe8b", + "rev": "41fd48e00c22b4ced525af521ead8792402de0ea", "type": "github" }, "original": { @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694760568, - "narHash": "sha256-3G07BiXrp2YQKxdcdms22MUx6spc6A++MSePtatCYuI=", + "lastModified": 1695318763, + "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "46688f8eb5cd6f1298d873d4d2b9cf245e09e88e", + "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", "type": "github" }, "original": { From 14af7044be6bead9f29e3481d9c8760d738f317b Mon Sep 17 00:00:00 2001 From: bolli24 <9805065+bolli24@users.noreply.github.com> Date: Sun, 24 Sep 2023 03:01:47 +0200 Subject: [PATCH 357/398] Update launcher/ui/dialogs/ModUpdateDialog.cpp Co-authored-by: TheKodeToad Signed-off-by: bolli24 <9805065+bolli24@users.noreply.github.com> --- launcher/ui/dialogs/ModUpdateDialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index cd115bd3b..04173c88a 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -237,7 +237,6 @@ auto ModUpdateDialog::ensureMetadata() -> bool continue; if (candidate->type() == ResourceType::FOLDER) { - m_failed_metadata.append({ candidate, tr("This is a folder.") }); continue; } From 1684cff7acde56aba7c8db232a918d96e220be29 Mon Sep 17 00:00:00 2001 From: alexia Date: Mon, 25 Sep 2023 15:46:22 +0200 Subject: [PATCH 358/398] Update links to Minecraft Wiki Minecraft Wiki has officially moved from Fandom to their own wiki. I updated some links I found in comments. Signed-off-by: alexia --- launcher/minecraft/MinecraftInstance.cpp | 2 +- launcher/minecraft/mod/DataPack.cpp | 2 +- launcher/minecraft/mod/DataPack.h | 2 +- launcher/minecraft/mod/ResourcePack.cpp | 2 +- launcher/minecraft/mod/ResourcePack.h | 2 +- launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp | 2 +- launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp | 2 +- launcher/ui/widgets/InfoFrame.cpp | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 0e64c46d4..86ef3b30e 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -311,7 +311,7 @@ QString MinecraftInstance::getLocalLibraryPath() const bool MinecraftInstance::supportsDemo() const { Version instance_ver{ getPackProfile()->getComponentVersion("net.minecraft") }; - // Demo mode was introduced in 1.3.1: https://minecraft.fandom.com/wiki/Demo_mode#History + // Demo mode was introduced in 1.3.1: https://minecraft.wiki/w/Demo_mode#History // FIXME: Due to Version constraints atm, this can't handle well non-release versions return instance_ver >= Version("1.3.1"); } diff --git a/launcher/minecraft/mod/DataPack.cpp b/launcher/minecraft/mod/DataPack.cpp index 7bf5a3112..fc2d3f68b 100644 --- a/launcher/minecraft/mod/DataPack.cpp +++ b/launcher/minecraft/mod/DataPack.cpp @@ -28,7 +28,7 @@ #include "Version.h" // Values taken from: -// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_data_pack#%22pack_format%22 +// https://minecraft.wiki/w/Tutorials/Creating_a_data_pack#%22pack_format%22 static const QMap> s_pack_format_versions = { { 4, { Version("1.13"), Version("1.14.4") } }, { 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } }, { 7, { Version("1.17"), Version("1.17.1") } }, diff --git a/launcher/minecraft/mod/DataPack.h b/launcher/minecraft/mod/DataPack.h index fc2703c7a..b3787b238 100644 --- a/launcher/minecraft/mod/DataPack.h +++ b/launcher/minecraft/mod/DataPack.h @@ -63,7 +63,7 @@ class DataPack : public Resource { mutable QMutex m_data_lock; /* The 'version' of a data pack, as defined in the pack.mcmeta file. - * See https://minecraft.fandom.com/wiki/Data_pack#pack.mcmeta + * See https://minecraft.wiki/w/Data_pack#pack.mcmeta */ int m_pack_format = 0; diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 2bb51dc5b..074534405 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -11,7 +11,7 @@ #include "minecraft/mod/tasks/LocalResourcePackParseTask.h" // Values taken from: -// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta +// https://minecraft.wiki/w/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta static const QMap> s_pack_format_versions = { { 1, { Version("1.6.1"), Version("1.8.9") } }, { 2, { Version("1.9"), Version("1.10.2") } }, { 3, { Version("1.11"), Version("1.12.2") } }, { 4, { Version("1.13"), Version("1.14.4") } }, diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h index da354bc1c..c06f3793d 100644 --- a/launcher/minecraft/mod/ResourcePack.h +++ b/launcher/minecraft/mod/ResourcePack.h @@ -51,7 +51,7 @@ class ResourcePack : public Resource { mutable QMutex m_data_lock; /* The 'version' of a resource pack, as defined in the pack.mcmeta file. - * See https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta + * See https://minecraft.wiki/w/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta */ int m_pack_format = 0; diff --git a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp index 5bb448778..82f6b9df9 100644 --- a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp @@ -133,7 +133,7 @@ bool processZIP(DataPack& pack, ProcessingLevel level) return true; } -// https://minecraft.fandom.com/wiki/Data_pack#pack.mcmeta +// https://minecraft.wiki/w/Data_pack#pack.mcmeta bool processMCMeta(DataPack& pack, QByteArray&& raw_data) { try { diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp index 73cbf891c..7b9f4f594 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp @@ -178,7 +178,7 @@ bool processZIP(ResourcePack& pack, ProcessingLevel level) return true; } -// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta +// https://minecraft.wiki/w/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data) { try { diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 1f03f9eaf..69f72fea2 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -158,12 +158,12 @@ QString InfoFrame::renderColorCodes(QString input) // // TODO: Wrap links inside tags - // https://minecraft.fandom.com/wiki/Formatting_codes#Color_codes + // https://minecraft.wiki/w/Formatting_codes#Color_codes const QMap color_codes_map = { { '0', "#000000" }, { '1', "#0000AA" }, { '2', "#00AA00" }, { '3', "#00AAAA" }, { '4', "#AA0000" }, { '5', "#AA00AA" }, { '6', "#FFAA00" }, { '7', "#AAAAAA" }, { '8', "#555555" }, { '9', "#5555FF" }, { 'a', "#55FF55" }, { 'b', "#55FFFF" }, { 'c', "#FF5555" }, { 'd', "#FF55FF" }, { 'e', "#FFFF55" }, { 'f', "#FFFFFF" } }; - // https://minecraft.fandom.com/wiki/Formatting_codes#Formatting_codes + // https://minecraft.wiki/w/Formatting_codes#Formatting_codes const QMap formatting_codes_map = { { 'l', "b" }, { 'm', "s" }, { 'n', "u" }, { 'o', "i" } }; QString html(""); From 7c636d46080443357d10471b00406c549687ee11 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 25 Sep 2023 17:44:04 +0300 Subject: [PATCH 359/398] Removed mojang Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 13 - launcher/minecraft/MinecraftInstance.cpp | 3 - launcher/minecraft/auth/AccountData.cpp | 121 +------ launcher/minecraft/auth/AccountData.h | 14 +- launcher/minecraft/auth/AccountList.cpp | 50 +-- launcher/minecraft/auth/AccountList.h | 2 - launcher/minecraft/auth/AuthSession.h | 4 - launcher/minecraft/auth/MinecraftAccount.cpp | 40 +- launcher/minecraft/auth/MinecraftAccount.h | 19 - launcher/minecraft/auth/Yggdrasil.cpp | 342 ------------------ launcher/minecraft/auth/Yggdrasil.h | 92 ----- launcher/minecraft/auth/flows/AuthFlow.h | 1 - launcher/minecraft/auth/flows/Mojang.cpp | 22 -- launcher/minecraft/auth/flows/Mojang.h | 17 - .../auth/steps/MigrationEligibilityStep.cpp | 45 --- .../auth/steps/MigrationEligibilityStep.h | 21 -- .../auth/steps/MinecraftProfileStep.cpp | 9 - .../auth/steps/MinecraftProfileStepMojang.cpp | 87 ----- .../auth/steps/MinecraftProfileStepMojang.h | 21 -- .../minecraft/auth/steps/YggdrasilStep.cpp | 57 --- launcher/minecraft/auth/steps/YggdrasilStep.h | 28 -- launcher/ui/dialogs/LoginDialog.cpp | 115 ------ launcher/ui/dialogs/LoginDialog.h | 56 --- launcher/ui/dialogs/LoginDialog.ui | 77 ---- launcher/ui/pages/global/AccountListPage.cpp | 18 +- launcher/ui/pages/global/AccountListPage.h | 1 - launcher/ui/pages/global/AccountListPage.ui | 6 - 27 files changed, 5 insertions(+), 1276 deletions(-) delete mode 100644 launcher/minecraft/auth/Yggdrasil.cpp delete mode 100644 launcher/minecraft/auth/Yggdrasil.h delete mode 100644 launcher/minecraft/auth/flows/Mojang.cpp delete mode 100644 launcher/minecraft/auth/flows/Mojang.h delete mode 100644 launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp delete mode 100644 launcher/minecraft/auth/steps/MigrationEligibilityStep.h delete mode 100644 launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp delete mode 100644 launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h delete mode 100644 launcher/minecraft/auth/steps/YggdrasilStep.cpp delete mode 100644 launcher/minecraft/auth/steps/YggdrasilStep.h delete mode 100644 launcher/ui/dialogs/LoginDialog.cpp delete mode 100644 launcher/ui/dialogs/LoginDialog.h delete mode 100644 launcher/ui/dialogs/LoginDialog.ui diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 18e0acab1..de750afde 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -216,13 +216,9 @@ set(MINECRAFT_SOURCES minecraft/auth/MinecraftAccount.h minecraft/auth/Parsers.cpp minecraft/auth/Parsers.h - minecraft/auth/Yggdrasil.cpp - minecraft/auth/Yggdrasil.h minecraft/auth/flows/AuthFlow.cpp minecraft/auth/flows/AuthFlow.h - minecraft/auth/flows/Mojang.cpp - minecraft/auth/flows/Mojang.h minecraft/auth/flows/MSA.cpp minecraft/auth/flows/MSA.h minecraft/auth/flows/Offline.cpp @@ -236,12 +232,8 @@ set(MINECRAFT_SOURCES minecraft/auth/steps/GetSkinStep.h minecraft/auth/steps/LauncherLoginStep.cpp minecraft/auth/steps/LauncherLoginStep.h - minecraft/auth/steps/MigrationEligibilityStep.cpp - minecraft/auth/steps/MigrationEligibilityStep.h minecraft/auth/steps/MinecraftProfileStep.cpp minecraft/auth/steps/MinecraftProfileStep.h - minecraft/auth/steps/MinecraftProfileStepMojang.cpp - minecraft/auth/steps/MinecraftProfileStepMojang.h minecraft/auth/steps/MSAStep.cpp minecraft/auth/steps/MSAStep.h minecraft/auth/steps/XboxAuthorizationStep.cpp @@ -250,8 +242,6 @@ set(MINECRAFT_SOURCES minecraft/auth/steps/XboxProfileStep.h minecraft/auth/steps/XboxUserStep.cpp minecraft/auth/steps/XboxUserStep.h - minecraft/auth/steps/YggdrasilStep.cpp - minecraft/auth/steps/YggdrasilStep.h minecraft/gameoptions/GameOptions.h minecraft/gameoptions/GameOptions.cpp @@ -944,8 +934,6 @@ SET(LAUNCHER_SOURCES ui/dialogs/IconPickerDialog.h ui/dialogs/ImportResourceDialog.cpp ui/dialogs/ImportResourceDialog.h - ui/dialogs/LoginDialog.cpp - ui/dialogs/LoginDialog.h ui/dialogs/MSALoginDialog.cpp ui/dialogs/MSALoginDialog.h ui/dialogs/OfflineLoginDialog.cpp @@ -1104,7 +1092,6 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/MSALoginDialog.ui ui/dialogs/OfflineLoginDialog.ui ui/dialogs/AboutDialog.ui - ui/dialogs/LoginDialog.ui ui/dialogs/EditAccountDialog.ui ui/dialogs/ReviewMessageBox.ui ui/dialogs/ScrollMessageBox.ui diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 0e64c46d4..57bbcd404 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -856,9 +856,6 @@ QMap MinecraftInstance::createCensorFilterFromSession(AuthSess if (sessionRef.access_token != "0") { addToFilter(sessionRef.access_token, tr("")); } - if (sessionRef.client_token.size()) { - addToFilter(sessionRef.client_token, tr("")); - } addToFilter(sessionRef.uuid, tr("")); return filter; diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp index 474bf7c6e..e1f1e9b1e 100644 --- a/launcher/minecraft/auth/AccountData.cpp +++ b/launcher/minecraft/auth/AccountData.cpp @@ -278,67 +278,6 @@ bool entitlementFromJSONV3(const QJsonObject& parent, MinecraftEntitlement& out) } // namespace -bool AccountData::resumeStateFromV2(QJsonObject data) -{ - // The JSON object must at least have a username for it to be valid. - if (!data.value("username").isString()) { - qCritical() << "Can't load Mojang account info from JSON object. Username field is missing or of the wrong type."; - return false; - } - - QString userName = data.value("username").toString(""); - QString clientToken = data.value("clientToken").toString(""); - QString accessToken = data.value("accessToken").toString(""); - - QJsonArray profileArray = data.value("profiles").toArray(); - if (profileArray.size() < 1) { - qCritical() << "Can't load Mojang account with username \"" << userName << "\". No profiles found."; - return false; - } - - struct AccountProfile { - QString id; - QString name; - bool legacy; - }; - - QList profiles; - int currentProfileIndex = 0; - int index = -1; - QString currentProfile = data.value("activeProfile").toString(""); - for (QJsonValue profileVal : profileArray) { - index++; - QJsonObject profileObject = profileVal.toObject(); - QString id = profileObject.value("id").toString(""); - QString name = profileObject.value("name").toString(""); - bool legacy_ = profileObject.value("legacy").toBool(false); - if (id.isEmpty() || name.isEmpty()) { - qWarning() << "Unable to load a profile" << name << "because it was missing an ID or a name."; - continue; - } - if (id == currentProfile) { - currentProfileIndex = index; - } - profiles.append({ id, name, legacy_ }); - } - auto& profile = profiles[currentProfileIndex]; - - type = AccountType::Mojang; - legacy = profile.legacy; - - minecraftProfile.id = profile.id; - minecraftProfile.name = profile.name; - minecraftProfile.validity = Katabasis::Validity::Assumed; - - yggdrasilToken.token = accessToken; - yggdrasilToken.extra["clientToken"] = clientToken; - yggdrasilToken.extra["userName"] = userName; - yggdrasilToken.validity = Katabasis::Validity::Assumed; - - validity_ = minecraftProfile.validity; - return true; -} - bool AccountData::resumeStateFromV3(QJsonObject data) { auto typeV = data.value("type"); @@ -349,8 +288,6 @@ bool AccountData::resumeStateFromV3(QJsonObject data) auto typeS = typeV.toString(); if (typeS == "MSA") { type = AccountType::MSA; - } else if (typeS == "Mojang") { - type = AccountType::Mojang; } else if (typeS == "Offline") { type = AccountType::Offline; } else { @@ -358,11 +295,6 @@ bool AccountData::resumeStateFromV3(QJsonObject data) return false; } - if (type == AccountType::Mojang) { - legacy = data.value("legacy").toBool(false); - canMigrateToMSA = data.value("canMigrateToMSA").toBool(false); - } - if (type == AccountType::MSA) { auto clientIDV = data.value("msa-client-id"); if (clientIDV.isString()) { @@ -395,15 +327,7 @@ bool AccountData::resumeStateFromV3(QJsonObject data) QJsonObject AccountData::saveState() const { QJsonObject output; - if (type == AccountType::Mojang) { - output["type"] = "Mojang"; - if (legacy) { - output["legacy"] = true; - } - if (canMigrateToMSA) { - output["canMigrateToMSA"] = true; - } - } else if (type == AccountType::MSA) { + if (type == AccountType::MSA) { output["type"] = "MSA"; output["msa-client-id"] = msaClientID; tokenToJSONV3(output, msaToken, "msa"); @@ -420,51 +344,11 @@ QJsonObject AccountData::saveState() const return output; } -QString AccountData::userName() const -{ - if (type == AccountType::MSA) { - return QString(); - } - return yggdrasilToken.extra["userName"].toString(); -} - QString AccountData::accessToken() const { return yggdrasilToken.token; } -QString AccountData::clientToken() const -{ - if (type != AccountType::Mojang) { - return QString(); - } - return yggdrasilToken.extra["clientToken"].toString(); -} - -void AccountData::setClientToken(QString clientToken) -{ - if (type != AccountType::Mojang) { - return; - } - yggdrasilToken.extra["clientToken"] = clientToken; -} - -void AccountData::generateClientTokenIfMissing() -{ - if (yggdrasilToken.extra.contains("clientToken")) { - return; - } - invalidateClientToken(); -} - -void AccountData::invalidateClientToken() -{ - if (type != AccountType::Mojang) { - return; - } - yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{-}]")); -} - QString AccountData::profileId() const { return minecraftProfile.id; @@ -482,9 +366,6 @@ QString AccountData::profileName() const QString AccountData::accountDisplayString() const { switch (type) { - case AccountType::Mojang: { - return userName(); - } case AccountType::Offline: { return QObject::tr(""); } diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h index 9b626c34e..bac77e17f 100644 --- a/launcher/minecraft/auth/AccountData.h +++ b/launcher/minecraft/auth/AccountData.h @@ -71,27 +71,17 @@ struct MinecraftProfile { Katabasis::Validity validity = Katabasis::Validity::None; }; -enum class AccountType { MSA, Mojang, Offline }; +enum class AccountType { MSA, Offline }; enum class AccountState { Unchecked, Offline, Working, Online, Disabled, Errored, Expired, Gone }; struct AccountData { QJsonObject saveState() const; - bool resumeStateFromV2(QJsonObject data); bool resumeStateFromV3(QJsonObject data); //! userName for Mojang accounts, gamertag for MSA QString accountDisplayString() const; - //! Only valid for Mojang accounts. MSA does not preserve this information - QString userName() const; - - //! Only valid for Mojang accounts. - QString clientToken() const; - void setClientToken(QString clientToken); - void invalidateClientToken(); - void generateClientTokenIfMissing(); - //! Yggdrasil access token, as passed to the game. QString accessToken() const; @@ -101,8 +91,6 @@ struct AccountData { QString lastError() const; AccountType type = AccountType::MSA; - bool legacy = false; - bool canMigrateToMSA = false; QString msaClientID; Katabasis::Token msaToken; diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 84dbd8416..a29de4ecf 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -54,7 +54,7 @@ #include -enum AccountListVersion { MojangOnly = 2, MojangMSA = 3 }; +enum AccountListVersion { MojangMSA = 3 }; AccountList::AccountList(QObject* parent) : QAbstractListModel(parent) { @@ -320,17 +320,6 @@ QVariant AccountList::data(const QModelIndex& index, int role) const } } - case MigrationColumn: { - if (account->isMSA() || account->isOffline()) { - return tr("N/A", "Can Migrate"); - } - if (account->canMigrate()) { - return tr("Yes", "Can Migrate"); - } else { - return tr("No", "Can Migrate"); - } - } - default: return QVariant(); } @@ -366,8 +355,6 @@ QVariant AccountList::headerData(int section, [[maybe_unused]] Qt::Orientation o return tr("Type"); case StatusColumn: return tr("Status"); - case MigrationColumn: - return tr("Can Migrate?"); default: return QVariant(); } @@ -382,8 +369,6 @@ QVariant AccountList::headerData(int section, [[maybe_unused]] Qt::Orientation o return tr("Type of the account - Mojang or MSA."); case StatusColumn: return tr("Current status of the account."); - case MigrationColumn: - return tr("Can this account migrate to a Microsoft account?"); default: return QVariant(); } @@ -473,9 +458,6 @@ bool AccountList::loadList() // Make sure the format version matches. auto listVersion = root.value("formatVersion").toVariant().toInt(); switch (listVersion) { - case AccountListVersion::MojangOnly: { - return loadV2(root); - } break; case AccountListVersion::MojangMSA: { return loadV3(root); } break; @@ -489,36 +471,6 @@ bool AccountList::loadList() } } -bool AccountList::loadV2(QJsonObject& root) -{ - beginResetModel(); - auto defaultUserName = root.value("activeAccount").toString(""); - QJsonArray accounts = root.value("accounts").toArray(); - for (QJsonValue accountVal : accounts) { - QJsonObject accountObj = accountVal.toObject(); - MinecraftAccountPtr account = MinecraftAccount::loadFromJsonV2(accountObj); - if (account.get() != nullptr) { - auto profileId = account->profileId(); - if (!profileId.size()) { - continue; - } - if (findAccountByProfileId(profileId) != -1) { - continue; - } - connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged); - connect(account.get(), &MinecraftAccount::activityChanged, this, &AccountList::accountActivityChanged); - m_accounts.append(account); - if (defaultUserName.size() && account->mojangUserName() == defaultUserName) { - m_defaultAccount = account; - } - } else { - qWarning() << "Failed to load an account."; - } - } - endResetModel(); - return true; -} - bool AccountList::loadV3(QJsonObject& root) { beginResetModel(); diff --git a/launcher/minecraft/auth/AccountList.h b/launcher/minecraft/auth/AccountList.h index 6a0b01916..051d8f958 100644 --- a/launcher/minecraft/auth/AccountList.h +++ b/launcher/minecraft/auth/AccountList.h @@ -55,7 +55,6 @@ class AccountList : public QAbstractListModel { // TODO: Add icon column. ProfileNameColumn = 0, NameColumn, - MigrationColumn, TypeColumn, StatusColumn, @@ -97,7 +96,6 @@ class AccountList : public QAbstractListModel { void setListFilePath(QString path, bool autosave = false); bool loadList(); - bool loadV2(QJsonObject& root); bool loadV3(QJsonObject& root); bool saveList(); diff --git a/launcher/minecraft/auth/AuthSession.h b/launcher/minecraft/auth/AuthSession.h index 40519476d..074b2d6e3 100644 --- a/launcher/minecraft/auth/AuthSession.h +++ b/launcher/minecraft/auth/AuthSession.h @@ -24,10 +24,6 @@ struct AuthSession { GoneOrMigrated } status = Undetermined; - // client token - QString client_token; - // account user name - QString username; // combined session ID QString session; // volatile auth token diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 6c2f0805f..545d06aed 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -51,7 +51,6 @@ #include #include "flows/MSA.h" -#include "flows/Mojang.h" #include "flows/Offline.h" MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) @@ -59,15 +58,6 @@ MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) data.internalId = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); } -MinecraftAccountPtr MinecraftAccount::loadFromJsonV2(const QJsonObject& json) -{ - MinecraftAccountPtr account(new MinecraftAccount()); - if (account->data.resumeStateFromV2(json)) { - return account; - } - return nullptr; -} - MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json) { MinecraftAccountPtr account(new MinecraftAccount()); @@ -77,15 +67,6 @@ MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json) return nullptr; } -MinecraftAccountPtr MinecraftAccount::createFromUsername(const QString& username) -{ - auto account = makeShared(); - account->data.type = AccountType::Mojang; - account->data.yggdrasilToken.extra["userName"] = username; - account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); - return account; -} - MinecraftAccountPtr MinecraftAccount::createBlankMSA() { MinecraftAccountPtr account(new MinecraftAccount()); @@ -138,18 +119,6 @@ QPixmap MinecraftAccount::getFace() const return skin.scaled(64, 64, Qt::KeepAspectRatio); } -shared_qobject_ptr MinecraftAccount::login(QString password) -{ - Q_ASSERT(m_currentTask.get() == nullptr); - - m_currentTask.reset(new MojangLogin(&data, password)); - connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); - connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); - connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); }); - emit activityChanged(true); - return m_currentTask; -} - shared_qobject_ptr MinecraftAccount::loginMSA() { Q_ASSERT(m_currentTask.get() == nullptr); @@ -182,10 +151,8 @@ shared_qobject_ptr MinecraftAccount::refresh() if (data.type == AccountType::MSA) { m_currentTask.reset(new MSASilent(&data)); - } else if (data.type == AccountType::Offline) { - m_currentTask.reset(new OfflineRefresh(&data)); } else { - m_currentTask.reset(new MojangRefresh(&data)); + m_currentTask.reset(new OfflineRefresh(&data)); } connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); @@ -296,13 +263,8 @@ void MinecraftAccount::fillSession(AuthSessionPtr session) } } - // the user name. you have to have an user name - // FIXME: not with MSA - session->username = data.userName(); // volatile auth token session->access_token = data.accessToken(); - // the semi-permanent client token - session->client_token = data.clientToken(); // profile name session->player_name = data.profileName(); // profile ID diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h index f04f947fa..910f4a28a 100644 --- a/launcher/minecraft/auth/MinecraftAccount.h +++ b/launcher/minecraft/auth/MinecraftAccount.h @@ -85,13 +85,10 @@ class MinecraftAccount : public QObject, public Usable { //! Default constructor explicit MinecraftAccount(QObject* parent = 0); - static MinecraftAccountPtr createFromUsername(const QString& username); - static MinecraftAccountPtr createBlankMSA(); static MinecraftAccountPtr createOffline(const QString& username); - static MinecraftAccountPtr loadFromJsonV2(const QJsonObject& json); static MinecraftAccountPtr loadFromJsonV3(const QJsonObject& json); static QUuid uuidFromUsername(QString username); @@ -100,12 +97,6 @@ class MinecraftAccount : public QObject, public Usable { QJsonObject saveToJson() const; public: /* manipulation */ - /** - * Attempt to login. Empty password means we use the token. - * If the attempt fails because we already are performing some task, it returns false. - */ - shared_qobject_ptr login(QString password); - shared_qobject_ptr loginMSA(); shared_qobject_ptr loginOffline(); @@ -119,8 +110,6 @@ class MinecraftAccount : public QObject, public Usable { QString accountDisplayString() const { return data.accountDisplayString(); } - QString mojangUserName() const { return data.userName(); } - QString accessToken() const { return data.accessToken(); } QString profileId() const { return data.profileId(); } @@ -129,8 +118,6 @@ class MinecraftAccount : public QObject, public Usable { bool isActive() const; - bool canMigrate() const { return data.canMigrateToMSA; } - bool isMSA() const { return data.type == AccountType::MSA; } bool isOffline() const { return data.type == AccountType::Offline; } @@ -142,12 +129,6 @@ class MinecraftAccount : public QObject, public Usable { QString typeString() const { switch (data.type) { - case AccountType::Mojang: { - if (data.legacy) { - return "legacy"; - } - return "mojang"; - } break; case AccountType::MSA: { return "msa"; } break; diff --git a/launcher/minecraft/auth/Yggdrasil.cpp b/launcher/minecraft/auth/Yggdrasil.cpp deleted file mode 100644 index 97f2a78d4..000000000 --- a/launcher/minecraft/auth/Yggdrasil.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* Copyright 2013-2021 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 "Yggdrasil.h" -#include "AccountData.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "Application.h" - -Yggdrasil::Yggdrasil(AccountData* data, QObject* parent) : AccountTask(data, parent) -{ - changeState(AccountTaskState::STATE_CREATED); -} - -void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) -{ - changeState(AccountTaskState::STATE_WORKING); - - QNetworkRequest netRequest(endpoint); - netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - m_netReply = APPLICATION->network()->post(netRequest, content); - connect(m_netReply, &QNetworkReply::finished, this, &Yggdrasil::processReply); - connect(m_netReply, &QNetworkReply::uploadProgress, this, &Yggdrasil::refreshTimers); - connect(m_netReply, &QNetworkReply::downloadProgress, this, &Yggdrasil::refreshTimers); - connect(m_netReply, &QNetworkReply::sslErrors, this, &Yggdrasil::sslErrors); - timeout_keeper.setSingleShot(true); - timeout_keeper.start(timeout_max); - counter.setSingleShot(false); - counter.start(time_step); - progress(0, timeout_max); - connect(&timeout_keeper, &QTimer::timeout, this, &Yggdrasil::abortByTimeout); - connect(&counter, &QTimer::timeout, this, &Yggdrasil::heartbeat); -} - -void Yggdrasil::executeTask() {} - -void Yggdrasil::refresh() -{ - start(); - /* - * { - * "clientToken": "client identifier" - * "accessToken": "current access token to be refreshed" - * "selectedProfile": // specifying this causes errors - * { - * "id": "profile ID" - * "name": "profile name" - * } - * "requestUser": true/false // request the user structure - * } - */ - QJsonObject req; - req.insert("clientToken", m_data->clientToken()); - req.insert("accessToken", m_data->accessToken()); - /* - { - auto currentProfile = m_account->currentProfile(); - QJsonObject profile; - profile.insert("id", currentProfile->id()); - profile.insert("name", currentProfile->name()); - req.insert("selectedProfile", profile); - } - */ - req.insert("requestUser", false); - QJsonDocument doc(req); - - QUrl reqUrl("https://authserver.mojang.com/refresh"); - QByteArray requestData = doc.toJson(); - - sendRequest(reqUrl, requestData); -} - -void Yggdrasil::login(QString password) -{ - start(); - /* - * { - * "agent": { // optional - * "name": "Minecraft", // So far this is the only encountered value - * "version": 1 // This number might be increased - * // by the vanilla client in the future - * }, - * "username": "mojang account name", // Can be an email address or player name for - * // unmigrated accounts - * "password": "mojang account password", - * "clientToken": "client identifier", // optional - * "requestUser": true/false // request the user structure - * } - */ - QJsonObject req; - - { - QJsonObject agent; - // C++ makes string literals void* for some stupid reason, so we have to tell it - // QString... Thanks Obama. - agent.insert("name", QString("Minecraft")); - agent.insert("version", 1); - req.insert("agent", agent); - } - - req.insert("username", m_data->userName()); - req.insert("password", password); - req.insert("requestUser", false); - - // If we already have a client token, give it to the server. - // Otherwise, let the server give us one. - - m_data->generateClientTokenIfMissing(); - req.insert("clientToken", m_data->clientToken()); - - QJsonDocument doc(req); - - QUrl reqUrl("https://authserver.mojang.com/authenticate"); - QNetworkRequest netRequest(reqUrl); - QByteArray requestData = doc.toJson(); - - sendRequest(reqUrl, requestData); -} - -void Yggdrasil::refreshTimers(qint64, qint64) -{ - timeout_keeper.stop(); - timeout_keeper.start(timeout_max); - progress(count = 0, timeout_max); -} - -void Yggdrasil::heartbeat() -{ - count += time_step; - progress(count, timeout_max); -} - -bool Yggdrasil::abort() -{ - progress(timeout_max, timeout_max); - // TODO: actually use this in a meaningful way - m_aborted = Yggdrasil::BY_USER; - m_netReply->abort(); - return true; -} - -void Yggdrasil::abortByTimeout() -{ - progress(timeout_max, timeout_max); - // TODO: actually use this in a meaningful way - m_aborted = Yggdrasil::BY_TIMEOUT; - m_netReply->abort(); -} - -void Yggdrasil::sslErrors(QList errors) -{ - int i = 1; - for (auto error : errors) { - qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString(); - auto cert = error.certificate(); - qCritical() << "Certificate in question:\n" << cert.toText(); - i++; - } -} - -void Yggdrasil::processResponse(QJsonObject responseData) -{ - // Read the response data. We need to get the client token, access token, and the selected - // profile. - qDebug() << "Processing authentication response."; - - // qDebug() << responseData; - // If we already have a client token, make sure the one the server gave us matches our - // existing one. - QString clientToken = responseData.value("clientToken").toString(""); - if (clientToken.isEmpty()) { - // Fail if the server gave us an empty client token - changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a client token.")); - return; - } - if (m_data->clientToken().isEmpty()) { - m_data->setClientToken(clientToken); - } else if (clientToken != m_data->clientToken()) { - changeState(AccountTaskState::STATE_FAILED_HARD, - tr("Authentication server attempted to change the client token. This isn't supported.")); - return; - } - - // Now, we set the access token. - qDebug() << "Getting access token."; - QString accessToken = responseData.value("accessToken").toString(""); - if (accessToken.isEmpty()) { - // Fail if the server didn't give us an access token. - changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send an access token.")); - return; - } - // Set the access token. - m_data->yggdrasilToken.token = accessToken; - m_data->yggdrasilToken.validity = Katabasis::Validity::Certain; - m_data->yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc(); - - // Get UUID here since we need it for later - auto profile = responseData.value("selectedProfile"); - if (!profile.isObject()) { - changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a selected profile.")); - return; - } - - auto profileObj = profile.toObject(); - for (auto i = profileObj.constBegin(); i != profileObj.constEnd(); ++i) { - if (i.key() == "name" && i.value().isString()) { - m_data->minecraftProfile.name = i->toString(); - } else if (i.key() == "id" && i.value().isString()) { - m_data->minecraftProfile.id = i->toString(); - } - } - - if (m_data->minecraftProfile.id.isEmpty()) { - changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a UUID in selected profile.")); - return; - } - - // We've made it through the minefield of possible errors. Return true to indicate that - // we've succeeded. - qDebug() << "Finished reading authentication response."; - changeState(AccountTaskState::STATE_SUCCEEDED); -} - -void Yggdrasil::processReply() -{ - changeState(AccountTaskState::STATE_WORKING); - - switch (m_netReply->error()) { - case QNetworkReply::NoError: - break; - case QNetworkReply::TimeoutError: - changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation timed out.")); - return; - case QNetworkReply::OperationCanceledError: - changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation cancelled.")); - return; - case QNetworkReply::SslHandshakeFailedError: - changeState(AccountTaskState::STATE_FAILED_SOFT, - tr("SSL Handshake failed.
There might be a few causes for it:
" - "
    " - "
  • You use Windows and need to update your root certificates, please install any outstanding updates.
  • " - "
  • Some device on your network is interfering with SSL traffic. In that case, " - "you have bigger worries than Minecraft not starting.
  • " - "
  • Possibly something else. Check the log file for details
  • " - "
")); - return; - // used for invalid credentials and similar errors. Fall through. - case QNetworkReply::ContentAccessDenied: - case QNetworkReply::ContentOperationNotPermittedError: - break; - case QNetworkReply::ContentGoneError: { - changeState(AccountTaskState::STATE_FAILED_GONE, - tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account.")); - return; - } - default: - changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation failed due to a network error: %1 (%2)") - .arg(m_netReply->errorString()) - .arg(m_netReply->error())); - return; - } - - // Try to parse the response regardless of the response code. - // Sometimes the auth server will give more information and an error code. - QJsonParseError jsonError; - QByteArray replyData = m_netReply->readAll(); - QJsonDocument doc = QJsonDocument::fromJson(replyData, &jsonError); - // Check the response code. - int responseCode = m_netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - if (responseCode == 200) { - // If the response code was 200, then there shouldn't be an error. Make sure - // anyways. - // Also, sometimes an empty reply indicates success. If there was no data received, - // pass an empty json object to the processResponse function. - if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) { - processResponse(replyData.size() > 0 ? doc.object() : QJsonObject()); - return; - } else { - changeState(AccountTaskState::STATE_FAILED_SOFT, - tr("Failed to parse authentication server response JSON response: %1 at offset %2.") - .arg(jsonError.errorString()) - .arg(jsonError.offset)); - qCritical() << replyData; - } - return; - } - - // If the response code was not 200, then Yggdrasil may have given us information - // about the error. - // If we can parse the response, then get information from it. Otherwise just say - // there was an unknown error. - if (jsonError.error == QJsonParseError::NoError) { - // We were able to parse the server's response. Woo! - // Call processError. If a subclass has overridden it then they'll handle their - // stuff there. - qDebug() << "The request failed, but the server gave us an error message. Processing error."; - processError(doc.object()); - } else { - // The server didn't say anything regarding the error. Give the user an unknown - // error. - qDebug() << "The request failed and the server gave no error message. Unknown error."; - changeState( - AccountTaskState::STATE_FAILED_SOFT, - tr("An unknown error occurred when trying to communicate with the authentication server: %1").arg(m_netReply->errorString())); - } -} - -void Yggdrasil::processError(QJsonObject responseData) -{ - QJsonValue errorVal = responseData.value("error"); - QJsonValue errorMessageValue = responseData.value("errorMessage"); - QJsonValue causeVal = responseData.value("cause"); - - if (errorVal.isString() && errorMessageValue.isString()) { - m_error = std::shared_ptr(new Error{ errorVal.toString(""), errorMessageValue.toString(""), causeVal.toString("") }); - changeState(AccountTaskState::STATE_FAILED_HARD, m_error->m_errorMessageVerbose); - } else { - // Error is not in standard format. Don't set m_error and return unknown error. - changeState(AccountTaskState::STATE_FAILED_HARD, tr("An unknown Yggdrasil error occurred.")); - } -} diff --git a/launcher/minecraft/auth/Yggdrasil.h b/launcher/minecraft/auth/Yggdrasil.h deleted file mode 100644 index 560d7fb81..000000000 --- a/launcher/minecraft/auth/Yggdrasil.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright 2013-2021 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 "AccountTask.h" - -#include -#include -#include -#include - -#include "MinecraftAccount.h" - -class QNetworkAccessManager; -class QNetworkReply; - -/** - * A Yggdrasil task is a task that performs an operation on a given mojang account. - */ -class Yggdrasil : public AccountTask { - Q_OBJECT - public: - explicit Yggdrasil(AccountData* data, QObject* parent = 0); - virtual ~Yggdrasil() = default; - - void refresh(); - void login(QString password); - - struct Error { - QString m_errorMessageShort; - QString m_errorMessageVerbose; - QString m_cause; - }; - std::shared_ptr m_error; - - enum AbortedBy { BY_NOTHING, BY_USER, BY_TIMEOUT } m_aborted = BY_NOTHING; - - protected: - void executeTask() override; - - /** - * Processes the response received from the server. - * If an error occurred, this should emit a failed signal. - * If Yggdrasil gave an error response, it should call setError() first, and then return false. - * Otherwise, it should return true. - * Note: If the response from the server was blank, and the HTTP code was 200, this function is called with - * an empty QJsonObject. - */ - void processResponse(QJsonObject responseData); - - /** - * Processes an error response received from the server. - * The default implementation will read data from Yggdrasil's standard error response format and set it as this task's Error. - * \returns a QString error message that will be passed to emitFailed. - */ - virtual void processError(QJsonObject responseData); - - protected slots: - void processReply(); - void refreshTimers(qint64, qint64); - void heartbeat(); - void sslErrors(QList); - void abortByTimeout(); - - public slots: - virtual bool abort() override; - - private: - void sendRequest(QUrl endpoint, QByteArray content); - - protected: - QNetworkReply* m_netReply = nullptr; - QTimer timeout_keeper; - QTimer counter; - int count = 0; // num msec since time reset - - const int timeout_max = 30000; - const int time_step = 50; -}; diff --git a/launcher/minecraft/auth/flows/AuthFlow.h b/launcher/minecraft/auth/flows/AuthFlow.h index c2c412abc..e39e926dd 100644 --- a/launcher/minecraft/auth/flows/AuthFlow.h +++ b/launcher/minecraft/auth/flows/AuthFlow.h @@ -12,7 +12,6 @@ #include "minecraft/auth/AccountData.h" #include "minecraft/auth/AccountTask.h" #include "minecraft/auth/AuthStep.h" -#include "minecraft/auth/Yggdrasil.h" class AuthFlow : public AccountTask { Q_OBJECT diff --git a/launcher/minecraft/auth/flows/Mojang.cpp b/launcher/minecraft/auth/flows/Mojang.cpp deleted file mode 100644 index 7e2db16fa..000000000 --- a/launcher/minecraft/auth/flows/Mojang.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "Mojang.h" - -#include "minecraft/auth/steps/GetSkinStep.h" -#include "minecraft/auth/steps/MigrationEligibilityStep.h" -#include "minecraft/auth/steps/MinecraftProfileStepMojang.h" -#include "minecraft/auth/steps/YggdrasilStep.h" - -MojangRefresh::MojangRefresh(AccountData* data, QObject* parent) : AuthFlow(data, parent) -{ - m_steps.append(makeShared(m_data, QString())); - m_steps.append(makeShared(m_data)); - m_steps.append(makeShared(m_data)); - m_steps.append(makeShared(m_data)); -} - -MojangLogin::MojangLogin(AccountData* data, QString password, QObject* parent) : AuthFlow(data, parent), m_password(password) -{ - m_steps.append(makeShared(m_data, m_password)); - m_steps.append(makeShared(m_data)); - m_steps.append(makeShared(m_data)); - m_steps.append(makeShared(m_data)); -} diff --git a/launcher/minecraft/auth/flows/Mojang.h b/launcher/minecraft/auth/flows/Mojang.h deleted file mode 100644 index 779ca7e34..000000000 --- a/launcher/minecraft/auth/flows/Mojang.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AuthFlow.h" - -class MojangRefresh : public AuthFlow { - Q_OBJECT - public: - explicit MojangRefresh(AccountData* data, QObject* parent = 0); -}; - -class MojangLogin : public AuthFlow { - Q_OBJECT - public: - explicit MojangLogin(AccountData* data, QString password, QObject* parent = 0); - - private: - QString m_password; -}; diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp b/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp deleted file mode 100644 index 5ce953dfb..000000000 --- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "MigrationEligibilityStep.h" - -#include - -#include "minecraft/auth/AuthRequest.h" -#include "minecraft/auth/Parsers.h" - -MigrationEligibilityStep::MigrationEligibilityStep(AccountData* data) : AuthStep(data) {} - -MigrationEligibilityStep::~MigrationEligibilityStep() noexcept = default; - -QString MigrationEligibilityStep::describe() -{ - return tr("Checking for migration eligibility."); -} - -void MigrationEligibilityStep::perform() -{ - auto url = QUrl("https://api.minecraftservices.com/rollout/v1/msamigration"); - QNetworkRequest request = QNetworkRequest(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8()); - - AuthRequest* requestor = new AuthRequest(this); - connect(requestor, &AuthRequest::finished, this, &MigrationEligibilityStep::onRequestDone); - requestor->get(request); -} - -void MigrationEligibilityStep::rehydrate() -{ - // NOOP, for now. We only save bools and there's nothing to check. -} - -void MigrationEligibilityStep::onRequestDone(QNetworkReply::NetworkError error, - QByteArray data, - QList headers) -{ - auto requestor = qobject_cast(QObject::sender()); - requestor->deleteLater(); - - if (error == QNetworkReply::NoError) { - Parsers::parseRolloutResponse(data, m_data->canMigrateToMSA); - } - emit finished(AccountTaskState::STATE_WORKING, tr("Got migration flags")); -} diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h b/launcher/minecraft/auth/steps/MigrationEligibilityStep.h deleted file mode 100644 index 8638975d8..000000000 --- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include - -#include "QObjectPtr.h" -#include "minecraft/auth/AuthStep.h" - -class MigrationEligibilityStep : public AuthStep { - Q_OBJECT - - public: - explicit MigrationEligibilityStep(AccountData* data); - virtual ~MigrationEligibilityStep() noexcept; - - void perform() override; - void rehydrate() override; - - QString describe() override; - - private slots: - void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); -}; diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp index 7cdce23f0..a854342bc 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp @@ -41,10 +41,6 @@ void MinecraftProfileStep::onRequestDone(QNetworkReply::NetworkError error, QByt qCDebug(authCredentials()) << data; if (error == QNetworkReply::ContentNotFoundError) { // NOTE: Succeed even if we do not have a profile. This is a valid account state. - if (m_data->type == AccountType::Mojang) { - m_data->minecraftEntitlement.canPlayMinecraft = false; - m_data->minecraftEntitlement.ownsMinecraft = false; - } m_data->minecraftProfile = MinecraftProfile(); emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Account has no Minecraft profile.")); return; @@ -73,10 +69,5 @@ void MinecraftProfileStep::onRequestDone(QNetworkReply::NetworkError error, QByt return; } - if (m_data->type == AccountType::Mojang) { - auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain; - m_data->minecraftEntitlement.canPlayMinecraft = validProfile; - m_data->minecraftEntitlement.ownsMinecraft = validProfile; - } emit finished(AccountTaskState::STATE_WORKING, tr("Minecraft Java profile acquisition succeeded.")); } diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp deleted file mode 100644 index d035e39a0..000000000 --- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "MinecraftProfileStepMojang.h" - -#include - -#include "Logging.h" -#include "minecraft/auth/AuthRequest.h" -#include "minecraft/auth/Parsers.h" -#include "net/NetUtils.h" - -MinecraftProfileStepMojang::MinecraftProfileStepMojang(AccountData* data) : AuthStep(data) {} - -MinecraftProfileStepMojang::~MinecraftProfileStepMojang() noexcept = default; - -QString MinecraftProfileStepMojang::describe() -{ - return tr("Fetching the Minecraft profile."); -} - -void MinecraftProfileStepMojang::perform() -{ - if (m_data->minecraftProfile.id.isEmpty()) { - emit finished(AccountTaskState::STATE_FAILED_HARD, tr("A UUID is required to get the profile.")); - return; - } - - // use session server instead of profile due to profile endpoint being locked for locked Mojang accounts - QUrl url = QUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + m_data->minecraftProfile.id); - QNetworkRequest req = QNetworkRequest(url); - AuthRequest* request = new AuthRequest(this); - connect(request, &AuthRequest::finished, this, &MinecraftProfileStepMojang::onRequestDone); - request->get(req); -} - -void MinecraftProfileStepMojang::rehydrate() -{ - // NOOP, for now. We only save bools and there's nothing to check. -} - -void MinecraftProfileStepMojang::onRequestDone(QNetworkReply::NetworkError error, - QByteArray data, - QList headers) -{ - auto requestor = qobject_cast(QObject::sender()); - requestor->deleteLater(); - - qCDebug(authCredentials()) << data; - if (error == QNetworkReply::ContentNotFoundError) { - // NOTE: Succeed even if we do not have a profile. This is a valid account state. - if (m_data->type == AccountType::Mojang) { - m_data->minecraftEntitlement.canPlayMinecraft = false; - m_data->minecraftEntitlement.ownsMinecraft = false; - } - m_data->minecraftProfile = MinecraftProfile(); - emit finished(AccountTaskState::STATE_SUCCEEDED, tr("Account has no Minecraft profile.")); - return; - } - if (error != QNetworkReply::NoError) { - qWarning() << "Error getting profile:"; - qWarning() << " HTTP Status: " << requestor->httpStatus_; - qWarning() << " Internal error no.: " << error; - qWarning() << " Error string: " << requestor->errorString_; - - qWarning() << " Response:"; - qWarning() << QString::fromUtf8(data); - - if (Net::isApplicationError(error)) { - emit finished(AccountTaskState::STATE_FAILED_SOFT, - tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)); - } else { - emit finished(AccountTaskState::STATE_OFFLINE, - tr("Minecraft Java profile acquisition failed: %1").arg(requestor->errorString_)); - } - return; - } - if (!Parsers::parseMinecraftProfileMojang(data, m_data->minecraftProfile)) { - m_data->minecraftProfile = MinecraftProfile(); - emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Minecraft Java profile response could not be parsed")); - return; - } - - if (m_data->type == AccountType::Mojang) { - auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain; - m_data->minecraftEntitlement.canPlayMinecraft = validProfile; - m_data->minecraftEntitlement.ownsMinecraft = validProfile; - } - emit finished(AccountTaskState::STATE_WORKING, tr("Minecraft Java profile acquisition succeeded.")); -} diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h b/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h deleted file mode 100644 index 730ec3f68..000000000 --- a/launcher/minecraft/auth/steps/MinecraftProfileStepMojang.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include - -#include "QObjectPtr.h" -#include "minecraft/auth/AuthStep.h" - -class MinecraftProfileStepMojang : public AuthStep { - Q_OBJECT - - public: - explicit MinecraftProfileStepMojang(AccountData* data); - virtual ~MinecraftProfileStepMojang() noexcept; - - void perform() override; - void rehydrate() override; - - QString describe() override; - - private slots: - void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList); -}; diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.cpp b/launcher/minecraft/auth/steps/YggdrasilStep.cpp deleted file mode 100644 index fdcaa0d67..000000000 --- a/launcher/minecraft/auth/steps/YggdrasilStep.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "YggdrasilStep.h" - -#include "minecraft/auth/AuthRequest.h" -#include "minecraft/auth/Parsers.h" -#include "minecraft/auth/Yggdrasil.h" - -YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(data), m_password(password) -{ - m_yggdrasil = new Yggdrasil(m_data, this); - - connect(m_yggdrasil, &Task::failed, this, &YggdrasilStep::onAuthFailed); - connect(m_yggdrasil, &Task::succeeded, this, &YggdrasilStep::onAuthSucceeded); - connect(m_yggdrasil, &Task::aborted, this, &YggdrasilStep::onAuthFailed); -} - -YggdrasilStep::~YggdrasilStep() noexcept = default; - -QString YggdrasilStep::describe() -{ - return tr("Logging in with Mojang account."); -} - -void YggdrasilStep::rehydrate() -{ - // NOOP, for now. -} - -void YggdrasilStep::perform() -{ - if (m_password.size()) { - m_yggdrasil->login(m_password); - } else { - m_yggdrasil->refresh(); - } -} - -void YggdrasilStep::onAuthSucceeded() -{ - emit finished(AccountTaskState::STATE_WORKING, tr("Logged in with Mojang")); -} - -void YggdrasilStep::onAuthFailed() -{ - // TODO: hook these in again, expand to MSA - // m_error = m_yggdrasil->m_error; - // m_aborted = m_yggdrasil->m_aborted; - - auto state = m_yggdrasil->taskState(); - QString errorMessage = tr("Mojang user authentication failed."); - - // NOTE: soft error in the first step means 'offline' - if (state == AccountTaskState::STATE_FAILED_SOFT) { - state = AccountTaskState::STATE_OFFLINE; - errorMessage = tr("Mojang user authentication ended with a network error."); - } - emit finished(state, errorMessage); -} diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.h b/launcher/minecraft/auth/steps/YggdrasilStep.h deleted file mode 100644 index ef31f34d5..000000000 --- a/launcher/minecraft/auth/steps/YggdrasilStep.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include - -#include "QObjectPtr.h" -#include "minecraft/auth/AuthStep.h" - -class Yggdrasil; - -class YggdrasilStep : public AuthStep { - Q_OBJECT - - public: - explicit YggdrasilStep(AccountData* data, QString password); - virtual ~YggdrasilStep() noexcept; - - void perform() override; - void rehydrate() override; - - QString describe() override; - - private slots: - void onAuthSucceeded(); - void onAuthFailed(); - - private: - Yggdrasil* m_yggdrasil = nullptr; - QString m_password; -}; diff --git a/launcher/ui/dialogs/LoginDialog.cpp b/launcher/ui/dialogs/LoginDialog.cpp deleted file mode 100644 index 7296a13ef..000000000 --- a/launcher/ui/dialogs/LoginDialog.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright 2013-2021 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 "LoginDialog.h" -#include "ui_LoginDialog.h" - -#include "minecraft/auth/AccountTask.h" - -#include - -LoginDialog::LoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LoginDialog) -{ - ui->setupUi(this); - ui->progressBar->setVisible(false); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - - connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); -} - -LoginDialog::~LoginDialog() -{ - delete ui; -} - -// Stage 1: User interaction -void LoginDialog::accept() -{ - setUserInputsEnabled(false); - ui->progressBar->setVisible(true); - - // Setup the login task and start it - m_account = MinecraftAccount::createFromUsername(ui->userTextBox->text()); - m_loginTask = m_account->login(ui->passTextBox->text()); - connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed); - connect(m_loginTask.get(), &Task::succeeded, this, &LoginDialog::onTaskSucceeded); - connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus); - connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress); - m_loginTask->start(); -} - -void LoginDialog::setUserInputsEnabled(bool enable) -{ - ui->userTextBox->setEnabled(enable); - ui->passTextBox->setEnabled(enable); - ui->buttonBox->setEnabled(enable); -} - -// Enable the OK button only when both textboxes contain something. -void LoginDialog::on_userTextBox_textEdited(const QString& newText) -{ - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty()); -} -void LoginDialog::on_passTextBox_textEdited(const QString& newText) -{ - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty()); -} - -void LoginDialog::onTaskFailed(const QString& reason) -{ - // Set message - auto lines = reason.split('\n'); - QString processed; - for (auto line : lines) { - if (line.size()) { - processed += "" + line + "
"; - } else { - processed += "
"; - } - } - ui->label->setText(processed); - - // Re-enable user-interaction - setUserInputsEnabled(true); - ui->progressBar->setVisible(false); -} - -void LoginDialog::onTaskSucceeded() -{ - QDialog::accept(); -} - -void LoginDialog::onTaskStatus(const QString& status) -{ - ui->label->setText(status); -} - -void LoginDialog::onTaskProgress(qint64 current, qint64 total) -{ - ui->progressBar->setMaximum(total); - ui->progressBar->setValue(current); -} - -// Public interface -MinecraftAccountPtr LoginDialog::newAccount(QWidget* parent, QString msg) -{ - LoginDialog dlg(parent); - dlg.ui->label->setText(msg); - if (dlg.exec() == QDialog::Accepted) { - return dlg.m_account; - } - return nullptr; -} diff --git a/launcher/ui/dialogs/LoginDialog.h b/launcher/ui/dialogs/LoginDialog.h deleted file mode 100644 index 601b5fa77..000000000 --- a/launcher/ui/dialogs/LoginDialog.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright 2013-2021 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 "minecraft/auth/MinecraftAccount.h" -#include "tasks/Task.h" - -namespace Ui { -class LoginDialog; -} - -class LoginDialog : public QDialog { - Q_OBJECT - - public: - ~LoginDialog(); - - static MinecraftAccountPtr newAccount(QWidget* parent, QString message); - - private: - explicit LoginDialog(QWidget* parent = 0); - - void setUserInputsEnabled(bool enable); - - protected slots: - void accept(); - - void onTaskFailed(const QString& reason); - void onTaskSucceeded(); - void onTaskStatus(const QString& status); - void onTaskProgress(qint64 current, qint64 total); - - void on_userTextBox_textEdited(const QString& newText); - void on_passTextBox_textEdited(const QString& newText); - - private: - Ui::LoginDialog* ui; - MinecraftAccountPtr m_account; - Task::Ptr m_loginTask; -}; diff --git a/launcher/ui/dialogs/LoginDialog.ui b/launcher/ui/dialogs/LoginDialog.ui deleted file mode 100644 index 8fa4a45d2..000000000 --- a/launcher/ui/dialogs/LoginDialog.ui +++ /dev/null @@ -1,77 +0,0 @@ - - - LoginDialog - - - - 0 - 0 - 421 - 198 - - - - - 0 - 0 - - - - Add Account - - - - - - Message label placeholder. - - - Qt::RichText - - - Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Email - - - - - - - QLineEdit::Password - - - Password - - - - - - - 24 - - - false - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index c95bfabdd..90591c7f6 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -45,7 +45,6 @@ #include "net/NetJob.h" #include "ui/dialogs/CustomMessageBox.h" -#include "ui/dialogs/LoginDialog.h" #include "ui/dialogs/MSALoginDialog.h" #include "ui/dialogs/OfflineLoginDialog.h" #include "ui/dialogs/ProgressDialog.h" @@ -64,8 +63,7 @@ AccountListPage::AccountListPage(QWidget* parent) : QMainWindow(parent), ui(new ui->setupUi(this); ui->listView->setEmptyString( tr("Welcome!\n" - "If you're new here, you can select the \"Add Microsoft\" or \"Add Mojang\" buttons to link your Microsoft and/or Mojang " - "accounts.")); + "If you're new here, you can select the \"Add Microsoft\" button to link your Microsoft account.")); ui->listView->setEmptyMode(VersionListView::String); ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -74,7 +72,6 @@ AccountListPage::AccountListPage(QWidget* parent) : QMainWindow(parent), ui(new ui->listView->setModel(m_accounts.get()); ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::ProfileNameColumn, QHeaderView::Stretch); ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::NameColumn, QHeaderView::Stretch); - ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::MigrationColumn, QHeaderView::ResizeToContents); ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::TypeColumn, QHeaderView::ResizeToContents); ui->listView->header()->setSectionResizeMode(AccountList::VListColumns::StatusColumn, QHeaderView::ResizeToContents); ui->listView->setSelectionMode(QAbstractItemView::SingleSelection); @@ -139,19 +136,6 @@ void AccountListPage::listChanged() updateButtonStates(); } -void AccountListPage::on_actionAddMojang_triggered() -{ - MinecraftAccountPtr account = - LoginDialog::newAccount(this, tr("Please enter your Mojang account email and password to add your account.")); - - if (account) { - m_accounts->addAccount(account); - if (m_accounts->count() == 1) { - m_accounts->setDefaultAccount(account); - } - } -} - void AccountListPage::on_actionAddMicrosoft_triggered() { MinecraftAccountPtr account = diff --git a/launcher/ui/pages/global/AccountListPage.h b/launcher/ui/pages/global/AccountListPage.h index add0f4aa0..f3b80191d 100644 --- a/launcher/ui/pages/global/AccountListPage.h +++ b/launcher/ui/pages/global/AccountListPage.h @@ -70,7 +70,6 @@ class AccountListPage : public QMainWindow, public BasePage { void retranslate() override; public slots: - void on_actionAddMojang_triggered(); void on_actionAddMicrosoft_triggered(); void on_actionAddOffline_triggered(); void on_actionRemove_triggered(); diff --git a/launcher/ui/pages/global/AccountListPage.ui b/launcher/ui/pages/global/AccountListPage.ui index 469955b51..d8cf3ac0a 100644 --- a/launcher/ui/pages/global/AccountListPage.ui +++ b/launcher/ui/pages/global/AccountListPage.ui @@ -53,7 +53,6 @@ false - @@ -63,11 +62,6 @@
- - - Add &Mojang - - Remo&ve From 86b47b3421101083a5d0a93a11d33f35c3f8f4a2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 25 Sep 2023 22:33:36 +0300 Subject: [PATCH 360/398] Do not display invalid shaders Signed-off-by: Trial97 --- launcher/minecraft/mod/ShaderPack.cpp | 7 ++++++- launcher/minecraft/mod/ShaderPack.h | 1 + launcher/minecraft/mod/ShaderPackFolderModel.h | 13 +++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/mod/ShaderPack.cpp b/launcher/minecraft/mod/ShaderPack.cpp index 6a9641de2..2c094f26a 100644 --- a/launcher/minecraft/mod/ShaderPack.cpp +++ b/launcher/minecraft/mod/ShaderPack.cpp @@ -22,7 +22,7 @@ #include "ShaderPack.h" -#include "minecraft/mod/tasks/LocalShaderPackParseTask.h" +#include void ShaderPack::setPackFormat(ShaderPackFormat new_format) { @@ -35,3 +35,8 @@ bool ShaderPack::valid() const { return m_pack_format != ShaderPackFormat::INVALID; } + +bool ShaderPack::applyFilter(QRegularExpression filter) const +{ + return valid() && Resource::applyFilter(filter); +} diff --git a/launcher/minecraft/mod/ShaderPack.h b/launcher/minecraft/mod/ShaderPack.h index ec0f9404e..d07c124be 100644 --- a/launcher/minecraft/mod/ShaderPack.h +++ b/launcher/minecraft/mod/ShaderPack.h @@ -54,6 +54,7 @@ class ShaderPack : public Resource { void setPackFormat(ShaderPackFormat new_format); bool valid() const override; + [[nodiscard]] bool applyFilter(QRegularExpression filter) const override; protected: mutable QMutex m_data_lock; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index 44ed37a47..186d02139 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -1,6 +1,9 @@ #pragma once #include "ResourceFolderModel.h" +#include "minecraft/mod/ShaderPack.h" +#include "minecraft/mod/tasks/BasicFolderLoadTask.h" +#include "minecraft/mod/tasks/LocalShaderPackParseTask.h" class ShaderPackFolderModel : public ResourceFolderModel { Q_OBJECT @@ -9,4 +12,14 @@ class ShaderPackFolderModel : public ResourceFolderModel { explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) {} virtual QString id() const override { return "shaderpacks"; } + + [[nodiscard]] Task* createUpdateTask() override + { + return new BasicFolderLoadTask(m_dir, [](QFileInfo const& entry) { return makeShared(entry); }); + } + + [[nodiscard]] Task* createParseTask(Resource& resource) override + { + return new LocalShaderPackParseTask(m_next_resolution_ticket, static_cast(resource)); + } }; From 4ee6a6711d462d4f85c84afe6bc0e0e6640b1244 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 25 Sep 2023 23:04:21 +0300 Subject: [PATCH 361/398] Added version check for neoforge filter Signed-off-by: Trial97 --- launcher/minecraft/PackProfile.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 9e42c5dd6..31974cd00 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -1018,8 +1018,8 @@ std::optional PackProfile::getSupportedModLoaders() // TODO: remove this or add version condition once Quilt drops official Fabric support if (loaders & ModPlatform::Quilt) loaders |= ModPlatform::Fabric; - // TODO: remove this or add version condition once NeoForge drops official Forge support - if (loaders & ModPlatform::NeoForge) + Version instance_ver{ getComponentVersion("net.minecraft") }; + if (instance_ver <= Version("1.20.1") && loaders & ModPlatform::NeoForge) loaders |= ModPlatform::Forge; return loaders; } From b8d9c3d7795692f2d012421a28232c3eb1a73301 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 26 Sep 2023 20:19:35 +0300 Subject: [PATCH 362/398] format Signed-off-by: Trial97 --- launcher/Application.cpp | 2 +- launcher/FileSystem.h | 2 -- launcher/MMCZip.cpp | 1 - launcher/MMCZip.h | 1 - launcher/StringUtils.h | 2 +- launcher/filelink/FileLink.h | 11 ++--------- launcher/filelink/filelink_main.cpp | 5 ++--- launcher/modplatform/modrinth/ModrinthAPI.cpp | 1 - launcher/ui/MainWindow.cpp | 6 ++---- launcher/ui/dialogs/UpdateAvailableDialog.cpp | 6 +++--- launcher/ui/dialogs/UpdateAvailableDialog.h | 3 +-- launcher/updater/prismupdater/UpdaterDialogs.h | 2 +- 12 files changed, 13 insertions(+), 29 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 955ec692f..ba60b1e04 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -875,7 +875,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) updateCapabilities(); detectLibraries(); - + // check update locks { auto update_log_path = FS::PathCombine(m_dataPath, "logs", "prism_launcher_update.log"); diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index c474334c3..861cfa267 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -61,7 +61,6 @@ class FileSystemException : public ::Exception { */ void write(const QString& filename, const QByteArray& data); - /** * append data to a file safely */ @@ -72,7 +71,6 @@ void appendSafe(const QString& filename, const QByteArray& data); */ void append(const QString& filename, const QByteArray& data); - /** * read data from a file safely\ */ diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 40790a824..3bfe16ab5 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -510,4 +510,3 @@ bool ExportToZipTask::abort() #endif } // namespace MMCZip - diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index 8afb12410..1c6ebe34a 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -151,7 +151,6 @@ bool extractFile(QString fileCompressed, QString file, QString dir); */ bool collectFileListRecursively(const QString& rootDir, const QString& subDir, QFileInfoList* files, FilterFunction excludeFilter); - #if defined(LAUNCHER_APPLICATION) class ExportToZipTask : public Task { public: diff --git a/launcher/StringUtils.h b/launcher/StringUtils.h index 9244d3461..9d2bdd85e 100644 --- a/launcher/StringUtils.h +++ b/launcher/StringUtils.h @@ -36,8 +36,8 @@ #pragma once -#include #include +#include #include #include diff --git a/launcher/filelink/FileLink.h b/launcher/filelink/FileLink.h index ab3e9d360..583d0d43a 100644 --- a/launcher/filelink/FileLink.h +++ b/launcher/filelink/FileLink.h @@ -41,17 +41,10 @@ class FileLinkApp : public QCoreApplication { // friends for the purpose of limiting access to deprecated stuff Q_OBJECT public: - enum Status { - Starting, - Failed, - Succeeded, - Initialized - }; + enum Status { Starting, Failed, Succeeded, Initialized }; FileLinkApp(int& argc, char** argv); virtual ~FileLinkApp(); - Status status() const { - return m_status; - } + Status status() const { return m_status; } private: void joinServer(QString server); diff --git a/launcher/filelink/filelink_main.cpp b/launcher/filelink/filelink_main.cpp index a656a9c96..2a8bcb703 100644 --- a/launcher/filelink/filelink_main.cpp +++ b/launcher/filelink/filelink_main.cpp @@ -26,10 +26,9 @@ int main(int argc, char* argv[]) { FileLinkApp ldh(argc, argv); - switch(ldh.status()) { + switch (ldh.status()) { case FileLinkApp::Starting: - case FileLinkApp::Initialized: - { + case FileLinkApp::Initialized: { return ldh.exec(); } case FileLinkApp::Failed: diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp index 355c759cd..f453f5cb9 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.cpp +++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp @@ -10,7 +10,6 @@ #include "net/ApiUpload.h" #include "net/NetJob.h" #include "net/Upload.h" -#include "net/ApiDownload.h" Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, std::shared_ptr response) { diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 3a5ce9c47..326b22043 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -676,8 +676,7 @@ void MainWindow::repopulateAccountsMenu() void MainWindow::updatesAllowedChanged(bool allowed) { - if(!APPLICATION->updaterEnabled()) - { + if (!APPLICATION->updaterEnabled()) { return; } ui->actionCheckUpdate->setEnabled(allowed); @@ -1209,8 +1208,7 @@ void MainWindow::refreshInstances() void MainWindow::checkForUpdates() { - if(APPLICATION->updaterEnabled()) - { + if (APPLICATION->updaterEnabled()) { APPLICATION->triggerUpdateCheck(); } else { qWarning() << "Updater not set up. Cannot check for updates."; diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.cpp b/launcher/ui/dialogs/UpdateAvailableDialog.cpp index 28f7167cb..5eebe87a3 100644 --- a/launcher/ui/dialogs/UpdateAvailableDialog.cpp +++ b/launcher/ui/dialogs/UpdateAvailableDialog.cpp @@ -46,17 +46,17 @@ UpdateAvailableDialog::UpdateAvailableDialog(const QString& currentVersion, ui->releaseNotes->setHtml(releaseNotesHtml); ui->releaseNotes->setOpenExternalLinks(true); - connect(ui->skipButton, &QPushButton::clicked, this, [this](){ + connect(ui->skipButton, &QPushButton::clicked, this, [this]() { setResult(ResultCode::Skip); done(ResultCode::Skip); }); - connect(ui->delayButton, &QPushButton::clicked, this, [this](){ + connect(ui->delayButton, &QPushButton::clicked, this, [this]() { setResult(ResultCode::DontInstall); done(ResultCode::DontInstall); }); - connect(ui->installButton, &QPushButton::clicked, this, [this](){ + connect(ui->installButton, &QPushButton::clicked, this, [this]() { setResult(ResultCode::Install); done(ResultCode::Install); }); diff --git a/launcher/ui/dialogs/UpdateAvailableDialog.h b/launcher/ui/dialogs/UpdateAvailableDialog.h index f3ea5cbb1..6af9ace36 100644 --- a/launcher/ui/dialogs/UpdateAvailableDialog.h +++ b/launcher/ui/dialogs/UpdateAvailableDialog.h @@ -31,13 +31,12 @@ class UpdateAvailableDialog : public QDialog { Q_OBJECT public: - enum ResultCode { Install = 10, DontInstall = 11, Skip = 12, }; - + explicit UpdateAvailableDialog(const QString& currentVersion, const QString& availableVersion, const QString& releaseNotes, diff --git a/launcher/updater/prismupdater/UpdaterDialogs.h b/launcher/updater/prismupdater/UpdaterDialogs.h index 249ca1b5d..e336c0e2c 100644 --- a/launcher/updater/prismupdater/UpdaterDialogs.h +++ b/launcher/updater/prismupdater/UpdaterDialogs.h @@ -25,8 +25,8 @@ #include #include -#include "Version.h" #include "GitHubRelease.h" +#include "Version.h" namespace Ui { class SelectReleaseDialog; From f370f0d749f4b4ff85daf3e494e4a64ae0c5782a Mon Sep 17 00:00:00 2001 From: seth Date: Wed, 27 Sep 2023 05:33:22 -0400 Subject: [PATCH 363/398] chore: cleanup a few more mentions of mojang accounts Signed-off-by: seth --- launcher/LaunchController.cpp | 4 ++-- launcher/minecraft/auth/AccountList.cpp | 2 +- launcher/ui/MainWindow.cpp | 2 +- launcher/ui/pages/global/AccountListPage.cpp | 2 +- launcher/ui/pages/instance/VersionPage.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index b21eb281f..e1953abd6 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -88,8 +88,8 @@ void LaunchController::decideAccount() if (accounts->count() <= 0) { // Tell the user they need to log in at least one account in order to play. auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"), - tr("In order to play Minecraft, you must have at least one Microsoft or Mojang " - "account logged in. Mojang accounts can only be used offline. " + tr("In order to play Minecraft, you must have at least one Microsoft " + "account logged in." "Would you like to open the account manager to add an account now?"), QMessageBox::Information, QMessageBox::Yes | QMessageBox::No) ->exec(); diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index a29de4ecf..eed11e030 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -366,7 +366,7 @@ QVariant AccountList::headerData(int section, [[maybe_unused]] Qt::Orientation o case NameColumn: return tr("User name of the account."); case TypeColumn: - return tr("Type of the account - Mojang or MSA."); + return tr("Type of the account (currently only MSA is supported.)"); case StatusColumn: return tr("Current status of the account."); default: diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 5e55a5abb..64873ebb8 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -872,7 +872,7 @@ void MainWindow::finalizeInstance(InstancePtr inst) } else { CustomMessageBox::selectable(this, tr("Error"), tr("The launcher cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Microsoft or Mojang account."), + "one account added.\nPlease add a Microsoft account."), QMessageBox::Warning) ->show(); } diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp index 90591c7f6..50f3ff2b6 100644 --- a/launcher/ui/pages/global/AccountListPage.cpp +++ b/launcher/ui/pages/global/AccountListPage.cpp @@ -153,7 +153,7 @@ void AccountListPage::on_actionAddOffline_triggered() { if (!m_accounts->anyAccountIsValid()) { QMessageBox::warning(this, tr("Error"), - tr("You must add a Microsoft or Mojang account that owns Minecraft before you can add an offline account." + tr("You must add a Microsoft account that owns Minecraft before you can add an offline account." "

" "If you have lost your account you can contact Microsoft for support.")); return; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index e22c764ca..2918261d2 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -411,7 +411,7 @@ void VersionPage::on_actionDownload_All_triggered() if (!APPLICATION->accounts()->anyAccountIsValid()) { CustomMessageBox::selectable(this, tr("Error"), tr("Cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Microsoft or Mojang account."), + "one account added.\nPlease add a Microsoft account."), QMessageBox::Warning) ->show(); return; From 498c9db1cedc9b20d631d6e3cb38b4145d660344 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 28 Sep 2023 15:14:59 +0300 Subject: [PATCH 364/398] fixed appImageUpdate Signed-off-by: Trial97 --- launcher/updater/PrismExternalUpdater.cpp | 2 ++ launcher/updater/prismupdater/PrismUpdater.cpp | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/launcher/updater/PrismExternalUpdater.cpp b/launcher/updater/PrismExternalUpdater.cpp index 3595042d6..bee72e3a0 100644 --- a/launcher/updater/PrismExternalUpdater.cpp +++ b/launcher/updater/PrismExternalUpdater.cpp @@ -338,6 +338,8 @@ void PrismExternalUpdater::performUpdate(const QString& version_tag) auto env = QProcessEnvironment::systemEnvironment(); env.insert("__COMPAT_LAYER", "RUNASINVOKER"); proc.setProcessEnvironment(env); +#else + exe_name = QString("bin/%1").arg(exe_name); #endif QStringList args = { "--dir", priv->dataDir.absolutePath(), "--install-version", version_tag }; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 2604d2e0b..4ffe29b35 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -900,7 +900,7 @@ bool PrismUpdaterApp::callAppImageUpdate() auto appimage_path = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); QProcess proc = QProcess(); qDebug() << "Calling: AppImageUpdate" << appimage_path; - proc.setProgram("AppImageUpdate"); + proc.setProgram("bin/AppImageUpdate"); proc.setArguments({ appimage_path }); auto result = proc.startDetached(); if (!result) @@ -1213,8 +1213,14 @@ bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) } auto out = proc.readAllStandardOutput(); auto lines = out.split('\n'); + lines.removeAll(""); if (lines.length() < 2) return false; + else if (lines.length() > 2) { + auto line1 = lines.takeLast(); + auto line2 = lines.takeLast(); + lines = { line2, line1 }; + } auto first = lines.takeFirst(); auto first_parts = first.split(' '); if (first_parts.length() < 2) @@ -1230,6 +1236,8 @@ bool PrismUpdaterApp::loadPrismVersionFromExe(const QString& exe_path) m_prsimVersionChannel = "stable"; } auto version_parts = version.split('.'); + if (version_parts.length() < 2) + return false; m_prismVersionMajor = version_parts.takeFirst().toInt(); m_prismVersionMinor = version_parts.takeFirst().toInt(); m_prismGitCommit = lines.takeFirst().simplified(); From 606c12ffeb871e711b15025dedf93634dc4989be Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 28 Sep 2023 18:47:21 +0300 Subject: [PATCH 365/398] more fixing Signed-off-by: Trial97 --- .github/workflows/build.yml | 74 ++++++++----------- .github/workflows/trigger_builds.yml | 29 ++++---- .github/workflows/trigger_release.yml | 9 ++- .../updater/prismupdater/PrismUpdater.cpp | 2 +- 4 files changed, 53 insertions(+), 61 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4b703977b..e1641ed50 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,6 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-20.04 qt_ver: 5 @@ -127,9 +126,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - submodules: 'true' + submodules: "true" - - name: 'Setup MSYS2' + - name: "Setup MSYS2" if: runner.os == 'Windows' && matrix.msystem != '' uses: msys2/setup-msys2@v2 with: @@ -169,7 +168,7 @@ jobs: path: '${{ github.workspace }}\.ccache' key: ${{ matrix.os }}-mingw-w64-ccache-${{ github.run_id }} restore-keys: | - ${{ matrix.os }}-mingw-w64-ccache + ${{ matrix.os }}-mingw-w64-ccache - name: Setup ccache (Windows MinGW-w64) if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug' @@ -214,35 +213,35 @@ jobs: if: runner.os == 'Windows' && matrix.architecture == 'arm64' uses: jurplel/install-qt-action@v3 with: - aqtversion: '==3.1.*' - py7zrversion: '>=0.20.2' - version: ${{ matrix.qt_version }} - host: 'windows' - target: 'desktop' - arch: '' - modules: ${{ matrix.qt_modules }} - tools: ${{ matrix.qt_tools }} - cache: ${{ inputs.is_qt_cached }} - cache-key-prefix: host-qt-arm64-windows - dir: ${{ github.workspace }}\HostQt - set-env: false + aqtversion: "==3.1.*" + py7zrversion: ">=0.20.2" + version: ${{ matrix.qt_version }} + host: "windows" + target: "desktop" + arch: "" + modules: ${{ matrix.qt_modules }} + tools: ${{ matrix.qt_tools }} + cache: ${{ inputs.is_qt_cached }} + cache-key-prefix: host-qt-arm64-windows + dir: ${{ github.workspace }}\HostQt + set-env: false - name: Install Qt (macOS, Linux, Qt 6 & Windows MSVC) if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '') uses: jurplel/install-qt-action@v3 with: - aqtversion: '==3.1.*' - py7zrversion: '>=0.20.2' - version: ${{ matrix.qt_version }} - host: ${{ matrix.qt_host }} - target: 'desktop' - arch: ${{ matrix.qt_arch }} - modules: ${{ matrix.qt_modules }} - tools: ${{ matrix.qt_tools }} - cache: ${{ inputs.is_qt_cached }} + aqtversion: "==3.1.*" + py7zrversion: ">=0.20.2" + version: ${{ matrix.qt_version }} + host: ${{ matrix.qt_host }} + target: "desktop" + arch: ${{ matrix.qt_arch }} + modules: ${{ matrix.qt_modules }} + tools: ${{ matrix.qt_tools }} + cache: ${{ inputs.is_qt_cached }} - name: Install MSVC (Windows MSVC) - if: runner.os == 'Windows' # We want this for MinGW builds as well, as we need SignTool + if: runner.os == 'Windows' # We want this for MinGW builds as well, as we need SignTool uses: ilammy/msvc-dev-cmd@v1 with: vsversion: 2022 @@ -343,7 +342,7 @@ jobs: - name: Test (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture != 'arm64' run: | - ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }} + ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }} ## # PACKAGE BUILDS @@ -385,7 +384,7 @@ jobs: run: | cmake --install ${{ env.BUILD_DIR }} touch ${{ env.INSTALL_DIR }}/manifest.txt - for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_DIR }}/manifest.txt + for l in $(find ${{ env.INSTALL_DIR }} -type f); do l=$(cygpath -u $l); l=${l#$(pwd)/}; l=${l#${{ env.INSTALL_DIR }}/}; l=${l#./}; echo $l; done >> ${{ env.INSTALL_DIR }}/manifest.txt - name: Package (Windows MSVC) if: runner.os == 'Windows' && matrix.msystem == '' @@ -402,10 +401,9 @@ jobs: Get-ChildItem ${{ env.INSTALL_DIR }} -Recurse | ForEach FullName | Resolve-Path -Relative | %{ $_.TrimStart('.\') } | %{ $_.TrimStart('${{ env.INSTALL_DIR }}') } | %{ $_.TrimStart('\') } | Out-File -FilePath ${{ env.INSTALL_DIR }}/manifest.txt - - name: Fetch codesign certificate (Windows) if: runner.os == 'Windows' - shell: bash # yes, we are not using MSYS2 or PowerShell here + shell: bash # yes, we are not using MSYS2 or PowerShell here run: | echo '${{ secrets.WINDOWS_CODESIGN_CERT }}' | base64 --decode > codesign.pfx @@ -507,15 +505,7 @@ jobs: export LD_LIBRARY_PATH chmod +x AppImageUpdate-x86_64.AppImage - ./AppImageUpdate-x86_64.AppImage --appimage-extract - - mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional - mkdir -p ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins - - cp -r squashfs-root/usr/bin/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin - cp -r squashfs-root/usr/lib/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/lib - cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/optional - cp -r squashfs-root/usr/optional/* ${{ env.INSTALL_APPIMAGE_DIR }}/usr/plugins + cp AppImageUpdate-x86_64.AppImage ${{ env.INSTALL_APPIMAGE_DIR }}/usr/bin export UPDATE_INFORMATION="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|PrismLauncher-Linux-x86_64.AppImage.zsync" @@ -599,7 +589,7 @@ jobs: with: name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage path: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }}-x86_64.AppImage - + - name: Upload AppImage Zsync (Linux) if: runner.os == 'Linux' && matrix.qt_ver != 5 uses: actions/upload-artifact@v3 @@ -623,10 +613,10 @@ jobs: uses: actions/checkout@v4 if: inputs.build_type == 'Debug' with: - submodules: 'true' + submodules: "true" - name: Build Flatpak (Linux) if: inputs.build_type == 'Debug' uses: flatpak/flatpak-github-actions/flatpak-builder@v6 with: bundle: "Prism Launcher.flatpak" - manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml + manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml diff --git a/.github/workflows/trigger_builds.yml b/.github/workflows/trigger_builds.yml index 26ee4380b..70fda60ed 100644 --- a/.github/workflows/trigger_builds.yml +++ b/.github/workflows/trigger_builds.yml @@ -3,26 +3,25 @@ name: Build Application on: push: branches-ignore: - - 'renovate/**' + - "renovate/**" paths-ignore: - - '**.md' - - '**/LICENSE' - - 'flake.lock' - - 'packages/**' - - '.github/ISSUE_TEMPLATE/**' - - '.markdownlint**' + - "**.md" + - "**/LICENSE" + - "flake.lock" + - "packages/**" + - ".github/ISSUE_TEMPLATE/**" + - ".markdownlint**" pull_request: paths-ignore: - - '**.md' - - '**/LICENSE' - - 'flake.lock' - - 'packages/**' - - '.github/ISSUE_TEMPLATE/**' - - '.markdownlint**' + - "**.md" + - "**/LICENSE" + - "flake.lock" + - "packages/**" + - ".github/ISSUE_TEMPLATE/**" + - ".markdownlint**" workflow_dispatch: jobs: - build_debug: name: Build Debug uses: ./.github/workflows/build.yml @@ -34,3 +33,5 @@ jobs: WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }} WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }} CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }} diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index bda75e354..44bcd539c 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -3,10 +3,9 @@ name: Build Application and Make Release on: push: tags: - - '*' + - "*" jobs: - build_release: name: Build Release uses: ./.github/workflows/build.yml @@ -18,6 +17,8 @@ jobs: WINDOWS_CODESIGN_CERT: ${{ secrets.WINDOWS_CODESIGN_CERT }} WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }} CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PRIVATE_KEY_ID: ${{ secrets.GPG_PRIVATE_KEY_ID }} create_release: needs: build_release @@ -28,8 +29,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - submodules: 'true' - path: 'PrismLauncher-source' + submodules: "true" + path: "PrismLauncher-source" - name: Download artifacts uses: actions/download-artifact@v3 - name: Grab and store version diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 4ffe29b35..761c368f0 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -900,7 +900,7 @@ bool PrismUpdaterApp::callAppImageUpdate() auto appimage_path = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); QProcess proc = QProcess(); qDebug() << "Calling: AppImageUpdate" << appimage_path; - proc.setProgram("bin/AppImageUpdate"); + proc.setProgram(FS::PathCombine(m_rootPath, "bin", "AppImageUpdate-x86_64.AppImage")); proc.setArguments({ appimage_path }); auto result = proc.startDetached(); if (!result) From 742384909f95eb25ab736094c81f4b48f834f176 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 28 Sep 2023 21:24:31 +0300 Subject: [PATCH 366/398] updated portable update Signed-off-by: Trial97 --- .../updater/prismupdater/PrismUpdater.cpp | 82 +++++++++++++------ 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 761c368f0..110945f55 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -27,20 +27,20 @@ #include #include -#include -#include -#include - #include +#include +#include +#include #include #include +#include #include #include +#include #include #include -#include #if defined Q_OS_WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -660,28 +660,42 @@ void PrismUpdaterApp::moveAndFinishUpdate(QDir target) bool error = false; - QProgressDialog progress(tr("Backing up install at %1").arg(m_rootPath), "", 0, file_list.length()); + QProgressDialog progress(tr("Installing from %1").arg(m_rootPath), "", 0, file_list.length()); progress.setCancelButton(nullptr); progress.setMinimumWidth(400); progress.adjustSize(); progress.show(); QCoreApplication::processEvents(); + logUpdate(tr("Installing from %1").arg(m_rootPath)); + + auto copy = [this, app_dir, target](QString to_install_file) { + auto rel_path = app_dir.relativeFilePath(to_install_file); + auto install_path = FS::PathCombine(target.absolutePath(), rel_path); + logUpdate(tr("Installing %1 from %2").arg(install_path).arg(to_install_file)); + FS::ensureFilePathExists(install_path); + auto result = FS::copy(to_install_file, install_path).overwrite(true)(); + if (!result) { + logUpdate(tr("Failed copy %1 to %2").arg(to_install_file).arg(install_path)); + return true; + } + return false; + }; + int i = 0; for (auto glob : file_list) { QDirIterator iter(m_rootPath, QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); progress.setValue(i); QCoreApplication::processEvents(); - while (iter.hasNext()) { - auto to_install_file = iter.next(); - auto rel_path = app_dir.relativeFilePath(to_install_file); - auto install_path = FS::PathCombine(target.absolutePath(), rel_path); - logUpdate(tr("Installing %1 from %2").arg(install_path).arg(to_install_file)); - FS::ensureFilePathExists(install_path); - auto result = FS::copy(to_install_file, install_path).overwrite(true)(); - if (!result) { - error = true; - logUpdate(tr("Failed copy %1 to %2").arg(to_install_file).arg(install_path)); + if (!iter.hasNext() && !glob.isEmpty()) { + if (auto file_info = QFileInfo(FS::PathCombine(m_rootPath, glob)); file_info.exists()) { + error |= copy(file_info.absoluteFilePath()); + } else { + logUpdate(tr("File doesn't exist, ignoring: %1").arg(FS::PathCombine(m_rootPath, glob))); + } + } else { + while (iter.hasNext()) { + error |= copy(iter.next()); } } i++; @@ -1124,23 +1138,37 @@ void PrismUpdaterApp::backupAppDir() progress.adjustSize(); progress.show(); QCoreApplication::processEvents(); + + logUpdate(tr("Backing up install at %1").arg(m_rootPath)); + + auto copy = [this, app_dir, backup_dir](QString to_bak_file) { + auto rel_path = app_dir.relativeFilePath(to_bak_file); + auto bak_path = FS::PathCombine(backup_dir, rel_path); + logUpdate(tr("Backing up and then removing %1").arg(to_bak_file)); + FS::ensureFilePathExists(bak_path); + auto result = FS::copy(to_bak_file, bak_path).overwrite(true)(); + if (!result) { + logUpdate(tr("Failed to backup %1 to %2").arg(to_bak_file).arg(bak_path)); + } else { + if (!FS::deletePath(to_bak_file)) + logUpdate(tr("Failed to remove %1").arg(to_bak_file)); + } + }; + int i = 0; for (auto glob : file_list) { QDirIterator iter(app_dir.absolutePath(), QStringList({ glob }), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); progress.setValue(i); QCoreApplication::processEvents(); - while (iter.hasNext()) { - auto to_bak_file = iter.next(); - auto rel_path = app_dir.relativeFilePath(to_bak_file); - auto bak_path = FS::PathCombine(backup_dir, rel_path); - logUpdate(tr("Backing up and then removing %1").arg(to_bak_file)); - FS::ensureFilePathExists(bak_path); - auto result = FS::copy(to_bak_file, bak_path).overwrite(true)(); - if (!result) { - logUpdate(tr("Failed to backup %1 to %2").arg(to_bak_file).arg(bak_path)); + if (!iter.hasNext() && !glob.isEmpty()) { + if (auto file_info = QFileInfo(FS::PathCombine(m_rootPath, glob)); file_info.exists()) { + copy(file_info.absoluteFilePath()); } else { - if (!FS::deletePath(to_bak_file)) - logUpdate(tr("Failed to remove %1").arg(to_bak_file)); + logUpdate(tr("File doesn't exist, ignoring: %1").arg(FS::PathCombine(m_rootPath, glob))); + } + } else { + while (iter.hasNext()) { + copy(iter.next()); } } i++; From bef701eba847ecb1c4e6b0420315bee1ea045eef Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 28 Sep 2023 21:27:11 +0300 Subject: [PATCH 367/398] chaged folder again Signed-off-by: Trial97 --- launcher/updater/prismupdater/PrismUpdater.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 110945f55..1c5aaf1e8 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -1161,10 +1161,10 @@ void PrismUpdaterApp::backupAppDir() progress.setValue(i); QCoreApplication::processEvents(); if (!iter.hasNext() && !glob.isEmpty()) { - if (auto file_info = QFileInfo(FS::PathCombine(m_rootPath, glob)); file_info.exists()) { + if (auto file_info = QFileInfo(FS::PathCombine(app_dir.absolutePath(), glob)); file_info.exists()) { copy(file_info.absoluteFilePath()); } else { - logUpdate(tr("File doesn't exist, ignoring: %1").arg(FS::PathCombine(m_rootPath, glob))); + logUpdate(tr("File doesn't exist, ignoring: %1").arg(FS::PathCombine(app_dir.absolutePath(), glob))); } } else { while (iter.hasNext()) { From 5b7c5607a90cbb6ff78ba140a15d6180842d069b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 28 Sep 2023 22:53:40 +0300 Subject: [PATCH 368/398] removed flame consturctor Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.cpp | 17 ----------------- launcher/modplatform/ModIndex.h | 1 - launcher/modplatform/flame/FlameModIndex.cpp | 17 ++++++++++++++++- launcher/modplatform/flame/FlamePackIndex.cpp | 17 ++++++++++++++++- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 72ba88d90..fc79dff15 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -32,23 +32,6 @@ static const QMap s_indexed_version_ty IndexedVersionType::IndexedVersionType(const QString& type) : IndexedVersionType(enumFromString(type)) {} -IndexedVersionType::IndexedVersionType(int flame_type) -{ - switch (flame_type) { - case 1: - m_type = IndexedVersionType::VersionType::Release; - break; - case 2: - m_type = IndexedVersionType::VersionType::Beta; - break; - case 3: - m_type = IndexedVersionType::VersionType::Alpha; - break; - default: - m_type = IndexedVersionType::VersionType::Unknown; - } -} - IndexedVersionType::IndexedVersionType(const IndexedVersionType::VersionType& type) { m_type = type; diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 4ed8bcd86..4d6759d3b 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -62,7 +62,6 @@ struct DonationData { struct IndexedVersionType { enum class VersionType { Release = 1, Beta, Alpha, Unknown }; IndexedVersionType(const QString& type); - IndexedVersionType(int flame_type); IndexedVersionType(const IndexedVersionType::VersionType& type); IndexedVersionType(const IndexedVersionType& type); IndexedVersionType() : IndexedVersionType(IndexedVersionType::VersionType::Unknown) {} diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 3754ae1a6..2adcd7814 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -139,7 +139,22 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> file.version = Json::requireString(obj, "displayName"); file.downloadUrl = Json::ensureString(obj, "downloadUrl"); file.fileName = Json::requireString(obj, "fileName"); - file.version_type = ModPlatform::IndexedVersionType(Json::requireInteger(obj, "releaseType")); + + ModPlatform::IndexedVersionType::VersionType ver_type; + switch (Json::requireInteger(obj, "releaseType")) { + case 1: + ver_type = ModPlatform::IndexedVersionType::VersionType::Release; + break; + case 2: + ver_type = ModPlatform::IndexedVersionType::VersionType::Beta; + break; + case 3: + ver_type = ModPlatform::IndexedVersionType::VersionType::Alpha; + break; + default: + ver_type = ModPlatform::IndexedVersionType::VersionType::Unknown; + } + file.version_type = ModPlatform::IndexedVersionType(ver_type); auto hash_list = Json::ensureArray(obj, "hashes"); for (auto h : hash_list) { diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp index 5a1606734..71f1e4a2d 100644 --- a/launcher/modplatform/flame/FlamePackIndex.cpp +++ b/launcher/modplatform/flame/FlamePackIndex.cpp @@ -89,7 +89,22 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr) // pick the latest version supported file.mcVersion = versionArray[0].toString(); file.version = Json::requireString(version, "displayName"); - file.version_type = ModPlatform::IndexedVersionType(Json::requireInteger(version, "releaseType")); + + ModPlatform::IndexedVersionType::VersionType ver_type; + switch (Json::requireInteger(version, "releaseType")) { + case 1: + ver_type = ModPlatform::IndexedVersionType::VersionType::Release; + break; + case 2: + ver_type = ModPlatform::IndexedVersionType::VersionType::Beta; + break; + case 3: + ver_type = ModPlatform::IndexedVersionType::VersionType::Alpha; + break; + default: + ver_type = ModPlatform::IndexedVersionType::VersionType::Unknown; + } + file.version_type = ModPlatform::IndexedVersionType(ver_type); file.downloadUrl = Json::ensureString(version, "downloadUrl"); // only add if we have a download URL (third party distribution is enabled) From 34294383ebaeff65d2a66a49426b2141c2d840c1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 28 Sep 2023 23:18:23 +0300 Subject: [PATCH 369/398] added version type to dep update Signed-off-by: Trial97 --- launcher/ui/dialogs/ModUpdateDialog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 43609121e..1a70ea59a 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -219,8 +219,10 @@ void ModUpdateDialog::checkCandidates() if (dep->pack->provider == ModPlatform::ResourceProvider::FLAME) changelog = api.getModFileChangelog(dep->version.addonId.toInt(), dep->version.fileId.toInt()); auto download_task = makeShared(dep->pack, dep->version, m_mod_model); - CheckUpdateTask::UpdatableMod updatable = { dep->pack->name, dep->version.hash, "", dep->version.version, - changelog, dep->pack->provider, download_task }; + CheckUpdateTask::UpdatableMod updatable = { + dep->pack->name, dep->version.hash, "", dep->version.version, dep->version.version_type, + changelog, dep->pack->provider, download_task + }; appendMod(updatable, getRequiredBy.value(dep->version.addonId.toString())); m_tasks.insert(updatable.name, updatable.download); From 84269f95961a49434c51b67aef15822ec3028ea6 Mon Sep 17 00:00:00 2001 From: seth Date: Sat, 30 Sep 2023 12:50:26 -0400 Subject: [PATCH 370/398] refactor(nix): use addOpenGLRunpath.driverLink in wrapper Signed-off-by: seth --- nix/pkg/wrapper.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nix/pkg/wrapper.nix b/nix/pkg/wrapper.nix index 8bc255e71..cd356c8d7 100644 --- a/nix/pkg/wrapper.nix +++ b/nix/pkg/wrapper.nix @@ -4,6 +4,7 @@ symlinkJoin, prismlauncher-unwrapped, wrapQtAppsHook, + addOpenGLRunpath, qtbase, # needed for wrapQtAppsHook qtsvg, qtwayland, @@ -85,7 +86,7 @@ in in ["--prefix PRISMLAUNCHER_JAVA_PATHS : ${lib.makeSearchPath "bin/java" jdks}"] ++ lib.optionals stdenv.isLinux [ - "--set LD_LIBRARY_PATH /run/opengl-driver/lib:${lib.makeLibraryPath runtimeLibs}" + "--set LD_LIBRARY_PATH ${addOpenGLRunpath.driverLink}/lib:${lib.makeLibraryPath runtimeLibs}" # xorg.xrandr needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128 "--prefix PATH : ${lib.makeBinPath runtimePrograms}" ]; From 00bbbdc6e9f9e3e772c73b024b5f06a6ddf76f9a Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sun, 1 Oct 2023 00:31:51 +0300 Subject: [PATCH 371/398] Update launcher/LaunchController.cpp Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/LaunchController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index e1953abd6..21a146062 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -89,7 +89,7 @@ void LaunchController::decideAccount() // Tell the user they need to log in at least one account in order to play. auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"), tr("In order to play Minecraft, you must have at least one Microsoft " - "account logged in." + "account which owns Minecraft logged in." "Would you like to open the account manager to add an account now?"), QMessageBox::Information, QMessageBox::Yes | QMessageBox::No) ->exec(); From 317c7b5544a0f797593c0465d927089953c2b506 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sun, 1 Oct 2023 00:32:17 +0300 Subject: [PATCH 372/398] Update launcher/minecraft/auth/AccountList.cpp Co-authored-by: Sefa Eyeoglu Signed-off-by: Alexandru Ionut Tripon --- launcher/minecraft/auth/AccountList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index eed11e030..b141909a9 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -366,7 +366,7 @@ QVariant AccountList::headerData(int section, [[maybe_unused]] Qt::Orientation o case NameColumn: return tr("User name of the account."); case TypeColumn: - return tr("Type of the account (currently only MSA is supported.)"); + return tr("Type of the account (MSA or Offline)"); case StatusColumn: return tr("Current status of the account."); default: From be8a9f6541b2fe4cf552e8e5bb12fde4b9e83c49 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 1 Oct 2023 00:19:50 +0000 Subject: [PATCH 373/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/e12483116b3b51a185a33a272bf351e357ba9a99' (2023-09-21) → 'github:nixos/nixpkgs/bd9b686c0168041aea600222be0805a0de6e6ab8' (2023-09-29) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/4f883a76282bc28eb952570afc3d8a1bf6f481d7' (2023-09-10) → 'github:cachix/pre-commit-hooks.nix/cb770e93516a1609652fa8e945a0f310e98f10c0' (2023-09-24) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index f96336551..3ffe2dc8e 100644 --- a/flake.lock +++ b/flake.lock @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1695318763, - "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", + "lastModified": 1695978539, + "narHash": "sha256-lta5HToBZMWZ2hl5CautNSUgIZViR41QxN7JKbMAjgQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", + "rev": "bd9b686c0168041aea600222be0805a0de6e6ab8", "type": "github" }, "original": { @@ -153,11 +153,11 @@ ] }, "locked": { - "lastModified": 1694364351, - "narHash": "sha256-oadhSCqopYXxURwIA6/Anpe5IAG11q2LhvTJNP5zE6o=", + "lastModified": 1695576016, + "narHash": "sha256-71KxwRhTfVuh7kNrg3/edNjYVg9DCyKZl2QIKbhRggg=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "4f883a76282bc28eb952570afc3d8a1bf6f481d7", + "rev": "cb770e93516a1609652fa8e945a0f310e98f10c0", "type": "github" }, "original": { From 2cea7454efc8195f12b077adb67acfb2f064c0bd Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 1 Oct 2023 23:04:19 +0300 Subject: [PATCH 374/398] fix: do not update mods if no mod loader is selected Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 69c34dafe..625d37933 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -206,6 +206,14 @@ void ModFolderPage::installMods() void ModFolderPage::updateMods() { + if (m_instance->typeName() != "Minecraft") + return; // this is a null instance or a legacy instance + + auto profile = static_cast(m_instance)->getPackProfile(); + if (!profile->getModLoaders().has_value()) { + QMessageBox::critical(this, tr("Error"), tr("Please install a mod loader first!")); + return; + } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto mods_list = m_model->selectedMods(selection); From 93be8b07356058f85dd2977f941ab1fe219b36de Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 2 Oct 2023 09:13:02 +0300 Subject: [PATCH 375/398] refresh default account when list changes Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 64873ebb8..1202c3319 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -363,7 +363,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi // Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit. // Template hell sucks... connect(APPLICATION->accounts().get(), &AccountList::defaultAccountChanged, [this] { defaultAccountChanged(); }); - connect(APPLICATION->accounts().get(), &AccountList::listChanged, [this] { repopulateAccountsMenu(); }); + connect(APPLICATION->accounts().get(), &AccountList::listChanged, [this] { defaultAccountChanged(); }); // Show initial account defaultAccountChanged(); From 8069de29b2857a357809c3d99a8b07c1bcb49b74 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 2 Oct 2023 18:03:00 +0300 Subject: [PATCH 376/398] fix folder attributes on windows copy Signed-off-by: Trial97 --- launcher/FileSystem.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index defb2cb9e..1f60a7db2 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -238,6 +238,28 @@ bool ensureFolderPathExists(QString foldernamepath) return success; } +bool copyFileAttributes(QString src, QString dst) +{ +#ifdef Q_OS_WIN32 + auto attrs = GetFileAttributesW(src.toStdWString().c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) + return false; + return SetFileAttributesW(dst.toStdWString().c_str(), attrs); +#endif + return true; +} + +// needs folders to exists +void copyFolderAttributes(QString src, QString dst, QString relative) +{ + auto path = PathCombine(src, relative); + QDir dsrc(src); + while ((path = QFileInfo(path).path()).length() >= src.length()) { + auto dst_path = PathCombine(dst, dsrc.relativeFilePath(path)); + copyFileAttributes(path, dst_path); + } +} + /** * @brief Copies a directory and it's contents from src to dest * @param offset subdirectory form src to copy to dest @@ -273,6 +295,9 @@ bool copy::operator()(const QString& offset, bool dryRun) auto dst_path = PathCombine(dst, relative_dst_path); if (!dryRun) { ensureFilePathExists(dst_path); +#ifdef Q_OS_WIN32 + copyFolderAttributes(src, dst, relative_dst_path); +#endif fs::copy(StringUtils::toStdString(src_path), StringUtils::toStdString(dst_path), opt, err); } if (err) { From 77979b4c953aeff261a8d8bdd5b8a44297012de8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 3 Oct 2023 17:23:26 +0300 Subject: [PATCH 377/398] revert back the release order Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.cpp | 4 +--- launcher/modplatform/flame/FlameModIndex.cpp | 3 +-- launcher/modplatform/modrinth/ModrinthPackIndex.cpp | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index a9697893d..e99ce3a56 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -133,9 +133,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - if (file_tmp.date > ver.date && - (!args.loaders.has_value() || !file_tmp.loaders || args.loaders.value() & file_tmp.loaders) && - file_tmp.version_type <= ver.version_type) + if (file_tmp.date > ver.date && (!args.loaders.has_value() || !file_tmp.loaders || args.loaders.value() & file_tmp.loaders)) ver = file_tmp; } diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 2adcd7814..345883c17 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -96,9 +96,8 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = a.version_type <= b.version_type; // dates are in RFC 3339 format - return a.date > b.date && a_better_release; + return a.date > b.date; }; std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); pack.versions = unsortedVersions; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index f1e77d465..5c8aed1ac 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -109,9 +109,8 @@ void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArra unsortedVersions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { - bool a_better_release = a.version_type <= b.version_type; // dates are in RFC 3339 format - return a.date > b.date && a_better_release; + return a.date > b.date; }; std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); pack.versions = unsortedVersions; From 3cba5adb5af0bac91f19805fbbc7a99611c6b5a5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 4 Oct 2023 09:41:40 +0300 Subject: [PATCH 378/398] updated dependency cycle Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index bd1fe9401..df8c690af 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -94,7 +94,7 @@ QList GetModDependenciesTask::getDependenciesForVersion for (auto ver_dep : version.dependencies) { if (ver_dep.type != ModPlatform::DependencyType::REQUIRED) continue; - + ver_dep = getOverride(ver_dep, providerName); auto isOnlyVersion = providerName == ModPlatform::ResourceProvider::MODRINTH && ver_dep.addonId.toString().isEmpty(); if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), [&ver_dep, isOnlyVersion](const ModPlatform::Dependency& i) { @@ -127,7 +127,7 @@ QList GetModDependenciesTask::getDependenciesForVersion dep != m_pack_dependencies.end()) // check loaded dependencies continue; - c_dependencies.append(getOverride(ver_dep, providerName)); + c_dependencies.append(ver_dep); } return c_dependencies; } From c78d4e7bb624cd79fcd330708040d92b9e607c88 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 4 Oct 2023 19:16:21 +0300 Subject: [PATCH 379/398] added version test for snapshot Signed-off-by: Trial97 --- tests/Version_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Version_test.cpp b/tests/Version_test.cpp index d25bf7bb5..4c67cc544 100644 --- a/tests/Version_test.cpp +++ b/tests/Version_test.cpp @@ -55,6 +55,8 @@ class VersionTest : public QObject { << "2.2.0" << true << false; QTest::newRow("lessThan, two-digit") << "1.41" << "1.42" << true << false; + QTest::newRow("lessThan, snapshot") << "1.20.0-rc2" + << "1.20.1" << true << false; QTest::newRow("greaterThan, explicit 1") << "1.2.1" << "1.2.0" << false << false; @@ -72,6 +74,8 @@ class VersionTest : public QObject { << "1.2" << false << false; QTest::newRow("greaterThan, two-digit") << "1.42" << "1.41" << false << false; + QTest::newRow("greaterThan, snapshot") << "1.20.2-rc2" + << "1.20.1" << false << false; } private slots: From e913f61305de434cda5755f1db6bd3bb2ce4ea5e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 4 Oct 2023 19:29:37 +0300 Subject: [PATCH 380/398] added a more strict condition for neoforge forge support Signed-off-by: Trial97 --- launcher/minecraft/PackProfile.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index 31974cd00..aea78b552 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -1018,8 +1018,7 @@ std::optional PackProfile::getSupportedModLoaders() // TODO: remove this or add version condition once Quilt drops official Fabric support if (loaders & ModPlatform::Quilt) loaders |= ModPlatform::Fabric; - Version instance_ver{ getComponentVersion("net.minecraft") }; - if (instance_ver <= Version("1.20.1") && loaders & ModPlatform::NeoForge) + if (getComponentVersion("net.minecraft") == "1.20.1" && loaders & ModPlatform::NeoForge) loaders |= ModPlatform::Forge; return loaders; } From c6c17036e3842e0197c1c1aa4207f45610b812a7 Mon Sep 17 00:00:00 2001 From: nea Date: Wed, 4 Oct 2023 21:20:59 +0200 Subject: [PATCH 381/398] Add more Java installation dirs Signed-off-by: nea --- launcher/java/JavaUtils.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index 3512c3079..cca1ed6d4 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -403,6 +403,14 @@ QList JavaUtils::FindJavaPaths() scanJavaDirs("/opt/jdks"); // flatpak scanJavaDirs("/app/jdk"); + + auto home = qEnvironmentVariable("HOME"); + + // javas downloaded by IntelliJ + scanJavaDirs(FS::PathCombine(home, ".jdks")); + // javas downloaded by sdkman + scanJavaDirs(FS::PathCombine(home, ".sdkman/candidates/java")); + javas = addJavasFromEnv(javas); javas.removeDuplicates(); return javas; From b67c2c71d10945775b9121c5f22e2b1ac5531fe8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 5 Oct 2023 22:44:49 +0300 Subject: [PATCH 382/398] removed windows legacy builds Signed-off-by: Trial97 --- .github/workflows/build.yml | 12 ------------ .github/workflows/trigger_release.yml | 10 +++------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 059795a11..4665a7d56 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,18 +54,6 @@ jobs: msystem: clang64 vcvars_arch: 'amd64_x86' - - os: windows-2022 - name: "Windows-MSVC-Legacy" - msystem: '' - architecture: 'win32' - vcvars_arch: 'amd64_x86' - qt_ver: 5 - qt_host: windows - qt_arch: 'win32_msvc2019' - qt_version: '5.15.2' - qt_modules: '' - qt_tools: 'tools_openssl_x86' - - os: windows-2022 name: "Windows-MSVC" msystem: '' diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index bda75e354..b67346d80 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -3,10 +3,9 @@ name: Build Application and Make Release on: push: tags: - - '*' + - "*" jobs: - build_release: name: Build Release uses: ./.github/workflows/build.yml @@ -28,8 +27,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - submodules: 'true' - path: 'PrismLauncher-source' + submodules: "true" + path: "PrismLauncher-source" - name: Download artifacts uses: actions/download-artifact@v3 - name: Grab and store version @@ -95,9 +94,6 @@ jobs: PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe - PrismLauncher-Windows-MSVC-Legacy-${{ env.VERSION }}.zip - PrismLauncher-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip - PrismLauncher-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe PrismLauncher-Windows-MSVC-arm64-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe From d49f81d132f57089361dd7f8af0e0ef1781028e0 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 6 Oct 2023 11:27:04 +0100 Subject: [PATCH 383/398] Drop leftover mod loader settings I messed up the merge. Signed-off-by: TheKodeToad --- launcher/Application.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 6209acf76..e5bbf2f30 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -579,9 +579,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("IgnoreJavaCompatibility", false); m_settings->registerSetting("IgnoreJavaWizard", false); - // Mod loader settings - m_settings->registerSetting("DisableQuiltBeacon", false); - // Legacy settings m_settings->registerSetting("OnlineFixes", true); From bca5e8f3952d44a1ff517123ff51ab439b295f84 Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Fri, 6 Oct 2023 16:16:03 +0300 Subject: [PATCH 384/398] Update launcher/minecraft/PackProfile.cpp Co-authored-by: TheKodeToad Signed-off-by: Alexandru Ionut Tripon --- launcher/minecraft/PackProfile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index aea78b552..9e706ae0a 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -1018,7 +1018,7 @@ std::optional PackProfile::getSupportedModLoaders() // TODO: remove this or add version condition once Quilt drops official Fabric support if (loaders & ModPlatform::Quilt) loaders |= ModPlatform::Fabric; - if (getComponentVersion("net.minecraft") == "1.20.1" && loaders & ModPlatform::NeoForge) + if (getComponentVersion("net.minecraft") == "1.20.1" && (loaders & ModPlatform::NeoForge)) loaders |= ModPlatform::Forge; return loaders; } From 05caa874bc3550c370ea6f278c1849cc481b8125 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 8 Oct 2023 00:18:30 +0000 Subject: [PATCH 385/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-compat': 'github:edolstra/flake-compat/35bb57c0c8d8b62bbfd284272c928ceb64ddbde9' (2023-01-17) → 'github:edolstra/flake-compat/0f9255e01c2351cc7d116c072cb317785dd33b33' (2023-10-04) • Updated input 'flake-parts': 'github:hercules-ci/flake-parts/7f53fdb7bdc5bb237da7fefef12d099e4fd611ca' (2023-09-01) → 'github:hercules-ci/flake-parts/c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4' (2023-10-03) • Updated input 'flake-parts/nixpkgs-lib': 'github:NixOS/nixpkgs/3e52e76b70d5508f3cec70b882a29199f4d1ee85?dir=lib' (2023-08-31) → 'github:NixOS/nixpkgs/f5892ddac112a1e9b3612c39af1b72987ee5783a?dir=lib' (2023-09-29) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/bd9b686c0168041aea600222be0805a0de6e6ab8' (2023-09-29) → 'github:nixos/nixpkgs/2de1be5b51c3d6fa833f1c1f222dc867dd054b31' (2023-10-07) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/cb770e93516a1609652fa8e945a0f310e98f10c0' (2023-09-24) → 'github:cachix/pre-commit-hooks.nix/66c352d33e0907239e4a69416334f64af2c685cc' (2023-10-05) --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 3ffe2dc8e..b381db5ae 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "owner": "edolstra", "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { @@ -21,11 +21,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1693611461, - "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", "type": "github" }, "original": { @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1695978539, - "narHash": "sha256-lta5HToBZMWZ2hl5CautNSUgIZViR41QxN7JKbMAjgQ=", + "lastModified": 1696661029, + "narHash": "sha256-GIB5VTkvsDIqfMpdtuetOzpm64P8wm8nBSv5Eo8XM3Y=", "owner": "nixos", "repo": "nixpkgs", - "rev": "bd9b686c0168041aea600222be0805a0de6e6ab8", + "rev": "2de1be5b51c3d6fa833f1c1f222dc867dd054b31", "type": "github" }, "original": { @@ -123,11 +123,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1693471703, - "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "type": "github" }, "original": { @@ -153,11 +153,11 @@ ] }, "locked": { - "lastModified": 1695576016, - "narHash": "sha256-71KxwRhTfVuh7kNrg3/edNjYVg9DCyKZl2QIKbhRggg=", + "lastModified": 1696516544, + "narHash": "sha256-8rKE8Je6twTNFRTGF63P9mE3lZIq917RAicdc4XJO80=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "cb770e93516a1609652fa8e945a0f310e98f10c0", + "rev": "66c352d33e0907239e4a69416334f64af2c685cc", "type": "github" }, "original": { From 5f5214e5dd21d70efb8481bf3aea0bb0dabf4b12 Mon Sep 17 00:00:00 2001 From: Muslim <42213155+GitMuslim@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:00:57 +0300 Subject: [PATCH 386/398] add fullstop Signed-off-by: Muslim <42213155+GitMuslim@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 641622b5c..8761b950a 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS* For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions: -[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-git) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-A80030?label=MPR&logo=debian&logoColor=white)](https://mpr.makedeb.org/packages/prismlauncher-git)
[![prismlauncher-nightly](https://img.shields.io/badge/copr-prismlauncher--nightly-51A2DA?label=COPR&logo=fedora&logoColor=white)](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [![prismlauncher-nightly](https://img.shields.io/badge/OBS-prismlauncher--nightly-3AB6A9?logo=opensuse&logoColor=white)](https://build.opensuse.org/project/show/home:getchoo) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-4D4270?label=Gentoo&logo=gentoo&logoColor=white)](https://packages.gentoo.org/packages/games-action/prismlauncher) +[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-git) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-A80030?label=MPR&logo=debian&logoColor=white)](https://mpr.makedeb.org/packages/prismlauncher-git)
[![prismlauncher-nightly](https://img.shields.io/badge/copr-prismlauncher--nightly-51A2DA?label=COPR&logo=fedora&logoColor=white)](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [![prismlauncher-nightly](https://img.shields.io/badge/OBS-prismlauncher--nightly-3AB6A9?logo=opensuse&logoColor=white)](https://build.opensuse.org/project/show/home:getchoo) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-4D4270?label=Gentoo&logo=gentoo&logoColor=white)](https://packages.gentoo.org/packages/games-action/prismlauncher). These packages are also availiable to all the distributions based on the ones mentioned above. From 8eb8f167ab86647da60fe81997acc397ddbd438d Mon Sep 17 00:00:00 2001 From: Muslim <42213155+GitMuslim@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:02:56 +0300 Subject: [PATCH 387/398] oops Signed-off-by: Muslim <42213155+GitMuslim@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8761b950a..093bc94da 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Prebuilt Development builds are provided for **Linux**, **Windows** and **macOS* For **Arch**, **Debian**, **Fedora**, **OpenSUSE (Tumbleweed)** and **Gentoo**, respectively, you can use these packages for the latest development versions: -[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-git) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-A80030?label=MPR&logo=debian&logoColor=white)](https://mpr.makedeb.org/packages/prismlauncher-git)
[![prismlauncher-nightly](https://img.shields.io/badge/copr-prismlauncher--nightly-51A2DA?label=COPR&logo=fedora&logoColor=white)](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [![prismlauncher-nightly](https://img.shields.io/badge/OBS-prismlauncher--nightly-3AB6A9?logo=opensuse&logoColor=white)](https://build.opensuse.org/project/show/home:getchoo) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-4D4270?label=Gentoo&logo=gentoo&logoColor=white)](https://packages.gentoo.org/packages/games-action/prismlauncher). +[![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-git) [![prismlauncher-git](https://img.shields.io/badge/aur-prismlauncher--qt5--git-1793D1?label=AUR&logo=archlinux&logoColor=white)](https://aur.archlinux.org/packages/prismlauncher-qt5-git) [![prismlauncher-git](https://img.shields.io/badge/mpr-prismlauncher--git-A80030?label=MPR&logo=debian&logoColor=white)](https://mpr.makedeb.org/packages/prismlauncher-git)
[![prismlauncher-nightly](https://img.shields.io/badge/copr-prismlauncher--nightly-51A2DA?label=COPR&logo=fedora&logoColor=white)](https://copr.fedorainfracloud.org/coprs/g3tchoo/prismlauncher/) [![prismlauncher-nightly](https://img.shields.io/badge/OBS-prismlauncher--nightly-3AB6A9?logo=opensuse&logoColor=white)](https://build.opensuse.org/project/show/home:getchoo) [![prismlauncher-9999](https://img.shields.io/badge/gentoo-prismlauncher--9999-4D4270?label=Gentoo&logo=gentoo&logoColor=white)](https://packages.gentoo.org/packages/games-action/prismlauncher) These packages are also availiable to all the distributions based on the ones mentioned above. @@ -50,7 +50,7 @@ Feel free to create a GitHub issue if you find a bug or want to suggest a new fe ## Translations -The translation effort for Prism Launcher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at +The translation effort for Prism Launcher is hosted on [Weblate](https://hosted.weblate.org/projects/prismlauncher/launcher/) and information about translating Prism Launcher is available at . ## Building From 5cb6d931360ff9924164f4bc08050674a93b87aa Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 9 Oct 2023 22:25:45 +0300 Subject: [PATCH 388/398] fixed updater build Signed-off-by: Trial97 --- launcher/net/NetJob.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp index b99c5acb0..784d81c37 100644 --- a/launcher/net/NetJob.cpp +++ b/launcher/net/NetJob.cpp @@ -36,11 +36,16 @@ */ #include "NetJob.h" +#if defined(LAUNCHER_APPLICATION) #include "Application.h" +#endif -NetJob::NetJob(QString job_name, shared_qobject_ptr network) - : ConcurrentTask(nullptr, job_name, APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()), m_network(network) -{} +NetJob::NetJob(QString job_name, shared_qobject_ptr network) : ConcurrentTask(nullptr, job_name), m_network(network) +{ +#if defined(LAUNCHER_APPLICATION) + setMaxConcurrent(APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt()); +#endif +} auto NetJob::addNetAction(NetAction::Ptr action) -> bool { From 32eaaa25d984519a3fddc9844f921c3b22f4d5de Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 13 Oct 2023 00:04:36 +0300 Subject: [PATCH 389/398] removed the better release for modrinth modpacks Signed-off-by: Trial97 --- launcher/modplatform/modrinth/ModrinthPackManifest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp index a154317fe..c1531a94d 100644 --- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp @@ -111,9 +111,8 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc) unsortedVersions.append(file); } auto orderSortPredicate = [](const ModpackVersion& a, const ModpackVersion& b) -> bool { - bool a_better_release = a.version_type <= b.version_type; // dates are in RFC 3339 format - return a.date > b.date && a_better_release; + return a.date > b.date; }; std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); From 023b3e3c3945592845fcae6eec8fc9d90871d2c2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 14 Oct 2023 09:40:56 +0300 Subject: [PATCH 390/398] Fixed arch build Signed-off-by: Trial97 --- launcher/translations/TranslationsModel.cpp | 36 +++++++++++---------- launcher/translations/TranslationsModel.h | 4 ++- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 933fe2d35..56ade8e32 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -206,7 +206,7 @@ void TranslationsModel::indexReceived() reloadLocalFiles(); auto language = d->m_system_locale; - if (!findLanguage(language)) { + if (!findLanguageAsOptional(language).has_value()) { language = d->m_system_language; } selectLanguage(language); @@ -417,14 +417,17 @@ int TranslationsModel::columnCount([[maybe_unused]] const QModelIndex& parent) c return 2; } -Language* TranslationsModel::findLanguage(const QString& key) +QVector::Iterator TranslationsModel::findLanguage(const QString& key) { - auto found = std::find_if(d->m_languages.begin(), d->m_languages.end(), [&](Language& lang) { return lang.key == key; }); - if (found == d->m_languages.end()) { - return nullptr; - } else { - return found; - } + return std::find_if(d->m_languages.begin(), d->m_languages.end(), [&](Language& lang) { return lang.key == key; }); +} + +std::optional TranslationsModel::findLanguageAsOptional(const QString& key) +{ + auto found = findLanguage(key); + if (found != d->m_languages.end()) + return *found; + return {}; } void TranslationsModel::setUseSystemLocale(bool useSystemLocale) @@ -436,13 +439,13 @@ void TranslationsModel::setUseSystemLocale(bool useSystemLocale) bool TranslationsModel::selectLanguage(QString key) { QString& langCode = key; - auto langPtr = findLanguage(key); + auto langPtr = findLanguageAsOptional(key); if (langCode.isEmpty()) { d->no_language_set = true; } - if (!langPtr) { + if (!langPtr.has_value()) { qWarning() << "Selected invalid language" << key << ", defaulting to" << defaultLangCode; langCode = defaultLangCode; } else { @@ -527,9 +530,8 @@ bool TranslationsModel::selectLanguage(QString key) QModelIndex TranslationsModel::selectedIndex() { auto found = findLanguage(d->m_selectedLanguage); - if (found) { - // QVector iterator freely converts to pointer to contained type - return index(found - d->m_languages.begin(), 0, QModelIndex()); + if (found != d->m_languages.end()) { + return index(std::distance(d->m_languages.begin(), found), 0, QModelIndex()); } return QModelIndex(); } @@ -562,8 +564,8 @@ void TranslationsModel::updateLanguage(QString key) qWarning() << "Cannot update builtin language" << key; return; } - auto found = findLanguage(key); - if (!found) { + auto found = findLanguageAsOptional(key); + if (!found.has_value()) { qWarning() << "Cannot update invalid language" << key; return; } @@ -578,8 +580,8 @@ void TranslationsModel::downloadTranslation(QString key) d->m_nextDownload = key; return; } - auto lang = findLanguage(key); - if (!lang) { + auto lang = findLanguageAsOptional(key); + if (!lang.has_value()) { qWarning() << "Will not download an unknown translation" << key; return; } diff --git a/launcher/translations/TranslationsModel.h b/launcher/translations/TranslationsModel.h index cff23ce74..96a0e9f8b 100644 --- a/launcher/translations/TranslationsModel.h +++ b/launcher/translations/TranslationsModel.h @@ -17,6 +17,7 @@ #include #include +#include struct Language; @@ -40,7 +41,8 @@ class TranslationsModel : public QAbstractListModel { void setUseSystemLocale(bool useSystemLocale); private: - Language* findLanguage(const QString& key); + QVector::Iterator findLanguage(const QString& key); + std::optional findLanguageAsOptional(const QString& key); void reloadLocalFiles(); void downloadTranslation(QString key); void downloadNext(); From 4939a33456916ceb03fbe04bb850089895cbf62d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Oct 2023 00:18:39 +0000 Subject: [PATCH 391/398] chore(nix): update lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:nixos/nixpkgs/2de1be5b51c3d6fa833f1c1f222dc867dd054b31' (2023-10-07) → 'github:nixos/nixpkgs/01441e14af5e29c9d27ace398e6dd0b293e25a54' (2023-10-11) • Updated input 'pre-commit-hooks': 'github:cachix/pre-commit-hooks.nix/66c352d33e0907239e4a69416334f64af2c685cc' (2023-10-05) → 'github:cachix/pre-commit-hooks.nix/42e1b6095ef80a51f79595d9951eb38e91c4e6ca' (2023-10-09) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index b381db5ae..ad18ff615 100644 --- a/flake.lock +++ b/flake.lock @@ -106,11 +106,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1696661029, - "narHash": "sha256-GIB5VTkvsDIqfMpdtuetOzpm64P8wm8nBSv5Eo8XM3Y=", + "lastModified": 1697009197, + "narHash": "sha256-viVRhBTFT8fPJTb1N3brQIpFZnttmwo3JVKNuWRVc3s=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2de1be5b51c3d6fa833f1c1f222dc867dd054b31", + "rev": "01441e14af5e29c9d27ace398e6dd0b293e25a54", "type": "github" }, "original": { @@ -153,11 +153,11 @@ ] }, "locked": { - "lastModified": 1696516544, - "narHash": "sha256-8rKE8Je6twTNFRTGF63P9mE3lZIq917RAicdc4XJO80=", + "lastModified": 1696846637, + "narHash": "sha256-0hv4kbXxci2+pxhuXlVgftj/Jq79VSmtAyvfabCCtYk=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "66c352d33e0907239e4a69416334f64af2c685cc", + "rev": "42e1b6095ef80a51f79595d9951eb38e91c4e6ca", "type": "github" }, "original": { From 7112d04df58e3cdf1e149157fe133f76c888da5e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 15 Oct 2023 14:11:08 +0100 Subject: [PATCH 392/398] Mark setting as optional Signed-off-by: TheKodeToad --- launcher/Application.cpp | 2 +- launcher/ui/pages/global/MinecraftPage.ui | 4 ++-- launcher/ui/pages/instance/InstanceSettingsPage.ui | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/launcher/Application.cpp b/launcher/Application.cpp index e5bbf2f30..73f594d17 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -580,7 +580,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("IgnoreJavaWizard", false); // Legacy settings - m_settings->registerSetting("OnlineFixes", true); + m_settings->registerSetting("OnlineFixes", false); // Native library workarounds m_settings->registerSetting("UseNativeOpenAL", false); diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 79785fc92..2a3c0d96d 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -138,7 +138,7 @@
- + Show time spent playing in hours @@ -209,7 +209,7 @@ <html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>This currently allows modern skins to be used.</p></body></html> - Enable online fixes + Enable online fixes (experimental) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index f4f4c5a9d..20992df6d 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -39,7 +39,7 @@ QTabWidget::Rounded - 0 + 5 @@ -601,7 +601,7 @@ <html><head/><body><p>Emulates usages of old online services which are no longer operating.</p><p>This currently allows modern skins to be used.</p></body></html> - Enable online fixes + Enable online fixes (experimental) From 6fb7a98901784ecb1052db2aa8e0dca1b3f0d920 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 15 Oct 2023 14:45:05 +0100 Subject: [PATCH 393/398] =?UTF-8?q?Fix=20small=20mistake=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/InstanceSettingsPage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 20992df6d..8defaccb3 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -39,7 +39,7 @@ QTabWidget::Rounded - 5 + 0 From ef0813754be290ed842b5acaa62d2de7fa620291 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 15 Oct 2023 17:56:11 +0300 Subject: [PATCH 394/398] added explicit qt version for linux portable Signed-off-by: Trial97 --- .github/workflows/build.yml | 56 +++++++++++++-------------- .github/workflows/trigger_release.yml | 10 ++--- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3c05747d0..ee5662ba6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,58 +43,58 @@ jobs: - os: ubuntu-20.04 qt_ver: 6 qt_host: linux - qt_arch: '' - qt_version: '6.2.4' - qt_modules: 'qt5compat qtimageformats' - qt_tools: '' + qt_arch: "" + qt_version: "6.2.4" + qt_modules: "qt5compat qtimageformats" + qt_tools: "" - os: windows-2022 name: "Windows-MinGW-w64" msystem: clang64 - vcvars_arch: 'amd64_x86' + vcvars_arch: "amd64_x86" - os: windows-2022 name: "Windows-MSVC" - msystem: '' - architecture: 'x64' - vcvars_arch: 'amd64' + msystem: "" + architecture: "x64" + vcvars_arch: "amd64" qt_ver: 6 qt_host: windows - qt_arch: '' - qt_version: '6.5.2' - qt_modules: 'qt5compat qtimageformats' - qt_tools: '' + qt_arch: "" + qt_version: "6.5.2" + qt_modules: "qt5compat qtimageformats" + qt_tools: "" - os: windows-2022 name: "Windows-MSVC-arm64" - msystem: '' - architecture: 'arm64' - vcvars_arch: 'amd64_arm64' + msystem: "" + architecture: "arm64" + vcvars_arch: "amd64_arm64" qt_ver: 6 qt_host: windows - qt_arch: 'win64_msvc2019_arm64' - qt_version: '6.5.2' - qt_modules: 'qt5compat qtimageformats' - qt_tools: '' + qt_arch: "win64_msvc2019_arm64" + qt_version: "6.5.2" + qt_modules: "qt5compat qtimageformats" + qt_tools: "" - os: macos-12 name: macOS macosx_deployment_target: 11.0 qt_ver: 6 qt_host: mac - qt_arch: '' - qt_version: '6.5.2' - qt_modules: 'qt5compat qtimageformats' - qt_tools: '' + qt_arch: "" + qt_version: "6.5.2" + qt_modules: "qt5compat qtimageformats" + qt_tools: "" - os: macos-12 name: macOS-Legacy macosx_deployment_target: 10.13 qt_ver: 5 qt_host: mac - qt_version: '5.15.2' - qt_modules: '' - qt_tools: '' + qt_version: "5.15.2" + qt_modules: "" + qt_tools: "" runs-on: ${{ matrix.os }} @@ -547,14 +547,14 @@ jobs: if: runner.os == 'Linux' && matrix.qt_ver != 6 uses: actions/upload-artifact@v3 with: - name: PrismLauncher-${{ runner.os }}-${{ env.VERSION }}-${{ inputs.build_type }} + name: PrismLauncher-${{ runner.os }}-Qt5-${{ env.VERSION }}-${{ inputs.build_type }} path: PrismLauncher.tar.gz - name: Upload binary tarball (Linux, portable, Qt 5) if: runner.os == 'Linux' && matrix.qt_ver != 6 uses: actions/upload-artifact@v3 with: - name: PrismLauncher-${{ runner.os }}-Portable-${{ env.VERSION }}-${{ inputs.build_type }} + name: PrismLauncher-${{ runner.os }}-Qt5-Portable-${{ env.VERSION }}-${{ inputs.build_type }} path: PrismLauncher-portable.tar.gz - name: Upload binary tarball (Linux, Qt 6) diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index 98842664d..28578165f 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -41,9 +41,9 @@ jobs: run: | mv ${{ github.workspace }}/PrismLauncher-source PrismLauncher-${{ env.VERSION }} mv PrismLauncher-Linux-Qt6-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz - mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz - mv PrismLauncher-Linux-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz - mv PrismLauncher-Linux*/PrismLauncher.tar.gz PrismLauncher-Linux-${{ env.VERSION }}.tar.gz + mv PrismLauncher-Linux-Qt6*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz + mv PrismLauncher-Linux-Qt5-Portable*/PrismLauncher-portable.tar.gz PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz + mv PrismLauncher-Linux-Qt5*/PrismLauncher.tar.gz PrismLauncher-Linux-Qt5-${{ env.VERSION }}.tar.gz mv PrismLauncher-*.AppImage/PrismLauncher-*.AppImage PrismLauncher-Linux-x86_64.AppImage mv PrismLauncher-*.AppImage.zsync/PrismLauncher-*.AppImage.zsync PrismLauncher-Linux-x86_64.AppImage.zsync mv PrismLauncher-macOS-Legacy*/PrismLauncher.tar.gz PrismLauncher-macOS-Legacy-${{ env.VERSION }}.tar.gz @@ -87,8 +87,8 @@ jobs: draft: true prerelease: false files: | - PrismLauncher-Linux-${{ env.VERSION }}.tar.gz - PrismLauncher-Linux-Portable-${{ env.VERSION }}.tar.gz + PrismLauncher-Linux-Qt5-${{ env.VERSION }}.tar.gz + PrismLauncher-Linux-Qt5-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-x86_64.AppImage PrismLauncher-Linux-x86_64.AppImage.zsync PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz From 6c9856b9dc8380cec9060156e464ca24b5533a5a Mon Sep 17 00:00:00 2001 From: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:42:16 +0200 Subject: [PATCH 395/398] chore: bump Qt to Qt 6.6.0 Signed-off-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4665a7d56..0521c00c7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: '' - qt_version: '6.5.2' + qt_version: '6.6.0' qt_modules: 'qt5compat qtimageformats' qt_tools: '' @@ -74,7 +74,7 @@ jobs: qt_ver: 6 qt_host: windows qt_arch: 'win64_msvc2019_arm64' - qt_version: '6.5.2' + qt_version: '6.6.0' qt_modules: 'qt5compat qtimageformats' qt_tools: '' @@ -84,7 +84,7 @@ jobs: qt_ver: 6 qt_host: mac qt_arch: '' - qt_version: '6.5.2' + qt_version: '6.6.0' qt_modules: 'qt5compat qtimageformats' qt_tools: '' From b1bd0ceadef1eeab7e4f5d10f26ba1865f46525e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 17 Oct 2023 09:29:47 +0300 Subject: [PATCH 396/398] fixed code signing for appImage Signed-off-by: Trial97 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e542d4e5..8077ea59a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -501,7 +501,7 @@ jobs: export SIGN=1 export SIGN_KEY=${{ secrets.GPG_PRIVATE_KEY_ID }} mkdir -p ~/.gnupg/ - printf "$GPG_PRIVATE_KEY" | base64 --decode > ~/.gnupg/private.key + echo "$GPG_PRIVATE_KEY" > ~/.gnupg/private.key gpg --import ~/.gnupg/private.key else echo ":warning: Skipped code signing for Linux AppImage, as gpg key was not present." >> $GITHUB_STEP_SUMMARY From d348f20dd994c7c60510e33d9ec0496d961f45d1 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Tue, 17 Oct 2023 10:00:17 +0200 Subject: [PATCH 397/398] fix: allow loading themes with missing resources folder Signed-off-by: Sefa Eyeoglu --- launcher/ui/themes/CustomTheme.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 29ecf6254..4859983c6 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -165,11 +165,15 @@ CustomTheme::CustomTheme(ITheme* baseTheme, QFileInfo& fileInfo, bool isManifest QString path = FS::PathCombine("themes", m_id); QString pathResources = FS::PathCombine("themes", m_id, "resources"); - if (!FS::ensureFolderPathExists(path) || !FS::ensureFolderPathExists(pathResources)) { - themeWarningLog() << "couldn't create folder for theme!"; + if (!FS::ensureFolderPathExists(path)) { + themeWarningLog() << "Theme directory for" << m_id << "could not be created. This theme might be invalid"; return; } + if (!FS::ensureFolderPathExists(pathResources)) { + themeWarningLog() << "Resources directory for" << m_id << "could not be created"; + } + auto themeFilePath = FS::PathCombine(path, themeFile); bool jsonDataIncomplete = false; @@ -230,7 +234,11 @@ CustomTheme::CustomTheme(ITheme* baseTheme, QFileInfo& fileInfo, bool isManifest QStringList CustomTheme::searchPaths() { - return { FS::PathCombine("themes", m_id, "resources") }; + QString pathResources = FS::PathCombine("themes", m_id, "resources"); + if (QFileInfo::exists(pathResources)) + return { pathResources }; + + return {}; } QString CustomTheme::id() From 069bc887f1f74b9ea29130d33042bafc82d97f57 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 17 Oct 2023 19:05:05 -0400 Subject: [PATCH 398/398] fix: don't always build updater on platforms besides mac Signed-off-by: seth --- CMakeLists.txt | 5 +++++ launcher/CMakeLists.txt | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be443fe31..faeb1c44e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -347,6 +347,11 @@ add_subdirectory(program_info) ####################################### Install layout ####################################### set(Launcher_ENABLE_UPDATER NO) +set(Launcher_BUILD_UPDATER NO) + +if (NOT APPLE AND (NOT Launcher_UPDATER_GITHUB_REPO STREQUAL "" AND NOT Launcher_BUILD_ARTIFACT STREQUAL "")) + set(Launcher_BUILD_UPDATER YES) +endif() if(NOT (UNIX AND APPLE)) # Install "portable.txt" if selected component is "portable" diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index d15dc85de..19b837a2f 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1306,7 +1306,7 @@ install(TARGETS ${Launcher_Name} FRAMEWORK DESTINATION ${FRAMEWORK_DEST_DIR} COMPONENT Runtime ) -if(NOT APPLE OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER)) +if(Launcher_BUILD_UPDATER) # Updater add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})