summaryrefslogtreecommitdiff
path: root/archived/projt-launcher/tests
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
commitd3261e64152397db2dca4d691a990c6bc2a6f4dd (patch)
treefac2f7be638651181a72453d714f0f96675c2b8b /archived/projt-launcher/tests
parent31b9a8949ed0a288143e23bf739f2eb64fdc63be (diff)
downloadProject-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.tar.gz
Project-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.zip
NOISSUE add archived projects
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to 'archived/projt-launcher/tests')
-rw-r--r--archived/projt-launcher/tests/ApplicationMessage_test.cpp103
-rw-r--r--archived/projt-launcher/tests/BaseInstanceSettings_test.cpp55
-rw-r--r--archived/projt-launcher/tests/CMakeLists.txt192
-rw-r--r--archived/projt-launcher/tests/CatPack_test.cpp65
-rw-r--r--archived/projt-launcher/tests/Commandline_test.cpp76
-rw-r--r--archived/projt-launcher/tests/DataPackParse_test.cpp81
-rw-r--r--archived/projt-launcher/tests/DefaultVariable_test.cpp47
-rw-r--r--archived/projt-launcher/tests/ExponentialSeries_test.cpp49
-rw-r--r--archived/projt-launcher/tests/FileSystem_test.cpp899
-rw-r--r--archived/projt-launcher/tests/Filter_test.cpp64
-rw-r--r--archived/projt-launcher/tests/GZip_test.cpp77
-rw-r--r--archived/projt-launcher/tests/GradleSpecifier_test.cpp95
-rw-r--r--archived/projt-launcher/tests/INIFile_test.cpp226
-rw-r--r--archived/projt-launcher/tests/Index_test.cpp52
-rw-r--r--archived/projt-launcher/tests/InstanceCopyPrefs_test.cpp74
-rw-r--r--archived/projt-launcher/tests/JavaVersion_test.cpp157
-rw-r--r--archived/projt-launcher/tests/JsonHelpers_test.cpp59
-rw-r--r--archived/projt-launcher/tests/JsonTypes_test.cpp89
-rw-r--r--archived/projt-launcher/tests/Json_test.cpp211
-rw-r--r--archived/projt-launcher/tests/KonamiCode_test.cpp107
-rw-r--r--archived/projt-launcher/tests/LaunchLineRouter_test.cpp53
-rw-r--r--archived/projt-launcher/tests/LaunchLogModel_test.cpp103
-rw-r--r--archived/projt-launcher/tests/LaunchPipeline_test.cpp58
-rw-r--r--archived/projt-launcher/tests/LaunchVariableExpander_test.cpp59
-rw-r--r--archived/projt-launcher/tests/Library_test.cpp337
-rw-r--r--archived/projt-launcher/tests/LogEventParser_test.cpp123
-rw-r--r--archived/projt-launcher/tests/MMCTime_test.cpp76
-rw-r--r--archived/projt-launcher/tests/MessageLevel_test.cpp73
-rw-r--r--archived/projt-launcher/tests/MetaComponentParse_test.cpp104
-rw-r--r--archived/projt-launcher/tests/ModPlatform_test.cpp114
-rw-r--r--archived/projt-launcher/tests/MojangVersionFormat_test.cpp56
-rw-r--r--archived/projt-launcher/tests/NetHeaderProxy_test.cpp48
-rw-r--r--archived/projt-launcher/tests/NetSink_test.cpp147
-rw-r--r--archived/projt-launcher/tests/NetUtils_test.cpp100
-rw-r--r--archived/projt-launcher/tests/Packwiz_test.cpp95
-rw-r--r--archived/projt-launcher/tests/ParseUtils_test.cpp55
-rw-r--r--archived/projt-launcher/tests/ProjTExternalUpdater_test.cpp61
-rw-r--r--archived/projt-launcher/tests/ResourceFolderModel_test.cpp250
-rw-r--r--archived/projt-launcher/tests/ResourcePackParse_test.cpp78
-rw-r--r--archived/projt-launcher/tests/RuntimeVersion_test.cpp73
-rw-r--r--archived/projt-launcher/tests/SeparatorPrefixTree_test.cpp168
-rw-r--r--archived/projt-launcher/tests/ShaderPackParse_test.cpp79
-rw-r--r--archived/projt-launcher/tests/StringUtilsHtmlPatch_test.cpp38
-rw-r--r--archived/projt-launcher/tests/StringUtilsNaturalCompare_test.cpp53
-rw-r--r--archived/projt-launcher/tests/StringUtilsSplitFirst_test.cpp48
-rw-r--r--archived/projt-launcher/tests/StringUtilsTruncateUrl_test.cpp44
-rw-r--r--archived/projt-launcher/tests/StringUtils_test.cpp136
-rw-r--r--archived/projt-launcher/tests/Task_test.cpp324
-rw-r--r--archived/projt-launcher/tests/TexturePackParse_test.cpp76
-rw-r--r--archived/projt-launcher/tests/VersionFilterData_test.cpp83
-rw-r--r--archived/projt-launcher/tests/Version_test.cpp197
-rw-r--r--archived/projt-launcher/tests/WorldSaveParse_test.cpp96
-rw-r--r--archived/projt-launcher/tests/XmlLogs_test.cpp158
-rw-r--r--archived/projt-launcher/tests/testdata/CatPacks/index.json50
-rw-r--r--archived/projt-launcher/tests/testdata/DataPackParse/another_test_folder/pack.mcmeta6
-rw-r--r--archived/projt-launcher/tests/testdata/DataPackParse/test_data_pack_boogaloo.zipbin0 -> 898 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/DataPackParse/test_folder/pack.mcmeta6
-rwxr-xr-xarchived/projt-launcher/tests/testdata/FileSystem/FileSystem-test_createShortcut-unix6
-rw-r--r--archived/projt-launcher/tests/testdata/FileSystem/test_folder/.secret_folder/.secret_file.txt1
-rw-r--r--archived/projt-launcher/tests/testdata/FileSystem/test_folder/assets/minecraft/textures/blah.txt1
-rw-r--r--archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.mcmeta6
-rw-r--r--archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.nfo1
-rw-r--r--archived/projt-launcher/tests/testdata/Libraries/1.9-simple.json199
-rw-r--r--archived/projt-launcher/tests/testdata/Libraries/1.9.json547
-rw-r--r--archived/projt-launcher/tests/testdata/Libraries/codecwav-20101023.jar1
-rw-r--r--archived/projt-launcher/tests/testdata/Libraries/lib-native-arch.json46
-rw-r--r--archived/projt-launcher/tests/testdata/Libraries/lib-native.json56
-rw-r--r--archived/projt-launcher/tests/testdata/Libraries/lib-simple.json11
-rw-r--r--archived/projt-launcher/tests/testdata/Libraries/testname-testversion-linux-32.jar1
-rw-r--r--archived/projt-launcher/tests/testdata/Library/1.9-simple.json199
-rw-r--r--archived/projt-launcher/tests/testdata/Library/1.9.json547
-rw-r--r--archived/projt-launcher/tests/testdata/Library/codecwav-20101023.jar1
-rw-r--r--archived/projt-launcher/tests/testdata/Library/lib-native-arch.json46
-rw-r--r--archived/projt-launcher/tests/testdata/Library/lib-native.json56
-rw-r--r--archived/projt-launcher/tests/testdata/Library/lib-simple.json11
-rw-r--r--archived/projt-launcher/tests/testdata/Library/testname-testversion-linux-32.jar1
-rw-r--r--archived/projt-launcher/tests/testdata/MetaComponentParse/component_basic.json8
-rw-r--r--archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_extra.json21
-rw-r--r--archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_format.json13
-rw-r--r--archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_link.json12
-rw-r--r--archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_mixed.json45
-rw-r--r--archived/projt-launcher/tests/testdata/PackageManifest/1.8.0_202-x64.json4667
-rwxr-xr-xarchived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b.txt0
l---------archived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b/b.txt1
-rw-r--r--archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b.txt0
-rw-r--r--archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b/b.txt0
-rw-r--r--archived/projt-launcher/tests/testdata/Packwiz/borderless-mining.pw.toml13
-rw-r--r--archived/projt-launcher/tests/testdata/Packwiz/screenshot-to-clipboard-fabric.pw.toml13
-rw-r--r--archived/projt-launcher/tests/testdata/ResourceFolderModel/another_test_folder/pack.mcmeta6
-rw-r--r--archived/projt-launcher/tests/testdata/ResourceFolderModel/supercoolmod.jar1
-rw-r--r--archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/assets/minecraft/textures/blah.txt1
-rw-r--r--archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.mcmeta6
-rw-r--r--archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.nfo1
-rw-r--r--archived/projt-launcher/tests/testdata/ResourceFolderModel/test_resource_pack_idk.zipbin0 -> 804 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/Resources/another_test_folder/pack.mcmeta6
-rw-r--r--archived/projt-launcher/tests/testdata/Resources/supercoolmod.jar1
-rw-r--r--archived/projt-launcher/tests/testdata/Resources/test_folder/assets/minecraft/textures/blah.txt1
-rw-r--r--archived/projt-launcher/tests/testdata/Resources/test_folder/pack.mcmeta6
-rw-r--r--archived/projt-launcher/tests/testdata/Resources/test_folder/pack.nfo1
-rw-r--r--archived/projt-launcher/tests/testdata/Resources/test_resource_pack_idk.zipbin0 -> 804 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack1.zipbin0 -> 242 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack2/shaders/shaders.properties0
-rw-r--r--archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack3.zipbin0 -> 128 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-levels.txt945
-rw-r--r--archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-xml-levels.txt869
-rw-r--r--archived/projt-launcher/tests/testdata/TestLogs/vanilla-1.21.5-levels.txt25
-rw-r--r--archived/projt-launcher/tests/testdata/TexturePackParse/another_test_texturefolder/pack.txt2
-rw-r--r--archived/projt-launcher/tests/testdata/TexturePackParse/test_texture_pack_idk.zipbin0 -> 184 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/assets/minecraft/textures/blah.txt1
-rw-r--r--archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/pack.txt1
-rw-r--r--archived/projt-launcher/tests/testdata/Version/test_vectors.txt63
-rw-r--r--archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_1.zipbin0 -> 184 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_2.zipbin0 -> 352 bytes
-rw-r--r--archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_3/world_3/level.dat0
-rw-r--r--archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_4/saves/world_4/level.dat0
115 files changed, 14869 insertions, 0 deletions
diff --git a/archived/projt-launcher/tests/ApplicationMessage_test.cpp b/archived/projt-launcher/tests/ApplicationMessage_test.cpp
new file mode 100644
index 0000000000..66e7eb6df9
--- /dev/null
+++ b/archived/projt-launcher/tests/ApplicationMessage_test.cpp
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QJsonObject>
+#include <QTest>
+
+#include <ApplicationMessage.h>
+#include <Json.h>
+
+class ApplicationMessageTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_roundTrip_data()
+ {
+ QTest::addColumn<QString>("command");
+ QTest::addColumn<QStringList>("keys");
+ QTest::addColumn<QStringList>("values");
+
+ QTest::newRow("empty-args") << "open" << QStringList{} << QStringList{};
+ QTest::newRow("single-arg") << "launch" << QStringList{ "instance" } << QStringList{ "main" };
+ QTest::newRow("multi-args") << "import"
+ << QStringList{ "path", "mode", "force" }
+ << QStringList{ "/tmp/test", "zip", "true" };
+ QTest::newRow("symbols") << "cmd"
+ << QStringList{ "k-1", "k_2" }
+ << QStringList{ "value with spaces", "x=y" };
+ }
+
+ void test_roundTrip()
+ {
+ QFETCH(QString, command);
+ QFETCH(QStringList, keys);
+ QFETCH(QStringList, values);
+
+ QCOMPARE(keys.size(), values.size());
+
+ ApplicationMessage in;
+ in.command = command;
+ for (int i = 0; i < keys.size(); ++i)
+ {
+ in.args.insert(keys.at(i), values.at(i));
+ }
+
+ ApplicationMessage out;
+ out.parse(in.serialize());
+
+ QCOMPARE(out.command, command);
+ QCOMPARE(out.args.size(), keys.size());
+ for (int i = 0; i < keys.size(); ++i)
+ {
+ QCOMPARE(out.args.value(keys.at(i)), values.at(i));
+ }
+ }
+
+ void test_parseMissingArgs()
+ {
+ QJsonObject root;
+ root.insert("command", "only-command");
+
+ ApplicationMessage msg;
+ msg.parse(Json::toText(root));
+
+ QCOMPARE(msg.command, QString("only-command"));
+ QVERIFY(msg.args.isEmpty());
+ }
+
+ void test_parseInvalidDocumentThrows()
+ {
+ ApplicationMessage msg;
+ bool threw = false;
+ try
+ {
+ msg.parse("{");
+ }
+ catch (const Json::JsonException&)
+ {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+
+ void test_parseArrayThrows()
+ {
+ ApplicationMessage msg;
+ bool threw = false;
+ try
+ {
+ msg.parse("[1,2,3]");
+ }
+ catch (const Json::JsonException&)
+ {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+};
+
+QTEST_GUILESS_MAIN(ApplicationMessageTest)
+
+#include "ApplicationMessage_test.moc"
diff --git a/archived/projt-launcher/tests/BaseInstanceSettings_test.cpp b/archived/projt-launcher/tests/BaseInstanceSettings_test.cpp
new file mode 100644
index 0000000000..60b1438220
--- /dev/null
+++ b/archived/projt-launcher/tests/BaseInstanceSettings_test.cpp
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTemporaryDir>
+#include <QTest>
+
+#include <BaseInstance.h>
+#include <settings/INISettingsObject.h>
+
+class BaseInstanceSettingsTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_consoleSettings()
+ {
+ QTemporaryDir dir;
+ QVERIFY(dir.isValid());
+ auto settings = std::make_shared<INISettingsObject>(dir.filePath("instance.ini"));
+ settings->registerSetting("ConsoleMaxLines", 500);
+ settings->registerSetting("ConsoleOverflowStop", false);
+
+ settings->set("ConsoleMaxLines", 2500);
+ QCOMPARE(getConsoleMaxLines(settings), 2500);
+
+ settings->set("ConsoleMaxLines", "nope");
+ QCOMPARE(getConsoleMaxLines(settings), 500);
+
+ QVERIFY(!shouldStopOnConsoleOverflow(settings));
+ settings->set("ConsoleOverflowStop", true);
+ QVERIFY(shouldStopOnConsoleOverflow(settings));
+ }
+};
+
+QTEST_GUILESS_MAIN(BaseInstanceSettingsTest)
+
+#include "BaseInstanceSettings_test.moc"
diff --git a/archived/projt-launcher/tests/CMakeLists.txt b/archived/projt-launcher/tests/CMakeLists.txt
new file mode 100644
index 0000000000..5274754c42
--- /dev/null
+++ b/archived/projt-launcher/tests/CMakeLists.txt
@@ -0,0 +1,192 @@
+project(tests)
+
+set(LAUNCHER_TESTS "")
+
+function(launcher_add_test source name)
+ ecm_add_test(${source} LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
+ TEST_NAME ${name})
+ if(TARGET projt_cef_runtime_deps)
+ target_link_libraries(${name} projt_cef_runtime_deps)
+ endif()
+ list(APPEND LAUNCHER_TESTS ${name})
+ set_property(GLOBAL APPEND PROPERTY PROJT_LAUNCHER_TEST_TARGETS ${name})
+ set(LAUNCHER_TESTS "${LAUNCHER_TESTS}" PARENT_SCOPE)
+endfunction()
+
+launcher_add_test(FileSystem_test.cpp FileSystem)
+launcher_add_test(GZip_test.cpp GZip)
+launcher_add_test(GradleSpecifier_test.cpp GradleSpecifier)
+launcher_add_test(MojangVersionFormat_test.cpp MojangVersionFormat)
+launcher_add_test(Library_test.cpp Library)
+launcher_add_test(ResourceFolderModel_test.cpp ResourceFolderModel)
+launcher_add_test(ResourcePackParse_test.cpp ResourcePackParse)
+launcher_add_test(TexturePackParse_test.cpp TexturePackParse)
+launcher_add_test(DataPackParse_test.cpp DataPackParse)
+launcher_add_test(ShaderPackParse_test.cpp ShaderPackParse)
+launcher_add_test(WorldSaveParse_test.cpp WorldSaveParse)
+launcher_add_test(ParseUtils_test.cpp ParseUtils)
+launcher_add_test(Task_test.cpp Task)
+launcher_add_test(INIFile_test.cpp INIFile)
+launcher_add_test(ExponentialSeries_test.cpp ExponentialSeries)
+launcher_add_test(Filter_test.cpp Filter)
+launcher_add_test(JavaVersion_test.cpp JavaVersion)
+launcher_add_test(RuntimeVersion_test.cpp RuntimeVersion)
+launcher_add_test(Packwiz_test.cpp Packwiz)
+launcher_add_test(Index_test.cpp Index)
+launcher_add_test(Version_test.cpp Version)
+launcher_add_test(SeparatorPrefixTree_test.cpp SeparatorPrefixTree)
+launcher_add_test(StringUtils_test.cpp StringUtils)
+launcher_add_test(Json_test.cpp Json)
+launcher_add_test(NetUtils_test.cpp NetUtils)
+launcher_add_test(ModPlatform_test.cpp ModPlatform)
+launcher_add_test(LaunchVariableExpander_test.cpp LaunchVariableExpander)
+launcher_add_test(LaunchLogModel_test.cpp LaunchLogModel)
+launcher_add_test(LaunchLineRouter_test.cpp LaunchLineRouter)
+launcher_add_test(LaunchPipeline_test.cpp LaunchPipeline)
+launcher_add_test(InstanceCopyPrefs_test.cpp InstanceCopyPrefs)
+launcher_add_test(MessageLevel_test.cpp MessageLevel)
+launcher_add_test(BaseInstanceSettings_test.cpp BaseInstanceSettings)
+launcher_add_test(NetHeaderProxy_test.cpp NetHeaderProxy)
+launcher_add_test(NetSink_test.cpp NetSink)
+launcher_add_test(MetaComponentParse_test.cpp MetaComponentParse)
+launcher_add_test(CatPack_test.cpp CatPack)
+launcher_add_test(DefaultVariable_test.cpp DefaultVariable)
+launcher_add_test(Commandline_test.cpp Commandline)
+launcher_add_test(KonamiCode_test.cpp KonamiCode)
+launcher_add_test(ApplicationMessage_test.cpp ApplicationMessage)
+launcher_add_test(XmlLogs_test.cpp XmlLogs)
+launcher_add_test(LogEventParser_test.cpp LogEventParser)
+launcher_add_test(MMCTime_test.cpp MMCTime)
+launcher_add_test(VersionFilterData_test.cpp VersionFilterData)
+launcher_add_test(StringUtilsNaturalCompare_test.cpp StringUtilsNaturalCompare)
+launcher_add_test(StringUtilsSplitFirst_test.cpp StringUtilsSplitFirst)
+launcher_add_test(StringUtilsTruncateUrl_test.cpp StringUtilsTruncateUrl)
+launcher_add_test(StringUtilsHtmlPatch_test.cpp StringUtilsHtmlPatch)
+launcher_add_test(JsonTypes_test.cpp JsonTypes)
+launcher_add_test(JsonHelpers_test.cpp JsonHelpers)
+if(NOT APPLE)
+ launcher_add_test(ProjTExternalUpdater_test.cpp ProjTExternalUpdater)
+endif()
+
+if(UNIX AND NOT APPLE)
+ set(_launcher_test_paths "")
+ if(TARGET MINIZIP::minizip)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:MINIZIP::minizip>")
+ endif()
+ if(TARGET PTlibzippy::PTlibzippy)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:PTlibzippy::PTlibzippy>")
+ endif()
+ if(TARGET QuaZip)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:QuaZip>")
+ elseif(TARGET QuaZip::QuaZip)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:QuaZip::QuaZip>")
+ endif()
+ if(TARGET cmark)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:cmark>")
+ elseif(TARGET cmark::cmark)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:cmark::cmark>")
+ endif()
+ if(TARGET OpenSSL::Crypto)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:OpenSSL::Crypto>")
+ endif()
+ if(TARGET OpenSSL::SSL)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:OpenSSL::SSL>")
+ endif()
+
+ list(JOIN _launcher_test_paths ":" _launcher_test_paths_joined)
+ if(_launcher_test_paths_joined)
+ set(_launcher_test_env_list "")
+ list(APPEND _launcher_test_env_list "LD_LIBRARY_PATH=${_launcher_test_paths_joined}:$ENV{LD_LIBRARY_PATH}")
+ set_property(TEST ${LAUNCHER_TESTS} PROPERTY ENVIRONMENT "${_launcher_test_env_list}")
+ endif()
+endif()
+
+if(WIN32)
+ set(_qt_cmake_dir "")
+ if(DEFINED Qt6_DIR)
+ set(_qt_cmake_dir "${Qt6_DIR}")
+ elseif(DEFINED Qt5_DIR)
+ set(_qt_cmake_dir "${Qt5_DIR}")
+ endif()
+
+ if(_qt_cmake_dir)
+ get_filename_component(_qt_prefix "${_qt_cmake_dir}" DIRECTORY)
+ get_filename_component(_qt_prefix "${_qt_prefix}" DIRECTORY)
+ get_filename_component(_qt_prefix "${_qt_prefix}" DIRECTORY)
+ set(_qt_bin_dir "${_qt_prefix}/bin")
+ else()
+ set(_qt_core_target "")
+ if(TARGET Qt6::Core)
+ set(_qt_core_target Qt6::Core)
+ elseif(TARGET Qt5::Core)
+ set(_qt_core_target Qt5::Core)
+ endif()
+ if(_qt_core_target)
+ get_target_property(_qt_core_location ${_qt_core_target} IMPORTED_LOCATION_RELEASE)
+ if(NOT _qt_core_location)
+ get_target_property(_qt_core_location ${_qt_core_target} IMPORTED_LOCATION_DEBUG)
+ endif()
+ if(NOT _qt_core_location)
+ get_target_property(_qt_core_location ${_qt_core_target} IMPORTED_LOCATION)
+ endif()
+ if(_qt_core_location)
+ get_filename_component(_qt_lib_dir "${_qt_core_location}" DIRECTORY)
+ get_filename_component(_qt_prefix "${_qt_lib_dir}" DIRECTORY)
+ set(_qt_bin_dir "${_qt_prefix}/bin")
+ endif()
+ endif()
+ endif()
+
+ if(EXISTS "${_qt_bin_dir}")
+ set(_launcher_test_env_list "")
+ set(_launcher_test_paths "${_qt_bin_dir}" "${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}/$<CONFIG>")
+ set(_qt_core_target "Qt${QT_VERSION_MAJOR}::Core")
+ if(TARGET ${_qt_core_target})
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:${_qt_core_target}>")
+ endif()
+ if(TARGET QuaZip)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:QuaZip>")
+ elseif(TARGET QuaZip::QuaZip)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:QuaZip::QuaZip>")
+ endif()
+ if(TARGET cmark)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:cmark>")
+ elseif(TARGET cmark::cmark)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:cmark::cmark>")
+ endif()
+ if(TARGET PTlibzippy::PTlibzippy)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:PTlibzippy::PTlibzippy>")
+ endif()
+ if(TARGET OpenSSL::SSL)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:OpenSSL::SSL>")
+ endif()
+ if(TARGET OpenSSL::Crypto)
+ list(APPEND _launcher_test_paths "$<TARGET_FILE_DIR:OpenSSL::Crypto>")
+ endif()
+ if(DEFINED OPENSSL_ROOT_DIR AND EXISTS "${OPENSSL_ROOT_DIR}/bin")
+ list(APPEND _launcher_test_paths "${OPENSSL_ROOT_DIR}/bin")
+ endif()
+ if(DEFINED OPENSSL_ROOT_DIR AND EXISTS "${OPENSSL_ROOT_DIR}")
+ list(APPEND _launcher_test_paths "${OPENSSL_ROOT_DIR}")
+ endif()
+ if(DEFINED OPENSSL_CRYPTO_LIBRARY AND EXISTS "${OPENSSL_CRYPTO_LIBRARY}")
+ get_filename_component(_launcher_openssl_lib_dir "${OPENSSL_CRYPTO_LIBRARY}" DIRECTORY)
+ list(APPEND _launcher_test_paths "${_launcher_openssl_lib_dir}")
+ endif()
+ if(DEFINED OPENSSL_SSL_LIBRARY AND EXISTS "${OPENSSL_SSL_LIBRARY}")
+ get_filename_component(_launcher_openssl_ssl_dir "${OPENSSL_SSL_LIBRARY}" DIRECTORY)
+ list(APPEND _launcher_test_paths "${_launcher_openssl_ssl_dir}")
+ endif()
+ set(_launcher_test_path "PATH=${_launcher_test_paths};$ENV{PATH}")
+ string(REPLACE ";" "\\;" _launcher_test_path "${_launcher_test_path}")
+ list(APPEND _launcher_test_env_list "${_launcher_test_path}")
+ if(EXISTS "${_qt_prefix}/plugins")
+ list(APPEND _launcher_test_env_list "QT_PLUGIN_PATH=${_qt_prefix}/plugins")
+ if(EXISTS "${_qt_prefix}/plugins/platforms")
+ list(APPEND _launcher_test_env_list "QT_QPA_PLATFORM_PLUGIN_PATH=${_qt_prefix}/plugins/platforms")
+ endif()
+ endif()
+ list(APPEND _launcher_test_env_list "QT_QPA_PLATFORM=windows")
+ set_property(TEST ${LAUNCHER_TESTS} PROPERTY ENVIRONMENT "${_launcher_test_env_list}")
+ endif()
+endif()
diff --git a/archived/projt-launcher/tests/CatPack_test.cpp b/archived/projt-launcher/tests/CatPack_test.cpp
new file mode 100644
index 0000000000..598573452b
--- /dev/null
+++ b/archived/projt-launcher/tests/CatPack_test.cpp
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <QDate>
+#include <QFileInfo>
+#include <QList>
+#include <QTemporaryFile>
+#include "FileSystem.h"
+#include "ui/themes/CatPack.h"
+
+class CatPackTest : public QObject
+{
+ Q_OBJECT
+ private slots:
+ void test_catPack()
+ {
+ auto dataDir = QDir(QFINDTESTDATA("testdata/CatPacks")).absolutePath();
+ auto fileName = FS::PathCombine(dataDir, "index.json");
+ 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"
diff --git a/archived/projt-launcher/tests/Commandline_test.cpp b/archived/projt-launcher/tests/Commandline_test.cpp
new file mode 100644
index 0000000000..40227c39af
--- /dev/null
+++ b/archived/projt-launcher/tests/Commandline_test.cpp
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <Commandline.h>
+
+class CommandlineTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_splitArgs_data()
+ {
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("empty") << "" << QStringList{};
+ QTest::newRow("spaces-only") << " " << QStringList{};
+ QTest::newRow("single") << "java" << QStringList{ "java" };
+ QTest::newRow("multiple-with-extra-spaces")
+ << " java -jar app.jar "
+ << QStringList{ "java", "-jar", "app.jar" };
+ QTest::newRow("double-quoted")
+ << "java -Dk=\"hello world\""
+ << QStringList{ "java", "-Dk=hello world" };
+ QTest::newRow("single-quoted")
+ << "java '-Dk=hello world' tail"
+ << QStringList{ "java", "-Dk=hello world", "tail" };
+ QTest::newRow("mixed-quotes")
+ << "cmd \"double quoted\" 'single quoted'"
+ << QStringList{ "cmd", "double quoted", "single quoted" };
+ QTest::newRow("escaped-quote-in-double-quotes")
+ << "\"a\\\"b\""
+ << QStringList{ "a\"b" };
+ QTest::newRow("escaped-backslash-in-double-quotes")
+ << "\"C:\\\\temp\\\\file.txt\""
+ << QStringList{ "C:\\temp\\file.txt" };
+ QTest::newRow("unclosed-quote")
+ << "\"hello world"
+ << QStringList{ "hello world" };
+ QTest::newRow("single-backslash-outside-quotes")
+ << "a\\ b"
+ << QStringList{ "a\\", "b" };
+ }
+
+ void test_splitArgs()
+ {
+ QFETCH(QString, input);
+ QFETCH(QStringList, expected);
+
+ QCOMPARE(Commandline::splitArgs(input), expected);
+ }
+};
+
+QTEST_GUILESS_MAIN(CommandlineTest)
+
+#include "Commandline_test.moc"
diff --git a/archived/projt-launcher/tests/DataPackParse_test.cpp b/archived/projt-launcher/tests/DataPackParse_test.cpp
new file mode 100644
index 0000000000..d3fba8d7b7
--- /dev/null
+++ b/archived/projt-launcher/tests/DataPackParse_test.cpp
@@ -0,0 +1,81 @@
+// 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+#include <QTimer>
+
+#include <FileSystem.h>
+
+#include <minecraft/mod/DataPack.hpp>
+#include <minecraft/mod/tasks/LocalDataPackParseTask.hpp>
+
+class DataPackParseTest : public QObject
+{
+ Q_OBJECT
+
+ 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) };
+
+ bool valid = DataPackUtils::processZIP(&pack);
+
+ QVERIFY(pack.packFormat() == 4);
+ QVERIFY(pack.description() == "Some data pack 2 boobgaloo");
+ QVERIFY(valid == true);
+ }
+
+ void test_parseFolder()
+ {
+ QString source = QFINDTESTDATA("testdata/DataPackParse");
+
+ QString folder_dp = FS::PathCombine(source, "test_folder");
+ DataPack pack{ QFileInfo(folder_dp) };
+
+ bool valid = DataPackUtils::processFolder(&pack);
+
+ QVERIFY(pack.packFormat() == 10);
+ QVERIFY(pack.description() == "Some data pack, maybe");
+ QVERIFY(valid == true);
+ }
+
+ void test_parseFolder2()
+ {
+ QString source = QFINDTESTDATA("testdata/DataPackParse");
+
+ QString folder_dp = FS::PathCombine(source, "another_test_folder");
+ DataPack pack{ QFileInfo(folder_dp) };
+
+ bool valid = DataPackUtils::process(&pack);
+
+ QVERIFY(pack.packFormat() == 6);
+ QVERIFY(pack.description() == "Some data pack three, leaves on the tree");
+ QVERIFY(valid == true);
+ }
+};
+
+QTEST_GUILESS_MAIN(DataPackParseTest)
+
+#include "DataPackParse_test.moc"
diff --git a/archived/projt-launcher/tests/DefaultVariable_test.cpp b/archived/projt-launcher/tests/DefaultVariable_test.cpp
new file mode 100644
index 0000000000..0c17ee54a3
--- /dev/null
+++ b/archived/projt-launcher/tests/DefaultVariable_test.cpp
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+
+#include <DefaultVariable.h>
+
+class DefaultVariableTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_initialState()
+ {
+ DefaultVariable<int> value(7);
+
+ QVERIFY(value.isDefault());
+ QVERIFY(!value.isExplicit());
+ QCOMPARE(static_cast<int>(value), 7);
+ }
+
+ void test_assignmentMarksExplicit()
+ {
+ DefaultVariable<QString> value("alpha");
+ value = "beta";
+
+ QVERIFY(!value.isDefault());
+ QVERIFY(value.isExplicit());
+ QCOMPARE(static_cast<QString>(value), QString("beta"));
+ }
+
+ void test_assignmentToDefaultRestoresDefaultFlag()
+ {
+ DefaultVariable<QString> value("alpha");
+ value = "beta";
+ value = "alpha";
+
+ QVERIFY(value.isDefault());
+ QVERIFY(value.isExplicit());
+ QCOMPARE(static_cast<QString>(value), QString("alpha"));
+ }
+};
+
+QTEST_GUILESS_MAIN(DefaultVariableTest)
+
+#include "DefaultVariable_test.moc"
diff --git a/archived/projt-launcher/tests/ExponentialSeries_test.cpp b/archived/projt-launcher/tests/ExponentialSeries_test.cpp
new file mode 100644
index 0000000000..1abba5ed2d
--- /dev/null
+++ b/archived/projt-launcher/tests/ExponentialSeries_test.cpp
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+
+#include <ExponentialSeries.h>
+
+class ExponentialSeriesTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_sequenceGrowsExponentially()
+ {
+ ExponentialSeries series(2, 32, 2);
+
+ QCOMPARE(series(), 2u);
+ QCOMPARE(series(), 4u);
+ QCOMPARE(series(), 8u);
+ QCOMPARE(series(), 16u);
+ }
+
+ void test_sequenceClampsAtMaximum()
+ {
+ ExponentialSeries series(3, 20, 3);
+
+ QCOMPARE(series(), 3u);
+ QCOMPARE(series(), 9u);
+ QCOMPARE(series(), 20u);
+ QCOMPARE(series(), 20u);
+ }
+
+ void test_resetRestoresMinimum()
+ {
+ ExponentialSeries series(5, 100, 4);
+
+ QCOMPARE(series(), 5u);
+ QCOMPARE(series(), 20u);
+
+ series.reset();
+
+ QCOMPARE(series(), 5u);
+ }
+};
+
+QTEST_GUILESS_MAIN(ExponentialSeriesTest)
+
+#include "ExponentialSeries_test.moc"
diff --git a/archived/projt-launcher/tests/FileSystem_test.cpp b/archived/projt-launcher/tests/FileSystem_test.cpp
new file mode 100644
index 0000000000..ed46154eea
--- /dev/null
+++ b/archived/projt-launcher/tests/FileSystem_test.cpp
@@ -0,0 +1,899 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QDir>
+#include <QFile>
+#include <QStandardPaths>
+#include <QTemporaryDir>
+#include <QTest>
+#include <memory>
+
+#include <tasks/Task.h>
+
+#include <FileSystem.h>
+#include <StringUtils.h>
+
+#include <filesystem>
+namespace fs = std::filesystem;
+
+#if defined(Q_OS_WIN32)
+[[maybe_unused]] static bool canCreateSymlink()
+{
+ QTemporaryDir tempDir;
+ if (!tempDir.isValid())
+ return false;
+
+ const QString target = FS::PathCombine(tempDir.path(), "target.txt");
+ QFile file(target);
+ if (!file.open(QIODevice::WriteOnly))
+ return false;
+ file.write("x");
+ file.close();
+
+ const QString link = FS::PathCombine(tempDir.path(), "link.txt");
+ std::error_code ec;
+ fs::create_symlink(StringUtils::toStdString(target), StringUtils::toStdString(link), ec);
+ if (ec)
+ return false;
+
+ fs::remove(StringUtils::toStdString(link), ec);
+ return true;
+}
+#else
+[[maybe_unused]] static bool canCreateSymlink()
+{
+ return true;
+}
+#endif
+
+class LinkTask : public Task
+{
+ Q_OBJECT
+
+ friend class FileSystemTest;
+
+ LinkTask(QString src, QString dst)
+ {
+ m_lnk = new FS::create_link(src, dst, this);
+ m_lnk->debug(true);
+ }
+
+ ~LinkTask()
+ {
+ delete m_lnk;
+ }
+
+ void matcher(Filter filter)
+ {
+ m_lnk->matcher(filter);
+ }
+
+ void linkRecursively(bool recursive)
+ {
+ m_lnk->linkRecursively(recursive);
+ m_linkRecursive = recursive;
+ }
+
+ void whitelist(bool b)
+ {
+ m_lnk->whitelist(b);
+ }
+
+ void setMaxDepth(int depth)
+ {
+ m_lnk->setMaxDepth(depth);
+ }
+
+ private:
+ void executeTask() override
+ {
+ 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,
+ [this](bool gotResults)
+ {
+ if (gotResults)
+ {
+ emitSucceeded();
+ }
+ else
+ {
+ qDebug() << "Privileged run exited without results!";
+ emitFailed();
+ }
+ });
+ 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;
+#if defined Q_OS_WIN32
+ bool m_useHard = false;
+#endif
+ bool m_linkRecursive = true;
+};
+
+class FileSystemTest : public QObject
+{
+ Q_OBJECT
+
+ const QString bothSlash = "/foo/";
+ const QString trailingSlash = "foo/";
+ const QString leadingSlash = "/foo";
+
+ private slots:
+ void test_pathCombine()
+ {
+ QCOMPARE(QString("/foo/foo"), FS::PathCombine(bothSlash, bothSlash));
+ QCOMPARE(QString("foo/foo"), FS::PathCombine(trailingSlash, trailingSlash));
+ QCOMPARE(QString("/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash));
+
+ QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(bothSlash, bothSlash, bothSlash));
+ QCOMPARE(QString("foo/foo/foo"), FS::PathCombine(trailingSlash, trailingSlash, trailingSlash));
+ QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash, leadingSlash));
+ }
+
+ void test_PathCombine1_data()
+ {
+ QTest::addColumn<QString>("result");
+ QTest::addColumn<QString>("path1");
+ QTest::addColumn<QString>("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";
+#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";
+#endif
+ }
+
+ void test_PathCombine1()
+ {
+ QFETCH(QString, result);
+ QFETCH(QString, path1);
+ QFETCH(QString, path2);
+
+ QCOMPARE(FS::PathCombine(path1, path2), result);
+ }
+
+ void test_PathCombine2_data()
+ {
+ QTest::addColumn<QString>("result");
+ QTest::addColumn<QString>("path1");
+ QTest::addColumn<QString>("path2");
+ QTest::addColumn<QString>("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";
+#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";
+#endif
+ }
+
+ void test_PathCombine2()
+ {
+ QFETCH(QString, result);
+ QFETCH(QString, path1);
+ QFETCH(QString, path2);
+ QFETCH(QString, path3);
+
+ QCOMPARE(FS::PathCombine(path1, path2, path3), result);
+ }
+
+ void test_copy()
+ {
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+ FS::copy c(folder, target_dir.path());
+ c();
+
+ for (auto entry : target_dir.entryList())
+ {
+ qDebug() << entry;
+ }
+ QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_copy_with_blacklist()
+ {
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+ FS::copy c(folder, target_dir.path());
+ auto re = Filters::regexp(QRegularExpression("[.]?mcmeta"));
+ c.matcher(re);
+ c();
+
+ for (auto entry : target_dir.entryList())
+ {
+ qDebug() << entry;
+ }
+ QVERIFY(!target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_copy_with_whitelist()
+ {
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+ FS::copy c(folder, target_dir.path());
+ auto re = Filters::regexp(QRegularExpression("[.]?mcmeta"));
+ c.matcher(re);
+ c.whitelist(true);
+ c();
+
+ for (auto entry : target_dir.entryList())
+ {
+ qDebug() << entry;
+ }
+ QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(!target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_copy_with_dot_hidden()
+ {
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+ FS::copy c(folder, target_dir.path());
+ c();
+
+ auto filter = QDir::Filter::Files | QDir::Filter::Dirs | QDir::Filter::Hidden;
+
+ for (auto entry : target_dir.entryList(filter))
+ {
+ qDebug() << entry;
+ }
+
+ QVERIFY(target_dir.entryList(filter).contains(".secret_folder"));
+ target_dir.cd(".secret_folder");
+ QVERIFY(target_dir.entryList(filter).contains(".secret_file.txt"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_copy_single_file()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+
+ {
+ QString file = QFINDTESTDATA("testdata/FileSystem/test_folder/pack.mcmeta");
+
+ qDebug() << "From:" << file << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "pack.mcmeta"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+ FS::copy c(file, target_dir.filePath("pack.mcmeta"));
+ c();
+
+ auto filter = QDir::Filter::Files;
+
+ for (auto entry : target_dir.entryList(filter))
+ {
+ qDebug() << entry;
+ }
+
+ QVERIFY(target_dir.entryList(filter).contains("pack.mcmeta"));
+ }
+ }
+
+ void test_getDesktop()
+ {
+ QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
+ }
+
+ void test_link()
+ {
+#if defined(Q_OS_WIN32)
+ if (!canCreateSymlink())
+ QSKIP("Symlink creation not permitted on this Windows runner.");
+#endif
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+
+ LinkTask lnk_tsk(folder, target_dir.path());
+ lnk_tsk.linkRecursively(false);
+ connect(&lnk_tsk,
+ &Task::finished,
+ [&lnk_tsk]
+ {
+ QVERIFY2(lnk_tsk.wasSuccessful(),
+ "Task finished but was not successful when it should have been.");
+ });
+ lnk_tsk.start();
+
+ QVERIFY2(QTest::qWaitFor([&lnk_tsk]() { return lnk_tsk.isFinished(); }, 100000),
+ "Task didn't finish as it should.");
+
+ for (auto entry : target_dir.entryList())
+ {
+ qDebug() << entry;
+ QFileInfo entry_lnk_info(target_dir.filePath(entry));
+ if (!entry_lnk_info.isDir())
+ QVERIFY(!entry_lnk_info.isSymLink());
+ }
+
+ QFileInfo lnk_info(target_dir.path());
+ QVERIFY(lnk_info.exists());
+ QVERIFY(lnk_info.isSymLink());
+
+ QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_hard_link()
+ {
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ // use working dir to prevent makeing a hard link to a tmpfs or across devices
+ QTemporaryDir tempDir("./tmp");
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+ FS::create_link lnk(folder, target_dir.path());
+ lnk.useHardLinks(true);
+ lnk.debug(true);
+ if (!lnk())
+ {
+ qDebug() << "Link Failed!" << lnk.getOSError().value() << lnk.getOSError().message().c_str();
+ }
+
+ 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()))));
+ }
+ }
+
+ QFileInfo lnk_info(target_dir.path());
+ QVERIFY(lnk_info.exists());
+ QVERIFY(!lnk_info.isSymLink());
+
+ QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_link_with_blacklist()
+ {
+#if defined(Q_OS_WIN32)
+ if (!canCreateSymlink())
+ QSKIP("Symlink creation not permitted on this Windows runner.");
+#endif
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+
+ LinkTask lnk_tsk(folder, target_dir.path());
+ auto re = Filters::regexp(QRegularExpression("[.]?mcmeta"));
+ lnk_tsk.matcher(re);
+ lnk_tsk.linkRecursively(true);
+ connect(&lnk_tsk,
+ &Task::finished,
+ [&lnk_tsk]
+ {
+ QVERIFY2(lnk_tsk.wasSuccessful(),
+ "Task finished but was not successful when it should have been.");
+ });
+ lnk_tsk.start();
+
+ QVERIFY2(QTest::qWaitFor([&lnk_tsk]() { return lnk_tsk.isFinished(); }, 100000),
+ "Task didn't finish as it should.");
+
+ for (auto entry : target_dir.entryList())
+ {
+ qDebug() << entry;
+ QFileInfo entry_lnk_info(target_dir.filePath(entry));
+ if (!entry_lnk_info.isDir())
+ QVERIFY(entry_lnk_info.isSymLink());
+ }
+
+ QFileInfo lnk_info(target_dir.path());
+ QVERIFY(lnk_info.exists());
+
+ QVERIFY(!target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_link_with_whitelist()
+ {
+#if defined(Q_OS_WIN32)
+ if (!canCreateSymlink())
+ QSKIP("Symlink creation not permitted on this Windows runner.");
+#endif
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+
+ LinkTask lnk_tsk(folder, target_dir.path());
+ auto re = Filters::regexp(QRegularExpression("[.]?mcmeta"));
+ lnk_tsk.matcher(re);
+ lnk_tsk.linkRecursively(true);
+ lnk_tsk.whitelist(true);
+ connect(&lnk_tsk,
+ &Task::finished,
+ [&lnk_tsk]
+ {
+ QVERIFY2(lnk_tsk.wasSuccessful(),
+ "Task finished but was not successful when it should have been.");
+ });
+ lnk_tsk.start();
+
+ QVERIFY2(QTest::qWaitFor([&lnk_tsk]() { return lnk_tsk.isFinished(); }, 100000),
+ "Task didn't finish as it should.");
+
+ for (auto entry : target_dir.entryList())
+ {
+ qDebug() << entry;
+ QFileInfo entry_lnk_info(target_dir.filePath(entry));
+ if (!entry_lnk_info.isDir())
+ QVERIFY(entry_lnk_info.isSymLink());
+ }
+
+ QFileInfo lnk_info(target_dir.path());
+ QVERIFY(lnk_info.exists());
+
+ QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(!target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_link_with_dot_hidden()
+ {
+#if defined(Q_OS_WIN32)
+ if (!canCreateSymlink())
+ QSKIP("Symlink creation not permitted on this Windows runner.");
+#endif
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+
+ LinkTask lnk_tsk(folder, target_dir.path());
+ lnk_tsk.linkRecursively(true);
+ connect(&lnk_tsk,
+ &Task::finished,
+ [&lnk_tsk]
+ {
+ QVERIFY2(lnk_tsk.wasSuccessful(),
+ "Task finished but was not successful when it should have been.");
+ });
+ lnk_tsk.start();
+
+ QVERIFY2(QTest::qWaitFor([&lnk_tsk]() { 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))
+ {
+ qDebug() << entry;
+ QFileInfo entry_lnk_info(target_dir.filePath(entry));
+ if (!entry_lnk_info.isDir())
+ QVERIFY(entry_lnk_info.isSymLink());
+ }
+
+ QFileInfo lnk_info(target_dir.path());
+ QVERIFY(lnk_info.exists());
+
+ QVERIFY(target_dir.entryList(filter).contains(".secret_folder"));
+ target_dir.cd(".secret_folder");
+ QVERIFY(target_dir.entryList(filter).contains(".secret_file.txt"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_link_single_file()
+ {
+#if defined(Q_OS_WIN32)
+ if (!canCreateSymlink())
+ QSKIP("Symlink creation not permitted on this Windows runner.");
+#endif
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+
+ {
+ QString file = QFINDTESTDATA("testdata/FileSystem/test_folder/pack.mcmeta");
+
+ qDebug() << "From:" << file << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "pack.mcmeta"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+
+ LinkTask lnk_tsk(file, target_dir.filePath("pack.mcmeta"));
+ connect(&lnk_tsk,
+ &Task::finished,
+ [&lnk_tsk]
+ {
+ QVERIFY2(lnk_tsk.wasSuccessful(),
+ "Task finished but was not successful when it should have been.");
+ });
+ lnk_tsk.start();
+
+ QVERIFY2(QTest::qWaitFor([&lnk_tsk]() { return lnk_tsk.isFinished(); }, 100000),
+ "Task didn't finish as it should.");
+
+ auto filter = QDir::Filter::Files;
+
+ for (auto entry : target_dir.entryList(filter))
+ {
+ qDebug() << entry;
+ }
+
+ QFileInfo lnk_info(target_dir.filePath("pack.mcmeta"));
+ QVERIFY(lnk_info.exists());
+ QVERIFY(lnk_info.isSymLink());
+
+ QVERIFY(target_dir.entryList(filter).contains("pack.mcmeta"));
+ }
+ }
+
+ void test_link_with_max_depth()
+ {
+#if defined(Q_OS_WIN32)
+ if (!canCreateSymlink())
+ QSKIP("Symlink creation not permitted on this Windows runner.");
+#endif
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+
+ LinkTask lnk_tsk(folder, target_dir.path());
+ lnk_tsk.linkRecursively(true);
+ lnk_tsk.setMaxDepth(0);
+ connect(&lnk_tsk,
+ &Task::finished,
+ [&lnk_tsk]
+ {
+ QVERIFY2(lnk_tsk.wasSuccessful(),
+ "Task finished but was not successful when it should have been.");
+ });
+ lnk_tsk.start();
+
+ QVERIFY2(QTest::qWaitFor([&lnk_tsk]() { 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))
+ {
+ qDebug() << entry;
+ if (entry == "." || entry == "..")
+ continue;
+ QFileInfo entry_lnk_info(target_dir.filePath(entry));
+ QVERIFY(entry_lnk_info.isSymLink());
+ }
+
+ QFileInfo lnk_info(target_dir.path());
+ QVERIFY(lnk_info.exists());
+ QVERIFY(!lnk_info.isSymLink());
+
+ QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_link_with_no_max_depth()
+ {
+#if defined(Q_OS_WIN32)
+ if (!canCreateSymlink())
+ QSKIP("Symlink creation not permitted on this Windows runner.");
+#endif
+ QString folder = QFINDTESTDATA("testdata/FileSystem/test_folder");
+ auto f = [&folder]()
+ {
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(true);
+ qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+ QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+ qDebug() << tempDir.path();
+ qDebug() << target_dir.path();
+
+ LinkTask lnk_tsk(folder, target_dir.path());
+ lnk_tsk.linkRecursively(true);
+ lnk_tsk.setMaxDepth(-1);
+ connect(&lnk_tsk,
+ &Task::finished,
+ [&lnk_tsk]
+ {
+ QVERIFY2(lnk_tsk.wasSuccessful(),
+ "Task finished but was not successful when it should have been.");
+ });
+ lnk_tsk.start();
+
+ QVERIFY2(QTest::qWaitFor([&lnk_tsk]() { return lnk_tsk.isFinished(); }, 100000),
+ "Task didn't finish as it should.");
+
+ std::function<void(QString)> verify_check = [&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))
+ {
+ QFileInfo entry_lnk_info(check_dir.filePath(entry));
+ qDebug() << entry << check_dir.filePath(entry);
+ if (!entry_lnk_info.isDir())
+ {
+ QVERIFY(entry_lnk_info.isSymLink());
+ }
+ else if (entry != "." && entry != "..")
+ {
+ qDebug() << "Decending tree to verify symlinks:" << check_dir.filePath(entry);
+ verify_check(entry_lnk_info.filePath());
+ }
+ }
+ };
+
+ verify_check(target_dir.path());
+
+ QFileInfo lnk_info(target_dir.path());
+ QVERIFY(lnk_info.exists());
+
+ QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+ QVERIFY(target_dir.entryList().contains("assets"));
+ };
+
+ // first try variant without trailing /
+ QVERIFY(!folder.endsWith('/'));
+ f();
+
+ // then variant with trailing /
+ folder.append('/');
+ QVERIFY(folder.endsWith('/'));
+ f();
+ }
+
+ void test_path_depth()
+ {
+ QCOMPARE(FS::pathDepth(""), 0);
+ QCOMPARE(FS::pathDepth("."), 0);
+ QCOMPARE(FS::pathDepth("foo.txt"), 0);
+ QCOMPARE(FS::pathDepth("./foo.txt"), 0);
+ QCOMPARE(FS::pathDepth("./bar/foo.txt"), 1);
+ QCOMPARE(FS::pathDepth("../bar/foo.txt"), 0);
+ QCOMPARE(FS::pathDepth("/bar/foo.txt"), 1);
+ QCOMPARE(FS::pathDepth("baz/bar/foo.txt"), 2);
+ QCOMPARE(FS::pathDepth("/baz/bar/foo.txt"), 2);
+ QCOMPARE(FS::pathDepth("./baz/bar/foo.txt"), 2);
+ QCOMPARE(FS::pathDepth("/baz/../bar/foo.txt"), 1);
+ }
+
+ 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(""));
+ QCOMPARE(FS::pathTruncate("./bar/foo.txt", 0), QDir::toNativeSeparators("./bar"));
+ QCOMPARE(FS::pathTruncate("./bar/foo.txt", 1), QDir::toNativeSeparators("./bar"));
+ QCOMPARE(FS::pathTruncate("/bar/foo.txt", 1), QDir::toNativeSeparators("/bar"));
+ QCOMPARE(FS::pathTruncate("bar/foo.txt", 1), QDir::toNativeSeparators("bar"));
+ QCOMPARE(FS::pathTruncate("baz/bar/foo.txt", 2), QDir::toNativeSeparators("baz/bar"));
+#if defined(Q_OS_WIN)
+ QCOMPARE(FS::pathTruncate("C:\\bar\\foo.txt", 1), QDir::toNativeSeparators("C:\\bar"));
+#endif
+ }
+};
+
+QTEST_GUILESS_MAIN(FileSystemTest)
+
+#include "FileSystem_test.moc"
diff --git a/archived/projt-launcher/tests/Filter_test.cpp b/archived/projt-launcher/tests/Filter_test.cpp
new file mode 100644
index 0000000000..fc1a6f0369
--- /dev/null
+++ b/archived/projt-launcher/tests/Filter_test.cpp
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+
+#include <Filter.h>
+
+class FilterTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_equalsAndContains()
+ {
+ const auto equals = Filters::equals("alpha");
+ const auto contains = Filters::contains("bet");
+
+ QVERIFY(equals("alpha"));
+ QVERIFY(!equals("alphA"));
+ QVERIFY(contains("alphabet"));
+ QVERIFY(!contains("gamma"));
+ }
+
+ void test_anyAndInverse()
+ {
+ const auto filter = Filters::any({ Filters::equals("one"), Filters::startsWith("two") });
+ const auto inverse = Filters::inverse(filter);
+
+ QVERIFY(filter("one"));
+ QVERIFY(filter("twofold"));
+ QVERIFY(!filter("three"));
+
+ QVERIFY(!inverse("one"));
+ QVERIFY(inverse("three"));
+ }
+
+ void test_equalsAnyAndEqualsOrEmpty()
+ {
+ const auto any = Filters::equalsAny({ "java", "system" });
+ const auto any_empty = Filters::equalsAny();
+ const auto empty_or_exact = Filters::equalsOrEmpty("release");
+
+ QVERIFY(any("java"));
+ QVERIFY(!any("other"));
+ QVERIFY(any_empty("anything"));
+
+ QVERIFY(empty_or_exact(""));
+ QVERIFY(empty_or_exact("release"));
+ QVERIFY(!empty_or_exact("debug"));
+ }
+
+ void test_regexp()
+ {
+ const auto filter = Filters::regexp(QRegularExpression("^mod-[0-9]+$"));
+
+ QVERIFY(filter("mod-123"));
+ QVERIFY(!filter("mod-abc"));
+ }
+};
+
+QTEST_GUILESS_MAIN(FilterTest)
+
+#include "Filter_test.moc"
diff --git a/archived/projt-launcher/tests/GZip_test.cpp b/archived/projt-launcher/tests/GZip_test.cpp
new file mode 100644
index 0000000000..50f2be2640
--- /dev/null
+++ b/archived/projt-launcher/tests/GZip_test.cpp
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <GZip.h>
+#include <random>
+
+void fib(int& prev, int& cur)
+{
+ auto ret = prev + cur;
+ prev = cur;
+ cur = ret;
+}
+
+class GZipTest : public QObject
+{
+ Q_OBJECT
+ private slots:
+
+ void test_Through()
+ {
+ // test up to 10 MB
+ static const int size = 10 * 1024 * 1024;
+ QByteArray random;
+ QByteArray compressed;
+ QByteArray decompressed;
+ std::default_random_engine eng((std::random_device())());
+ std::uniform_int_distribution<uint16_t> idis(0, std::numeric_limits<uint8_t>::max());
+
+ // initialize random buffer
+ for (int i = 0; i < size; i++)
+ {
+ random.append(static_cast<char>(idis(eng)));
+ }
+
+ // initialize fibonacci
+ int prev = 1;
+ int cur = 1;
+
+ // test if fibonacci long random buffers pass through GZip
+ do
+ {
+ QByteArray copy = random;
+ copy.resize(cur);
+ compressed.clear();
+ decompressed.clear();
+ QVERIFY(GZip::zip(copy, compressed));
+ QVERIFY(GZip::unzip(compressed, decompressed));
+ QCOMPARE(decompressed, copy);
+ fib(prev, cur);
+ }
+ while (cur < size);
+ }
+};
+
+QTEST_GUILESS_MAIN(GZipTest)
+
+#include "GZip_test.moc"
diff --git a/archived/projt-launcher/tests/GradleSpecifier_test.cpp b/archived/projt-launcher/tests/GradleSpecifier_test.cpp
new file mode 100644
index 0000000000..35574a5761
--- /dev/null
+++ b/archived/projt-launcher/tests/GradleSpecifier_test.cpp
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <minecraft/GradleSpecifier.h>
+
+class GradleSpecifierTest : public QObject
+{
+ Q_OBJECT
+ private slots:
+ void initTestCase()
+ {}
+ void cleanupTestCase()
+ {}
+
+ void test_Positive_data()
+ {
+ QTest::addColumn<QString>("through");
+
+ QTest::newRow("3 parter") << "org.gradle.test.classifiers:service:1.0";
+ QTest::newRow("classifier") << "org.gradle.test.classifiers:service:1.0:jdk15";
+ QTest::newRow("jarextension") << "org.gradle.test.classifiers:service:1.0@jar";
+ QTest::newRow("jarboth") << "org.gradle.test.classifiers:service:1.0:jdk15@jar";
+ QTest::newRow("packxz") << "org.gradle.test.classifiers:service:1.0:jdk15@jar.pack.xz";
+ }
+ void test_Positive()
+ {
+ QFETCH(QString, through);
+
+ QString converted = GradleSpecifier(through).serialize();
+
+ QCOMPARE(converted, through);
+ }
+
+ void test_Path_data()
+ {
+ QTest::addColumn<QString>("spec");
+ QTest::addColumn<QString>("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";
+ }
+ void test_Path()
+ {
+ QFETCH(QString, spec);
+ QFETCH(QString, expected);
+
+ QString converted = GradleSpecifier(spec).toPath();
+
+ QCOMPARE(converted, expected);
+ }
+ void test_Negative_data()
+ {
+ QTest::addColumn<QString>("input");
+
+ QTest::newRow("too many :") << "org:gradle.test:class:::ifiers:service:1.0::";
+ QTest::newRow("nonsense") << "I like turtles";
+ QTest::newRow("empty string") << "";
+ QTest::newRow("missing version") << "herp.derp:artifact";
+ }
+ void test_Negative()
+ {
+ QFETCH(QString, input);
+
+ GradleSpecifier spec(input);
+ QVERIFY(!spec.valid());
+ QCOMPARE(spec.serialize(), input);
+ QCOMPARE(spec.toPath(), QString());
+ }
+};
+
+QTEST_GUILESS_MAIN(GradleSpecifierTest)
+
+#include "GradleSpecifier_test.moc"
diff --git a/archived/projt-launcher/tests/INIFile_test.cpp b/archived/projt-launcher/tests/INIFile_test.cpp
new file mode 100644
index 0000000000..dba12baaf3
--- /dev/null
+++ b/archived/projt-launcher/tests/INIFile_test.cpp
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <settings/INIFile.h>
+#include <QList>
+#include <QSettings>
+#include <QTemporaryFile>
+#include <QVariant>
+#include "FileSystem.h"
+
+#include <QVariantUtils.h>
+
+class IniFileTest : public QObject
+{
+ Q_OBJECT
+ private slots:
+ void initTestCase()
+ {}
+ void cleanupTestCase()
+ {}
+
+ void test_Escape_data()
+ {
+ QTest::addColumn<QString>("through");
+
+ QTest::newRow("unix path") << "/abc/def/ghi/jkl";
+ QTest::newRow("windows path") << "C:\\Program files\\terrible\\name\\of something\\";
+ QTest::newRow("Plain text") << "Lorem ipsum dolor sit amet.";
+ QTest::newRow("Escape sequences") << "Lorem\n\t\n\\n\\tAAZ\nipsum dolor\n\nsit amet.";
+ QTest::newRow("Escape sequences 2") << "\"\n\n\"";
+ QTest::newRow("Hashtags") << "some data#something";
+ }
+
+ void test_SaveLoad()
+ {
+ QString a = "a";
+ QString b = "a\nb\t\n\\\\\\C:\\Program files\\terrible\\name\\of something\\#thisIsNotAComment";
+ QString filename = "test_SaveLoad.ini";
+
+ // save
+ INIFile f;
+ f.set("a", a);
+ f.set("b", b);
+ f.saveFile(filename);
+
+ // load
+ INIFile f2;
+ f2.loadFile(filename);
+ QCOMPARE(f2.get("a", "NOT SET").toString(), a);
+ QCOMPARE(f2.get("b", "NOT SET").toString(), b);
+ }
+
+ void test_SaveLoadLists()
+ {
+ QString slist_strings = "(\"a\",\"b\",\"c\")";
+ QStringList list_strings = { "a", "b", "c" };
+
+ QString slist_numbers = "(1,2,3,10)";
+ QList<int> list_numbers = { 1, 2, 3, 10 };
+
+ QString filename = "test_SaveLoadLists.ini";
+
+ INIFile f;
+ f.set("list_strings", list_strings);
+ f.set("list_numbers", QVariantUtils::fromList(list_numbers));
+ f.saveFile(filename);
+
+ // load
+ INIFile f2;
+ f2.loadFile(filename);
+
+ QStringList out_list_strings = f2.get("list_strings", QStringList()).toStringList();
+ qDebug() << "OutStringList" << out_list_strings;
+
+ QList<int> out_list_numbers =
+ QVariantUtils::toList<int>(f2.get("list_numbers", QVariantUtils::fromList(QList<int>())));
+ qDebug() << "OutNumbersList" << out_list_numbers;
+
+ QCOMPARE(out_list_strings, list_strings);
+ QCOMPARE(out_list_numbers, list_numbers);
+ }
+
+ void test_SaveAlreadyExistingFile()
+ {
+ QString fileContent = R"(InstanceType=OneSix
+iconKey=vanillia_icon
+name=Minecraft Vanillia
+OverrideCommands=true
+PreLaunchCommand="$INST_JAVA" -jar packwiz-installer-bootstrap.jar link
+Wrapperommand=)";
+ fileContent += "\"";
+ fileContent += +R"(\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =)";
+ fileContent += "\"\n";
+#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();
+
+ // load
+ INIFile f1;
+ f1.loadFile(fileName);
+ QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(),
+ "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link");
+ QCOMPARE(f1.get("Wrapperommand", "NOT SET").toString(),
+ "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =");
+ f1.saveFile(fileName);
+ INIFile f2;
+ f2.loadFile(fileName);
+ QCOMPARE(f2.get("PreLaunchCommand", "NOT SET").toString(),
+ "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link");
+ QCOMPARE(f2.get("Wrapperommand", "NOT SET").toString(),
+ "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =");
+ QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.3");
+#if defined(Q_OS_WIN)
+ FS::deletePath(fileName);
+#endif
+ }
+
+ void test_SaveAlreadyExistingFileWithSpecialChars()
+ {
+#if defined(Q_OS_WIN)
+ QString fileName = "test_SaveAlreadyExistingFileWithSpecialChars.ini";
+#else
+ QTemporaryFile file;
+ QCOMPARE(file.open(), true);
+ QCOMPARE(file.fileName().isEmpty(), false);
+ QString fileName = file.fileName();
+ file.close();
+#endif
+ QSettings settings{ fileName, QSettings::Format::IniFormat };
+ settings.setFallbacksEnabled(false);
+
+ settings.setValue("simple", "value1");
+ settings.setValue("withQuotes", R"("value2" with quotes)");
+ settings.setValue("withSpecialCharacters", "env mesa=true");
+ settings.setValue("withSpecialCharacters2", "1,2,3,4");
+ settings.setValue("withSpecialCharacters2", "1;2;3;4");
+ settings.setValue("withAll", "val=\"$INST_JAVA\" -jar; ls ");
+
+ settings.sync();
+
+ QCOMPARE(settings.status(), QSettings::Status::NoError);
+
+ // load
+ INIFile f1;
+ f1.loadFile(fileName);
+ for (auto key : settings.allKeys())
+ QCOMPARE(f1.get(key, "NOT SET").toString(), settings.value(key).toString());
+ f1.saveFile(fileName);
+ INIFile f2;
+ f2.loadFile(fileName);
+ for (auto key : settings.allKeys())
+ QCOMPARE(f2.get(key, "NOT SET").toString(), settings.value(key).toString());
+ QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.3");
+#if defined(Q_OS_WIN)
+ FS::deletePath(fileName);
+#endif
+ }
+
+ void test_SaveAlreadyExistingFileWithSpecialCharsV1()
+ {
+ QString fileContent = R"(InstanceType=OneSix
+ConfigVersion=1.1
+iconKey=vanillia_icon
+name=Minecraft Vanillia
+OverrideCommands=true
+PreLaunchCommand=)";
+ fileContent += "\"\\\"env mesa=true\\\"\"\n";
+
+#if defined(Q_OS_WIN)
+ QString fileName = "test_SaveAlreadyExistingFileWithSpecialCharsV1.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();
+
+ // load
+ INIFile f1;
+ f1.loadFile(fileName);
+ QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "env mesa=true");
+ QCOMPARE(f1.get("ConfigVersion", "NOT SET").toString(), "1.3");
+#if defined(Q_OS_WIN)
+ FS::deletePath(fileName);
+#endif
+ }
+};
+
+QTEST_GUILESS_MAIN(IniFileTest)
+
+#include "INIFile_test.moc"
diff --git a/archived/projt-launcher/tests/Index_test.cpp b/archived/projt-launcher/tests/Index_test.cpp
new file mode 100644
index 0000000000..0e097184cb
--- /dev/null
+++ b/archived/projt-launcher/tests/Index_test.cpp
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <meta/Index.hpp>
+#include <meta/VersionList.hpp>
+
+class IndexTest : public QObject
+{
+ Q_OBJECT
+ private slots:
+ void test_hasComponent_and_component()
+ {
+ projt::meta::MetaIndex windex;
+ // Note: MetaIndex now requires different initialization
+ // Basic test for component existence
+ QVERIFY(!windex.hasComponent("nonexistent"));
+ }
+
+ void test_version_access()
+ {
+ projt::meta::MetaIndex windex;
+ // Test that accessing a non-existent version creates one
+ auto version = windex.version("test.component", "1.0.0");
+ QVERIFY(version != nullptr);
+ QCOMPARE(version->componentUid(), QString("test.component"));
+ QCOMPARE(version->versionId(), QString("1.0.0"));
+ }
+};
+
+QTEST_GUILESS_MAIN(IndexTest)
+
+#include "Index_test.moc"
diff --git a/archived/projt-launcher/tests/InstanceCopyPrefs_test.cpp b/archived/projt-launcher/tests/InstanceCopyPrefs_test.cpp
new file mode 100644
index 0000000000..30eb10aeac
--- /dev/null
+++ b/archived/projt-launcher/tests/InstanceCopyPrefs_test.cpp
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <InstanceCopyPrefs.h>
+
+class InstanceCopyPrefsTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_defaults()
+ {
+ InstanceCopyPrefs prefs;
+ QVERIFY(prefs.allTrue());
+ QVERIFY(prefs.isCopySavesEnabled());
+ QVERIFY(prefs.isKeepPlaytimeEnabled());
+ QVERIFY(prefs.isCopyGameOptionsEnabled());
+ QVERIFY(prefs.isCopyResourcePacksEnabled());
+ QVERIFY(prefs.isCopyShaderPacksEnabled());
+ QVERIFY(prefs.isCopyServersEnabled());
+ QVERIFY(prefs.isCopyModsEnabled());
+ QVERIFY(prefs.isCopyScreenshotsEnabled());
+ QVERIFY(!prefs.isUseSymLinksEnabled());
+ QVERIFY(!prefs.isUseHardLinksEnabled());
+ QVERIFY(!prefs.isLinkRecursivelyEnabled());
+ QVERIFY(!prefs.isDontLinkSavesEnabled());
+ QVERIFY(!prefs.isUseCloneEnabled());
+ }
+
+ void test_filtersAndFlags()
+ {
+ InstanceCopyPrefs prefs;
+ prefs.enableCopySaves(false);
+ prefs.enableCopyMods(false);
+ prefs.enableCopyServers(false);
+
+ const QString regex = prefs.getSelectedFiltersAsRegex({"extra"});
+ QVERIFY(regex.contains("[.]?minecraft/saves"));
+ QVERIFY(regex.contains("[.]?minecraft/mods"));
+ QVERIFY(regex.contains("[.]?minecraft/servers.dat"));
+ QVERIFY(regex.contains("[.]?minecraft/extra"));
+ QVERIFY(!prefs.allTrue());
+ }
+
+ void test_emptyFiltersWhenAllEnabled()
+ {
+ InstanceCopyPrefs prefs;
+ QCOMPARE(prefs.getSelectedFiltersAsRegex(), QString(""));
+ }
+};
+
+QTEST_GUILESS_MAIN(InstanceCopyPrefsTest)
+
+#include "InstanceCopyPrefs_test.moc"
diff --git a/archived/projt-launcher/tests/JavaVersion_test.cpp b/archived/projt-launcher/tests/JavaVersion_test.cpp
new file mode 100644
index 0000000000..7c8846656b
--- /dev/null
+++ b/archived/projt-launcher/tests/JavaVersion_test.cpp
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <java/core/RuntimeVersion.hpp>
+
+using projt::java::RuntimeVersion;
+
+class RuntimeVersionTest : public QObject
+{
+ Q_OBJECT
+ private slots:
+ void test_Parse_data()
+ {
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<int>("major");
+ QTest::addColumn<int>("minor");
+ QTest::addColumn<int>("security");
+ QTest::addColumn<QString>("prerelease");
+
+ QTest::newRow("old format") << "1.6.0_33" << 6 << 0 << 33 << QString();
+ QTest::newRow("old format prerelease") << "1.9.0_1-ea" << 9 << 0 << 1 << "ea";
+
+ QTest::newRow("new format major") << "9" << 9 << 0 << 0 << QString();
+ QTest::newRow("new format minor") << "9.1" << 9 << 1 << 0 << QString();
+ QTest::newRow("new format security") << "9.0.1" << 9 << 0 << 1 << QString();
+ QTest::newRow("new format prerelease") << "9-ea" << 9 << 0 << 0 << "ea";
+ QTest::newRow("new format long prerelease") << "9.0.1-ea" << 9 << 0 << 1 << "ea";
+ }
+ void test_Parse()
+ {
+ QFETCH(QString, string);
+ QFETCH(int, major);
+ QFETCH(int, minor);
+ QFETCH(int, security);
+ QFETCH(QString, prerelease);
+
+ RuntimeVersion test(string);
+ QCOMPARE(test.toString(), string);
+ QCOMPARE(test.major(), major);
+ QCOMPARE(test.minor(), minor);
+ QCOMPARE(test.security(), security);
+ QCOMPARE(test.prerelease(), prerelease);
+ }
+
+ void test_Sort_data()
+ {
+ QTest::addColumn<QString>("lhs");
+ QTest::addColumn<QString>("rhs");
+ QTest::addColumn<bool>("smaller");
+ QTest::addColumn<bool>("equal");
+ QTest::addColumn<bool>("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;
+ // 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;
+ // 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;
+ // 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;
+ // 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;
+ // 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;
+ // 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;
+ }
+ void test_Sort()
+ {
+ QFETCH(QString, lhs);
+ QFETCH(QString, rhs);
+ QFETCH(bool, smaller);
+ QFETCH(bool, equal);
+ QFETCH(bool, bigger);
+ RuntimeVersion lver(lhs);
+ RuntimeVersion rver(rhs);
+ QCOMPARE(lver < rver, smaller);
+ QCOMPARE(lver == rver, equal);
+ QCOMPARE(lver > rver, bigger);
+ }
+ void test_PermGen_data()
+ {
+ QTest::addColumn<QString>("version");
+ QTest::addColumn<bool>("needs_permgen");
+ QTest::newRow("1.6.0_33") << "1.6.0_33" << true;
+ QTest::newRow("1.7.0_60") << "1.7.0_60" << true;
+ QTest::newRow("1.8.0_22") << "1.8.0_22" << false;
+ QTest::newRow("9-ea") << "9-ea" << false;
+ QTest::newRow("9.2.4") << "9.2.4" << false;
+ }
+ void test_PermGen()
+ {
+ QFETCH(QString, version);
+ QFETCH(bool, needs_permgen);
+ RuntimeVersion v(version);
+ QCOMPARE(needs_permgen, v.needsPermGen());
+ }
+};
+
+QTEST_GUILESS_MAIN(RuntimeVersionTest)
+
+#include "JavaVersion_test.moc"
diff --git a/archived/projt-launcher/tests/JsonHelpers_test.cpp b/archived/projt-launcher/tests/JsonHelpers_test.cpp
new file mode 100644
index 0000000000..2a8682eb4b
--- /dev/null
+++ b/archived/projt-launcher/tests/JsonHelpers_test.cpp
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+#include <QVariantMap>
+
+#include <Json.h>
+
+class JsonHelpersTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_stringListRoundTrip_data()
+ {
+ QTest::addColumn<QStringList>("input");
+
+ QTest::newRow("empty") << QStringList{};
+ QTest::newRow("single") << QStringList{ "a" };
+ QTest::newRow("multi") << QStringList{ "one", "two", "three" };
+ QTest::newRow("spaces") << QStringList{ "a b", " c ", "x=y" };
+ }
+
+ void test_stringListRoundTrip()
+ {
+ QFETCH(QStringList, input);
+ QCOMPARE(Json::toStringList(Json::fromStringList(input)), input);
+ }
+
+ void test_stringListInvalid()
+ {
+ QCOMPARE(Json::toStringList("not-json"), QStringList{});
+ QCOMPARE(Json::toStringList("{}"), QStringList{});
+ }
+
+ void test_mapRoundTrip()
+ {
+ QVariantMap map;
+ map.insert("int", 5);
+ map.insert("bool", true);
+ map.insert("str", "abc");
+
+ const QVariantMap out = Json::toMap(Json::fromMap(map));
+ QCOMPARE(out.value("int").toInt(), 5);
+ QCOMPARE(out.value("bool").toBool(), true);
+ QCOMPARE(out.value("str").toString(), QString("abc"));
+ }
+
+ void test_mapInvalid()
+ {
+ QCOMPARE(Json::toMap("not-json"), QVariantMap{});
+ QCOMPARE(Json::toMap("[]"), QVariantMap{});
+ }
+};
+
+QTEST_GUILESS_MAIN(JsonHelpersTest)
+
+#include "JsonHelpers_test.moc"
diff --git a/archived/projt-launcher/tests/JsonTypes_test.cpp b/archived/projt-launcher/tests/JsonTypes_test.cpp
new file mode 100644
index 0000000000..d9da9ba4a7
--- /dev/null
+++ b/archived/projt-launcher/tests/JsonTypes_test.cpp
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QDir>
+#include <QTest>
+
+#include <Json.h>
+
+class JsonTypesTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_requireInteger_data()
+ {
+ QTest::addColumn<QJsonValue>("input");
+ QTest::addColumn<bool>("throws");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("int") << QJsonValue(42) << false << 42;
+ QTest::newRow("negative-int") << QJsonValue(-11) << false << -11;
+ QTest::newRow("float") << QJsonValue(1.2) << true << 0;
+ QTest::newRow("string") << QJsonValue("42") << true << 0;
+ }
+
+ void test_requireInteger()
+ {
+ QFETCH(QJsonValue, input);
+ QFETCH(bool, throws);
+ QFETCH(int, expected);
+
+ bool threw = false;
+ int value = 0;
+ try
+ {
+ value = Json::requireInteger(input, "int");
+ }
+ catch (const Json::JsonException&)
+ {
+ threw = true;
+ }
+
+ QCOMPARE(threw, throws);
+ if (!throws)
+ {
+ QCOMPARE(value, expected);
+ }
+ }
+
+ void test_requireUrl()
+ {
+ QCOMPARE(Json::requireUrl(QJsonValue(QString("")), "url"), QUrl());
+ QVERIFY(Json::requireUrl(QJsonValue(QString("https://example.com/path")), "url").isValid());
+
+ bool threw = false;
+ try
+ {
+ Json::requireUrl(QJsonValue(QString("http://exa mple.com")), "url");
+ }
+ catch (const Json::JsonException&)
+ {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+
+ void test_requireDir()
+ {
+ QDir dir = Json::requireDir(QJsonValue(QString("a/../b/test")), "dir");
+ QVERIFY(dir.isAbsolute());
+ QVERIFY(!dir.absolutePath().contains(".."));
+
+ bool threw = false;
+ try
+ {
+ Json::requireDir(QJsonValue(QString("/etc")), "dir");
+ }
+ catch (const Json::JsonException&)
+ {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+};
+
+QTEST_GUILESS_MAIN(JsonTypesTest)
+
+#include "JsonTypes_test.moc"
diff --git a/archived/projt-launcher/tests/Json_test.cpp b/archived/projt-launcher/tests/Json_test.cpp
new file mode 100644
index 0000000000..5c47ba253c
--- /dev/null
+++ b/archived/projt-launcher/tests/Json_test.cpp
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QDateTime>
+#include <QDir>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QTemporaryDir>
+#include <QTest>
+#include <QUuid>
+
+#include <Json.h>
+
+class JsonTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_requireDocument_valid()
+ {
+ const QByteArray json = "{\"a\":1}";
+ QJsonDocument doc = Json::requireDocument(json, "doc");
+ QVERIFY(doc.isObject());
+ QCOMPARE(doc.object().value("a").toInt(), 1);
+ }
+
+ void test_requireDocument_invalid()
+ {
+ bool threw = false;
+ try {
+ Json::requireDocument(QByteArray("{"), "doc");
+ } catch (const Json::JsonException&) {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+
+ void test_requireDocument_binary()
+ {
+ QByteArray binary;
+ auto tag = QJsonDocument::BinaryFormatTag;
+ binary.append(reinterpret_cast<const char*>(&tag), sizeof(tag));
+ binary.append("junk");
+
+ bool threw = false;
+ try {
+ Json::requireDocument(binary, "doc");
+ } catch (const Json::JsonException&) {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+
+ void test_requireObjectAndArray()
+ {
+ QJsonDocument objDoc(QJsonObject{{"a", 1}});
+ QJsonObject obj = Json::requireObject(objDoc, "obj");
+ QCOMPARE(obj.value("a").toInt(), 1);
+
+ QJsonDocument arrayDoc(QJsonArray{1, 2});
+ QJsonArray arr = Json::requireArray(arrayDoc, "arr");
+ QCOMPARE(arr.size(), 2);
+ }
+
+ void test_writeStringAndList()
+ {
+ QJsonObject obj;
+ Json::writeString(obj, "name", "value");
+ Json::writeString(obj, "empty", "");
+ QVERIFY(obj.contains("name"));
+ QVERIFY(!obj.contains("empty"));
+
+ Json::writeStringList(obj, "list", QStringList{"a", "b"});
+ Json::writeStringList(obj, "list_empty", {});
+ QVERIFY(obj.contains("list"));
+ QVERIFY(!obj.contains("list_empty"));
+ }
+
+ void test_toTextRoundtrip()
+ {
+ QJsonObject obj{{"a", 1}, {"b", "x"}};
+ QByteArray text = Json::toText(obj);
+ QJsonDocument roundtrip = QJsonDocument::fromJson(text);
+ QVERIFY(roundtrip.isObject());
+ QCOMPARE(roundtrip.object().value("a").toInt(), 1);
+ QCOMPARE(roundtrip.object().value("b").toString(), QString("x"));
+ }
+
+ void test_requireIsTypeBasics()
+ {
+ QJsonValue intValue(3);
+ QCOMPARE(Json::requireInteger(intValue, "int"), 3);
+
+ bool threw = false;
+ try {
+ Json::requireInteger(QJsonValue(1.5), "int");
+ } catch (const Json::JsonException&) {
+ threw = true;
+ }
+ QVERIFY(threw);
+
+ QJsonValue boolValue(true);
+ QCOMPARE(Json::requireBoolean(boolValue, "bool"), true);
+ }
+
+ void test_requireByteArray()
+ {
+ QJsonValue value(QString("ff"));
+ QByteArray bytes = Json::requireByteArray(value, "bytes");
+ QCOMPARE(bytes, QByteArray::fromHex("ff"));
+
+ bool threw = false;
+ try {
+ Json::requireByteArray(QJsonValue(QString::fromUtf8("Ж")), "bytes");
+ } catch (const Json::JsonException&) {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+
+ void test_requireUrlAndUuid()
+ {
+ QJsonValue emptyUrl(QString(""));
+ QCOMPARE(Json::requireUrl(emptyUrl, "url"), QUrl());
+
+ QJsonValue goodUrl(QString("https://example.com/test"));
+ QCOMPARE(Json::requireUrl(goodUrl, "url").toString(), QString("https://example.com/test"));
+
+ const QString uuidStr = QUuid::createUuid().toString();
+ QCOMPARE(Json::requireUuid(QJsonValue(uuidStr), "uuid").toString(), uuidStr);
+
+ bool threw = false;
+ try {
+ Json::requireUuid(QJsonValue(QString("not-a-uuid")), "uuid");
+ } catch (const Json::JsonException&) {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+
+ void test_requireDir()
+ {
+ QJsonValue rel(QString("foo/../bar"));
+ QDir dir = Json::requireDir(rel, "dir");
+ QVERIFY(dir.isAbsolute());
+ QVERIFY(!dir.absolutePath().contains(".."));
+
+ bool threw = false;
+ try {
+ Json::requireDir(QJsonValue(QString("/etc")), "dir");
+ } catch (const Json::JsonException&) {
+ threw = true;
+ }
+ QVERIFY(threw);
+ }
+
+ void test_stringListAndMapHelpers()
+ {
+ const QStringList list{"a", "b"};
+ const QString jsonList = Json::fromStringList(list);
+ QCOMPARE(Json::toStringList(jsonList), list);
+
+ QVariantMap map;
+ map.insert("a", 1);
+ map.insert("b", "x");
+ const QString jsonMap = Json::fromMap(map);
+ QVariantMap roundtrip = Json::toMap(jsonMap);
+ QCOMPARE(roundtrip.value("a").toInt(), 1);
+ QCOMPARE(roundtrip.value("b").toString(), QString("x"));
+
+ QCOMPARE(Json::toStringList("not-json"), QStringList{});
+ QCOMPARE(Json::toMap("not-json"), QVariantMap{});
+ }
+
+ void test_writeAndReadFile()
+ {
+ QTemporaryDir dir;
+ QVERIFY(dir.isValid());
+ const QString path = dir.filePath("test.json");
+
+ QJsonObject obj{{"a", 5}};
+ Json::write(obj, path);
+ QJsonDocument doc = Json::requireDocument(path, "doc");
+ QVERIFY(doc.isObject());
+ QCOMPARE(doc.object().value("a").toInt(), 5);
+ }
+};
+
+QTEST_GUILESS_MAIN(JsonTest)
+
+#include "Json_test.moc"
diff --git a/archived/projt-launcher/tests/KonamiCode_test.cpp b/archived/projt-launcher/tests/KonamiCode_test.cpp
new file mode 100644
index 0000000000..abb3c3b6d4
--- /dev/null
+++ b/archived/projt-launcher/tests/KonamiCode_test.cpp
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QEvent>
+#include <QSignalSpy>
+#include <QTest>
+
+#include <KonamiCode.h>
+
+class KonamiCodeTest : public QObject
+{
+ Q_OBJECT
+
+ void feedKey(KonamiCode& konami, Qt::Key key)
+ {
+ QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier);
+ konami.input(&event);
+ }
+
+ private slots:
+ void test_doesNotTriggerOnNonKeyEvent()
+ {
+ KonamiCode konami;
+ QSignalSpy spy(&konami, &KonamiCode::triggered);
+
+ QEvent event(QEvent::MouseButtonPress);
+ konami.input(&event);
+
+ QCOMPARE(spy.count(), 0);
+ }
+
+ void test_triggersOnExactSequence()
+ {
+ KonamiCode konami;
+ QSignalSpy spy(&konami, &KonamiCode::triggered);
+
+ const QList<Qt::Key> sequence = { 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 };
+
+ for (const auto key : sequence)
+ {
+ feedKey(konami, key);
+ }
+
+ QCOMPARE(spy.count(), 1);
+ }
+
+ void test_wrongKeyResetsProgress()
+ {
+ KonamiCode konami;
+ QSignalSpy spy(&konami, &KonamiCode::triggered);
+
+ feedKey(konami, Qt::Key_Up);
+ feedKey(konami, Qt::Key_Up);
+ feedKey(konami, Qt::Key_X); // wrong key resets progress
+
+ const QList<Qt::Key> sequence = { 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 };
+ for (const auto key : sequence)
+ {
+ feedKey(konami, key);
+ }
+
+ QCOMPARE(spy.count(), 1);
+ }
+
+ void test_canTriggerTwiceBackToBack()
+ {
+ KonamiCode konami;
+ QSignalSpy spy(&konami, &KonamiCode::triggered);
+
+ const QList<Qt::Key> sequence = { 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 };
+
+ for (int i = 0; i < 2; ++i)
+ {
+ for (const auto key : sequence)
+ {
+ feedKey(konami, key);
+ }
+ }
+
+ QCOMPARE(spy.count(), 2);
+ }
+};
+
+QTEST_GUILESS_MAIN(KonamiCodeTest)
+
+#include "KonamiCode_test.moc"
diff --git a/archived/projt-launcher/tests/LaunchLineRouter_test.cpp b/archived/projt-launcher/tests/LaunchLineRouter_test.cpp
new file mode 100644
index 0000000000..bb725a5fe8
--- /dev/null
+++ b/archived/projt-launcher/tests/LaunchLineRouter_test.cpp
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QMap>
+#include <QTest>
+
+#include <launch/LaunchLineRouter.hpp>
+#include <launch/LaunchLogModel.hpp>
+
+class LaunchLineRouterTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_routeLineWithRedaction()
+ {
+ projt::launch::LaunchLineRouter router;
+ projt::launch::LaunchLogModel model;
+
+ QMap<QString, QString> redactions;
+ redactions.insert("SECRET", "REDACTED");
+
+ QString line = "!![INFO]! user SECRET";
+ router.routeLine(line, MessageLevel::Unknown, model, redactions);
+
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0), Qt::DisplayRole).toString(), QString(" user REDACTED"));
+ QCOMPARE(model.data(model.index(0), projt::launch::LaunchLogModel::LevelRole).toInt(),
+ MessageLevel::Info);
+ }
+};
+
+QTEST_GUILESS_MAIN(LaunchLineRouterTest)
+
+#include "LaunchLineRouter_test.moc"
diff --git a/archived/projt-launcher/tests/LaunchLogModel_test.cpp b/archived/projt-launcher/tests/LaunchLogModel_test.cpp
new file mode 100644
index 0000000000..f73c6d874b
--- /dev/null
+++ b/archived/projt-launcher/tests/LaunchLogModel_test.cpp
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <launch/LaunchLogModel.hpp>
+
+class LaunchLogModelTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_appendAndToPlainText()
+ {
+ projt::launch::LaunchLogModel model;
+ QCOMPARE(model.rowCount(), 0);
+
+ model.append(MessageLevel::Info, "line1");
+ model.append(MessageLevel::Warning, "line2");
+
+ QCOMPARE(model.rowCount(), 2);
+ const QString text = model.toPlainText();
+ QVERIFY(text.contains("line1"));
+ QVERIFY(text.contains("line2"));
+ }
+
+ void test_setMaxLinesKeepsTail()
+ {
+ projt::launch::LaunchLogModel model;
+ model.setMaxLines(3);
+ model.append(MessageLevel::Info, "a");
+ model.append(MessageLevel::Info, "b");
+ model.append(MessageLevel::Info, "c");
+ model.append(MessageLevel::Info, "d");
+
+ QCOMPARE(model.rowCount(), 3);
+ const QString text = model.toPlainText();
+ QVERIFY(!text.contains("a\n"));
+ QVERIFY(text.contains("b\n"));
+ QVERIFY(text.contains("c\n"));
+ QVERIFY(text.contains("d\n"));
+ }
+
+ void test_overflowStops()
+ {
+ projt::launch::LaunchLogModel model;
+ model.setMaxLines(2);
+ model.setStopOnOverflow(true);
+ model.setOverflowMessage("OVERFLOW");
+
+ model.append(MessageLevel::Info, "first");
+ model.append(MessageLevel::Info, "second");
+
+ QCOMPARE(model.rowCount(), 2);
+ QVERIFY(model.isOverflow());
+
+ auto overflowIndex = model.index(1);
+ QCOMPARE(model.data(overflowIndex, Qt::DisplayRole).toString(), QString("OVERFLOW"));
+ QCOMPARE(model.data(overflowIndex, projt::launch::LaunchLogModel::LevelRole).toInt(),
+ MessageLevel::Fatal);
+
+ model.append(MessageLevel::Info, "third");
+ QCOMPARE(model.rowCount(), 2);
+ }
+
+ void test_suspendAndOptions()
+ {
+ projt::launch::LaunchLogModel model;
+ model.suspend(true);
+ model.append(MessageLevel::Info, "line");
+ QCOMPARE(model.rowCount(), 0);
+ model.suspend(false);
+ model.append(MessageLevel::Info, "line");
+ QCOMPARE(model.rowCount(), 1);
+
+ model.setLineWrap(false);
+ QVERIFY(!model.wrapLines());
+ model.setColorLines(false);
+ QVERIFY(!model.colorLines());
+ }
+};
+
+QTEST_GUILESS_MAIN(LaunchLogModelTest)
+
+#include "LaunchLogModel_test.moc"
diff --git a/archived/projt-launcher/tests/LaunchPipeline_test.cpp b/archived/projt-launcher/tests/LaunchPipeline_test.cpp
new file mode 100644
index 0000000000..ca846f9ae3
--- /dev/null
+++ b/archived/projt-launcher/tests/LaunchPipeline_test.cpp
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QSignalSpy>
+#include <QTest>
+
+#include <launch/LaunchPipeline.hpp>
+
+class LaunchPipelineTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_executeTaskWithoutInstance()
+ {
+ projt::launch::LaunchPipeline pipeline(nullptr);
+ QSignalSpy failedSpy(&pipeline, &Task::failed);
+
+ pipeline.start();
+ QCOMPARE(failedSpy.count(), 1);
+ QCOMPARE(failedSpy.takeFirst().at(0).toString(), QString("Missing instance for launch."));
+ }
+
+ void test_censorPrivateInfo()
+ {
+ projt::launch::LaunchPipeline pipeline(nullptr);
+ pipeline.setCensorFilter({{"SECRET", "REDACTED"}});
+ QCOMPARE(pipeline.censorPrivateInfo("token SECRET"), QString("token REDACTED"));
+ }
+
+ void test_canAbortIdle()
+ {
+ projt::launch::LaunchPipeline pipeline(nullptr);
+ QVERIFY(pipeline.canAbort());
+ }
+};
+
+QTEST_GUILESS_MAIN(LaunchPipelineTest)
+
+#include "LaunchPipeline_test.moc"
diff --git a/archived/projt-launcher/tests/LaunchVariableExpander_test.cpp b/archived/projt-launcher/tests/LaunchVariableExpander_test.cpp
new file mode 100644
index 0000000000..6b97c2f86d
--- /dev/null
+++ b/archived/projt-launcher/tests/LaunchVariableExpander_test.cpp
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QProcessEnvironment>
+#include <QTest>
+
+#include <launch/LaunchVariableExpander.hpp>
+
+class LaunchVariableExpanderTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_expandVariables()
+ {
+ projt::launch::LaunchVariableExpander expander;
+ QProcessEnvironment env;
+ env.insert("HOME", "/home/test");
+ env.insert("USER", "bob");
+
+ QCOMPARE(expander.expand("$HOME/bin", env), QString("/home/test/bin"));
+ QCOMPARE(expander.expand("Hello $USER", env), QString("Hello bob"));
+ QCOMPARE(expander.expand("${HOME}/.config", env), QString("/home/test/.config"));
+ QCOMPARE(expander.expand("$USER:$HOME", env), QString("bob:/home/test"));
+ }
+
+ void test_missingVariablesRemain()
+ {
+ projt::launch::LaunchVariableExpander expander;
+ QProcessEnvironment env;
+ env.insert("HOME", "/home/test");
+
+ QCOMPARE(expander.expand("$MISSING/path", env), QString("$MISSING/path"));
+ QCOMPARE(expander.expand("${MISSING}/path", env), QString("${MISSING}/path"));
+ QCOMPARE(expander.expand("$HOME/$MISSING", env), QString("/home/test/$MISSING"));
+ }
+};
+
+QTEST_GUILESS_MAIN(LaunchVariableExpanderTest)
+
+#include "LaunchVariableExpander_test.moc"
diff --git a/archived/projt-launcher/tests/Library_test.cpp b/archived/projt-launcher/tests/Library_test.cpp
new file mode 100644
index 0000000000..4649bfe1b8
--- /dev/null
+++ b/archived/projt-launcher/tests/Library_test.cpp
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ * 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 <QTest>
+
+#include <FileSystem.h>
+#include <RuntimeContext.h>
+#include <minecraft/Library.h>
+#include <minecraft/MojangVersionFormat.h>
+#include <minecraft/OneSixVersionFormat.h>
+#include <net/HttpMetaCache.h>
+
+class LibraryTest : public QObject {
+ Q_OBJECT
+ private:
+ LibraryPtr readMojangJson(const QString path)
+ {
+ QFile jsonFile(path);
+ if (!jsonFile.open(QIODevice::ReadOnly)) {
+ qCritical() << "Failed to open file" << jsonFile.fileName() << "for reading!";
+ return LibraryPtr();
+ }
+ auto data = jsonFile.readAll();
+ jsonFile.close();
+ ProblemContainer problems;
+ 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) }; }
+
+ 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:
+ void initTestCase()
+ {
+ cache.reset(new HttpMetaCache());
+ cache->addBase("libraries", QDir("libraries").absolutePath());
+ dataDir = QDir(QFINDTESTDATA("testdata/Libraries")).absolutePath();
+ }
+ void test_legacy()
+ {
+ RuntimeContext r = dummyContext();
+ Library test("test.package:testname:testversion");
+ QCOMPARE(test.artifactPrefix(), QString("test.package:testname"));
+ QCOMPARE(test.isNative(), false);
+
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(r, jar, native, native32, native64, QString());
+ QCOMPARE(jar, getStorage("test/package/testname/testversion/testname-testversion.jar"));
+ QCOMPARE(native, {});
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ }
+ void test_legacy_url()
+ {
+ RuntimeContext r = dummyContext();
+ QStringList failedFiles;
+ Library test("test.package:testname:testversion");
+ test.setRepositoryURL("file://foo/bar");
+ auto downloads = test.getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(downloads.size(), 1);
+ QCOMPARE(failedFiles, {});
+ Net::NetRequest::Ptr dl = downloads[0];
+ QCOMPARE(dl->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion.jar"));
+ }
+ void test_legacy_url_local_broken()
+ {
+ RuntimeContext r = dummyContext();
+ Library test("test.package:testname:testversion");
+ QCOMPARE(test.isNative(), false);
+ QStringList failedFiles;
+ test.setHint("local");
+ auto downloads = test.getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(downloads.size(), 0);
+ QCOMPARE(failedFiles, { "testname-testversion.jar" });
+ }
+ void test_legacy_url_local_override()
+ {
+ RuntimeContext r = dummyContext();
+ Library test("com.paulscode:codecwav:20101023");
+ QCOMPARE(test.isNative(), false);
+ QStringList failedFiles;
+ test.setHint("local");
+ auto downloads = test.getDownloads(r, cache.get(), failedFiles, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(downloads.size(), 0);
+ qDebug() << failedFiles;
+ QCOMPARE(failedFiles.size(), 0);
+
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(jar, { QFileInfo(QFINDTESTDATA("testdata/Libraries/codecwav-20101023.jar")).absoluteFilePath() });
+ QCOMPARE(native, {});
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ }
+ void test_legacy_native()
+ {
+ RuntimeContext r = dummyContext();
+ Library test("test.package:testname:testversion");
+ test.m_nativeClassifiers["linux"] = "linux";
+ QCOMPARE(test.isNative(), true);
+ test.setRepositoryURL("file://foo/bar");
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(r, jar, native, native32, native64, QString());
+ QCOMPARE(jar, {});
+ QCOMPARE(native, getStorage("test/package/testname/testversion/testname-testversion-linux.jar"));
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ QStringList failedFiles;
+ auto dls = test.getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(dls.size(), 1);
+ QCOMPARE(failedFiles, {});
+ auto dl = dls[0];
+ QCOMPARE(dl->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux.jar"));
+ }
+ }
+ void test_legacy_native_arch()
+ {
+ 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}";
+ QCOMPARE(test.isNative(), true);
+ test.setRepositoryURL("file://foo/bar");
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(r, jar, native, native32, native64, QString());
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-linux-32.jar"));
+ QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar"));
+ QStringList failedFiles;
+ auto dls = test.getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-32.jar"));
+ QCOMPARE(dls[1]->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-64.jar"));
+ }
+ r.system = "windows";
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(r, jar, native, native32, native64, QString());
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-windows-32.jar"));
+ QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-windows-64.jar"));
+ QStringList failedFiles;
+ auto dls = test.getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-32.jar"));
+ QCOMPARE(dls[1]->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-64.jar"));
+ }
+ r.system = "osx";
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(r, jar, native, native32, native64, QString());
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-osx-32.jar"));
+ QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-osx-64.jar"));
+ QStringList failedFiles;
+ auto dls = test.getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-32.jar"));
+ QCOMPARE(dls[1]->url(), QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-64.jar"));
+ }
+ }
+ void test_legacy_native_arch_local_override()
+ {
+ RuntimeContext r = dummyContext();
+ Library test("test.package:testname:testversion");
+ test.m_nativeClassifiers["linux"] = "linux-${arch}";
+ test.setHint("local");
+ QCOMPARE(test.isNative(), true);
+ test.setRepositoryURL("file://foo/bar");
+ {
+ QStringList jar, native, native32, native64;
+ test.getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, { QFileInfo(QFINDTESTDATA("testdata/Libraries/testname-testversion-linux-32.jar")).absoluteFilePath() });
+ QCOMPARE(native64,
+ { QFileInfo(QFINDTESTDATA("testdata/Libraries") + "/testname-testversion-linux-64.jar").absoluteFilePath() });
+ QStringList failedFiles;
+ auto dls = test.getDownloads(r, cache.get(), failedFiles, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(dls.size(), 0);
+ QCOMPARE(failedFiles,
+ { QFileInfo(QFINDTESTDATA("testdata/Libraries") + "/testname-testversion-linux-64.jar").absoluteFilePath() });
+ }
+ }
+ void test_onenine()
+ {
+ RuntimeContext r = dummyContext("osx");
+ auto test = readMojangJson(QFINDTESTDATA("testdata/Libraries/lib-simple.json"));
+ {
+ QStringList jar, native, native32, native64;
+ test->getApplicableFiles(r, jar, native, native32, native64, QString());
+ QCOMPARE(jar, getStorage("com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
+ QCOMPARE(native, {});
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ }
+ r.system = "linux";
+ {
+ QStringList failedFiles;
+ auto dls = test->getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(dls.size(), 1);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->url(), QUrl("https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
+ }
+ r.system = "osx";
+ test->setHint("local");
+ {
+ QStringList jar, native, native32, native64;
+ test->getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(jar, { QFileInfo(QFINDTESTDATA("testdata/Libraries/codecwav-20101023.jar")).absoluteFilePath() });
+ QCOMPARE(native, {});
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ }
+ r.system = "linux";
+ {
+ QStringList failedFiles;
+ auto dls = test->getDownloads(r, cache.get(), failedFiles, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(dls.size(), 0);
+ QCOMPARE(failedFiles, {});
+ }
+ }
+ void test_onenine_local_override()
+ {
+ RuntimeContext r = dummyContext("osx");
+ auto test = readMojangJson(QFINDTESTDATA("testdata/Libraries/lib-simple.json"));
+ test->setHint("local");
+ {
+ QStringList jar, native, native32, native64;
+ test->getApplicableFiles(r, jar, native, native32, native64, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(jar, { QFileInfo(QFINDTESTDATA("testdata/Libraries/codecwav-20101023.jar")).absoluteFilePath() });
+ QCOMPARE(native, {});
+ QCOMPARE(native32, {});
+ QCOMPARE(native64, {});
+ }
+ r.system = "linux";
+ {
+ QStringList failedFiles;
+ auto dls = test->getDownloads(r, cache.get(), failedFiles, QFINDTESTDATA("testdata/Libraries"));
+ QCOMPARE(dls.size(), 0);
+ QCOMPARE(failedFiles, {});
+ }
+ }
+ void test_onenine_native()
+ {
+ RuntimeContext r = dummyContext("osx");
+ auto test = readMojangJson(QFINDTESTDATA("testdata/Libraries/lib-native.json"));
+ 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(native32, {});
+ QCOMPARE(native64, {});
+ QStringList failedFiles;
+ auto dls = test->getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(dls.size(), 1);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->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()
+ {
+ RuntimeContext r = dummyContext("windows");
+ auto test = readMojangJson(QFINDTESTDATA("testdata/Libraries/lib-native-arch.json"));
+ QStringList jar, native, native32, native64;
+ test->getApplicableFiles(r, jar, native, native32, native64, QString());
+ QCOMPARE(jar, {});
+ QCOMPARE(native, {});
+ QCOMPARE(native32, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
+ QCOMPARE(native64, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
+ QStringList failedFiles;
+ auto dls = test->getDownloads(r, cache.get(), failedFiles, QString());
+ QCOMPARE(dls.size(), 2);
+ QCOMPARE(failedFiles, {});
+ QCOMPARE(dls[0]->url(),
+ QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
+ QCOMPARE(dls[1]->url(),
+ QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
+ }
+
+ private:
+ std::unique_ptr<HttpMetaCache> cache;
+ QString dataDir;
+};
+
+QTEST_GUILESS_MAIN(LibraryTest)
+
+#include "Library_test.moc"
diff --git a/archived/projt-launcher/tests/LogEventParser_test.cpp b/archived/projt-launcher/tests/LogEventParser_test.cpp
new file mode 100644
index 0000000000..66f622b96f
--- /dev/null
+++ b/archived/projt-launcher/tests/LogEventParser_test.cpp
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+
+#include <logs/LogEventParser.hpp>
+
+using projt::logs::LogEventParser;
+
+class LogEventParserTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void parseLog4jComplete()
+ {
+ LogEventParser parser;
+ const QString xml =
+ "<log4j:Event logger=\"Test.Logger\" timestamp=\"1700000000\" level=\"WARN\" thread=\"Main\">"
+ "<log4j:Message>Hello World</log4j:Message>"
+ "</log4j:Event>";
+
+ parser.pushLine(xml);
+ auto item = parser.popNext();
+ QVERIFY(item.has_value());
+ QVERIFY(std::holds_alternative<LogEventParser::LogRecord>(item.value()));
+
+ auto entry = std::get<LogEventParser::LogRecord>(item.value());
+ QCOMPARE(entry.logger, QStringLiteral("Test.Logger"));
+ QCOMPARE(entry.levelText, QStringLiteral("WARN"));
+ QCOMPARE(entry.level, MessageLevel::Warning);
+ QCOMPARE(entry.thread, QStringLiteral("Main"));
+ QCOMPARE(entry.message, QStringLiteral("Hello World"));
+ QCOMPARE(entry.timestamp.toSecsSinceEpoch(), 1700000000LL);
+ }
+
+ void parseLog4jMissingLogger()
+ {
+ LogEventParser parser;
+ const QString xml = "<log4j:Event timestamp=\"1700000000\" level=\"INFO\" thread=\"Main\">"
+ "<log4j:Message>Missing logger</log4j:Message>"
+ "</log4j:Event>";
+
+ parser.pushLine(xml);
+ auto item = parser.popNext();
+ QVERIFY(!item.has_value());
+ auto err = parser.lastError();
+ QVERIFY(err.has_value());
+ QVERIFY(err->message.contains(QStringLiteral("missing logger"), Qt::CaseInsensitive));
+ }
+
+ void parseLog4jPendingChunk()
+ {
+ LogEventParser parser;
+ const QString partial =
+ "<log4j:Event logger=\"Test.Logger\" timestamp=\"1700000000\" level=\"INFO\" thread=\"Main\">"
+ "<log4j:Message>Partial";
+ const QString remainder = "</log4j:Message></log4j:Event>";
+
+ parser.pushLine(partial);
+ auto first = parser.popNext();
+ QVERIFY(first.has_value());
+ QVERIFY(std::holds_alternative<LogEventParser::PendingChunk>(first.value()));
+
+ parser.pushLine(remainder);
+ auto second = parser.popNext();
+ QVERIFY(second.has_value());
+ QVERIFY(std::holds_alternative<LogEventParser::LogRecord>(second.value()));
+ auto entry = std::get<LogEventParser::LogRecord>(second.value());
+ QCOMPARE(entry.message, QStringLiteral("Partial"));
+ }
+
+ void parseLog4jLeadingWhitespace()
+ {
+ LogEventParser parser;
+ const QString xml =
+ " <log4j:Event logger=\"Test.Logger\" timestamp=\"1700000000\" level=\"INFO\" thread=\"Main\">"
+ "<log4j:Message>Whitespace</log4j:Message>"
+ "</log4j:Event>";
+
+ parser.pushLine(xml);
+ auto item = parser.popNext();
+ QVERIFY(item.has_value());
+ QVERIFY(std::holds_alternative<LogEventParser::LogRecord>(item.value()));
+ }
+
+ void guessLevelFromLine_data()
+ {
+ QTest::addColumn<QString>("line");
+ QTest::addColumn<int>("fallback");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("header-info") << "[12:34:56] [Server thread/INFO] Hello"
+ << static_cast<int>(MessageLevel::Unknown) << static_cast<int>(MessageLevel::Info);
+
+ QTest::newRow("bracket-severe") << "[SEVERE] Something bad" << static_cast<int>(MessageLevel::Unknown)
+ << static_cast<int>(MessageLevel::Error);
+
+ QTest::newRow("warning-tag") << "[WARNING] Potential issue" << static_cast<int>(MessageLevel::Unknown)
+ << static_cast<int>(MessageLevel::Warning);
+
+ QTest::newRow("fatal-overwrite") << "overwriting existing" << static_cast<int>(MessageLevel::Unknown)
+ << static_cast<int>(MessageLevel::Fatal);
+
+ QTest::newRow("fallback-preserved")
+ << "overwriting existing" << static_cast<int>(MessageLevel::Info) << static_cast<int>(MessageLevel::Info);
+ }
+
+ void guessLevelFromLine()
+ {
+ QFETCH(QString, line);
+ QFETCH(int, fallback);
+ QFETCH(int, expected);
+
+ auto result = LogEventParser::guessLevelFromLine(line, static_cast<MessageLevel::Enum>(fallback));
+ QCOMPARE(static_cast<int>(result), expected);
+ }
+};
+
+QTEST_GUILESS_MAIN(LogEventParserTest)
+
+#include "LogEventParser_test.moc"
diff --git a/archived/projt-launcher/tests/MMCTime_test.cpp b/archived/projt-launcher/tests/MMCTime_test.cpp
new file mode 100644
index 0000000000..2adc9effd0
--- /dev/null
+++ b/archived/projt-launcher/tests/MMCTime_test.cpp
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <MMCTime.h>
+
+class MMCTimeTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_prettifyDuration_data()
+ {
+ QTest::addColumn<int64_t>("seconds");
+ QTest::addColumn<bool>("noDays");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("seconds-only") << int64_t(59) << false << "0min 59s";
+ QTest::newRow("minutes-and-seconds") << int64_t(125) << false << "2min 5s";
+ QTest::newRow("hours") << int64_t(3661) << false << "1h 1min";
+ QTest::newRow("days") << int64_t(90061) << false << "1d 1h 1min";
+ QTest::newRow("noDays-folds-days-into-hours") << int64_t(90061) << true << "25h 1min";
+ }
+
+ void test_prettifyDuration()
+ {
+ QFETCH(int64_t, seconds);
+ QFETCH(bool, noDays);
+ QFETCH(QString, expected);
+
+ QCOMPARE(Time::prettifyDuration(seconds, noDays), expected);
+ }
+
+ void test_humanReadableDuration_signAndUnits()
+ {
+ const auto zero = Time::humanReadableDuration(0.0);
+ QCOMPARE(zero, QString("0ms"));
+
+ const auto negative = Time::humanReadableDuration(-0.5, 1);
+ QVERIFY(negative.startsWith('-'));
+ QVERIFY(negative.contains("ms"));
+
+ const auto withSeconds = Time::humanReadableDuration(65.0);
+ QVERIFY(withSeconds.contains("m"));
+ QVERIFY(withSeconds.contains("s"));
+
+ const auto withDays = Time::humanReadableDuration(90061.0);
+ QVERIFY(withDays.contains("days"));
+ QVERIFY(withDays.contains("h"));
+ QVERIFY(withDays.contains("m"));
+ QVERIFY(withDays.contains("s"));
+ }
+};
+
+QTEST_GUILESS_MAIN(MMCTimeTest)
+
+#include "MMCTime_test.moc"
diff --git a/archived/projt-launcher/tests/MessageLevel_test.cpp b/archived/projt-launcher/tests/MessageLevel_test.cpp
new file mode 100644
index 0000000000..83bf14c227
--- /dev/null
+++ b/archived/projt-launcher/tests/MessageLevel_test.cpp
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <MessageLevel.h>
+
+class MessageLevelTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_getLevelString()
+ {
+ QCOMPARE(MessageLevel::getLevel("info"), MessageLevel::Info);
+ QCOMPARE(MessageLevel::getLevel("WARN"), MessageLevel::Warning);
+ QCOMPARE(MessageLevel::getLevel("critical"), MessageLevel::Error);
+ QCOMPARE(MessageLevel::getLevel("nope"), MessageLevel::Unknown);
+ }
+
+ void test_getLevelQtMsgType()
+ {
+ QCOMPARE(MessageLevel::getLevel(QtDebugMsg), MessageLevel::Debug);
+ QCOMPARE(MessageLevel::getLevel(QtInfoMsg), MessageLevel::Info);
+ QCOMPARE(MessageLevel::getLevel(QtWarningMsg), MessageLevel::Warning);
+ QCOMPARE(MessageLevel::getLevel(QtCriticalMsg), MessageLevel::Error);
+ QCOMPARE(MessageLevel::getLevel(QtFatalMsg), MessageLevel::Fatal);
+ }
+
+ void test_fromLine()
+ {
+ QString line = "!![INFO]! hello";
+ QCOMPARE(MessageLevel::fromLine(line), MessageLevel::Info);
+ QCOMPARE(line, QString(" hello"));
+
+ QString noPrefix = "plain";
+ QCOMPARE(MessageLevel::fromLine(noPrefix), MessageLevel::Unknown);
+ QCOMPARE(noPrefix, QString("plain"));
+ }
+
+ void test_fromLauncherLine()
+ {
+ QString line = "12 INFO: message";
+ QCOMPARE(MessageLevel::fromLauncherLine(line), MessageLevel::Info);
+ QCOMPARE(line, QString("message"));
+
+ QString bad = "nope";
+ QCOMPARE(MessageLevel::fromLauncherLine(bad), MessageLevel::Unknown);
+ QCOMPARE(bad, QString("nope"));
+ }
+};
+
+QTEST_GUILESS_MAIN(MessageLevelTest)
+
+#include "MessageLevel_test.moc"
diff --git a/archived/projt-launcher/tests/MetaComponentParse_test.cpp b/archived/projt-launcher/tests/MetaComponentParse_test.cpp
new file mode 100644
index 0000000000..db4442de5a
--- /dev/null
+++ b/archived/projt-launcher/tests/MetaComponentParse_test.cpp
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * 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 <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QTest>
+#include <QTimer>
+
+#include <FileSystem.h>
+
+#include <minecraft/mod/tasks/LocalDataPackParseTask.hpp>
+
+class MetaComponentParseTest : public QObject
+{
+ Q_OBJECT
+
+ void doTest(QString name)
+ {
+ QString source = QFINDTESTDATA("testdata/MetaComponentParse");
+
+ QString comp_rp = FS::PathCombine(source, name);
+
+ QFile file;
+ file.setFileName(comp_rp);
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ QString data = file.readAll();
+ file.close();
+
+ QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8());
+ QJsonObject obj = doc.object();
+
+ QJsonValue description_json = obj.value("description");
+ QJsonValue expected_json = obj.value("expected_output");
+
+ QVERIFY(!description_json.isUndefined());
+ QVERIFY(expected_json.isString());
+
+ QString expected = expected_json.toString();
+
+ QString processed = DataPackUtils::processComponent(description_json);
+
+ QCOMPARE(processed, expected);
+ }
+
+ private slots:
+ void test_parseComponentBasic()
+ {
+ doTest("component_basic.json");
+ }
+ void test_parseComponentWithFormat()
+ {
+ doTest("component_with_format.json");
+ }
+ void test_parseComponentWithExtra()
+ {
+ doTest("component_with_extra.json");
+ }
+ void test_parseComponentWithLink()
+ {
+ doTest("component_with_link.json");
+ }
+ void test_parseComponentWithMixed()
+ {
+ doTest("component_with_mixed.json");
+ }
+};
+
+QTEST_GUILESS_MAIN(MetaComponentParseTest)
+
+#include "MetaComponentParse_test.moc"
diff --git a/archived/projt-launcher/tests/ModPlatform_test.cpp b/archived/projt-launcher/tests/ModPlatform_test.cpp
new file mode 100644
index 0000000000..3a230864e2
--- /dev/null
+++ b/archived/projt-launcher/tests/ModPlatform_test.cpp
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QSet>
+#include <QTest>
+
+#include <modplatform/ModIndex.h>
+#include <modplatform/ResourceType.h>
+
+class ModPlatformTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_resourceTypeNames()
+ {
+ using ModPlatform::ResourceType;
+ QCOMPARE(ModPlatform::ResourceTypeUtils::getName(ResourceType::Mod), QString("mod"));
+ QCOMPARE(ModPlatform::ResourceTypeUtils::getName(ResourceType::ResourcePack), QString("resource pack"));
+ QCOMPARE(ModPlatform::ResourceTypeUtils::getName(ResourceType::Unknown), QString("unknown"));
+ }
+
+ void test_versionTypeConversions()
+ {
+ using ModPlatform::IndexedVersionType;
+ QCOMPARE(IndexedVersionType::enumFromString("release"), IndexedVersionType::VersionType::Release);
+ QCOMPARE(IndexedVersionType::enumFromString("beta"), IndexedVersionType::VersionType::Beta);
+ QCOMPARE(IndexedVersionType::enumFromString("alpha"), IndexedVersionType::VersionType::Alpha);
+ QCOMPARE(IndexedVersionType::enumFromString("nope"), IndexedVersionType::VersionType::Unknown);
+ QCOMPARE(IndexedVersionType::toString(IndexedVersionType::VersionType::Release), QString("release"));
+ QCOMPARE(IndexedVersionType::toString(IndexedVersionType::VersionType::Unknown), QString("unknown"));
+ }
+
+ void test_providerCapabilities()
+ {
+ using ModPlatform::ProviderCapabilities::hashType;
+ using ModPlatform::ProviderCapabilities::name;
+ using ModPlatform::ProviderCapabilities::readableName;
+ using ModPlatform::ResourceProvider;
+
+ QCOMPARE(QString(name(ResourceProvider::MODRINTH)), QString("modrinth"));
+ QCOMPARE(readableName(ResourceProvider::MODRINTH), QString("Modrinth"));
+ QCOMPARE(hashType(ResourceProvider::MODRINTH), QStringList({"sha512", "sha1"}));
+
+ QCOMPARE(QString(name(ResourceProvider::FLAME)), QString("curseforge"));
+ QCOMPARE(readableName(ResourceProvider::FLAME), QString("CurseForge"));
+ QCOMPARE(hashType(ResourceProvider::FLAME), QStringList({"sha1", "md5", "murmur2"}));
+ }
+
+ void test_metaUrl()
+ {
+ QCOMPARE(ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, "123"),
+ QString("https://www.curseforge.com/projects/123"));
+ QCOMPARE(ModPlatform::getMetaURL(ModPlatform::ResourceProvider::MODRINTH, "abc"),
+ QString("https://modrinth.com/mod/abc"));
+ }
+
+ void test_modLoaderStrings()
+ {
+ QCOMPARE(ModPlatform::getModLoaderAsString(ModPlatform::Forge), QString("forge"));
+ QCOMPARE(ModPlatform::getModLoaderFromString("forge"), ModPlatform::Forge);
+ QCOMPARE(ModPlatform::getModLoaderFromString("unknown"), static_cast<ModPlatform::ModLoaderType>(0));
+ }
+
+ void test_modLoaderFlagsToList()
+ {
+ ModPlatform::ModLoaderTypes flags;
+ flags |= ModPlatform::Forge;
+ flags |= ModPlatform::Fabric;
+ flags |= ModPlatform::Optifine;
+ QList<ModPlatform::ModLoaderType> list = ModPlatform::modLoaderTypesToList(flags);
+ QSet<int> values;
+ for (auto entry : list) {
+ values.insert(static_cast<int>(entry));
+ }
+ QCOMPARE(values.size(), 3);
+ QVERIFY(values.contains(static_cast<int>(ModPlatform::Forge)));
+ QVERIFY(values.contains(static_cast<int>(ModPlatform::Fabric)));
+ QVERIFY(values.contains(static_cast<int>(ModPlatform::Optifine)));
+ }
+
+ void test_sideConversions()
+ {
+ QCOMPARE(ModPlatform::SideUtils::fromString("client"), ModPlatform::Side::ClientSide);
+ QCOMPARE(ModPlatform::SideUtils::toString(ModPlatform::Side::ClientSide), QString("client"));
+ QCOMPARE(ModPlatform::SideUtils::fromString("server"), ModPlatform::Side::ServerSide);
+ QCOMPARE(ModPlatform::SideUtils::toString(ModPlatform::Side::ServerSide), QString("server"));
+ QCOMPARE(ModPlatform::SideUtils::fromString("both"), ModPlatform::Side::UniversalSide);
+ QCOMPARE(ModPlatform::SideUtils::toString(ModPlatform::Side::UniversalSide), QString("both"));
+ QCOMPARE(ModPlatform::SideUtils::fromString("unknown"), ModPlatform::Side::UniversalSide);
+ }
+};
+
+QTEST_GUILESS_MAIN(ModPlatformTest)
+
+#include "ModPlatform_test.moc"
diff --git a/archived/projt-launcher/tests/MojangVersionFormat_test.cpp b/archived/projt-launcher/tests/MojangVersionFormat_test.cpp
new file mode 100644
index 0000000000..d55c6561ea
--- /dev/null
+++ b/archived/projt-launcher/tests/MojangVersionFormat_test.cpp
@@ -0,0 +1,56 @@
+#include <QDebug>
+#include <QTest>
+
+#include <minecraft/MojangVersionFormat.h>
+
+class MojangVersionFormatTest : public QObject {
+ Q_OBJECT
+
+ static QJsonDocument readJson(const QString path)
+ {
+ QFile jsonFile(path);
+ if (!jsonFile.open(QIODevice::ReadOnly)) {
+ qWarning() << "Failed to open file '" << jsonFile.fileName() << "' for reading!";
+ return QJsonDocument();
+ }
+ auto data = jsonFile.readAll();
+ jsonFile.close();
+ return QJsonDocument::fromJson(data);
+ }
+ static void writeJson(const char* file, QJsonDocument doc)
+ {
+ QFile jsonFile(file);
+ if (!jsonFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qCritical() << "Failed to open file '" << jsonFile.fileName() << "' for writing!";
+ return;
+ }
+ auto data = doc.toJson(QJsonDocument::Indented);
+ qDebug() << QString::fromUtf8(data);
+ jsonFile.write(data);
+ jsonFile.close();
+ }
+
+ private slots:
+ void test_Through_Simple()
+ {
+ QJsonDocument doc = readJson(QFINDTESTDATA("testdata/Libraries/1.9-simple.json"));
+ auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9-simple.json");
+ auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
+ writeJson("1.9-simple-passthorugh.json", doc2);
+
+ QCOMPARE(doc.toJson(), doc2.toJson());
+ }
+
+ void test_Through()
+ {
+ QJsonDocument doc = readJson(QFINDTESTDATA("testdata/Libraries/1.9.json"));
+ auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9.json");
+ auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
+ writeJson("1.9-passthorugh.json", doc2);
+ QCOMPARE(doc.toJson(), doc2.toJson());
+ }
+};
+
+QTEST_GUILESS_MAIN(MojangVersionFormatTest)
+
+#include "MojangVersionFormat_test.moc"
diff --git a/archived/projt-launcher/tests/NetHeaderProxy_test.cpp b/archived/projt-launcher/tests/NetHeaderProxy_test.cpp
new file mode 100644
index 0000000000..7e11da30ac
--- /dev/null
+++ b/archived/projt-launcher/tests/NetHeaderProxy_test.cpp
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QNetworkRequest>
+#include <QTest>
+
+#include <net/RawHeaderProxy.h>
+
+class NetHeaderProxyTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_rawHeaderProxy()
+ {
+ Net::RawHeaderProxy proxy;
+ proxy.addHeader("X-Test", "1");
+ proxy.addHeader("X-Other", "value");
+
+ QNetworkRequest request(QUrl("https://example.com"));
+ proxy.writeHeaders(request);
+
+ QCOMPARE(request.rawHeader("X-Test"), QByteArray("1"));
+ QCOMPARE(request.rawHeader("X-Other"), QByteArray("value"));
+ }
+};
+
+QTEST_GUILESS_MAIN(NetHeaderProxyTest)
+
+#include "NetHeaderProxy_test.moc"
diff --git a/archived/projt-launcher/tests/NetSink_test.cpp b/archived/projt-launcher/tests/NetSink_test.cpp
new file mode 100644
index 0000000000..ab6dd0d793
--- /dev/null
+++ b/archived/projt-launcher/tests/NetSink_test.cpp
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QNetworkRequest>
+#include <QTest>
+
+#include <net/ByteArraySink.h>
+#include <net/Validator.h>
+#include <tasks/Task.h>
+
+class DummyReply : public QNetworkReply
+{
+ Q_OBJECT
+
+ public:
+ explicit DummyReply(QObject* parent = nullptr) : QNetworkReply(parent)
+ {
+ setUrl(QUrl("https://example.com/"));
+ open(QIODevice::ReadOnly);
+ setFinished(true);
+ setError(QNetworkReply::NoError, {});
+ }
+
+ void abort() override {}
+
+ protected:
+ qint64 readData(char*, qint64) override { return -1; }
+};
+
+class DummyValidator : public Net::Validator
+{
+ public:
+ bool initResult = true;
+ bool writeResult = true;
+ bool abortResult = true;
+ bool validateResult = true;
+
+ bool init(QNetworkRequest&) override { return initResult; }
+ bool write(QByteArray&) override { return writeResult; }
+ bool abort() override { return abortResult; }
+ bool validate(QNetworkReply&) override { return validateResult; }
+};
+
+class NetSinkTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_byteArraySinkHappyPath()
+ {
+ auto buffer = std::make_shared<QByteArray>("preset");
+ Net::ByteArraySink sink(buffer);
+ sink.addValidator(new DummyValidator());
+
+ QNetworkRequest request(QUrl("https://example.com"));
+ QCOMPARE(sink.init(request), Task::State::Running);
+ QCOMPARE(*buffer, QByteArray());
+
+ QByteArray data("abc");
+ QCOMPARE(sink.write(data), Task::State::Running);
+ QCOMPARE(*buffer, QByteArray("abc"));
+
+ DummyReply reply;
+ QCOMPARE(sink.finalize(reply), Task::State::Succeeded);
+ QVERIFY(!sink.hasLocalData());
+ }
+
+ void test_byteArraySinkInitFailure()
+ {
+ auto buffer = std::make_shared<QByteArray>();
+ Net::ByteArraySink sink(buffer);
+ auto validator = new DummyValidator();
+ validator->initResult = false;
+ sink.addValidator(validator);
+
+ QNetworkRequest request(QUrl("https://example.com"));
+ QCOMPARE(sink.init(request), Task::State::Failed);
+ QCOMPARE(sink.failReason(), QString("Failed to initialize validators"));
+ }
+
+ void test_byteArraySinkWriteFailure()
+ {
+ auto buffer = std::make_shared<QByteArray>();
+ Net::ByteArraySink sink(buffer);
+ auto validator = new DummyValidator();
+ validator->writeResult = false;
+ sink.addValidator(validator);
+
+ QNetworkRequest request(QUrl("https://example.com"));
+ QCOMPARE(sink.init(request), Task::State::Running);
+
+ QByteArray data("abc");
+ QCOMPARE(sink.write(data), Task::State::Failed);
+ QCOMPARE(sink.failReason(), QString("Failed to write validators"));
+ }
+
+ void test_byteArraySinkFinalizeFailure()
+ {
+ auto buffer = std::make_shared<QByteArray>();
+ Net::ByteArraySink sink(buffer);
+ auto validator = new DummyValidator();
+ validator->validateResult = false;
+ sink.addValidator(validator);
+
+ QNetworkRequest request(QUrl("https://example.com"));
+ QCOMPARE(sink.init(request), Task::State::Running);
+
+ QByteArray data("abc");
+ QCOMPARE(sink.write(data), Task::State::Running);
+
+ DummyReply reply;
+ QCOMPARE(sink.finalize(reply), Task::State::Failed);
+ QCOMPARE(sink.failReason(), QString("Failed to finalize validators"));
+ }
+
+ void test_byteArraySinkAbort()
+ {
+ auto buffer = std::make_shared<QByteArray>();
+ Net::ByteArraySink sink(buffer);
+ sink.addValidator(new DummyValidator());
+
+ QCOMPARE(sink.abort(), Task::State::Failed);
+ QCOMPARE(sink.failReason(), QString("Aborted"));
+ }
+};
+
+QTEST_GUILESS_MAIN(NetSinkTest)
+
+#include "NetSink_test.moc"
diff --git a/archived/projt-launcher/tests/NetUtils_test.cpp b/archived/projt-launcher/tests/NetUtils_test.cpp
new file mode 100644
index 0000000000..2bbbbc9167
--- /dev/null
+++ b/archived/projt-launcher/tests/NetUtils_test.cpp
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QCryptographicHash>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QTest>
+
+#include <net/ChecksumValidator.h>
+#include <net/NetUtils.h>
+
+class DummyReply : public QNetworkReply
+{
+ Q_OBJECT
+
+ public:
+ explicit DummyReply(QObject* parent = nullptr) : QNetworkReply(parent)
+ {
+ setUrl(QUrl("https://example.com/"));
+ open(QIODevice::ReadOnly);
+ setFinished(true);
+ setError(QNetworkReply::NoError, {});
+ }
+
+ void abort() override {}
+
+ protected:
+ qint64 readData(char*, qint64) override { return -1; }
+};
+
+class NetUtilsTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_isApplicationError()
+ {
+ QVERIFY(Net::isApplicationError(QNetworkReply::ContentNotFoundError));
+ QVERIFY(Net::isApplicationError(QNetworkReply::AuthenticationRequiredError));
+ QVERIFY(Net::isApplicationError(QNetworkReply::InternalServerError));
+
+ QVERIFY(!Net::isApplicationError(QNetworkReply::NoError));
+ QVERIFY(!Net::isApplicationError(QNetworkReply::ConnectionRefusedError));
+ QVERIFY(!Net::isApplicationError(QNetworkReply::TimeoutError));
+ }
+
+ void test_checksumValidator_matches()
+ {
+ QCryptographicHash hash(QCryptographicHash::Sha256);
+ hash.addData(QByteArrayView("hello", 5));
+ const QByteArray expected = hash.result();
+
+ Net::ChecksumValidator validator(QCryptographicHash::Sha256, expected);
+ QNetworkRequest request;
+ QVERIFY(validator.init(request));
+ QByteArray data("hello");
+ QVERIFY(validator.write(data));
+
+ DummyReply reply;
+ QVERIFY(validator.validate(reply));
+ }
+
+ void test_checksumValidator_mismatch()
+ {
+ QCryptographicHash hash(QCryptographicHash::Sha256);
+ hash.addData(QByteArrayView("world", 5));
+ const QByteArray expected = hash.result();
+
+ Net::ChecksumValidator validator(QCryptographicHash::Sha256, expected);
+ QNetworkRequest request;
+ QVERIFY(validator.init(request));
+ QByteArray data("hello");
+ QVERIFY(validator.write(data));
+
+ DummyReply reply;
+ QVERIFY(!validator.validate(reply));
+ }
+};
+
+QTEST_GUILESS_MAIN(NetUtilsTest)
+
+#include "NetUtils_test.moc"
diff --git a/archived/projt-launcher/tests/Packwiz_test.cpp b/archived/projt-launcher/tests/Packwiz_test.cpp
new file mode 100644
index 0000000000..7931fbddeb
--- /dev/null
+++ b/archived/projt-launcher/tests/Packwiz_test.cpp
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTemporaryDir>
+#include <QTest>
+#include "modplatform/ModIndex.h"
+
+#include <modplatform/packwiz/Packwiz.h>
+
+class PackwizTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ // Files taken from https://github.com/packwiz/packwiz-example-pack
+ void loadFromFile_Modrinth()
+ {
+ QString source = QFINDTESTDATA("testdata/Packwiz");
+
+ QDir index_dir(source);
+ QString slug_mod("borderless-mining");
+ QString file_name = slug_mod + ".pw.toml";
+ QVERIFY(index_dir.entryList().contains(file_name));
+
+ auto metadata = Packwiz::V1::getIndexForMod(index_dir, slug_mod);
+
+ QVERIFY(metadata.isValid());
+
+ QCOMPARE(metadata.name, "Borderless Mining");
+ QCOMPARE(metadata.filename, "borderless-mining-1.1.1+1.18.jar");
+ QCOMPARE(metadata.side, ModPlatform::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");
+ QCOMPARE(metadata.hash,
+ "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c"
+ "6d5346f1ba6362306449"
+ "9b3188d");
+
+ QCOMPARE(metadata.provider, ModPlatform::ResourceProvider::MODRINTH);
+ QCOMPARE(metadata.version(), "ug2qKTPR");
+ QCOMPARE(metadata.mod_id(), "kYq5qkSL");
+ }
+
+ void loadFromFile_Curseforge()
+ {
+ QString source = QFINDTESTDATA("testdata/Packwiz");
+
+ QDir index_dir(source);
+ QString name_mod("screenshot-to-clipboard-fabric.pw.toml");
+ QVERIFY(index_dir.entryList().contains(name_mod));
+
+ // Try without the .pw.toml at the end
+ name_mod.chop(8);
+
+ auto metadata = Packwiz::V1::getIndexForMod(index_dir, name_mod);
+
+ QVERIFY(metadata.isValid());
+
+ QCOMPARE(metadata.name, "Screenshot to Clipboard (Fabric)");
+ QCOMPARE(metadata.filename, "screenshot-to-clipboard-1.0.7-fabric.jar");
+ QCOMPARE(metadata.side, ModPlatform::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");
+ QCOMPARE(metadata.hash, "1781245820");
+
+ QCOMPARE(metadata.provider, ModPlatform::ResourceProvider::FLAME);
+ QCOMPARE(metadata.file_id, 3509043);
+ QCOMPARE(metadata.project_id, 327154);
+ }
+};
+
+QTEST_GUILESS_MAIN(PackwizTest)
+
+#include "Packwiz_test.moc"
diff --git a/archived/projt-launcher/tests/ParseUtils_test.cpp b/archived/projt-launcher/tests/ParseUtils_test.cpp
new file mode 100644
index 0000000000..0ba06233a6
--- /dev/null
+++ b/archived/projt-launcher/tests/ParseUtils_test.cpp
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <minecraft/ParseUtils.h>
+
+class ParseUtilsTest : public QObject
+{
+ Q_OBJECT
+ private slots:
+ void test_Through_data()
+ {
+ QTest::addColumn<QString>("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++)
+ {
+ QTest::newRow(timestamps[i]) << QString(timestamps[i]);
+ }
+ }
+ void test_Through()
+ {
+ QFETCH(QString, timestamp);
+
+ auto time_parsed = timeFromS3Time(timestamp);
+ auto time_serialized = timeToS3Time(time_parsed);
+
+ QCOMPARE(time_serialized, timestamp);
+ }
+};
+
+QTEST_GUILESS_MAIN(ParseUtilsTest)
+
+#include "ParseUtils_test.moc"
diff --git a/archived/projt-launcher/tests/ProjTExternalUpdater_test.cpp b/archived/projt-launcher/tests/ProjTExternalUpdater_test.cpp
new file mode 100644
index 0000000000..4c22ca9040
--- /dev/null
+++ b/archived/projt-launcher/tests/ProjTExternalUpdater_test.cpp
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QSettings>
+#include <QTemporaryDir>
+#include <QTest>
+
+#include <updater/ProjTExternalUpdater.h>
+
+class ProjTExternalUpdaterTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void defaultsFromEmptySettings()
+ {
+ QTemporaryDir tempDir;
+ QVERIFY(tempDir.isValid());
+
+ ProjTExternalUpdater updater(nullptr, tempDir.path(), tempDir.path());
+ QCOMPARE(updater.getAutomaticallyChecksForUpdates(), false);
+ QCOMPARE(updater.getBetaAllowed(), false);
+ QCOMPARE(updater.getUpdateCheckInterval(), 86400.0);
+ }
+
+ void invalidIntervalFallsBackToDefault()
+ {
+ QTemporaryDir tempDir;
+ QVERIFY(tempDir.isValid());
+
+ const auto settingsPath = QDir(tempDir.path()).absoluteFilePath("projtlauncher_update.cfg");
+ {
+ QSettings settings(settingsPath, QSettings::IniFormat);
+ settings.setValue("update_interval", "not-a-number");
+ settings.sync();
+ }
+
+ ProjTExternalUpdater updater(nullptr, tempDir.path(), tempDir.path());
+ QCOMPARE(updater.getUpdateCheckInterval(), 86400.0);
+ }
+
+ void settersUpdateState()
+ {
+ QTemporaryDir tempDir;
+ QVERIFY(tempDir.isValid());
+
+ ProjTExternalUpdater updater(nullptr, tempDir.path(), tempDir.path());
+ updater.setUpdateCheckInterval(3600);
+ updater.setAutomaticallyChecksForUpdates(true);
+ updater.setBetaAllowed(true);
+
+ QCOMPARE(updater.getUpdateCheckInterval(), 3600.0);
+ QCOMPARE(updater.getAutomaticallyChecksForUpdates(), true);
+ QCOMPARE(updater.getBetaAllowed(), true);
+ }
+};
+
+QTEST_GUILESS_MAIN(ProjTExternalUpdaterTest)
+
+#include "ProjTExternalUpdater_test.moc"
diff --git a/archived/projt-launcher/tests/ResourceFolderModel_test.cpp b/archived/projt-launcher/tests/ResourceFolderModel_test.cpp
new file mode 100644
index 0000000000..e67f5e8257
--- /dev/null
+++ b/archived/projt-launcher/tests/ResourceFolderModel_test.cpp
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ * 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 <QTemporaryDir>
+#include <QTest>
+#include <QTimer>
+#include "BaseInstance.h"
+
+#include <FileSystem.h>
+
+#include <minecraft/mod/ModFolderModel.hpp>
+#include <minecraft/mod/ResourceFolderModel.hpp>
+
+#define EXEC_UPDATE_TASK(EXEC, VERIFY) \
+ QEventLoop loop; \
+ \
+ connect(&model, &ResourceFolderModel::updateFinished, &loop, &QEventLoop::quit); \
+ \
+ QTimer expire_timer; \
+ expire_timer.callOnTimeout(&loop, &QEventLoop::quit); \
+ expire_timer.setSingleShot(true); \
+ expire_timer.start(4000); \
+ \
+ VERIFY(EXEC); \
+ loop.exec(); \
+ \
+ QVERIFY2(expire_timer.isActive(), "Timer has expired. The update never finished."); \
+ expire_timer.stop(); \
+ \
+ disconnect(&model, nullptr, &loop, nullptr);
+
+class ResourceFolderModelTest : public QObject {
+ Q_OBJECT
+
+ private slots:
+ // test for GH-1178 - install a folder with files to a mod list
+ void test_1178()
+ {
+ // source
+ QString source = QFINDTESTDATA("testdata/Resources/test_folder");
+
+ // sanity check
+ QVERIFY(!source.endsWith('/'));
+
+ 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"));
+ };
+
+ // 1. test with no trailing /
+ {
+ QString folder = source;
+ QTemporaryDir tempDir;
+
+ QEventLoop loop;
+
+ ModFolderModel m(tempDir.path(), nullptr, true, true);
+
+ connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
+
+ QTimer expire_timer;
+ expire_timer.callOnTimeout(&loop, &QEventLoop::quit);
+ expire_timer.setSingleShot(true);
+ expire_timer.start(4000);
+
+ m.installResource(folder);
+
+ loop.exec();
+
+ QVERIFY2(expire_timer.isActive(), "Timer has expired. The update never finished.");
+ expire_timer.stop();
+
+ verify(tempDir.path());
+ }
+
+ // 2. test with trailing /
+ {
+ QString folder = source + '/';
+ QTemporaryDir tempDir;
+ QEventLoop loop;
+ ModFolderModel m(tempDir.path(), nullptr, true, true);
+
+ connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
+
+ QTimer expire_timer;
+ expire_timer.callOnTimeout(&loop, &QEventLoop::quit);
+ expire_timer.setSingleShot(true);
+ expire_timer.start(4000);
+
+ m.installResource(folder);
+
+ loop.exec();
+
+ QVERIFY2(expire_timer.isActive(), "Timer has expired. The update never finished.");
+ expire_timer.stop();
+
+ verify(tempDir.path());
+ }
+ }
+
+ void test_addFromWatch()
+ {
+ QString source = QFINDTESTDATA("testdata/Resources");
+ ModFolderModel model(source, nullptr, false, true);
+
+ QCOMPARE(model.size(), 0);
+
+ EXEC_UPDATE_TASK(model.startWatching(), )
+
+ for (auto mod : model.allMods())
+ qDebug() << mod->name();
+
+ QCOMPARE(model.size(), 4);
+
+ model.stopWatching();
+ }
+
+ void test_removeResource()
+ {
+ QString folder_resource = QFINDTESTDATA("testdata/Resources/test_folder");
+ QString file_mod = QFINDTESTDATA("testdata/Resources/supercoolmod.jar");
+
+ QTemporaryDir tmp;
+ ResourceFolderModel model(QDir(tmp.path()), nullptr, false, false);
+
+ QCOMPARE(model.size(), 0);
+
+ { EXEC_UPDATE_TASK(model.installResource(file_mod), QVERIFY) }
+
+ QCOMPARE(model.size(), 1);
+ qDebug() << "Added first mod.";
+
+ { EXEC_UPDATE_TASK(model.startWatching(), ) }
+
+ QCOMPARE(model.size(), 1);
+ qDebug() << "Started watching the temp folder.";
+
+ { EXEC_UPDATE_TASK(model.installResource(folder_resource), QVERIFY) }
+
+ QCOMPARE(model.size(), 2);
+ qDebug() << "Added second mod.";
+
+ {
+ EXEC_UPDATE_TASK(model.uninstallResource("supercoolmod.jar"), QVERIFY);
+ }
+
+ QCOMPARE(model.size(), 1);
+ qDebug() << "Removed first mod.";
+
+ QString mod_file_name{ model.at(0).fileinfo().fileName() };
+ QVERIFY(!mod_file_name.isEmpty());
+
+ {
+ EXEC_UPDATE_TASK(model.uninstallResource(mod_file_name), QVERIFY);
+ }
+
+ QCOMPARE(model.size(), 0);
+ qDebug() << "Removed second mod.";
+
+ model.stopWatching();
+ }
+
+ void test_enable_disable()
+ {
+ QString folder_resource = QFINDTESTDATA("testdata/Resources/test_folder");
+ QString file_mod = QFINDTESTDATA("testdata/Resources/supercoolmod.jar");
+
+ QTemporaryDir tmp;
+ ResourceFolderModel model(tmp.path(), nullptr, false, false);
+
+ QCOMPARE(model.size(), 0);
+
+ {
+ EXEC_UPDATE_TASK(model.installResource(folder_resource), QVERIFY)
+ }
+ {
+ EXEC_UPDATE_TASK(model.installResource(file_mod), QVERIFY)
+ }
+
+ for (auto res : model.allResources())
+ qDebug() << res->name();
+
+ QCOMPARE(model.size(), 2);
+
+ auto& res_1 = model.at(0).type() != ResourceType::FOLDER ? model.at(0) : model.at(1);
+ 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();
+
+ QVERIFY(res_1.type() != ResourceType::FOLDER && res_1.type() != ResourceType::UNKNOWN);
+ qDebug() << "res_1 is of the correct type.";
+ QVERIFY(res_1.enabled());
+ qDebug() << "res_1 is initially enabled.";
+
+ QVERIFY(res_1.enable(EnableAction::TOGGLE));
+
+ QVERIFY(res_1.enabled() == !initial_enabled_res_1);
+ qDebug() << "res_1 got successfully toggled.";
+
+ QVERIFY(res_1.enable(EnableAction::TOGGLE));
+ qDebug() << "res_1 got successfully toggled again.";
+
+ QVERIFY(res_1.enabled() == initial_enabled_res_1);
+ QVERIFY(res_1.internal_id() == id_1);
+ qDebug() << "res_1 got back to its initial state.";
+
+ QVERIFY(!res_2.enable(initial_enabled_res_2 ? EnableAction::ENABLE : EnableAction::DISABLE));
+ QVERIFY(res_2.enabled() == initial_enabled_res_2);
+ QVERIFY(res_2.internal_id() == id_2);
+ }
+};
+
+QTEST_GUILESS_MAIN(ResourceFolderModelTest)
+
+#include "ResourceFolderModel_test.moc"
diff --git a/archived/projt-launcher/tests/ResourcePackParse_test.cpp b/archived/projt-launcher/tests/ResourcePackParse_test.cpp
new file mode 100644
index 0000000000..045887173e
--- /dev/null
+++ b/archived/projt-launcher/tests/ResourcePackParse_test.cpp
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (c) 2022 flowln <flowlnlnln@gmail.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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <QTest>
+#include <QTimer>
+#include "minecraft/mod/tasks/LocalDataPackParseTask.hpp"
+
+#include <FileSystem.h>
+
+#include <minecraft/mod/ResourcePack.hpp>
+
+class ResourcePackParseTest : public QObject {
+ Q_OBJECT
+
+ private slots:
+ void test_parseZIP()
+ {
+ QString source = QFINDTESTDATA("testdata/Resources");
+
+ QString zip_rp = FS::PathCombine(source, "test_resource_pack_idk.zip");
+ ResourcePack pack{ QFileInfo(zip_rp) };
+
+ bool valid = DataPackUtils::processZIP(&pack, DataPackUtils::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(valid == true);
+ }
+
+ void test_parseFolder()
+ {
+ QString source = QFINDTESTDATA("testdata/Resources");
+
+ QString folder_rp = FS::PathCombine(source, "test_folder");
+ ResourcePack pack{ QFileInfo(folder_rp) };
+
+ bool valid = DataPackUtils::processFolder(&pack, DataPackUtils::ProcessingLevel::BasicInfoOnly);
+
+ QVERIFY(pack.packFormat() == 1);
+ QVERIFY(pack.description() == "Some resource pack maybe");
+ QVERIFY(valid == true);
+ }
+
+ void test_parseFolder2()
+ {
+ QString source = QFINDTESTDATA("testdata/Resources");
+
+ QString folder_rp = FS::PathCombine(source, "another_test_folder");
+ ResourcePack pack{ QFileInfo(folder_rp) };
+
+ bool valid = DataPackUtils::process(&pack, DataPackUtils::ProcessingLevel::BasicInfoOnly);
+
+ QVERIFY(pack.packFormat() == 6);
+ QVERIFY(pack.description() == "o quartel pegou fogo, policia deu sinal, acode acode acode a bandeira nacional");
+ QVERIFY(valid == true); // no assets dir but it is still valid based on https://minecraft.wiki/w/Resource_pack
+ }
+};
+
+QTEST_GUILESS_MAIN(ResourcePackParseTest)
+
+#include "ResourcePackParse_test.moc"
diff --git a/archived/projt-launcher/tests/RuntimeVersion_test.cpp b/archived/projt-launcher/tests/RuntimeVersion_test.cpp
new file mode 100644
index 0000000000..75653f1274
--- /dev/null
+++ b/archived/projt-launcher/tests/RuntimeVersion_test.cpp
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+
+#include <java/core/RuntimeVersion.hpp>
+
+using projt::java::RuntimeVersion;
+
+class RuntimeVersionTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void parseLegacyJava8()
+ {
+ RuntimeVersion v("1.8.0_312");
+ QCOMPARE(v.major(), 8);
+ QCOMPARE(v.minor(), 0);
+ QCOMPARE(v.security(), 312);
+ QCOMPARE(v.prerelease(), QString());
+ QVERIFY(!v.needsPermGen());
+ QVERIFY(!v.supportsModules());
+ }
+
+ void parseModernJava()
+ {
+ RuntimeVersion v("17.0.2");
+ QCOMPARE(v.major(), 17);
+ QCOMPARE(v.minor(), 0);
+ QCOMPARE(v.security(), 2);
+ QVERIFY(!v.needsPermGen());
+ QVERIFY(v.supportsModules());
+ QVERIFY(!v.defaultsToUtf8());
+ }
+
+ void parsePrerelease()
+ {
+ RuntimeVersion v("21.0.1-rc1");
+ QCOMPARE(v.major(), 21);
+ QCOMPARE(v.minor(), 0);
+ QCOMPARE(v.security(), 1);
+ QCOMPARE(v.prerelease(), QStringLiteral("rc1"));
+ QVERIFY(v.defaultsToUtf8());
+ }
+
+ void parseInvalid()
+ {
+ RuntimeVersion v("not-a-version");
+ QCOMPARE(v.major(), 0);
+ QCOMPARE(v.security(), 0);
+ QVERIFY(v.needsPermGen());
+ QVERIFY(!v.supportsModules());
+ QVERIFY(!v.defaultsToUtf8());
+ }
+
+ void compareVersions()
+ {
+ RuntimeVersion base("17.0.2");
+ RuntimeVersion higher("17.0.3");
+ RuntimeVersion prerelease("17.0.3-ea");
+
+ QVERIFY(base < higher);
+ QVERIFY(higher > base);
+ QVERIFY(prerelease < higher);
+ QVERIFY(!(prerelease == higher)); // Use negated == instead of !=
+ }
+};
+
+QTEST_GUILESS_MAIN(RuntimeVersionTest)
+
+#include "RuntimeVersion_test.moc"
diff --git a/archived/projt-launcher/tests/SeparatorPrefixTree_test.cpp b/archived/projt-launcher/tests/SeparatorPrefixTree_test.cpp
new file mode 100644
index 0000000000..3207079e37
--- /dev/null
+++ b/archived/projt-launcher/tests/SeparatorPrefixTree_test.cpp
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QByteArray>
+#include <QRandomGenerator>
+#include <QSet>
+#include <QStringList>
+#include <QTest>
+
+#include <SeparatorPrefixTree.h>
+
+namespace {
+QString randomPath(QRandomGenerator& rng)
+{
+ static const char kAlphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789-_.";
+ const int alphabet_len = static_cast<int>(sizeof(kAlphabet) - 1);
+
+ const int segments = rng.bounded(1, 5);
+ QStringList parts;
+ parts.reserve(segments);
+
+ for (int i = 0; i < segments; ++i) {
+ const int length = rng.bounded(1, 9);
+ QByteArray bytes;
+ bytes.reserve(length);
+ for (int j = 0; j < length; ++j) {
+ bytes.append(kAlphabet[rng.bounded(alphabet_len)]);
+ }
+ parts.append(QString::fromLatin1(bytes));
+ }
+
+ return parts.join('/');
+}
+
+QString shortestContainedPrefix(const SeparatorPrefixTree<'/'> &tree, const QString& path)
+{
+ const auto parts = path.split('/');
+ QString prefix;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (i == 0)
+ prefix = parts.at(i);
+ else
+ prefix = prefix + '/' + parts.at(i);
+ if (tree.contains(prefix))
+ return prefix;
+ }
+ return QString();
+}
+} // namespace
+
+class SeparatorPrefixTreeTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_basicInsertAndCovers()
+ {
+ SeparatorPrefixTree<'/'> tree;
+ tree.insert("a/b");
+ tree.insert("a/c");
+ tree.insert("d");
+
+ QVERIFY(tree.contains("a/b"));
+ QVERIFY(tree.contains("a/c"));
+ QVERIFY(tree.contains("d"));
+ QVERIFY(!tree.contains("a"));
+
+ QVERIFY(tree.covers("a/b/c"));
+ QCOMPARE(tree.cover("a/b/c"), QString("a/b"));
+ QVERIFY(tree.covers("d/x"));
+ QCOMPARE(tree.cover("d/x"), QString("d"));
+ QVERIFY(!tree.covers("x"));
+ QVERIFY(tree.cover("x").isNull());
+ }
+
+ void test_removeKeepsDescendants()
+ {
+ SeparatorPrefixTree<'/'> tree;
+ tree.insert("a/b");
+ tree.insert("a/b/c");
+ tree.insert("x/y");
+
+ QVERIFY(tree.remove("a/b"));
+ QVERIFY(!tree.contains("a/b"));
+ QVERIFY(tree.contains("a/b/c"));
+ QVERIFY(tree.covers("a/b/c"));
+ QCOMPARE(tree.cover("a/b/c"), QString("a/b/c"));
+ QVERIFY(tree.contains("x/y"));
+ }
+
+ void test_toStringListMatchesContainment()
+ {
+ SeparatorPrefixTree<'/'> tree;
+ QSet<QString> expected{ "alpha/bravo", "alpha/charlie", "delta" };
+ for (const auto& path : expected)
+ tree.insert(path);
+
+ const auto list = tree.toStringList();
+ QSet<QString> actual(list.cbegin(), list.cend());
+ QCOMPARE(actual, expected);
+
+ for (const auto& path : list)
+ QVERIFY(tree.contains(path));
+ }
+
+ void test_randomizedStability()
+ {
+ SeparatorPrefixTree<'/'> tree;
+ QSet<QString> inserted;
+ QRandomGenerator rng(0xC0FFEEu);
+
+ for (int i = 0; i < 250; ++i) {
+ const auto path = randomPath(rng);
+ inserted.insert(path);
+ tree.insert(path);
+ QVERIFY(tree.contains(path));
+ QVERIFY(tree.covers(path));
+ QCOMPARE(tree.cover(path), shortestContainedPrefix(tree, path));
+ }
+
+ for (int i = 0; i < 200; ++i) {
+ const auto probe = randomPath(rng);
+ const auto cover = tree.cover(probe);
+ const auto expected = shortestContainedPrefix(tree, probe);
+ if (expected.isNull()) {
+ QVERIFY(!tree.covers(probe));
+ QVERIFY(cover.isNull());
+ } else {
+ QVERIFY(tree.covers(probe));
+ QCOMPARE(cover, expected);
+ }
+ }
+
+ QStringList list = tree.toStringList();
+ for (const auto& path : list)
+ QVERIFY(tree.contains(path));
+
+ const auto values = inserted.values();
+ for (int i = 0; i < 80 && !inserted.isEmpty(); ++i) {
+ const auto& path = values.at(rng.bounded(values.size()));
+ if (tree.remove(path))
+ inserted.remove(path);
+ QVERIFY(!tree.contains(path));
+ }
+ }
+};
+
+QTEST_GUILESS_MAIN(SeparatorPrefixTreeTest)
+
+#include "SeparatorPrefixTree_test.moc"
diff --git a/archived/projt-launcher/tests/ShaderPackParse_test.cpp b/archived/projt-launcher/tests/ShaderPackParse_test.cpp
new file mode 100644
index 0000000000..20bcbb13e6
--- /dev/null
+++ b/archived/projt-launcher/tests/ShaderPackParse_test.cpp
@@ -0,0 +1,79 @@
+
+// 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+#include <QTimer>
+
+#include <FileSystem.h>
+
+#include <minecraft/mod/ShaderPack.hpp>
+#include <minecraft/mod/tasks/LocalShaderPackParseTask.hpp>
+
+class ShaderPackParseTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_parseZIP()
+ {
+ QString source = QFINDTESTDATA("testdata/ShaderPackParse");
+
+ QString zip_sp = FS::PathCombine(source, "shaderpack1.zip");
+ ShaderPack pack{ QFileInfo(zip_sp) };
+
+ bool valid = ShaderPackUtils::processZIP(pack);
+
+ QVERIFY(pack.packFormat() == ShaderPackFormat::VALID);
+ QVERIFY(valid == true);
+ }
+
+ void test_parseFolder()
+ {
+ QString source = QFINDTESTDATA("testdata/ShaderPackParse");
+
+ QString folder_sp = FS::PathCombine(source, "shaderpack2");
+ ShaderPack pack{ QFileInfo(folder_sp) };
+
+ bool valid = ShaderPackUtils::processFolder(pack);
+
+ QVERIFY(pack.packFormat() == ShaderPackFormat::VALID);
+ QVERIFY(valid == true);
+ }
+
+ void test_parseZIP2()
+ {
+ QString source = QFINDTESTDATA("testdata/ShaderPackParse");
+
+ QString folder_sp = FS::PathCombine(source, "shaderpack3.zip");
+ ShaderPack pack{ QFileInfo(folder_sp) };
+
+ bool valid = ShaderPackUtils::process(pack);
+
+ QVERIFY(pack.packFormat() == ShaderPackFormat::INVALID);
+ QVERIFY(valid == false);
+ }
+};
+
+QTEST_GUILESS_MAIN(ShaderPackParseTest)
+
+#include "ShaderPackParse_test.moc"
diff --git a/archived/projt-launcher/tests/StringUtilsHtmlPatch_test.cpp b/archived/projt-launcher/tests/StringUtilsHtmlPatch_test.cpp
new file mode 100644
index 0000000000..0f4b7009eb
--- /dev/null
+++ b/archived/projt-launcher/tests/StringUtilsHtmlPatch_test.cpp
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+
+#include <StringUtils.h>
+
+class StringUtilsHtmlPatchTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_insertsBreakBeforeImage()
+ {
+ const QString html = "<ul><li>a</li></ul> <img src=\"x\">";
+ const QString patched = StringUtils::htmlListPatch(html);
+ QVERIFY(patched.contains("</ul><br>"));
+ }
+
+ void test_noBreakWhenTextExists()
+ {
+ const QString html = "<ul></ul> text <img src=\"x\">";
+ const QString patched = StringUtils::htmlListPatch(html);
+ QVERIFY(!patched.contains("</ul><br>"));
+ }
+
+ void test_multipleLists()
+ {
+ const QString html = "<ul></ul> <img src=\"a\"><ul></ul> <img src=\"b\">";
+ const QString patched = StringUtils::htmlListPatch(html);
+ QCOMPARE(patched.count("</ul><br>"), 2);
+ }
+};
+
+QTEST_GUILESS_MAIN(StringUtilsHtmlPatchTest)
+
+#include "StringUtilsHtmlPatch_test.moc"
diff --git a/archived/projt-launcher/tests/StringUtilsNaturalCompare_test.cpp b/archived/projt-launcher/tests/StringUtilsNaturalCompare_test.cpp
new file mode 100644
index 0000000000..c3a4470a55
--- /dev/null
+++ b/archived/projt-launcher/tests/StringUtilsNaturalCompare_test.cpp
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+
+#include <StringUtils.h>
+
+class StringUtilsNaturalCompareTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_compare_data()
+ {
+ QTest::addColumn<QString>("first");
+ QTest::addColumn<QString>("second");
+ QTest::addColumn<Qt::CaseSensitivity>("cs");
+ QTest::addColumn<int>("expectedSign");
+
+ QTest::newRow("number-order-1") << "file 2" << "file 10" << Qt::CaseSensitive << -1;
+ QTest::newRow("number-order-2") << "mod9" << "mod10" << Qt::CaseSensitive << -1;
+ QTest::newRow("reverse-number") << "mod10" << "mod9" << Qt::CaseSensitive << 1;
+ QTest::newRow("leading-zero") << "file 02" << "file 2" << Qt::CaseSensitive << -1;
+ QTest::newRow("spaces-ignored") << "a 1" << "a 2" << Qt::CaseSensitive << -1;
+ QTest::newRow("case-insensitive-eq") << "Alpha42" << "aLpHa42" << Qt::CaseInsensitive << 0;
+ QTest::newRow("suffix-alpha") << "a10a" << "a10b" << Qt::CaseSensitive << -1;
+ QTest::newRow("different-prefix") << "b1" << "a9" << Qt::CaseSensitive << 1;
+ QTest::newRow("equal") << "same" << "same" << Qt::CaseSensitive << 0;
+ }
+
+ void test_compare()
+ {
+ QFETCH(QString, first);
+ QFETCH(QString, second);
+ QFETCH(Qt::CaseSensitivity, cs);
+ QFETCH(int, expectedSign);
+
+ const int result = StringUtils::naturalCompare(first, second, cs);
+ QVERIFY((expectedSign < 0 && result < 0) || (expectedSign == 0 && result == 0) ||
+ (expectedSign > 0 && result > 0));
+ }
+
+ void test_caseSensitiveDifferentCaseIsNotEqual()
+ {
+ const int result = StringUtils::naturalCompare("Alpha", "alpha", Qt::CaseSensitive);
+ QVERIFY(result != 0);
+ }
+};
+
+QTEST_GUILESS_MAIN(StringUtilsNaturalCompareTest)
+
+#include "StringUtilsNaturalCompare_test.moc"
diff --git a/archived/projt-launcher/tests/StringUtilsSplitFirst_test.cpp b/archived/projt-launcher/tests/StringUtilsSplitFirst_test.cpp
new file mode 100644
index 0000000000..2ef1dc175e
--- /dev/null
+++ b/archived/projt-launcher/tests/StringUtilsSplitFirst_test.cpp
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QRegularExpression>
+#include <QTest>
+
+#include <StringUtils.h>
+
+class StringUtilsSplitFirstTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_splitStringSeparator()
+ {
+ auto p1 = StringUtils::splitFirst("name: value:rest", ": ");
+ QCOMPARE(p1.first, QString("name"));
+ QCOMPARE(p1.second, QString("value:rest"));
+
+ auto p2 = StringUtils::splitFirst("a::b::c", "::");
+ QCOMPARE(p2.first, QString("a"));
+ QCOMPARE(p2.second, QString("b::c"));
+ }
+
+ void test_splitCharSeparator()
+ {
+ auto p = StringUtils::splitFirst("left/right/inner", '/');
+ QCOMPARE(p.first, QString("left"));
+ QCOMPARE(p.second, QString("right/inner"));
+ }
+
+ void test_splitRegexSeparator()
+ {
+ QRegularExpression re("\\d+");
+ auto p1 = StringUtils::splitFirst("abc123def", re);
+ QCOMPARE(p1.first, QString("abc"));
+ QCOMPARE(p1.second, QString("def"));
+
+ auto p2 = StringUtils::splitFirst("no_digits_here", re);
+ QCOMPARE(p2.first, QString("no_digits_here"));
+ QCOMPARE(p2.second, QString(""));
+ }
+};
+
+QTEST_GUILESS_MAIN(StringUtilsSplitFirstTest)
+
+#include "StringUtilsSplitFirst_test.moc"
diff --git a/archived/projt-launcher/tests/StringUtilsTruncateUrl_test.cpp b/archived/projt-launcher/tests/StringUtilsTruncateUrl_test.cpp
new file mode 100644
index 0000000000..9141eeb938
--- /dev/null
+++ b/archived/projt-launcher/tests/StringUtilsTruncateUrl_test.cpp
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+
+#include <QTest>
+#include <QUrl>
+
+#include <StringUtils.h>
+
+class StringUtilsTruncateUrlTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_noTruncationWhenLongEnough()
+ {
+ QUrl url("https://user:pass@example.com/one/two#frag");
+ const QString out = StringUtils::truncateUrlHumanFriendly(url, 200);
+ QCOMPARE(out, QString("https://example.com/one/two"));
+ }
+
+ void test_softTruncationKeepsTail()
+ {
+ QUrl url("https://example.com/alpha/bravo/charlie/delta");
+ const QString out = StringUtils::truncateUrlHumanFriendly(url, 30, false);
+
+ QVERIFY(out.contains("..."));
+ QVERIFY(out.endsWith("/delta"));
+ QVERIFY(out.startsWith("https://example.com"));
+ }
+
+ void test_hardLimitRespected()
+ {
+ QUrl url("https://example.com/very/long/path/for/testing/truncation");
+ const QString out = StringUtils::truncateUrlHumanFriendly(url, 18, true);
+
+ QVERIFY(out.size() <= 18);
+ QVERIFY(out.endsWith("..."));
+ }
+};
+
+QTEST_GUILESS_MAIN(StringUtilsTruncateUrlTest)
+
+#include "StringUtilsTruncateUrl_test.moc"
diff --git a/archived/projt-launcher/tests/StringUtils_test.cpp b/archived/projt-launcher/tests/StringUtils_test.cpp
new file mode 100644
index 0000000000..f25ccacebd
--- /dev/null
+++ b/archived/projt-launcher/tests/StringUtils_test.cpp
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QRegularExpression>
+#include <QTest>
+#include <QUrl>
+
+#include <StringUtils.h>
+
+class StringUtilsTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_naturalCompare_data()
+ {
+ QTest::addColumn<QString>("first");
+ QTest::addColumn<QString>("second");
+ QTest::addColumn<int>("expected");
+ QTest::addColumn<Qt::CaseSensitivity>("caseSensitivity");
+
+ QTest::newRow("numeric-order") << "file 2" << "file 10" << -1 << Qt::CaseSensitive;
+ QTest::newRow("numeric-order-2") << "a9" << "a10" << -1 << Qt::CaseSensitive;
+ QTest::newRow("leading-zeros") << "file 02" << "file 2" << -1 << Qt::CaseSensitive;
+ QTest::newRow("case-insensitive") << "Alpha2" << "alpha10" << -1 << Qt::CaseInsensitive;
+ }
+
+ void test_naturalCompare()
+ {
+ QFETCH(QString, first);
+ QFETCH(QString, second);
+ QFETCH(int, expected);
+ QFETCH(Qt::CaseSensitivity, caseSensitivity);
+
+ const int result = StringUtils::naturalCompare(first, second, caseSensitivity);
+ QVERIFY((expected < 0 && result < 0) || (expected == 0 && result == 0) || (expected > 0 && result > 0));
+ }
+
+ void test_truncateUrlHumanFriendly()
+ {
+ QUrl url_no_truncation("https://user:pass@example.com/one/two#frag");
+ const QString display = StringUtils::truncateUrlHumanFriendly(url_no_truncation, 200);
+ QCOMPARE(display, QString("https://example.com/one/two"));
+
+ QUrl url_truncate("https://example.com/alpha/bravo/charlie/delta");
+ const QString truncated = StringUtils::truncateUrlHumanFriendly(url_truncate, 30);
+ QVERIFY(truncated.contains("..."));
+ QVERIFY(truncated.endsWith("/delta"));
+ QVERIFY(truncated.size() <= 30);
+
+ QUrl url_hard("https://example.com/alpha/bravo/charlie/delta");
+ const QString hard = StringUtils::truncateUrlHumanFriendly(url_hard, 15, true);
+ QVERIFY(hard.size() <= 15);
+ QVERIFY(hard.endsWith("..."));
+ }
+
+ void test_humanReadableFileSize()
+ {
+ QCOMPARE(StringUtils::humanReadableFileSize(1024.0, false), QString("1.00 KiB"));
+ QCOMPARE(StringUtils::humanReadableFileSize(1000.0, true), QString("1.00 KB"));
+ }
+
+ void test_getRandomAlphaNumeric()
+ {
+ const QString first = StringUtils::getRandomAlphaNumeric();
+ const QString second = StringUtils::getRandomAlphaNumeric();
+
+ QVERIFY(first.size() == 32);
+ QVERIFY(second.size() == 32);
+ QVERIFY(first != second);
+
+ QRegularExpression re("^[0-9a-fA-F]{32}$");
+ QVERIFY(re.match(first).hasMatch());
+ QVERIFY(re.match(second).hasMatch());
+ }
+
+ void test_splitFirst()
+ {
+ {
+ auto result = StringUtils::splitFirst("version: 1.2.3", ": ");
+ QCOMPARE(result.first, QString("version"));
+ QCOMPARE(result.second, QString("1.2.3"));
+ }
+ {
+ auto result = StringUtils::splitFirst("a:b:c", ':');
+ QCOMPARE(result.first, QString("a"));
+ QCOMPARE(result.second, QString("b:c"));
+ }
+ {
+ QRegularExpression re("\\d+");
+ auto result = StringUtils::splitFirst("ab12cd", re);
+ QCOMPARE(result.first, QString("ab"));
+ QCOMPARE(result.second, QString("cd"));
+ }
+ {
+ QRegularExpression re("\\d+");
+ auto result = StringUtils::splitFirst("abc", re);
+ QCOMPARE(result.first, QString("abc"));
+ QCOMPARE(result.second, QString(""));
+ }
+ }
+
+ void test_htmlListPatch()
+ {
+ const QString html = "<ul><li>a</li></ul> <img src=\"x\">";
+ const QString patched = StringUtils::htmlListPatch(html);
+ QVERIFY(patched.contains("</ul><br>"));
+ QVERIFY(patched.contains("<img"));
+
+ const QString html_with_text = "<ul></ul> text <img src=\"x\">";
+ const QString patched_with_text = StringUtils::htmlListPatch(html_with_text);
+ QVERIFY(!patched_with_text.contains("</ul><br>"));
+ }
+};
+
+QTEST_GUILESS_MAIN(StringUtilsTest)
+
+#include "StringUtils_test.moc"
diff --git a/archived/projt-launcher/tests/Task_test.cpp b/archived/projt-launcher/tests/Task_test.cpp
new file mode 100644
index 0000000000..8e3c2f8a33
--- /dev/null
+++ b/archived/projt-launcher/tests/Task_test.cpp
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+#include <QThread>
+#include <QTimer>
+
+#include <tasks/ConcurrentTask.h>
+#include <tasks/MultipleOptionsTask.h>
+#include <tasks/SequentialTask.h>
+#include <tasks/Task.h>
+
+#include <array>
+
+/* Does nothing. Only used for testing. */
+class BasicTask : public Task
+{
+ Q_OBJECT
+
+ friend class TaskTest;
+
+ public:
+ BasicTask(bool show_debug_log = true) : Task(show_debug_log)
+ {}
+
+ private:
+ void executeTask() override
+ {
+ emitSucceeded();
+ }
+};
+
+/* Does nothing. Only used for testing. */
+class BasicTask_MultiStep : public Task
+{
+ Q_OBJECT
+
+ friend class TaskTest;
+
+ private:
+ auto isMultiStep() const -> bool override
+ {
+ return true;
+ }
+
+ void executeTask() override
+ {}
+};
+
+class BigConcurrentTask : public ConcurrentTask
+{
+ Q_OBJECT
+
+ void executeNextSubTask() override
+ {
+ // This is here only to help fill the stack a bit more quickly (if there's an issue, of course :^))
+ // Each tasks thus adds 1024 * 4 bytes to the stack, at the very least.
+ [[maybe_unused]] volatile std::array<uint32_t, 1024> some_data_on_the_stack{};
+
+ ConcurrentTask::executeNextSubTask();
+ }
+};
+
+class BigConcurrentTaskThread : public QThread
+{
+ Q_OBJECT
+
+ QTimer m_deadline;
+ void run() override
+ {
+ BigConcurrentTask big_task;
+ // This test is sensitive to runner performance and can be flaky on slower CI hardware.
+ m_deadline.setInterval(30000);
+
+ // NOTE: Arbitrary value that manages to trigger a problem when there is one.
+ // Considering each tasks, in a problematic state, adds 1024 * 4 bytes to the stack,
+ // this number is enough to fill up 16 MiB of stack, more than enough to cause a problem.
+ static const unsigned s_num_tasks = 1 << 12;
+ for (unsigned i = 0; i < s_num_tasks; i++)
+ {
+ auto sub_task = makeShared<BasicTask>(false);
+ big_task.addTask(sub_task);
+ }
+
+ connect(&big_task, &Task::finished, this, &QThread::quit);
+ connect(&m_deadline,
+ &QTimer::timeout,
+ this,
+ [this]
+ {
+ passed_the_deadline = true;
+ quit();
+ });
+
+ if (thread() != QThread::currentThread())
+ {
+ QMetaObject::invokeMethod(this, &BigConcurrentTaskThread::start_timer, Qt::QueuedConnection);
+ }
+ big_task.run();
+
+ exec();
+ }
+ void start_timer()
+ {
+ m_deadline.start();
+ }
+
+ public:
+ bool passed_the_deadline = false;
+};
+
+class TaskTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_SetStatus_NoMultiStep()
+ {
+ BasicTask t;
+ QString status{ "test status" };
+
+ t.setStatus(status);
+
+ QCOMPARE(t.getStatus(), status);
+ QCOMPARE(t.getStepProgress().isEmpty(), TaskStepProgressList{}.isEmpty());
+ }
+
+ void test_SetStatus_MultiStep()
+ {
+ BasicTask_MultiStep t;
+ QString status{ "test status" };
+
+ t.setStatus(status);
+
+ QCOMPARE(t.getStatus(), status);
+ // Even though it is multi step, it does not override the getStepStatus method,
+ // so it should remain the same.
+ QCOMPARE(t.getStepProgress().isEmpty(), TaskStepProgressList{}.isEmpty());
+ }
+
+ void test_SetProgress()
+ {
+ BasicTask t;
+ int current = 42;
+ int total = 207;
+
+ t.setProgress(current, total);
+
+ QCOMPARE(t.getProgress(), current);
+ QCOMPARE(t.getTotalProgress(), total);
+ }
+
+ void test_basicRun()
+ {
+ BasicTask t;
+ connect(&t,
+ &Task::finished,
+ [&t]
+ { QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); });
+ t.start();
+
+ QVERIFY2(QTest::qWaitFor([&t]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
+ }
+
+ void test_basicConcurrentRun()
+ {
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
+
+ ConcurrentTask t;
+
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
+
+ connect(&t,
+ &Task::finished,
+ [&t, &t1, &t2, &t3]
+ {
+ QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(t2->wasSuccessful());
+ QVERIFY(t3->wasSuccessful());
+ });
+
+ t.start();
+ QVERIFY2(QTest::qWaitFor([&t]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
+ }
+
+ // Tests if starting new tasks after the 6 initial ones is working
+ void test_moreConcurrentRun()
+ {
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
+ auto t4 = makeShared<BasicTask>();
+ auto t5 = makeShared<BasicTask>();
+ auto t6 = makeShared<BasicTask>();
+ auto t7 = makeShared<BasicTask>();
+ auto t8 = makeShared<BasicTask>();
+ auto t9 = makeShared<BasicTask>();
+
+ ConcurrentTask t;
+
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
+ t.addTask(t4);
+ t.addTask(t5);
+ t.addTask(t6);
+ t.addTask(t7);
+ t.addTask(t8);
+ t.addTask(t9);
+
+ connect(&t,
+ &Task::finished,
+ [&t, &t1, &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9]
+ {
+ QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(t2->wasSuccessful());
+ QVERIFY(t3->wasSuccessful());
+ QVERIFY(t4->wasSuccessful());
+ QVERIFY(t5->wasSuccessful());
+ QVERIFY(t6->wasSuccessful());
+ QVERIFY(t7->wasSuccessful());
+ QVERIFY(t8->wasSuccessful());
+ QVERIFY(t9->wasSuccessful());
+ });
+
+ t.start();
+ QVERIFY2(QTest::qWaitFor([&t]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
+ }
+
+ void test_basicSequentialRun()
+ {
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
+
+ SequentialTask t;
+
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
+
+ connect(&t,
+ &Task::finished,
+ [&t, &t1, &t2, &t3]
+ {
+ QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(t2->wasSuccessful());
+ QVERIFY(t3->wasSuccessful());
+ });
+
+ t.start();
+ QVERIFY2(QTest::qWaitFor([&t]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
+ }
+
+ void test_basicMultipleOptionsRun()
+ {
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
+
+ MultipleOptionsTask t;
+
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
+
+ connect(&t,
+ &Task::finished,
+ [&t, &t1, &t2, &t3]
+ {
+ QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(!t2->wasSuccessful());
+ QVERIFY(!t3->wasSuccessful());
+ });
+
+ t.start();
+ QVERIFY2(QTest::qWaitFor([&t]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
+ }
+
+ void test_stackOverflowInConcurrentTask()
+ {
+ QEventLoop loop;
+
+ BigConcurrentTaskThread thread;
+
+ connect(&thread, &BigConcurrentTaskThread::finished, &loop, &QEventLoop::quit);
+
+ thread.start();
+
+ loop.exec();
+
+ QVERIFY(!thread.passed_the_deadline);
+ }
+};
+
+QTEST_GUILESS_MAIN(TaskTest)
+
+#include "Task_test.moc"
diff --git a/archived/projt-launcher/tests/TexturePackParse_test.cpp b/archived/projt-launcher/tests/TexturePackParse_test.cpp
new file mode 100644
index 0000000000..1df44b7b2d
--- /dev/null
+++ b/archived/projt-launcher/tests/TexturePackParse_test.cpp
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+#include <QTimer>
+
+#include "FileSystem.h"
+
+#include "minecraft/mod/TexturePack.hpp"
+#include "minecraft/mod/tasks/LocalTexturePackParseTask.hpp"
+
+class TexturePackParseTest : public QObject
+{
+ Q_OBJECT
+
+ 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) };
+
+ bool valid = TexturePackUtils::processZIP(pack);
+
+ QVERIFY(pack.description() == "joe biden, wake up");
+ QVERIFY(valid == true);
+ }
+
+ void test_parseFolder()
+ {
+ QString source = QFINDTESTDATA("testdata/TexturePackParse");
+
+ QString folder_rp = FS::PathCombine(source, "test_texturefolder");
+ TexturePack pack{ QFileInfo(folder_rp) };
+
+ bool valid = TexturePackUtils::processFolder(pack, TexturePackUtils::ProcessingLevel::BasicInfoOnly);
+
+ QVERIFY(pack.description() == "Some texture pack surely");
+ QVERIFY(valid == true);
+ }
+
+ void test_parseFolder2()
+ {
+ QString source = QFINDTESTDATA("testdata/TexturePackParse");
+
+ QString folder_rp = FS::PathCombine(source, "another_test_texturefolder");
+ TexturePack pack{ QFileInfo(folder_rp) };
+
+ bool valid = TexturePackUtils::process(pack, TexturePackUtils::ProcessingLevel::BasicInfoOnly);
+
+ QVERIFY(pack.description() == "quieres\nfor real");
+ QVERIFY(valid == true);
+ }
+};
+
+QTEST_GUILESS_MAIN(TexturePackParseTest)
+
+#include "TexturePackParse_test.moc"
diff --git a/archived/projt-launcher/tests/VersionFilterData_test.cpp b/archived/projt-launcher/tests/VersionFilterData_test.cpp
new file mode 100644
index 0000000000..06a79369ac
--- /dev/null
+++ b/archived/projt-launcher/tests/VersionFilterData_test.cpp
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <minecraft/VersionFilterData.h>
+
+class VersionFilterDataTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ void test_hasKnownVersionMappings()
+ {
+ QVERIFY(g_VersionFilterData.fmlLibsMapping.contains("1.3.2"));
+ QVERIFY(g_VersionFilterData.fmlLibsMapping.contains("1.4.7"));
+ QVERIFY(g_VersionFilterData.fmlLibsMapping.contains("1.5.2"));
+
+ const auto libs15 = g_VersionFilterData.fmlLibsMapping.value("1.5.2");
+ QVERIFY(!libs15.isEmpty());
+ QCOMPARE(libs15.front().filename, QString("argo-small-3.2.jar"));
+ QCOMPARE(libs15.back().filename, QString("scala-library.jar"));
+ }
+
+ void test_allMappedLibrariesHaveFilenameAndChecksum()
+ {
+ for (auto it = g_VersionFilterData.fmlLibsMapping.constBegin(); it != g_VersionFilterData.fmlLibsMapping.constEnd();
+ ++it)
+ {
+ QVERIFY2(!it.key().isEmpty(), "Minecraft version key must not be empty");
+ for (const auto& lib : it.value())
+ {
+ QVERIFY2(!lib.filename.isEmpty(), "Library filename must not be empty");
+ QVERIFY2(!lib.checksum.isEmpty(), "Library checksum must not be empty");
+ }
+ }
+ }
+
+ void test_installerBlacklist()
+ {
+ QVERIFY(g_VersionFilterData.forgeInstallerBlacklist.contains("1.5.2"));
+ QVERIFY(!g_VersionFilterData.forgeInstallerBlacklist.contains("1.5.1"));
+ }
+
+ void test_lwjglWhitelistContainsExpectedEntries()
+ {
+ QVERIFY(g_VersionFilterData.lwjglWhitelist.contains("org.lwjgl.lwjgl:lwjgl"));
+ QVERIFY(g_VersionFilterData.lwjglWhitelist.contains("org.lwjgl.lwjgl:lwjgl_util"));
+ QVERIFY(g_VersionFilterData.lwjglWhitelist.contains("org.lwjgl.lwjgl:lwjgl-platform"));
+ }
+
+ void test_javaTransitionDatesAreOrdered()
+ {
+ QVERIFY(g_VersionFilterData.java8BeginsDate.isValid());
+ QVERIFY(g_VersionFilterData.java16BeginsDate.isValid());
+ QVERIFY(g_VersionFilterData.java17BeginsDate.isValid());
+
+ QVERIFY(g_VersionFilterData.java8BeginsDate < g_VersionFilterData.java16BeginsDate);
+ QVERIFY(g_VersionFilterData.java16BeginsDate < g_VersionFilterData.java17BeginsDate);
+ }
+};
+
+QTEST_GUILESS_MAIN(VersionFilterDataTest)
+
+#include "VersionFilterData_test.moc"
diff --git a/archived/projt-launcher/tests/Version_test.cpp b/archived/projt-launcher/tests/Version_test.cpp
new file mode 100644
index 0000000000..d6949dbba6
--- /dev/null
+++ b/archived/projt-launcher/tests/Version_test.cpp
@@ -0,0 +1,197 @@
+/* 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 <QTest>
+
+#include <Version.h>
+
+class VersionTest : public QObject
+{
+ Q_OBJECT
+
+ QStringList m_flex_test_names = {};
+
+ void addDataColumns()
+ {
+ QTest::addColumn<QString>("first");
+ QTest::addColumn<QString>("second");
+ QTest::addColumn<bool>("lessThan");
+ QTest::addColumn<bool>("equal");
+ }
+
+ void setupVersions()
+ {
+ 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("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, snapshot") << "1.20.0-rc2"
+ << "1.20.1" << 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, snapshot") << "1.20.2-rc2"
+ << "1.20.1" << false << false;
+ }
+
+ private slots:
+ void test_versionCompare_data()
+ {
+ setupVersions();
+ }
+
+ void test_versionCompare()
+ {
+ QFETCH(QString, first);
+ QFETCH(QString, second);
+ QFETCH(bool, lessThan);
+ QFETCH(bool, equal);
+
+ const auto v1 = Version(first);
+ const auto v2 = Version(second);
+
+ qDebug() << v1 << "vs" << v2;
+
+ QCOMPARE(v1 < v2, lessThan);
+ QCOMPARE(v1 > v2, !lessThan && !equal);
+ QCOMPARE(v1 == v2, equal);
+ }
+
+ void test_flexVerTestVector_data()
+ {
+ addDataColumns();
+
+ QDir test_vector_dir(QFINDTESTDATA("testdata/Version"));
+
+ QFile vector_file{ test_vector_dir.absoluteFilePath("test_vectors.txt") };
+
+ if (!vector_file.open(QFile::OpenModeFlag::ReadOnly))
+ {
+ qCritical() << "Failed to open file '" << vector_file.fileName() << "' for reading!";
+ return;
+ }
+
+ int test_number = 0;
+ 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())
+ continue;
+
+ test_number += 1;
+
+ auto split_line = line.split('<');
+ if (split_line.size() == 2)
+ {
+ 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);
+ QTest::newRow(m_flex_test_names.last().toLatin1().data()) << first << second << true << false;
+
+ continue;
+ }
+
+ split_line = line.split('=');
+ if (split_line.size() == 2)
+ {
+ 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);
+ QTest::newRow(m_flex_test_names.last().toLatin1().data()) << first << second << false << true;
+
+ continue;
+ }
+
+ split_line = line.split('>');
+ if (split_line.size() == 2)
+ {
+ 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);
+ QTest::newRow(m_flex_test_names.last().toLatin1().data()) << first << second << false << false;
+
+ continue;
+ }
+
+ qCritical() << "Unexpected separator in the test vector: ";
+ qCritical() << line;
+
+ QVERIFY(0 != 0);
+ }
+
+ vector_file.close();
+ }
+
+ void test_flexVerTestVector()
+ {
+ QFETCH(QString, first);
+ QFETCH(QString, second);
+ QFETCH(bool, lessThan);
+ QFETCH(bool, equal);
+
+ const auto v1 = Version(first);
+ const auto v2 = Version(second);
+
+ qDebug() << v1 << "vs" << v2;
+
+ QCOMPARE(v1 < v2, lessThan);
+ QCOMPARE(v1 > v2, !lessThan && !equal);
+ QCOMPARE(v1 == v2, equal);
+ }
+};
+
+QTEST_GUILESS_MAIN(VersionTest)
+
+#include "Version_test.moc"
diff --git a/archived/projt-launcher/tests/WorldSaveParse_test.cpp b/archived/projt-launcher/tests/WorldSaveParse_test.cpp
new file mode 100644
index 0000000000..39e8384562
--- /dev/null
+++ b/archived/projt-launcher/tests/WorldSaveParse_test.cpp
@@ -0,0 +1,96 @@
+
+// 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+#include <QTimer>
+
+#include <FileSystem.h>
+
+#include <minecraft/mod/WorldSave.hpp>
+#include <minecraft/mod/tasks/LocalWorldSaveParseTask.hpp>
+
+class WorldSaveParseTest : public QObject
+{
+ Q_OBJECT
+
+ 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) };
+
+ bool valid = WorldSaveUtils::processZIP(save);
+
+ QVERIFY(save.saveFormat() == WorldSaveFormat::SINGLE);
+ 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) };
+
+ bool valid = WorldSaveUtils::processZIP(save);
+
+ QVERIFY(save.saveFormat() == WorldSaveFormat::MULTI);
+ 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) };
+
+ bool valid = WorldSaveUtils::processFolder(save);
+
+ QVERIFY(save.saveFormat() == WorldSaveFormat::SINGLE);
+ QVERIFY(save.saveDirName() == "world_3");
+ QVERIFY(valid == true);
+ }
+
+ void test_parseFolder2()
+ {
+ QString source = QFINDTESTDATA("testdata/WorldSaveParse");
+
+ QString folder_ws = FS::PathCombine(source, "minecraft_save_4");
+ WorldSave save{ QFileInfo(folder_ws) };
+
+ bool valid = WorldSaveUtils::process(save);
+
+ QVERIFY(save.saveFormat() == WorldSaveFormat::MULTI);
+ QVERIFY(save.saveDirName() == "world_4");
+ QVERIFY(valid == true);
+ }
+};
+
+QTEST_GUILESS_MAIN(WorldSaveParseTest)
+
+#include "WorldSaveParse_test.moc"
diff --git a/archived/projt-launcher/tests/XmlLogs_test.cpp b/archived/projt-launcher/tests/XmlLogs_test.cpp
new file mode 100644
index 0000000000..c27fd500bd
--- /dev/null
+++ b/archived/projt-launcher/tests/XmlLogs_test.cpp
@@ -0,0 +1,158 @@
+// SPDX-FileCopyrightText: 2025 Rachel Powers <508861+Ryex@users.noreply.github.com>
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2025 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <QTest>
+
+#include <QList>
+#include <QObject>
+#include <QRegularExpression>
+#include <QString>
+
+#include <algorithm>
+#include <iterator>
+
+#include <FileSystem.h>
+#include <MessageLevel.h>
+#include <logs/LogEventParser.hpp>
+
+class XmlLogParseTest : public QObject
+{
+ Q_OBJECT
+
+ private slots:
+
+ void parseXml_data()
+ {
+ QString source = QFINDTESTDATA("testdata/TestLogs");
+
+ QString shortXml = QString::fromUtf8(FS::read(FS::PathCombine(source, "vanilla-1.21.5.xml.log")));
+ QString shortText = QString::fromUtf8(FS::read(FS::PathCombine(source, "vanilla-1.21.5.text.log")));
+ QStringList shortTextLevels_s =
+ QString::fromUtf8(FS::read(FS::PathCombine(source, "vanilla-1.21.5-levels.txt")))
+ .split(QRegularExpression("\n|\r\n|\r"), Qt::SkipEmptyParts);
+
+ QList<MessageLevel::Enum> shortTextLevels;
+ shortTextLevels.reserve(24);
+ std::transform(shortTextLevels_s.cbegin(),
+ shortTextLevels_s.cend(),
+ std::back_inserter(shortTextLevels),
+ [](const QString& line) { return MessageLevel::getLevel(line.trimmed()); });
+
+ QString longXml = QString::fromUtf8(FS::read(FS::PathCombine(source, "TerraFirmaGreg-Modern-forge.xml.log")));
+ QString longText = QString::fromUtf8(FS::read(FS::PathCombine(source, "TerraFirmaGreg-Modern-forge.text.log")));
+ QStringList longTextLevels_s =
+ QString::fromUtf8(FS::read(FS::PathCombine(source, "TerraFirmaGreg-Modern-levels.txt")))
+ .split(QRegularExpression("\n|\r\n|\r"), Qt::SkipEmptyParts);
+ QStringList longTextLevelsXml_s =
+ QString::fromUtf8(FS::read(FS::PathCombine(source, "TerraFirmaGreg-Modern-xml-levels.txt")))
+ .split(QRegularExpression("\n|\r\n|\r"), Qt::SkipEmptyParts);
+
+ QList<MessageLevel::Enum> longTextLevelsPlain;
+ longTextLevelsPlain.reserve(974);
+ std::transform(longTextLevels_s.cbegin(),
+ longTextLevels_s.cend(),
+ std::back_inserter(longTextLevelsPlain),
+ [](const QString& line) { return MessageLevel::getLevel(line.trimmed()); });
+ QList<MessageLevel::Enum> longTextLevelsXml;
+ longTextLevelsXml.reserve(896);
+ std::transform(longTextLevelsXml_s.cbegin(),
+ longTextLevelsXml_s.cend(),
+ std::back_inserter(longTextLevelsXml),
+ [](const QString& line) { return MessageLevel::getLevel(line.trimmed()); });
+
+ QTest::addColumn<QString>("log");
+ QTest::addColumn<int>("num_entries");
+ QTest::addColumn<QList<MessageLevel::Enum>>("entry_levels");
+
+ QTest::newRow("short-vanilla-plain") << shortText << 25 << shortTextLevels;
+ QTest::newRow("short-vanilla-xml") << shortXml << 25 << shortTextLevels;
+ QTest::newRow("long-forge-plain") << longText << 945 << longTextLevelsPlain;
+ QTest::newRow("long-forge-xml") << longXml << 869 << longTextLevelsXml;
+ }
+
+ void parseXml()
+ {
+ QFETCH(QString, log);
+ QFETCH(int, num_entries);
+ QFETCH(QList<MessageLevel::Enum>, entry_levels);
+
+ QList<std::pair<MessageLevel::Enum, QString>> entries = {};
+
+ QBENCHMARK
+ {
+ entries = parseLines(log.split(QRegularExpression("\n|\r\n|\r")));
+ }
+
+ QCOMPARE(entries.length(), num_entries);
+
+ QList<MessageLevel::Enum> levels = {};
+
+ std::transform(entries.cbegin(),
+ entries.cend(),
+ std::back_inserter(levels),
+ [](std::pair<MessageLevel::Enum, QString> entry) { return entry.first; });
+
+ QCOMPARE(levels, entry_levels);
+ }
+
+ private:
+ QList<std::pair<MessageLevel::Enum, QString>> parseLines(const QStringList& lines)
+ {
+ QList<std::pair<MessageLevel::Enum, QString>> out;
+ MessageLevel::Enum last = MessageLevel::Unknown;
+ projt::logs::LogEventParser parser; // Fresh parser for each call
+
+ for (const auto& line : lines)
+ {
+ parser.pushLine(line);
+
+ auto items = parser.drainAvailable();
+ for (const auto& item : items)
+ {
+ if (std::holds_alternative<projt::logs::LogEventParser::LogRecord>(item))
+ {
+ auto entry = std::get<projt::logs::LogEventParser::LogRecord>(item);
+ auto msg = QString("[%1] [%2/%3] [%4]: %5")
+ .arg(entry.timestamp.toString("HH:mm:ss"))
+ .arg(entry.thread)
+ .arg(entry.levelText)
+ .arg(entry.logger)
+ .arg(entry.message);
+ out.append(std::make_pair(entry.level, msg));
+ last = entry.level;
+ }
+ else if (std::holds_alternative<projt::logs::LogEventParser::RawLine>(item))
+ {
+ auto msg = std::get<projt::logs::LogEventParser::RawLine>(item).text;
+ auto level = projt::logs::LogEventParser::guessLevelFromLine(msg, last);
+ out.append(std::make_pair(level, msg));
+ last = level;
+ }
+ }
+ }
+ return out;
+ }
+};
+
+QTEST_GUILESS_MAIN(XmlLogParseTest)
+
+#include "XmlLogs_test.moc"
diff --git a/archived/projt-launcher/tests/testdata/CatPacks/index.json b/archived/projt-launcher/tests/testdata/CatPacks/index.json
new file mode 100644
index 0000000000..b5401d2305
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/CatPacks/index.json
@@ -0,0 +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"
+ }
+ ]
+}
diff --git a/archived/projt-launcher/tests/testdata/DataPackParse/another_test_folder/pack.mcmeta b/archived/projt-launcher/tests/testdata/DataPackParse/another_test_folder/pack.mcmeta
new file mode 100644
index 0000000000..5509d007bb
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/DataPackParse/another_test_folder/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 6,
+ "description": "Some data pack three, leaves on the tree"
+ }
+}
diff --git a/archived/projt-launcher/tests/testdata/DataPackParse/test_data_pack_boogaloo.zip b/archived/projt-launcher/tests/testdata/DataPackParse/test_data_pack_boogaloo.zip
new file mode 100644
index 0000000000..cb0b9f3c69
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/DataPackParse/test_data_pack_boogaloo.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/DataPackParse/test_folder/pack.mcmeta b/archived/projt-launcher/tests/testdata/DataPackParse/test_folder/pack.mcmeta
new file mode 100644
index 0000000000..dbfc7e9b87
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/DataPackParse/test_folder/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 10,
+ "description": "Some data pack, maybe"
+ }
+}
diff --git a/archived/projt-launcher/tests/testdata/FileSystem/FileSystem-test_createShortcut-unix b/archived/projt-launcher/tests/testdata/FileSystem/FileSystem-test_createShortcut-unix
new file mode 100755
index 0000000000..1ce3a2bd61
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/FileSystem/FileSystem-test_createShortcut-unix
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Type=Application
+TryExec=asdfDest
+Exec=asdfDest 'arg1' 'arg2'
+Name=asdf
+Icon=
diff --git a/archived/projt-launcher/tests/testdata/FileSystem/test_folder/.secret_folder/.secret_file.txt b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/.secret_folder/.secret_file.txt
new file mode 100644
index 0000000000..65e37085f4
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/.secret_folder/.secret_file.txt
@@ -0,0 +1 @@
+oooooo spooky easter egg :oo
diff --git a/archived/projt-launcher/tests/testdata/FileSystem/test_folder/assets/minecraft/textures/blah.txt b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/assets/minecraft/textures/blah.txt
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/assets/minecraft/textures/blah.txt
@@ -0,0 +1 @@
+
diff --git a/archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.mcmeta b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.mcmeta
new file mode 100644
index 0000000000..67ee043486
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 1,
+ "description": "Some resource pack maybe"
+ }
+}
diff --git a/archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.nfo b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.nfo
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/FileSystem/test_folder/pack.nfo
@@ -0,0 +1 @@
+
diff --git a/archived/projt-launcher/tests/testdata/Libraries/1.9-simple.json b/archived/projt-launcher/tests/testdata/Libraries/1.9-simple.json
new file mode 100644
index 0000000000..c71bc65538
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Libraries/1.9-simple.json
@@ -0,0 +1,199 @@
+{
+ "assets": "1.9",
+ "id": "1.9",
+ "libraries": [
+ {
+ "name": "oshi-project:oshi-core:1.1"
+ },
+ {
+ "name": "net.java.dev.jna:jna:3.4.0"
+ },
+ {
+ "name": "net.java.dev.jna:platform:3.4.0"
+ },
+ {
+ "name": "com.ibm.icu:icu4j-core-mojang:51.2"
+ },
+ {
+ "name": "net.sf.jopt-simple:jopt-simple:4.6"
+ },
+ {
+ "name": "com.paulscode:codecjorbis:20101023"
+ },
+ {
+ "name": "com.paulscode:codecwav:20101023"
+ },
+ {
+ "name": "com.paulscode:libraryjavasound:20101123"
+ },
+ {
+ "name": "com.paulscode:librarylwjglopenal:20100824"
+ },
+ {
+ "name": "com.paulscode:soundsystem:20120107"
+ },
+ {
+ "name": "io.netty:netty-all:4.0.23.Final"
+ },
+ {
+ "name": "com.google.guava:guava:17.0"
+ },
+ {
+ "name": "org.apache.commons:commons-lang3:3.3.2"
+ },
+ {
+ "name": "commons-io:commons-io:2.4"
+ },
+ {
+ "name": "commons-codec:commons-codec:1.9"
+ },
+ {
+ "name": "net.java.jinput:jinput:2.0.5"
+ },
+ {
+ "name": "net.java.jutils:jutils:1.0.0"
+ },
+ {
+ "name": "com.google.code.gson:gson:2.2.4"
+ },
+ {
+ "name": "com.mojang:authlib:1.5.22"
+ },
+ {
+ "name": "com.mojang:realms:1.8.4"
+ },
+ {
+ "name": "org.apache.commons:commons-compress:1.8.1"
+ },
+ {
+ "name": "org.apache.httpcomponents:httpclient:4.3.3"
+ },
+ {
+ "name": "commons-logging:commons-logging:1.1.3"
+ },
+ {
+ "name": "org.apache.httpcomponents:httpcore:4.3.2"
+ },
+ {
+ "name": "org.apache.logging.log4j:log4j-api:2.0-beta9"
+ },
+ {
+ "name": "org.apache.logging.log4j:log4j-core:2.0-beta9"
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.2-nightly-20140822",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "net.java.jinput:jinput-platform:2.0.5",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ }
+ }
+ ],
+ "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}",
+ "minimumLauncherVersion": 18,
+ "releaseTime": "2016-02-29T13:49:54+00:00",
+ "time": "2016-03-01T13:14:53+00:00",
+ "type": "release"
+}
diff --git a/archived/projt-launcher/tests/testdata/Libraries/1.9.json b/archived/projt-launcher/tests/testdata/Libraries/1.9.json
new file mode 100644
index 0000000000..b298634ad3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Libraries/1.9.json
@@ -0,0 +1,547 @@
+{
+ "assetIndex": {
+ "id": "1.9",
+ "sha1": "cde65b47a43f638653ab1da3848b53f8a7477b16",
+ "size": 136916,
+ "totalSize": 119917473,
+ "url": "https://launchermeta.mojang.com/mc-staging/assets/1.9/cde65b47a43f638653ab1da3848b53f8a7477b16/1.9.json"
+ },
+ "assets": "1.9",
+ "downloads": {
+ "client": {
+ "sha1": "2f67dfe8953299440d1902f9124f0f2c3a2c940f",
+ "size": 8697592,
+ "url": "https://launcher.mojang.com/mc/game/1.9/client/2f67dfe8953299440d1902f9124f0f2c3a2c940f/client.jar"
+ },
+ "server": {
+ "sha1": "b4d449cf2918e0f3bd8aa18954b916a4d1880f0d",
+ "size": 8848015,
+ "url": "https://launcher.mojang.com/mc/game/1.9/server/b4d449cf2918e0f3bd8aa18954b916a4d1880f0d/server.jar"
+ }
+ },
+ "id": "1.9",
+ "libraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "path": "oshi-project/oshi-core/1.1/oshi-core-1.1.jar",
+ "sha1": "9ddf7b048a8d701be231c0f4f95fd986198fd2d8",
+ "size": 30973,
+ "url": "https://libraries.minecraft.net/oshi-project/oshi-core/1.1/oshi-core-1.1.jar"
+ }
+ },
+ "name": "oshi-project:oshi-core:1.1"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar",
+ "sha1": "803ff252fedbd395baffd43b37341dc4a150a554",
+ "size": 1008730,
+ "url": "https://libraries.minecraft.net/net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar"
+ }
+ },
+ "name": "net.java.dev.jna:jna:3.4.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar",
+ "sha1": "e3f70017be8100d3d6923f50b3d2ee17714e9c13",
+ "size": 913436,
+ "url": "https://libraries.minecraft.net/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar"
+ }
+ },
+ "name": "net.java.dev.jna:platform:3.4.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar",
+ "sha1": "63d216a9311cca6be337c1e458e587f99d382b84",
+ "size": 1634692,
+ "url": "https://libraries.minecraft.net/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar"
+ }
+ },
+ "name": "com.ibm.icu:icu4j-core-mojang:51.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/sf/jopt-simple/jopt-simple/4.6/jopt-simple-4.6.jar",
+ "sha1": "306816fb57cf94f108a43c95731b08934dcae15c",
+ "size": 62477,
+ "url": "https://libraries.minecraft.net/net/sf/jopt-simple/jopt-simple/4.6/jopt-simple-4.6.jar"
+ }
+ },
+ "name": "net.sf.jopt-simple:jopt-simple:4.6"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/codecjorbis/20101023/codecjorbis-20101023.jar",
+ "sha1": "c73b5636faf089d9f00e8732a829577de25237ee",
+ "size": 103871,
+ "url": "https://libraries.minecraft.net/com/paulscode/codecjorbis/20101023/codecjorbis-20101023.jar"
+ }
+ },
+ "name": "com.paulscode:codecjorbis:20101023"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
+ "sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
+ "size": 5618,
+ "url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
+ }
+ },
+ "name": "com.paulscode:codecwav:20101023"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/libraryjavasound/20101123/libraryjavasound-20101123.jar",
+ "sha1": "5c5e304366f75f9eaa2e8cca546a1fb6109348b3",
+ "size": 21679,
+ "url": "https://libraries.minecraft.net/com/paulscode/libraryjavasound/20101123/libraryjavasound-20101123.jar"
+ }
+ },
+ "name": "com.paulscode:libraryjavasound:20101123"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/librarylwjglopenal/20100824/librarylwjglopenal-20100824.jar",
+ "sha1": "73e80d0794c39665aec3f62eee88ca91676674ef",
+ "size": 18981,
+ "url": "https://libraries.minecraft.net/com/paulscode/librarylwjglopenal/20100824/librarylwjglopenal-20100824.jar"
+ }
+ },
+ "name": "com.paulscode:librarylwjglopenal:20100824"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/soundsystem/20120107/soundsystem-20120107.jar",
+ "sha1": "419c05fe9be71f792b2d76cfc9b67f1ed0fec7f6",
+ "size": 65020,
+ "url": "https://libraries.minecraft.net/com/paulscode/soundsystem/20120107/soundsystem-20120107.jar"
+ }
+ },
+ "name": "com.paulscode:soundsystem:20120107"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "io/netty/netty-all/4.0.23.Final/netty-all-4.0.23.Final.jar",
+ "sha1": "0294104aaf1781d6a56a07d561e792c5d0c95f45",
+ "size": 1779991,
+ "url": "https://libraries.minecraft.net/io/netty/netty-all/4.0.23.Final/netty-all-4.0.23.Final.jar"
+ }
+ },
+ "name": "io.netty:netty-all:4.0.23.Final"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/google/guava/guava/17.0/guava-17.0.jar",
+ "sha1": "9c6ef172e8de35fd8d4d8783e4821e57cdef7445",
+ "size": 2243036,
+ "url": "https://libraries.minecraft.net/com/google/guava/guava/17.0/guava-17.0.jar"
+ }
+ },
+ "name": "com.google.guava:guava:17.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar",
+ "sha1": "90a3822c38ec8c996e84c16a3477ef632cbc87a3",
+ "size": 412739,
+ "url": "https://libraries.minecraft.net/org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar"
+ }
+ },
+ "name": "org.apache.commons:commons-lang3:3.3.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "commons-io/commons-io/2.4/commons-io-2.4.jar",
+ "sha1": "b1b6ea3b7e4aa4f492509a4952029cd8e48019ad",
+ "size": 185140,
+ "url": "https://libraries.minecraft.net/commons-io/commons-io/2.4/commons-io-2.4.jar"
+ }
+ },
+ "name": "commons-io:commons-io:2.4"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "commons-codec/commons-codec/1.9/commons-codec-1.9.jar",
+ "sha1": "9ce04e34240f674bc72680f8b843b1457383161a",
+ "size": 263965,
+ "url": "https://libraries.minecraft.net/commons-codec/commons-codec/1.9/commons-codec-1.9.jar"
+ }
+ },
+ "name": "commons-codec:commons-codec:1.9"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar",
+ "sha1": "39c7796b469a600f72380316f6b1f11db6c2c7c4",
+ "size": 208338,
+ "url": "https://libraries.minecraft.net/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar"
+ }
+ },
+ "name": "net.java.jinput:jinput:2.0.5"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar",
+ "sha1": "e12fe1fda814bd348c1579329c86943d2cd3c6a6",
+ "size": 7508,
+ "url": "https://libraries.minecraft.net/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar"
+ }
+ },
+ "name": "net.java.jutils:jutils:1.0.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/google/code/gson/gson/2.2.4/gson-2.2.4.jar",
+ "sha1": "a60a5e993c98c864010053cb901b7eab25306568",
+ "size": 190432,
+ "url": "https://libraries.minecraft.net/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar"
+ }
+ },
+ "name": "com.google.code.gson:gson:2.2.4"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/mojang/authlib/1.5.22/authlib-1.5.22.jar",
+ "sha1": "afaa8f6df976fcb5520e76ef1d5798c9e6b5c0b2",
+ "size": 64539,
+ "url": "https://libraries.minecraft.net/com/mojang/authlib/1.5.22/authlib-1.5.22.jar"
+ }
+ },
+ "name": "com.mojang:authlib:1.5.22"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/mojang/realms/1.8.4/realms-1.8.4.jar",
+ "sha1": "15f8dc326c97a96dee6e65392e145ad6d1cb46cb",
+ "size": 1131574,
+ "url": "https://libraries.minecraft.net/com/mojang/realms/1.8.4/realms-1.8.4.jar"
+ }
+ },
+ "name": "com.mojang:realms:1.8.4"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar",
+ "sha1": "a698750c16740fd5b3871425f4cb3bbaa87f529d",
+ "size": 365552,
+ "url": "https://libraries.minecraft.net/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar"
+ }
+ },
+ "name": "org.apache.commons:commons-compress:1.8.1"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar",
+ "sha1": "18f4247ff4572a074444572cee34647c43e7c9c7",
+ "size": 589512,
+ "url": "https://libraries.minecraft.net/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar"
+ }
+ },
+ "name": "org.apache.httpcomponents:httpclient:4.3.3"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar",
+ "sha1": "f6f66e966c70a83ffbdb6f17a0919eaf7c8aca7f",
+ "size": 62050,
+ "url": "https://libraries.minecraft.net/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar"
+ }
+ },
+ "name": "commons-logging:commons-logging:1.1.3"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar",
+ "sha1": "31fbbff1ddbf98f3aa7377c94d33b0447c646b6e",
+ "size": 282269,
+ "url": "https://libraries.minecraft.net/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar"
+ }
+ },
+ "name": "org.apache.httpcomponents:httpcore:4.3.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar",
+ "sha1": "1dd66e68cccd907880229f9e2de1314bd13ff785",
+ "size": 108161,
+ "url": "https://libraries.minecraft.net/org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar"
+ }
+ },
+ "name": "org.apache.logging.log4j:log4j-api:2.0-beta9"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar",
+ "sha1": "678861ba1b2e1fccb594bb0ca03114bb05da9695",
+ "size": 681134,
+ "url": "https://libraries.minecraft.net/org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar"
+ }
+ },
+ "name": "org.apache.logging.log4j:log4j-core:2.0-beta9"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar",
+ "sha1": "697517568c68e78ae0b4544145af031c81082dfe",
+ "size": 1047168,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "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"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "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"
+ },
+ "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"
+ },
+ "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"
+ },
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/lwjgl/lwjgl/lwjgl/2.9.2-nightly-20140822/lwjgl-2.9.2-nightly-20140822.jar",
+ "sha1": "7707204c9ffa5d91662de95f0a224e2f721b22af",
+ "size": 1045632,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.2-nightly-20140822/lwjgl-2.9.2-nightly-20140822.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "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"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "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",
+ "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"
+ },
+ "natives-osx": {
+ "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"
+ },
+ "natives-windows": {
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.2-nightly-20140822",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "classifiers": {
+ "natives-linux": {
+ "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"
+ },
+ "natives-osx": {
+ "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar",
+ "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232",
+ "size": 12186,
+ "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar"
+ },
+ "natives-windows": {
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "net.java.jinput:jinput-platform:2.0.5",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ }
+ }
+ ],
+ "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}",
+ "minimumLauncherVersion": 18,
+ "releaseTime": "2016-02-29T13:49:54+00:00",
+ "time": "2016-03-01T13:14:53+00:00",
+ "type": "release"
+}
diff --git a/archived/projt-launcher/tests/testdata/Libraries/codecwav-20101023.jar b/archived/projt-launcher/tests/testdata/Libraries/codecwav-20101023.jar
new file mode 100644
index 0000000000..f5236083c6
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Libraries/codecwav-20101023.jar
@@ -0,0 +1 @@
+dummy test file.
diff --git a/archived/projt-launcher/tests/testdata/Libraries/lib-native-arch.json b/archived/projt-launcher/tests/testdata/Libraries/lib-native-arch.json
new file mode 100644
index 0000000000..501826ae10
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Libraries/lib-native-arch.json
@@ -0,0 +1,46 @@
+{
+ "downloads": {
+ "classifiers": {
+ "natives-osx": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar",
+ "sha1": "62503ee712766cf77f97252e5902786fd834b8c5",
+ "size": 418331,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar"
+ },
+ "natives-windows-32": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar",
+ "sha1": "7c6affe439099806a4f552da14c42f9d643d8b23",
+ "size": 386792,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"
+ },
+ "natives-windows-64": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar",
+ "sha1": "39d0c3d363735b4785598e0e7fbf8297c706a9f9",
+ "size": 463390,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "tv.twitch:twitch-platform:5.16",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows-${arch}"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux"
+ }
+ }
+ ]
+}
diff --git a/archived/projt-launcher/tests/testdata/Libraries/lib-native.json b/archived/projt-launcher/tests/testdata/Libraries/lib-native.json
new file mode 100644
index 0000000000..e7a6094f93
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Libraries/lib-native.json
@@ -0,0 +1,56 @@
+{
+ "downloads": {
+ "artifact": {
+ "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"
+ },
+ "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"
+ },
+ "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"
+ },
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+}
diff --git a/archived/projt-launcher/tests/testdata/Libraries/lib-simple.json b/archived/projt-launcher/tests/testdata/Libraries/lib-simple.json
new file mode 100644
index 0000000000..90bbff074d
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Libraries/lib-simple.json
@@ -0,0 +1,11 @@
+{
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
+ "sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
+ "size": 5618,
+ "url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
+ }
+ },
+ "name": "com.paulscode:codecwav:20101023"
+}
diff --git a/archived/projt-launcher/tests/testdata/Libraries/testname-testversion-linux-32.jar b/archived/projt-launcher/tests/testdata/Libraries/testname-testversion-linux-32.jar
new file mode 100644
index 0000000000..f5236083c6
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Libraries/testname-testversion-linux-32.jar
@@ -0,0 +1 @@
+dummy test file.
diff --git a/archived/projt-launcher/tests/testdata/Library/1.9-simple.json b/archived/projt-launcher/tests/testdata/Library/1.9-simple.json
new file mode 100644
index 0000000000..c71bc65538
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Library/1.9-simple.json
@@ -0,0 +1,199 @@
+{
+ "assets": "1.9",
+ "id": "1.9",
+ "libraries": [
+ {
+ "name": "oshi-project:oshi-core:1.1"
+ },
+ {
+ "name": "net.java.dev.jna:jna:3.4.0"
+ },
+ {
+ "name": "net.java.dev.jna:platform:3.4.0"
+ },
+ {
+ "name": "com.ibm.icu:icu4j-core-mojang:51.2"
+ },
+ {
+ "name": "net.sf.jopt-simple:jopt-simple:4.6"
+ },
+ {
+ "name": "com.paulscode:codecjorbis:20101023"
+ },
+ {
+ "name": "com.paulscode:codecwav:20101023"
+ },
+ {
+ "name": "com.paulscode:libraryjavasound:20101123"
+ },
+ {
+ "name": "com.paulscode:librarylwjglopenal:20100824"
+ },
+ {
+ "name": "com.paulscode:soundsystem:20120107"
+ },
+ {
+ "name": "io.netty:netty-all:4.0.23.Final"
+ },
+ {
+ "name": "com.google.guava:guava:17.0"
+ },
+ {
+ "name": "org.apache.commons:commons-lang3:3.3.2"
+ },
+ {
+ "name": "commons-io:commons-io:2.4"
+ },
+ {
+ "name": "commons-codec:commons-codec:1.9"
+ },
+ {
+ "name": "net.java.jinput:jinput:2.0.5"
+ },
+ {
+ "name": "net.java.jutils:jutils:1.0.0"
+ },
+ {
+ "name": "com.google.code.gson:gson:2.2.4"
+ },
+ {
+ "name": "com.mojang:authlib:1.5.22"
+ },
+ {
+ "name": "com.mojang:realms:1.8.4"
+ },
+ {
+ "name": "org.apache.commons:commons-compress:1.8.1"
+ },
+ {
+ "name": "org.apache.httpcomponents:httpclient:4.3.3"
+ },
+ {
+ "name": "commons-logging:commons-logging:1.1.3"
+ },
+ {
+ "name": "org.apache.httpcomponents:httpcore:4.3.2"
+ },
+ {
+ "name": "org.apache.logging.log4j:log4j-api:2.0-beta9"
+ },
+ {
+ "name": "org.apache.logging.log4j:log4j-core:2.0-beta9"
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.2-nightly-20140822",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "net.java.jinput:jinput-platform:2.0.5",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ }
+ }
+ ],
+ "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}",
+ "minimumLauncherVersion": 18,
+ "releaseTime": "2016-02-29T13:49:54+00:00",
+ "time": "2016-03-01T13:14:53+00:00",
+ "type": "release"
+}
diff --git a/archived/projt-launcher/tests/testdata/Library/1.9.json b/archived/projt-launcher/tests/testdata/Library/1.9.json
new file mode 100644
index 0000000000..b298634ad3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Library/1.9.json
@@ -0,0 +1,547 @@
+{
+ "assetIndex": {
+ "id": "1.9",
+ "sha1": "cde65b47a43f638653ab1da3848b53f8a7477b16",
+ "size": 136916,
+ "totalSize": 119917473,
+ "url": "https://launchermeta.mojang.com/mc-staging/assets/1.9/cde65b47a43f638653ab1da3848b53f8a7477b16/1.9.json"
+ },
+ "assets": "1.9",
+ "downloads": {
+ "client": {
+ "sha1": "2f67dfe8953299440d1902f9124f0f2c3a2c940f",
+ "size": 8697592,
+ "url": "https://launcher.mojang.com/mc/game/1.9/client/2f67dfe8953299440d1902f9124f0f2c3a2c940f/client.jar"
+ },
+ "server": {
+ "sha1": "b4d449cf2918e0f3bd8aa18954b916a4d1880f0d",
+ "size": 8848015,
+ "url": "https://launcher.mojang.com/mc/game/1.9/server/b4d449cf2918e0f3bd8aa18954b916a4d1880f0d/server.jar"
+ }
+ },
+ "id": "1.9",
+ "libraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "path": "oshi-project/oshi-core/1.1/oshi-core-1.1.jar",
+ "sha1": "9ddf7b048a8d701be231c0f4f95fd986198fd2d8",
+ "size": 30973,
+ "url": "https://libraries.minecraft.net/oshi-project/oshi-core/1.1/oshi-core-1.1.jar"
+ }
+ },
+ "name": "oshi-project:oshi-core:1.1"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar",
+ "sha1": "803ff252fedbd395baffd43b37341dc4a150a554",
+ "size": 1008730,
+ "url": "https://libraries.minecraft.net/net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar"
+ }
+ },
+ "name": "net.java.dev.jna:jna:3.4.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar",
+ "sha1": "e3f70017be8100d3d6923f50b3d2ee17714e9c13",
+ "size": 913436,
+ "url": "https://libraries.minecraft.net/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar"
+ }
+ },
+ "name": "net.java.dev.jna:platform:3.4.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar",
+ "sha1": "63d216a9311cca6be337c1e458e587f99d382b84",
+ "size": 1634692,
+ "url": "https://libraries.minecraft.net/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar"
+ }
+ },
+ "name": "com.ibm.icu:icu4j-core-mojang:51.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/sf/jopt-simple/jopt-simple/4.6/jopt-simple-4.6.jar",
+ "sha1": "306816fb57cf94f108a43c95731b08934dcae15c",
+ "size": 62477,
+ "url": "https://libraries.minecraft.net/net/sf/jopt-simple/jopt-simple/4.6/jopt-simple-4.6.jar"
+ }
+ },
+ "name": "net.sf.jopt-simple:jopt-simple:4.6"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/codecjorbis/20101023/codecjorbis-20101023.jar",
+ "sha1": "c73b5636faf089d9f00e8732a829577de25237ee",
+ "size": 103871,
+ "url": "https://libraries.minecraft.net/com/paulscode/codecjorbis/20101023/codecjorbis-20101023.jar"
+ }
+ },
+ "name": "com.paulscode:codecjorbis:20101023"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
+ "sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
+ "size": 5618,
+ "url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
+ }
+ },
+ "name": "com.paulscode:codecwav:20101023"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/libraryjavasound/20101123/libraryjavasound-20101123.jar",
+ "sha1": "5c5e304366f75f9eaa2e8cca546a1fb6109348b3",
+ "size": 21679,
+ "url": "https://libraries.minecraft.net/com/paulscode/libraryjavasound/20101123/libraryjavasound-20101123.jar"
+ }
+ },
+ "name": "com.paulscode:libraryjavasound:20101123"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/librarylwjglopenal/20100824/librarylwjglopenal-20100824.jar",
+ "sha1": "73e80d0794c39665aec3f62eee88ca91676674ef",
+ "size": 18981,
+ "url": "https://libraries.minecraft.net/com/paulscode/librarylwjglopenal/20100824/librarylwjglopenal-20100824.jar"
+ }
+ },
+ "name": "com.paulscode:librarylwjglopenal:20100824"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/soundsystem/20120107/soundsystem-20120107.jar",
+ "sha1": "419c05fe9be71f792b2d76cfc9b67f1ed0fec7f6",
+ "size": 65020,
+ "url": "https://libraries.minecraft.net/com/paulscode/soundsystem/20120107/soundsystem-20120107.jar"
+ }
+ },
+ "name": "com.paulscode:soundsystem:20120107"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "io/netty/netty-all/4.0.23.Final/netty-all-4.0.23.Final.jar",
+ "sha1": "0294104aaf1781d6a56a07d561e792c5d0c95f45",
+ "size": 1779991,
+ "url": "https://libraries.minecraft.net/io/netty/netty-all/4.0.23.Final/netty-all-4.0.23.Final.jar"
+ }
+ },
+ "name": "io.netty:netty-all:4.0.23.Final"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/google/guava/guava/17.0/guava-17.0.jar",
+ "sha1": "9c6ef172e8de35fd8d4d8783e4821e57cdef7445",
+ "size": 2243036,
+ "url": "https://libraries.minecraft.net/com/google/guava/guava/17.0/guava-17.0.jar"
+ }
+ },
+ "name": "com.google.guava:guava:17.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar",
+ "sha1": "90a3822c38ec8c996e84c16a3477ef632cbc87a3",
+ "size": 412739,
+ "url": "https://libraries.minecraft.net/org/apache/commons/commons-lang3/3.3.2/commons-lang3-3.3.2.jar"
+ }
+ },
+ "name": "org.apache.commons:commons-lang3:3.3.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "commons-io/commons-io/2.4/commons-io-2.4.jar",
+ "sha1": "b1b6ea3b7e4aa4f492509a4952029cd8e48019ad",
+ "size": 185140,
+ "url": "https://libraries.minecraft.net/commons-io/commons-io/2.4/commons-io-2.4.jar"
+ }
+ },
+ "name": "commons-io:commons-io:2.4"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "commons-codec/commons-codec/1.9/commons-codec-1.9.jar",
+ "sha1": "9ce04e34240f674bc72680f8b843b1457383161a",
+ "size": 263965,
+ "url": "https://libraries.minecraft.net/commons-codec/commons-codec/1.9/commons-codec-1.9.jar"
+ }
+ },
+ "name": "commons-codec:commons-codec:1.9"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar",
+ "sha1": "39c7796b469a600f72380316f6b1f11db6c2c7c4",
+ "size": 208338,
+ "url": "https://libraries.minecraft.net/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar"
+ }
+ },
+ "name": "net.java.jinput:jinput:2.0.5"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar",
+ "sha1": "e12fe1fda814bd348c1579329c86943d2cd3c6a6",
+ "size": 7508,
+ "url": "https://libraries.minecraft.net/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar"
+ }
+ },
+ "name": "net.java.jutils:jutils:1.0.0"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/google/code/gson/gson/2.2.4/gson-2.2.4.jar",
+ "sha1": "a60a5e993c98c864010053cb901b7eab25306568",
+ "size": 190432,
+ "url": "https://libraries.minecraft.net/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar"
+ }
+ },
+ "name": "com.google.code.gson:gson:2.2.4"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/mojang/authlib/1.5.22/authlib-1.5.22.jar",
+ "sha1": "afaa8f6df976fcb5520e76ef1d5798c9e6b5c0b2",
+ "size": 64539,
+ "url": "https://libraries.minecraft.net/com/mojang/authlib/1.5.22/authlib-1.5.22.jar"
+ }
+ },
+ "name": "com.mojang:authlib:1.5.22"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "com/mojang/realms/1.8.4/realms-1.8.4.jar",
+ "sha1": "15f8dc326c97a96dee6e65392e145ad6d1cb46cb",
+ "size": 1131574,
+ "url": "https://libraries.minecraft.net/com/mojang/realms/1.8.4/realms-1.8.4.jar"
+ }
+ },
+ "name": "com.mojang:realms:1.8.4"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar",
+ "sha1": "a698750c16740fd5b3871425f4cb3bbaa87f529d",
+ "size": 365552,
+ "url": "https://libraries.minecraft.net/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar"
+ }
+ },
+ "name": "org.apache.commons:commons-compress:1.8.1"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar",
+ "sha1": "18f4247ff4572a074444572cee34647c43e7c9c7",
+ "size": 589512,
+ "url": "https://libraries.minecraft.net/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar"
+ }
+ },
+ "name": "org.apache.httpcomponents:httpclient:4.3.3"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar",
+ "sha1": "f6f66e966c70a83ffbdb6f17a0919eaf7c8aca7f",
+ "size": 62050,
+ "url": "https://libraries.minecraft.net/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar"
+ }
+ },
+ "name": "commons-logging:commons-logging:1.1.3"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar",
+ "sha1": "31fbbff1ddbf98f3aa7377c94d33b0447c646b6e",
+ "size": 282269,
+ "url": "https://libraries.minecraft.net/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar"
+ }
+ },
+ "name": "org.apache.httpcomponents:httpcore:4.3.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar",
+ "sha1": "1dd66e68cccd907880229f9e2de1314bd13ff785",
+ "size": 108161,
+ "url": "https://libraries.minecraft.net/org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar"
+ }
+ },
+ "name": "org.apache.logging.log4j:log4j-api:2.0-beta9"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar",
+ "sha1": "678861ba1b2e1fccb594bb0ca03114bb05da9695",
+ "size": 681134,
+ "url": "https://libraries.minecraft.net/org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar"
+ }
+ },
+ "name": "org.apache.logging.log4j:log4j-core:2.0-beta9"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar",
+ "sha1": "697517568c68e78ae0b4544145af031c81082dfe",
+ "size": 1047168,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "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"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "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"
+ },
+ "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"
+ },
+ "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"
+ },
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "path": "org/lwjgl/lwjgl/lwjgl/2.9.2-nightly-20140822/lwjgl-2.9.2-nightly-20140822.jar",
+ "sha1": "7707204c9ffa5d91662de95f0a224e2f721b22af",
+ "size": 1045632,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.2-nightly-20140822/lwjgl-2.9.2-nightly-20140822.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "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"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.2-nightly-20140822",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "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",
+ "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"
+ },
+ "natives-osx": {
+ "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"
+ },
+ "natives-windows": {
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.2-nightly-20140822",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "classifiers": {
+ "natives-linux": {
+ "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"
+ },
+ "natives-osx": {
+ "path": "net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar",
+ "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232",
+ "size": 12186,
+ "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar"
+ },
+ "natives-windows": {
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "net.java.jinput:jinput-platform:2.0.5",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ }
+ }
+ ],
+ "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}",
+ "minimumLauncherVersion": 18,
+ "releaseTime": "2016-02-29T13:49:54+00:00",
+ "time": "2016-03-01T13:14:53+00:00",
+ "type": "release"
+}
diff --git a/archived/projt-launcher/tests/testdata/Library/codecwav-20101023.jar b/archived/projt-launcher/tests/testdata/Library/codecwav-20101023.jar
new file mode 100644
index 0000000000..f5236083c6
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Library/codecwav-20101023.jar
@@ -0,0 +1 @@
+dummy test file.
diff --git a/archived/projt-launcher/tests/testdata/Library/lib-native-arch.json b/archived/projt-launcher/tests/testdata/Library/lib-native-arch.json
new file mode 100644
index 0000000000..501826ae10
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Library/lib-native-arch.json
@@ -0,0 +1,46 @@
+{
+ "downloads": {
+ "classifiers": {
+ "natives-osx": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar",
+ "sha1": "62503ee712766cf77f97252e5902786fd834b8c5",
+ "size": 418331,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar"
+ },
+ "natives-windows-32": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar",
+ "sha1": "7c6affe439099806a4f552da14c42f9d643d8b23",
+ "size": 386792,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"
+ },
+ "natives-windows-64": {
+ "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar",
+ "sha1": "39d0c3d363735b4785598e0e7fbf8297c706a9f9",
+ "size": 463390,
+ "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "tv.twitch:twitch-platform:5.16",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows-${arch}"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux"
+ }
+ }
+ ]
+}
diff --git a/archived/projt-launcher/tests/testdata/Library/lib-native.json b/archived/projt-launcher/tests/testdata/Library/lib-native.json
new file mode 100644
index 0000000000..e7a6094f93
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Library/lib-native.json
@@ -0,0 +1,56 @@
+{
+ "downloads": {
+ "artifact": {
+ "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"
+ },
+ "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"
+ },
+ "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"
+ },
+ "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"
+ }
+ }
+ },
+ "extract": {
+ "exclude": [
+ "META-INF/"
+ ]
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-osx",
+ "windows": "natives-windows"
+ },
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+}
diff --git a/archived/projt-launcher/tests/testdata/Library/lib-simple.json b/archived/projt-launcher/tests/testdata/Library/lib-simple.json
new file mode 100644
index 0000000000..90bbff074d
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Library/lib-simple.json
@@ -0,0 +1,11 @@
+{
+ "downloads": {
+ "artifact": {
+ "path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
+ "sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
+ "size": 5618,
+ "url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
+ }
+ },
+ "name": "com.paulscode:codecwav:20101023"
+}
diff --git a/archived/projt-launcher/tests/testdata/Library/testname-testversion-linux-32.jar b/archived/projt-launcher/tests/testdata/Library/testname-testversion-linux-32.jar
new file mode 100644
index 0000000000..f5236083c6
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Library/testname-testversion-linux-32.jar
@@ -0,0 +1 @@
+dummy test file.
diff --git a/archived/projt-launcher/tests/testdata/MetaComponentParse/component_basic.json b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_basic.json
new file mode 100644
index 0000000000..908cb353ca
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_basic.json
@@ -0,0 +1,8 @@
+{
+ "description": [
+ {
+ "text": "Hello, Component!"
+ }
+ ],
+ "expected_output": "Hello, Component!"
+}
diff --git a/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_extra.json b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_extra.json
new file mode 100644
index 0000000000..887becdbeb
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_extra.json
@@ -0,0 +1,21 @@
+{
+ "description": [
+ {
+ "text": "Hello, ",
+ "color": "red",
+ "bold": true,
+ "italic": true,
+ "extra": [
+ {
+ "extra": [
+ "Component!"
+ ],
+ "bold": false,
+ "italic": false
+ }
+ ]
+ }
+ ],
+ "expected_output":
+ "<span style=\"color: red; font-weight: bold; font-style: italic;\">Hello, <span style=\"font-weight: normal; font-style: normal;\">Component!</span></span>"
+} \ No newline at end of file
diff --git a/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_format.json b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_format.json
new file mode 100644
index 0000000000..1078886a6b
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_format.json
@@ -0,0 +1,13 @@
+{
+ "description": [
+ {
+ "text": "Hello, Component!",
+ "color": "blue",
+ "bold": true,
+ "italic": true,
+ "underlined": true,
+ "strikethrough": true
+ }
+ ],
+ "expected_output": "<span style=\"color: blue; font-weight: bold; font-style: italic;\"><s><u>Hello, Component!</u></s></span>"
+} \ No newline at end of file
diff --git a/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_link.json b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_link.json
new file mode 100644
index 0000000000..188c004cd5
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_link.json
@@ -0,0 +1,12 @@
+{
+ "description": [
+ {
+ "text": "Hello, Component!",
+ "clickEvent": {
+ "action": "open_url",
+ "value": "https://google.com"
+ }
+ }
+ ],
+ "expected_output": "<a href=\"https://google.com\">Hello, Component!</a>"
+}
diff --git a/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_mixed.json b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_mixed.json
new file mode 100644
index 0000000000..661fc1a3e9
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/MetaComponentParse/component_with_mixed.json
@@ -0,0 +1,45 @@
+{
+ "description": [
+ {
+ "text": "The quick ",
+ "color": "blue",
+ "italic": true
+ },
+ {
+ "text": "brown fox ",
+ "color": "#873600",
+ "bold": true,
+ "underlined": true,
+ "extra": [
+ {
+ "text": "jumped over ",
+ "color": "blue",
+ "bold": false,
+ "underlined": false,
+ "italic": true,
+ "strikethrough": true
+ }
+ ]
+ },
+ {
+ "text": "the lazy dog's back. ",
+ "color": "green",
+ "bold": true,
+ "italic": true,
+ "underlined": true,
+ "strikethrough": true,
+ "extra": [
+ {
+ "text": "1234567890 ",
+ "color": "black",
+ "strikethrough": false,
+ "extra": [
+ "How vexingly quick daft zebras jump!"
+ ]
+ }
+ ]
+ }
+ ],
+ "expected_output":
+ "<span style=\"color: blue; font-style: italic;\">The quick </span><span style=\"color: #873600; font-weight: bold;\"><u>brown fox </u><span style=\"color: blue; font-weight: normal; font-style: italic;\"><s>jumped over </s></span></span><span style=\"color: green; font-weight: bold; font-style: italic;\"><s><u>the lazy dog's back. </u></s><span style=\"color: black;\"><u>1234567890 </u>How vexingly quick daft zebras jump!</span></span>"
+}
diff --git a/archived/projt-launcher/tests/testdata/PackageManifest/1.8.0_202-x64.json b/archived/projt-launcher/tests/testdata/PackageManifest/1.8.0_202-x64.json
new file mode 100644
index 0000000000..eaf67a7ac4
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/PackageManifest/1.8.0_202-x64.json
@@ -0,0 +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
diff --git a/archived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b.txt b/archived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b.txt
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b.txt
diff --git a/archived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b/b.txt b/archived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b/b.txt
new file mode 120000
index 0000000000..4e19a044f2
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/PackageManifest/inspect/a/b/b.txt
@@ -0,0 +1 @@
+../b.txt \ No newline at end of file
diff --git a/archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b.txt b/archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b.txt
diff --git a/archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b/b.txt b/archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b/b.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/PackageManifest/inspect_win/a/b/b.txt
diff --git a/archived/projt-launcher/tests/testdata/Packwiz/borderless-mining.pw.toml b/archived/projt-launcher/tests/testdata/Packwiz/borderless-mining.pw.toml
new file mode 100644
index 0000000000..16545fd436
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Packwiz/borderless-mining.pw.toml
@@ -0,0 +1,13 @@
+name = "Borderless Mining"
+filename = "borderless-mining-1.1.1+1.18.jar"
+side = "client"
+
+[download]
+url = "https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar"
+hash-format = "sha512"
+hash = "c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba63623064499b3188d"
+
+[update]
+[update.modrinth]
+mod-id = "kYq5qkSL"
+version = "ug2qKTPR"
diff --git a/archived/projt-launcher/tests/testdata/Packwiz/screenshot-to-clipboard-fabric.pw.toml b/archived/projt-launcher/tests/testdata/Packwiz/screenshot-to-clipboard-fabric.pw.toml
new file mode 100644
index 0000000000..87d70ada52
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Packwiz/screenshot-to-clipboard-fabric.pw.toml
@@ -0,0 +1,13 @@
+name = "Screenshot to Clipboard (Fabric)"
+filename = "screenshot-to-clipboard-1.0.7-fabric.jar"
+side = "both"
+
+[download]
+url = "https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar"
+hash-format = "murmur2"
+hash = "1781245820"
+
+[update]
+[update.curseforge]
+file-id = 3509043
+project-id = 327154
diff --git a/archived/projt-launcher/tests/testdata/ResourceFolderModel/another_test_folder/pack.mcmeta b/archived/projt-launcher/tests/testdata/ResourceFolderModel/another_test_folder/pack.mcmeta
new file mode 100644
index 0000000000..d33a0e5dba
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ResourceFolderModel/another_test_folder/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 6,
+ "description": "o quartel pegou fogo, policia deu sinal, acode acode acode a bandeira nacional"
+ }
+}
diff --git a/archived/projt-launcher/tests/testdata/ResourceFolderModel/supercoolmod.jar b/archived/projt-launcher/tests/testdata/ResourceFolderModel/supercoolmod.jar
new file mode 100644
index 0000000000..d8cf98605c
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ResourceFolderModel/supercoolmod.jar
@@ -0,0 +1 @@
+the best mod.
diff --git a/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/assets/minecraft/textures/blah.txt b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/assets/minecraft/textures/blah.txt
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/assets/minecraft/textures/blah.txt
@@ -0,0 +1 @@
+
diff --git a/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.mcmeta b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.mcmeta
new file mode 100644
index 0000000000..67ee043486
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 1,
+ "description": "Some resource pack maybe"
+ }
+}
diff --git a/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.nfo b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.nfo
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_folder/pack.nfo
@@ -0,0 +1 @@
+
diff --git a/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_resource_pack_idk.zip b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_resource_pack_idk.zip
new file mode 100644
index 0000000000..b4e66a6094
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ResourceFolderModel/test_resource_pack_idk.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/Resources/another_test_folder/pack.mcmeta b/archived/projt-launcher/tests/testdata/Resources/another_test_folder/pack.mcmeta
new file mode 100644
index 0000000000..d33a0e5dba
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Resources/another_test_folder/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 6,
+ "description": "o quartel pegou fogo, policia deu sinal, acode acode acode a bandeira nacional"
+ }
+}
diff --git a/archived/projt-launcher/tests/testdata/Resources/supercoolmod.jar b/archived/projt-launcher/tests/testdata/Resources/supercoolmod.jar
new file mode 100644
index 0000000000..d8cf98605c
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Resources/supercoolmod.jar
@@ -0,0 +1 @@
+the best mod.
diff --git a/archived/projt-launcher/tests/testdata/Resources/test_folder/assets/minecraft/textures/blah.txt b/archived/projt-launcher/tests/testdata/Resources/test_folder/assets/minecraft/textures/blah.txt
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Resources/test_folder/assets/minecraft/textures/blah.txt
@@ -0,0 +1 @@
+
diff --git a/archived/projt-launcher/tests/testdata/Resources/test_folder/pack.mcmeta b/archived/projt-launcher/tests/testdata/Resources/test_folder/pack.mcmeta
new file mode 100644
index 0000000000..67ee043486
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Resources/test_folder/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 1,
+ "description": "Some resource pack maybe"
+ }
+}
diff --git a/archived/projt-launcher/tests/testdata/Resources/test_folder/pack.nfo b/archived/projt-launcher/tests/testdata/Resources/test_folder/pack.nfo
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Resources/test_folder/pack.nfo
@@ -0,0 +1 @@
+
diff --git a/archived/projt-launcher/tests/testdata/Resources/test_resource_pack_idk.zip b/archived/projt-launcher/tests/testdata/Resources/test_resource_pack_idk.zip
new file mode 100644
index 0000000000..b4e66a6094
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Resources/test_resource_pack_idk.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack1.zip b/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack1.zip
new file mode 100644
index 0000000000..9a8fb186cf
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack1.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack2/shaders/shaders.properties b/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack2/shaders/shaders.properties
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack2/shaders/shaders.properties
diff --git a/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack3.zip b/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack3.zip
new file mode 100644
index 0000000000..dbec042df5
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/ShaderPackParse/shaderpack3.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-levels.txt b/archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-levels.txt
new file mode 100644
index 0000000000..1b30021179
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-levels.txt
@@ -0,0 +1,945 @@
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+ERROR
+INFO
+ERROR
+ERROR
+ERROR
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+INFO
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+WARN
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+ERROR
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+ERROR
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+ERROR
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+ERROR
+ERROR
+ERROR
+ERROR
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
diff --git a/archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-xml-levels.txt b/archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-xml-levels.txt
new file mode 100644
index 0000000000..941e5e3fe4
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/TestLogs/TerraFirmaGreg-Modern-xml-levels.txt
@@ -0,0 +1,869 @@
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+ERROR
+INFO
+ERROR
+ERROR
+ERROR
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+WARN
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+INFO
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+WARN
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+ERROR
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+ERROR
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+ERROR
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+WARN
+WARN
+WARN
+WARN
+WARN
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+ERROR
+ERROR
+ERROR
+ERROR
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
diff --git a/archived/projt-launcher/tests/testdata/TestLogs/vanilla-1.21.5-levels.txt b/archived/projt-launcher/tests/testdata/TestLogs/vanilla-1.21.5-levels.txt
new file mode 100644
index 0000000000..02734e56f1
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/TestLogs/vanilla-1.21.5-levels.txt
@@ -0,0 +1,25 @@
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+WARN
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
+INFO
diff --git a/archived/projt-launcher/tests/testdata/TexturePackParse/another_test_texturefolder/pack.txt b/archived/projt-launcher/tests/testdata/TexturePackParse/another_test_texturefolder/pack.txt
new file mode 100644
index 0000000000..bbc0d271af
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/TexturePackParse/another_test_texturefolder/pack.txt
@@ -0,0 +1,2 @@
+quieres
+for real \ No newline at end of file
diff --git a/archived/projt-launcher/tests/testdata/TexturePackParse/test_texture_pack_idk.zip b/archived/projt-launcher/tests/testdata/TexturePackParse/test_texture_pack_idk.zip
new file mode 100644
index 0000000000..fb4d3370ad
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/TexturePackParse/test_texture_pack_idk.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/assets/minecraft/textures/blah.txt b/archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/assets/minecraft/textures/blah.txt
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/assets/minecraft/textures/blah.txt
@@ -0,0 +1 @@
+
diff --git a/archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/pack.txt b/archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/pack.txt
new file mode 100644
index 0000000000..f626072595
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/TexturePackParse/test_texturefolder/pack.txt
@@ -0,0 +1 @@
+Some texture pack surely \ No newline at end of file
diff --git a/archived/projt-launcher/tests/testdata/Version/test_vectors.txt b/archived/projt-launcher/tests/testdata/Version/test_vectors.txt
new file mode 100644
index 0000000000..e6c6507cf8
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/Version/test_vectors.txt
@@ -0,0 +1,63 @@
+# Test vector from:
+# https://github.com/unascribed/FlexVer/blob/704e12759b6e59220ff888f8bf2ec15b8f8fd969/test/test_vectors.txt
+#
+# This test file is formatted as "<lefthand> <operator> <righthand>", seperated by the space character
+# Implementations should ignore lines starting with "#" and lines that have a length of 0
+
+# Basic numeric ordering (lexical string sort fails these)
+10 > 2
+100 > 10
+
+# Trivial common numerics
+1.0 < 1.1
+1.0 < 1.0.1
+1.1 > 1.0.1
+
+# SemVer compatibility
+1.5 > 1.5-pre1
+1.5 = 1.5+foobar
+
+# SemVer incompatibility
+1.5 < 1.5-2
+1.5-pre10 > 1.5-pre2
+
+# Empty strings
+ =
+1 >
+ < 1
+
+# Check boundary between textual and prerelease
+a-a < a
+
+# Check boundary between textual and appendix
+a+a = a
+
+# Dash is included in prerelease comparison (if stripped it will be a smaller component)
+# Note that a-a < a=a regardless since the prerelease splits the component creating a smaller first component; 0 is added to force splitting regardless
+a0-a < a0=a
+
+# Pre-releases must contain only non-digit
+1.16.5-10 > 1.16.5
+
+# Pre-releases can have multiple dashes (should not be split)
+# Reasoning for test data: "p-a!" > "p-a-" (correct); "p-a!" < "p-a t-" (what happens if every dash creates a new component)
+-a- > -a!
+
+# Misc
+b1.7.3 > a1.2.6
+b1.2.6 > a1.7.3
+a1.1.2 < a1.1.2_01
+1.16.5-0.00.5 > 1.14.2-1.3.7
+1.0.0 < 1.0.0_01
+1.0.1 > 1.0.0_01
+1.0.0_01 < 1.0.1
+0.17.1-beta.1 < 0.17.1
+0.17.1-beta.1 < 0.17.1-beta.2
+1.4.5_01 = 1.4.5_01+fabric-1.17
+1.4.5_01 = 1.4.5_01+fabric-1.17+ohgod
+14w16a < 18w40b
+18w40a < 18w40b
+1.4.5_01+fabric-1.17 < 18w40b
+13w02a < c0.3.0_01
+0.6.0-1.18.x < 0.9.beta-1.18.x
+
diff --git a/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_1.zip b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_1.zip
new file mode 100644
index 0000000000..832a243d66
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_1.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_2.zip b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_2.zip
new file mode 100644
index 0000000000..6c895176e0
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_2.zip
Binary files differ
diff --git a/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_3/world_3/level.dat b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_3/world_3/level.dat
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_3/world_3/level.dat
diff --git a/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_4/saves/world_4/level.dat b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_4/saves/world_4/level.dat
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/archived/projt-launcher/tests/testdata/WorldSaveParse/minecraft_save_4/saves/world_4/level.dat