Merge branch 'develop' of upstream into develop

This commit is contained in:
fn2006 2022-11-13 23:28:58 +00:00
commit ef713cf414
225 changed files with 4291 additions and 754 deletions

View File

@ -6,9 +6,9 @@ body:
attributes:
value: |
Before submitting a bug report, please make sure you have read this *entire* form, and that:
* You have read the [PolyMC wiki](https://polymc.org/wiki/) and it has not answered your question.
* You have read the [Prism Launcher wiki](https://prismlauncher.org/wiki/) and it has not answered your question.
* Your bug is not caused by Minecraft or any mods you have installed.
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PolyMC/PolyMC/issues)
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/PrismLauncher/PrismLauncher/issues)
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
- type: dropdown
@ -25,7 +25,7 @@ body:
attributes:
label: Version of PollyMC
description: The version of PollyMC used in the bug report.
placeholder: PollyMC 1.4.1
placeholder: PollyMC 5.1
validations:
required: true
- type: textarea

9
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,9 @@
<!--
Hey there! Thanks for your contribution.
Please make sure that your commits are signed off first.
If you don't know how that works, check out our contribution guidelines: https://github.com/PrismLauncher/PrismLauncher/blob/develop/CONTRIBUTING.md#signing-your-work
If you already created your commits, you can run `git rebase --signoff develop` to retroactively sign-off all your commits and `git push --force` to override what you have pushed already.
Note that signing and signing-off are two different things!
-->

View File

@ -25,8 +25,10 @@ jobs:
- os: ubuntu-20.04
qt_ver: 6
qt_host: linux
qt_arch: ''
qt_version: '6.2.4'
qt_modules: 'qt5compat qtimageformats'
qt_tools: ''
- os: windows-2022
name: "Windows-Legacy"
@ -38,13 +40,39 @@ jobs:
msystem: clang64
qt_ver: 6
- os: windows-2022
name: "Windows-Legacy-MSVC"
msystem: ''
architecture: 'win32'
vcvars_arch: 'amd64_x86'
qt_ver: 5
qt_host: windows
qt_arch: 'win32_msvc2019'
qt_version: '5.15.2'
qt_modules: ''
qt_tools: 'tools_openssl_x86'
- os: windows-2022
name: "Windows-MSVC"
msystem: ''
architecture: 'x64'
vcvars_arch: 'amd64'
qt_ver: 6
qt_host: windows
qt_arch: ''
qt_version: '6.4.0'
qt_modules: 'qt5compat qtimageformats'
qt_tools: ''
- os: macos-12
name: macOS
macosx_deployment_target: 10.15
qt_ver: 6
qt_host: mac
qt_arch: ''
qt_version: '6.3.0'
qt_modules: 'qt5compat qtimageformats'
qt_tools: ''
- os: macos-12
name: macOS-Legacy
@ -53,6 +81,7 @@ jobs:
qt_host: mac
qt_version: '5.15.2'
qt_modules: ''
qt_tools: ''
runs-on: ${{ matrix.os }}
@ -82,7 +111,7 @@ jobs:
languages: cpp, java
- name: 'Setup MSYS2'
if: runner.os == 'Windows'
if: runner.os == 'Windows' && matrix.msystem != ''
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
@ -102,14 +131,19 @@ jobs:
ccache:p
${{ matrix.qt_ver == 6 && 'qt6-5compat:p' || '' }}
- name: Force newer ccache
if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug'
run: |
choco install ccache --version 4.7.1
- name: Setup ccache
if: runner.os != 'Windows' && inputs.build_type == 'Debug'
uses: hendrikmuhs/ccache-action@v1.2.3
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
uses: hendrikmuhs/ccache-action@v1.2.5
with:
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}
- name: Setup ccache (Windows)
if: runner.os == 'Windows' && inputs.build_type == 'Debug'
- name: Setup ccache (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
shell: msys2 {0}
run: |
ccache --set-config=cache_dir='${{ github.workspace }}\.ccache'
@ -124,8 +158,8 @@ jobs:
run: |
echo "CCACHE_VAR=ccache" >> $GITHUB_ENV
- name: Retrieve ccache cache (Windows)
if: runner.os == 'Windows' && inputs.build_type == 'Debug'
- name: Retrieve ccache cache (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
uses: actions/cache@v3.0.11
with:
path: '${{ github.workspace }}\.ccache'
@ -156,14 +190,16 @@ jobs:
run: |
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
- name: Install Qt (macOS and AppImage)
if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS'
- name: Install Qt (macOS, AppImage & Windows MSVC)
if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '')
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_version }}
host: ${{ matrix.qt_host }}
target: 'desktop'
arch: ${{ matrix.qt_arch }}
modules: ${{ matrix.qt_modules }}
tools: ${{ matrix.qt_tools }}
cache: true
cache-key-prefix: ${{ matrix.qt_host }}-${{ matrix.qt_version }}-"${{ matrix.qt_modules }}"-qt_cache
@ -190,12 +226,27 @@ jobs:
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DMACOSX_SPARKLE_UPDATE_PUBLIC_KEY="" -DMACOSX_SPARKLE_UPDATE_FEED_URL="" -G Ninja
- name: Configure CMake (Windows)
if: runner.os == 'Windows'
- name: Configure CMake (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0}
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja
- name: Configure CMake (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}}
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
if ("${{ env.CCACHE_VAR }}")
{
Copy-Item C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/ccache.exe -Destination C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/cl.exe
echo "CLToolExe=cl.exe" >> $env:GITHUB_ENV
echo "CLToolPath=C:/ProgramData/chocolatey/lib/ccache/tools/ccache-4.7.1-windows-x86_64/" >> $env:GITHUB_ENV
echo "TrackFileAccess=false" >> $env:GITHUB_ENV
}
# Needed for ccache, but also speeds up compile
echo "UseMultiToolTask=true" >> $env:GITHUB_ENV
- name: Configure CMake (Linux)
if: runner.os == 'Linux'
run: |
@ -210,12 +261,17 @@ jobs:
run: |
cmake --build ${{ env.BUILD_DIR }}
- name: Build (Windows)
if: runner.os == 'Windows'
- name: Build (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0}
run: |
cmake --build ${{ env.BUILD_DIR }}
- name: Build (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cmake --build ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
##
# TEST
##
@ -223,13 +279,18 @@ jobs:
- name: Test
if: runner.os != 'Windows'
run: |
ctest --test-dir build --output-on-failure
ctest -E "^example64|example$" --test-dir build --output-on-failure
- name: Test (Windows)
if: runner.os == 'Windows'
- name: Test (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0}
run: |
ctest --test-dir build --output-on-failure
ctest -E "^example64|example$" --test-dir build --output-on-failure
- name: Test (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }}
##
# CODE SCAN
@ -272,8 +333,14 @@ jobs:
EOF
fi
- name: Package (Windows)
if: runner.os == 'Windows'
- name: Add VC Enviroment Variables
if: runner.os == 'Windows' && matrix.msystem == ''
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.vcvars_arch }}
- name: Package (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0}
run: |
cmake --install ${{ env.BUILD_DIR }}
@ -283,13 +350,31 @@ jobs:
cp /clang32/bin/libcrypto-1_1.dll /clang32/bin/libssl-1_1.dll ./
fi
- name: Package (Windows, portable)
if: runner.os == 'Windows'
- name: Package (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cmake --install ${{ env.BUILD_DIR }} --config ${{ inputs.build_type }}
cd ${{ env.INSTALL_DIR }}
if ("${{ matrix.qt_ver }}" -eq "5")
{
Copy-Item D:/a/PollyMC/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll -Destination libcrypto-1_1.dll
Copy-Item D:/a/PollyMC/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll -Destination libssl-1_1.dll
}
- name: Package (Windows MinGW-w64, portable)
if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0}
run: |
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
- name: Package (Windows MSVC, portable)
if: runner.os == 'Windows' && matrix.msystem == ''
run: |
cp -r ${{ env.INSTALL_DIR }} ${{ env.INSTALL_PORTABLE_DIR }} # cmake install on Windows is slow, let's just copy instead
cmake --install ${{ env.BUILD_DIR }} --prefix ${{ env.INSTALL_PORTABLE_DIR }} --component portable
- name: Package (Windows, installer)
if: runner.os == 'Windows'
run: |

View File

@ -3,7 +3,7 @@ name: Build Application
on:
push:
branches-ignore:
- 'stable'
- 'renovate/**'
paths-ignore:
- '**.md'
- '**/LICENSE'

View File

@ -47,10 +47,12 @@ jobs:
for d in PollyMC-Windows-*; do
cd "${d}" || continue
MSVC="$(echo -n ${d} | grep -o MSVC || true)"
LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
INST="$(echo -n ${d} | grep -o Setup || true)"
PORT="$(echo -n ${d} | grep -o Portable || true)"
NAME="PollyMC-Windows"
test -z "${MSVC}" && NAME="${NAME}-MinGW" || NAME="${NAME}-MSVC"
test -z "${LEGACY}" || NAME="${NAME}-Legacy"
test -z "${PORT}" || NAME="${NAME}-Portable"
test -z "${INST}" || mv PollyMC-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
@ -72,14 +74,20 @@ jobs:
PollyMC-Linux-${{ env.VERSION }}.tar.gz
PollyMC-Linux-Portable-${{ env.VERSION }}.tar.gz
PollyMC-Linux-${{ env.VERSION }}-x86_64.AppImage
PollyMC-Windows-Legacy-${{ env.VERSION }}.zip
PollyMC-Linux-Qt6-${{ env.VERSION }}.tar.gz
PollyMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
PollyMC-Windows-Legacy-Portable-${{ env.VERSION }}.zip
PollyMC-Windows-Legacy-Setup-${{ env.VERSION }}.exe
PollyMC-Windows-${{ env.VERSION }}.zip
PollyMC-Windows-Portable-${{ env.VERSION }}.zip
PollyMC-Windows-Setup-${{ env.VERSION }}.exe
PollyMC-Windows-MinGW-Legacy-${{ env.VERSION }}.zip
PollyMC-Windows-MinGW-Legacy-Portable-${{ env.VERSION }}.zip
PollyMC-Windows-MinGW-Legacy-Setup-${{ env.VERSION }}.exe
PollyMC-Windows-MinGW-${{ env.VERSION }}.zip
PollyMC-Windows-MinGW-Portable-${{ env.VERSION }}.zip
PollyMC-Windows-MinGW-Setup-${{ env.VERSION }}.exe
PollyMC-Windows-MSVC-Legacy-${{ env.VERSION }}.zip
PollyMC-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip
PollyMC-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe
PollyMC-Windows-MSVC-${{ env.VERSION }}.zip
PollyMC-Windows-MSVC-Portable-${{ env.VERSION }}.zip
PollyMC-Windows-MSVC-Setup-${{ env.VERSION }}.exe
PollyMC-macOS-${{ env.VERSION }}.tar.gz
PollyMC-macOS-Legacy-${{ env.VERSION }}.tar.gz
PollyMC-${{ env.VERSION }}.tar.gz

3
.gitignore vendored
View File

@ -47,3 +47,6 @@ result/
# Flatpak
.flatpak-builder
flatbuild
# Snap
*.snap

6
.gitmodules vendored
View File

@ -10,3 +10,9 @@
[submodule "libraries/libnbtplusplus"]
path = libraries/libnbtplusplus
url = https://github.com/PrismLauncher/libnbtplusplus.git
[submodule "libraries/zlib"]
path = libraries/zlib
url = https://github.com/madler/zlib.git
[submodule "libraries/extra-cmake-modules"]
path = libraries/extra-cmake-modules
url = https://github.com/KDE/extra-cmake-modules

View File

@ -1,10 +1,5 @@
cmake_minimum_required(VERSION 3.15) # minimum version required by QuaZip
if(WIN32)
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
cmake_policy(SET CMP0020 OLD)
endif()
project(Launcher)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
@ -32,7 +27,43 @@ set(CMAKE_C_STANDARD_REQUIRED true)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)
include(GenerateExportHeader)
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
if(MSVC)
# Use /W4 as /Wall includes unnesserey warnings such as added padding to structs
# /permissive- specify standards-conforming compiler behavior, also enabled by Qt6, default on with std:c++20
# /GS Adds buffer security checks, default on but incuded anyway to mirror gcc's fstack-protector flag
set(CMAKE_CXX_FLAGS "/W4 /permissive- /GS ${CMAKE_CXX_FLAGS}")
# LINK accepts /SUBSYSTEM whics sets if we are a WINDOWS (gui) or a CONSOLE programs
# This implicitly selects an entrypoint specific to the subsystem selected
# qtmain/QtEntryPointLib provides the correct entrypoint (wWinMain) for gui programs
# Additinaly LINK autodetects we use a GUI so we can omit /SUBSYSTEM
# This allows tests to still use have console without using seperate linker flags
# /MANIFEST:NO disables generating a manifest file, we instead provide our own
# /STACK sets the stack reserve size, ATL's pack list needs 3-4 MiB as of November 2022, provide 8 MiB
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST:NO /STACK:8388608 ${CMAKE_EXE_LINKER_FLAGS}")
# See https://github.com/ccache/ccache/issues/1040
# Note, CMake 3.25 replaces this with CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
# See https://cmake.org/cmake/help/v3.25/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.html
foreach(config DEBUG RELWITHDEBINFO)
foreach(lang C CXX)
set(flags_var "CMAKE_${lang}_FLAGS_${config}")
string(REGEX REPLACE "/Z[Ii]" "/Z7" ${flags_var} "${${flags_var}}")
endforeach()
endforeach()
if(CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL")
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release "")
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release "")
endif()
else()
set(CMAKE_CXX_FLAGS "-Wall -pedantic -fstack-protector-strong --param=ssp-buffer-size=4 ${CMAKE_CXX_FLAGS}")
# ATL's pack list needs more than the default 1 Mib stack on windows
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,8388608 ${CMAKE_EXE_LINKER_FLAGS}")
endif()
endif()
# Fix build with Qt 5.13
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_DEPRECATED_WARNINGS=Y")
@ -48,11 +79,18 @@ if(ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error)
if(ipo_supported AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel"))
message(STATUS "IPO / LTO enabled")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
elseif(ipo_supported)
message(STATUS "Not enabling IPO / LTO on debug builds")
if(ipo_supported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE)
if(CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
message(STATUS "IPO / LTO enabled")
else()
message(STATUS "Not enabling IPO / LTO on debug builds")
endif()
else()
message(STATUS "IPO / LTO will only be enabled for release builds")
endif()
else()
message(STATUS "IPO / LTO not supported: <${ipo_error}>")
endif()
@ -60,8 +98,20 @@ endif()
option(BUILD_TESTING "Build the testing tree." ON)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
find_package(ECM QUIET NO_MODULE)
if(NOT ECM_FOUND)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/CMakeLists.txt")
message(STATUS "Using bundled ECM")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libraries/extra-cmake-modules/modules;${CMAKE_MODULE_PATH}")
else()
message(FATAL_ERROR
" Could not find ECM\n \n"
" Either install ECM using the system package manager or clone submodules\n"
" Submodules can be cloned with 'git submodule update --init --recursive'")
endif()
else()
set(CMAKE_MODULE_PATH "${ECM_MODULE_PATH};${CMAKE_MODULE_PATH}")
endif()
include(CTest)
include(ECMAddTests)
if(BUILD_TESTING)
@ -76,8 +126,8 @@ set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL th
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
######## Set version numbers ########
set(Launcher_VERSION_MAJOR 5)
set(Launcher_VERSION_MINOR 1)
set(Launcher_VERSION_MAJOR 6)
set(Launcher_VERSION_MINOR 0)
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
set(Launcher_VERSION_NAME4 "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.0.0")
@ -145,6 +195,10 @@ set(Launcher_BUILD_TIMESTAMP "${TODAY}")
################################ 3rd Party Libs ################################
if(NOT Launcher_FORCE_BUNDLED_LIBS)
find_package(ZLIB QUIET)
endif()
# Find the required Qt parts
include(QtVersionlessBackport)
if(Launcher_QT_VERSION_MAJOR EQUAL 5)
@ -246,13 +300,11 @@ if(UNIX AND APPLE)
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
elseif(UNIX)
include(KDEInstallDirs)
set(BINARY_DEST_DIR "bin")
set(LIBRARY_DEST_DIR "lib${LIB_SUFFIX}")
set(JARS_DEST_DIR "share/${Launcher_APP_BINARY_NAME}")
set(LAUNCHER_DESKTOP_DEST_DIR "share/applications" CACHE STRING "Path to the desktop file directory")
set(LAUNCHER_METAINFO_DEST_DIR "share/metainfo" CACHE STRING "Path to the metainfo directory")
set(LAUNCHER_ICON_DEST_DIR "share/icons/hicolor/scalable/apps" CACHE STRING "Path to the scalable icon directory")
set(LAUNCHER_MAN_DEST_DIR "share/man/man6" CACHE STRING "Path to the man page directory")
# install as bundle with no dependencies included
set(INSTALL_BUNDLE "nodeps")
@ -260,12 +312,13 @@ elseif(UNIX)
# Set RPATH
SET(Launcher_BINARY_RPATH "$ORIGIN/")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${LAUNCHER_DESKTOP_DEST_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${LAUNCHER_METAINFO_DEST_DIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION ${LAUNCHER_ICON_DEST_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_Desktop} DESTINATION ${KDE_INSTALL_APPDIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_MetaInfo} DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_SVG} DESTINATION "${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps")
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${Launcher_mrpack_MIMEInfo} DESTINATION ${KDE_INSTALL_MIMEDIR})
if(Launcher_ManPage)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION ${LAUNCHER_MAN_DEST_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION "${KDE_INSTALL_MANDIR}/man6")
endif()
# Install basic runner script if component "portable" is selected
@ -305,6 +358,21 @@ add_subdirectory(libraries/systeminfo) # system information library
add_subdirectory(libraries/hoedown) # markdown parser
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
add_subdirectory(libraries/javacheck) # java compatibility checker
if(NOT ZLIB_FOUND)
message(STATUS "Using bundled zlib")
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) # Suppress cmake warnings and allow INTERPROCEDURAL_OPTIMIZATION for zlib
set(SKIP_INSTALL_ALL ON)
add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL)
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib")
set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}")
add_library(ZLIB::ZLIB ALIAS zlibstatic)
set(ZLIB_LIBRARY ZLIB::ZLIB)
set(ZLIB_FOUND true)
find_package(ZLIB REQUIRED)
else()
message(STATUS "Using system zlib")
endif()
if (FORCE_BUNDLED_QUAZIP)
message(STATUS "Using bundled QuaZip")
set(BUILD_SHARED_LIBS 0) # link statically to avoid conflicts.

View File

@ -44,5 +44,28 @@
<string>${MACOSX_SPARKLE_UPDATE_PUBLIC_KEY}</string>
<key>SUFeedURL</key>
<string>${MACOSX_SPARKLE_UPDATE_FEED_URL}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>zip</string>
<string>mrpack</string>
</array>
<key>CFBundleTypeName</key>
<string>Prism Launcher instance</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>TEXT</string>
<string>utxt</string>
<string>TUTX</string>
<string>****</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
</array>
</dict>
</plist>

View File

@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 Lenny McLennington <lenny@sneed.church>
* Copyright (C) 2022 Tayou <tayou@gmx.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
@ -54,12 +55,6 @@
#include "ui/pages/global/APIPage.h"
#include "ui/pages/global/CustomCommandsPage.h"
#include "ui/themes/ITheme.h"
#include "ui/themes/SystemTheme.h"
#include "ui/themes/DarkTheme.h"
#include "ui/themes/BrightTheme.h"
#include "ui/themes/CustomTheme.h"
#ifdef Q_OS_WIN
#include "ui/WinDarkmode.h"
#include <versionhelpers.h>
@ -74,6 +69,8 @@
#include "ui/pagedialog/PageDialog.h"
#include "ui/themes/ThemeManager.h"
#include "ApplicationMessage.h"
#include <iostream>
@ -246,7 +243,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
{{"s", "server"}, "Join the specified server on launch (only valid in combination with --launch)", "address"},
{{"a", "profile"}, "Use the account specified by its profile name (only valid in combination with --launch)", "profile"},
{"alive", "Write a small '" + liveCheckFile + "' file after the launcher starts"},
{{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"}
{{"I", "import"}, "Import instance from specified zip (local path or URL)", "file"},
{"show", "Opens the window for the specified instance (by instance ID)", "show"}
});
parser.addHelpOption();
parser.addVersionOption();
@ -258,6 +256,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_profileToUse = parser.value("profile");
m_liveCheck = parser.isSet("alive");
m_zipToImport = parser.value("import");
m_instanceIdToShowWindowOf = parser.value("show");
// error if --launch is missing with --server or --profile
if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
@ -501,6 +500,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// Theming
m_settings->registerSetting("IconTheme", QString("pe_colored"));
m_settings->registerSetting("ApplicationTheme", QString("system"));
m_settings->registerSetting("BackgroundCat", QString("kitteh"));
// Remembered state
m_settings->registerSetting("LastUsedGroupForNewInstance", QString());
@ -565,7 +565,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// Memory
m_settings->registerSetting({"MinMemAlloc", "MinMemoryAlloc"}, 512);
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, 4096);
m_settings->registerSetting({"MaxMemAlloc", "MaxMemoryAlloc"}, suitableMaxMem());
m_settings->registerSetting("PermGen", 128);
// Java Settings
@ -613,6 +613,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// The cat
m_settings->registerSetting("TheCat", false);
m_settings->registerSetting("ToolbarsLocked", false);
m_settings->registerSetting("InstSortMode", "Name");
m_settings->registerSetting("SelectedInstance", QString());
@ -749,29 +751,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "<> Instance icons intialized.";
}
// Icon themes
{
// TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies!
// set icon theme search path!
auto searchPaths = QIcon::themeSearchPaths();
searchPaths.append("iconthemes");
QIcon::setThemeSearchPaths(searchPaths);
qDebug() << "<> Icon themes initialized.";
}
// Initialize widget themes
{
auto insertTheme = [this](ITheme * theme)
{
m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme)));
};
auto darkTheme = new DarkTheme();
insertTheme(new SystemTheme());
insertTheme(darkTheme);
insertTheme(new BrightTheme());
insertTheme(new CustomTheme(darkTheme, "custom"));
qDebug() << "<> Widget themes initialized.";
}
// Themes
m_themeManager = std::make_unique<ThemeManager>(m_mainWindow);
// initialize and load all instances
{
@ -949,6 +930,12 @@ bool Application::event(QEvent* event) {
m_prevAppState = ev->applicationState();
}
#endif
if (event->type() == QEvent::FileOpen) {
auto ev = static_cast<QFileOpenEvent*>(event);
m_mainWindow->droppedURLs({ ev->url() });
}
return QApplication::event(event);
}
@ -990,6 +977,16 @@ void Application::performMainStartupAction()
return;
}
}
if(!m_instanceIdToShowWindowOf.isEmpty())
{
auto inst = instances()->getInstanceById(m_instanceIdToShowWindowOf);
if(inst)
{
qDebug() << "<> Showing window of instance " << m_instanceIdToShowWindowOf;
showInstanceWindow(inst);
return;
}
}
if(!m_mainWindow)
{
// normal main window
@ -1116,45 +1113,19 @@ std::shared_ptr<JavaInstallList> Application::javalist()
return m_javalist;
}
std::vector<ITheme *> Application::getValidApplicationThemes()
QList<ITheme*> Application::getValidApplicationThemes()
{
std::vector<ITheme *> ret;
auto iter = m_themes.cbegin();
while (iter != m_themes.cend())
{
ret.push_back((*iter).second.get());
iter++;
}
return ret;
return m_themeManager->getValidApplicationThemes();
}
void Application::setApplicationTheme(const QString& name, bool initial)
{
auto systemPalette = qApp->palette();
auto themeIter = m_themes.find(name);
if(themeIter != m_themes.end())
{
auto & theme = (*themeIter).second;
theme->apply(initial);
#ifdef Q_OS_WIN
if (m_mainWindow && IsWindows10OrGreater()) {
if (QString::compare(theme->id(), "dark") == 0) {
WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true);
} else {
WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false);
}
}
#endif
}
else
{
qWarning() << "Tried to set invalid theme:" << name;
}
m_themeManager->setApplicationTheme(name, initial);
}
void Application::setIconTheme(const QString& name)
{
QIcon::setThemeName(name);
m_themeManager->setIconTheme(name);
}
QIcon Application::getThemedIcon(const QString& name)
@ -1623,3 +1594,17 @@ QString Application::getUserAgentUncached()
return BuildConfig.USER_AGENT_UNCACHED;
}
int Application::suitableMaxMem()
{
float totalRAM = (float)Sys::getSystemRam() / (float)Sys::mebibyte;
int maxMemoryAlloc;
// If totalRAM < 6GB, use (totalRAM / 1.5), else 4GB
if (totalRAM < (4096 * 1.5))
maxMemoryAlloc = (int) (totalRAM / 1.5);
else
maxMemoryAlloc = 4096;
return maxMemoryAlloc;
}

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 Tayou <tayou@gmx.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
@ -68,6 +69,7 @@ class BaseDetachedToolFactory;
class TranslationsModel;
class ITheme;
class MCEditTool;
class ThemeManager;
namespace Meta {
class Index;
@ -118,7 +120,7 @@ public:
void setIconTheme(const QString& name);
std::vector<ITheme *> getValidApplicationThemes();
QList<ITheme*> getValidApplicationThemes();
void setApplicationTheme(const QString& name, bool initial);
@ -198,6 +200,8 @@ public:
void ShowGlobalSettings(class QWidget * parent, QString open_page = QString());
int suitableMaxMem();
signals:
void updateAllowedChanged(bool status);
void globalSettingsAboutToOpen();
@ -255,9 +259,9 @@ private:
std::shared_ptr<JavaInstallList> m_javalist;
std::shared_ptr<TranslationsModel> m_translations;
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
std::map<QString, std::unique_ptr<ITheme>> m_themes;
std::unique_ptr<MCEditTool> m_mcedit;
QSet<QString> m_features;
std::unique_ptr<ThemeManager> m_themeManager;
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
@ -299,6 +303,7 @@ public:
QString m_profileToUse;
bool m_liveCheck = false;
QUrl m_zipToImport;
QString m_instanceIdToShowWindowOf;
std::unique_ptr<QFile> logFile;
};

View File

@ -17,13 +17,14 @@
#include <memory>
#include "BaseVersion.h"
class MinecraftInstance;
class QDir;
class QString;
class QObject;
class Task;
class BaseVersion;
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
class BaseInstaller
{
@ -35,7 +36,7 @@ public:
virtual bool add(MinecraftInstance *to);
virtual bool remove(MinecraftInstance *from);
virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersionPtr version, QObject *parent) = 0;
virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersion::Ptr version, QObject *parent) = 0;
protected:
virtual QString id() const = 0;

View File

@ -25,6 +25,7 @@
class BaseVersion
{
public:
using Ptr = std::shared_ptr<BaseVersion>;
virtual ~BaseVersion() {}
/*!
* A string used to identify this version in config files.
@ -54,6 +55,4 @@ public:
};
};
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
Q_DECLARE_METATYPE(BaseVersionPtr)
Q_DECLARE_METATYPE(BaseVersion::Ptr)

View File

@ -40,20 +40,20 @@ BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent)
{
}
BaseVersionPtr BaseVersionList::findVersion(const QString &descriptor)
BaseVersion::Ptr BaseVersionList::findVersion(const QString &descriptor)
{
for (int i = 0; i < count(); i++)
{
if (at(i)->descriptor() == descriptor)
return at(i);
}
return BaseVersionPtr();
return nullptr;
}
BaseVersionPtr BaseVersionList::getRecommended() const
BaseVersion::Ptr BaseVersionList::getRecommended() const
{
if (count() <= 0)
return BaseVersionPtr();
return nullptr;
else
return at(0);
}
@ -66,7 +66,7 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const
if (index.row() > count())
return QVariant();
BaseVersionPtr version = at(index.row());
BaseVersion::Ptr version = at(index.row());
switch (role)
{

View File

@ -70,7 +70,7 @@ public:
virtual bool isLoaded() = 0;
//! Gets the version at the given index.
virtual const BaseVersionPtr at(int i) const = 0;
virtual const BaseVersion::Ptr at(int i) const = 0;
//! Returns the number of versions in the list.
virtual int count() const = 0;
@ -90,13 +90,13 @@ public:
* \return A const pointer to the version with the given descriptor. NULL if
* one doesn't exist.
*/
virtual BaseVersionPtr findVersion(const QString &descriptor);
virtual BaseVersion::Ptr findVersion(const QString &descriptor);
/*!
* \brief Gets the recommended version from this list
* If the list doesn't support recommended versions, this works exactly as getLatestStable
*/
virtual BaseVersionPtr getRecommended() const;
virtual BaseVersion::Ptr getRecommended() const;
/*!
* Sorts the version list.
@ -117,5 +117,5 @@ slots:
* then copies the versions and sets their parents correctly.
* \param versions List of versions whose parents should be set.
*/
virtual void updateListData(QList<BaseVersionPtr> versions) = 0;
virtual void updateListData(QList<BaseVersion::Ptr> versions) = 0;
};

View File

@ -24,13 +24,15 @@ set(CORE_SOURCES
NullInstance.h
MMCZip.h
MMCZip.cpp
MMCStrings.h
MMCStrings.cpp
StringUtils.h
StringUtils.cpp
RuntimeContext.h
# Basic instance manipulation tasks (derived from InstanceTask)
InstanceCreationTask.h
InstanceCreationTask.cpp
InstanceCopyPrefs.h
InstanceCopyPrefs.cpp
InstanceCopyTask.h
InstanceCopyTask.cpp
InstanceImportTask.h
@ -547,9 +549,6 @@ set(ATLAUNCHER_SOURCES
################################ COMPILE ################################
# we need zlib
find_package(ZLIB REQUIRED)
set(LOGIC_SOURCES
${CORE_SOURCES}
${PATHMATCHER_SOURCES}
@ -610,6 +609,7 @@ SET(LAUNCHER_SOURCES
resources/OSX/OSX.qrc
resources/iOS/iOS.qrc
resources/flat/flat.qrc
resources/flat_white/flat_white.qrc
resources/documents/documents.qrc
../${Launcher_Branding_LogoQRC}
@ -657,6 +657,8 @@ SET(LAUNCHER_SOURCES
ui/themes/ITheme.h
ui/themes/SystemTheme.cpp
ui/themes/SystemTheme.h
ui/themes/ThemeManager.cpp
ui/themes/ThemeManager.h
# Processes
LaunchController.h
@ -1072,96 +1074,95 @@ if(INSTALL_BUNDLE STREQUAL "full")
COMPONENT Runtime
)
# Bundle plugins
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
# Image formats
# Image formats
install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
)
install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Icon engines
install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "fontawesome" EXCLUDE
)
install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "fontawesome" EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Platform plugins
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE
)
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE
REGEX "[^2]d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Style plugins
if(EXISTS "${QT_PLUGINS_DIR}/styles")
install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DIRECTORY "${QT_PLUGINS_DIR}/styles"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
)
# Icon engines
install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
DIRECTORY "${QT_PLUGINS_DIR}/styles"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "fontawesome" EXCLUDE
)
# Platform plugins
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE
)
# Style plugins
if(EXISTS "${QT_PLUGINS_DIR}/styles")
install(
DIRECTORY "${QT_PLUGINS_DIR}/styles"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
)
endif()
# TLS plugins (Qt 6 only)
if(EXISTS "${QT_PLUGINS_DIR}/tls")
install(
DIRECTORY "${QT_PLUGINS_DIR}/tls"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
)
endif()
else()
# Image formats
install(
DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "tga|tiff|mng" EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Icon engines
endif()
# TLS plugins (Qt 6 only)
if(EXISTS "${QT_PLUGINS_DIR}/tls")
install(
DIRECTORY "${QT_PLUGINS_DIR}/iconengines"
DIRECTORY "${QT_PLUGINS_DIR}/tls"
CONFIGURATIONS Debug RelWithDebInfo ""
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "fontawesome" EXCLUDE
REGEX "d\\." EXCLUDE
)
install(
DIRECTORY "${QT_PLUGINS_DIR}/tls"
CONFIGURATIONS Release MinSizeRel
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "dd\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Platform plugins
install(
DIRECTORY "${QT_PLUGINS_DIR}/platforms"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "minimal|linuxfb|offscreen" EXCLUDE
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
# Style plugins
if(EXISTS "${QT_PLUGINS_DIR}/styles")
install(
DIRECTORY "${QT_PLUGINS_DIR}/styles"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "d\\." EXCLUDE
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
endif()
# TLS plugins (Qt 6 only)
if(EXISTS "${QT_PLUGINS_DIR}/tls")
install(
DIRECTORY "${QT_PLUGINS_DIR}/tls"
DESTINATION ${PLUGIN_DEST_DIR}
COMPONENT Runtime
REGEX "_debug\\." EXCLUDE
REGEX "\\.dSYM" EXCLUDE
)
endif()
endif()
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/install_prereqs.cmake.in"

View File

@ -44,7 +44,9 @@
#include <QStandardPaths>
#include <QTextStream>
#include <QUrl>
#include "DesktopServices.h"
#include "StringUtils.h"
#if defined Q_OS_WIN32
#include <objbase.h>
@ -79,22 +81,6 @@ namespace fs = std::filesystem;
namespace fs = ghc::filesystem;
#endif
#if defined Q_OS_WIN32
std::wstring toStdString(QString s)
{
return s.toStdWString();
}
#else
std::string toStdString(QString s)
{
return s.toStdString();
}
#endif
namespace FS {
void ensureExists(const QDir& dir)
@ -163,6 +149,9 @@ bool ensureFolderPathExists(QString foldernamepath)
return success;
}
/// @brief Copies a directory and it's contents from src to dest
/// @param offset subdirectory form src to copy to dest
/// @return if there was an error during the filecopy
bool copy::operator()(const QString& offset)
{
using copy_opts = fs::copy_options;
@ -191,7 +180,7 @@ bool copy::operator()(const QString& offset)
auto dst_path = PathCombine(dst, relative_dst_path);
ensureFilePathExists(dst_path);
fs::copy(toStdString(src_path), toStdString(dst_path), opt, err);
fs::copy(StringUtils::toStdString(src_path), StringUtils::toStdString(dst_path), opt, err);
if (err) {
qWarning() << "Failed to copy files:" << QString::fromStdString(err.message());
qDebug() << "Source file:" << src_path;
@ -213,7 +202,7 @@ bool copy::operator()(const QString& offset)
}
// If the root src is not a directory, the previous iterator won't run.
if (!fs::is_directory(toStdString(src)))
if (!fs::is_directory(StringUtils::toStdString(src)))
copy_file(src, "");
return err.value() == 0;
@ -223,7 +212,7 @@ bool deletePath(QString path)
{
std::error_code err;
fs::remove_all(toStdString(path), err);
fs::remove_all(StringUtils::toStdString(path), err);
if (err) {
qWarning() << "Failed to remove files:" << QString::fromStdString(err.message());
@ -414,7 +403,7 @@ bool overrideFolder(QString overwritten_path, QString override_path)
fs::copy_options opt = copy_opts::recursive | copy_opts::overwrite_existing;
// FIXME: hello traveller! Apparently std::copy does NOT overwrite existing files on GNU libstdc++ on Windows?
fs::copy(toStdString(override_path), toStdString(overwritten_path), opt, err);
fs::copy(StringUtils::toStdString(override_path), StringUtils::toStdString(overwritten_path), opt, err);
if (err) {
qCritical() << QString("Failed to apply override from %1 to %2").arg(override_path, overwritten_path);

View File

@ -75,6 +75,7 @@ bool ensureFilePathExists(QString filenamepath);
*/
bool ensureFolderPathExists(QString filenamepath);
/// @brief Copies a directory and it's contents from src to dest
class copy {
public:
copy(const QString& src, const QString& dst)

View File

@ -0,0 +1,135 @@
//
// Created by marcelohdez on 10/22/22.
//
#include "InstanceCopyPrefs.h"
bool InstanceCopyPrefs::allTrue() const
{
return copySaves &&
keepPlaytime &&
copyGameOptions &&
copyResourcePacks &&
copyShaderPacks &&
copyServers &&
copyMods &&
copyScreenshots;
}
// Returns a single RegEx string of the selected folders/files to filter out (ex: ".minecraft/saves|.minecraft/server.dat")
QString InstanceCopyPrefs::getSelectedFiltersAsRegex() const
{
QStringList filters;
if(!copySaves)
filters << "saves";
if(!copyGameOptions)
filters << "options.txt";
if(!copyResourcePacks)
filters << "resourcepacks" << "texturepacks";
if(!copyShaderPacks)
filters << "shaderpacks";
if(!copyServers)
filters << "servers.dat" << "servers.dat_old" << "server-resource-packs";
if(!copyMods)
filters << "coremods" << "mods" << "config";
if(!copyScreenshots)
filters << "screenshots";
// If we have any filters to add, join them as a single regex string to return:
if (!filters.isEmpty()) {
const QString MC_ROOT = "[.]?minecraft/";
// Ensure first filter starts with root, then join other filters with OR regex before root (ex: ".minecraft/saves|.minecraft/mods"):
return MC_ROOT + filters.join("|" + MC_ROOT);
}
return {};
}
// ======= Getters =======
bool InstanceCopyPrefs::isCopySavesEnabled() const
{
return copySaves;
}
bool InstanceCopyPrefs::isKeepPlaytimeEnabled() const
{
return keepPlaytime;
}
bool InstanceCopyPrefs::isCopyGameOptionsEnabled() const
{
return copyGameOptions;
}
bool InstanceCopyPrefs::isCopyResourcePacksEnabled() const
{
return copyResourcePacks;
}
bool InstanceCopyPrefs::isCopyShaderPacksEnabled() const
{
return copyShaderPacks;
}
bool InstanceCopyPrefs::isCopyServersEnabled() const
{
return copyServers;
}
bool InstanceCopyPrefs::isCopyModsEnabled() const
{
return copyMods;
}
bool InstanceCopyPrefs::isCopyScreenshotsEnabled() const
{
return copyScreenshots;
}
// ======= Setters =======
void InstanceCopyPrefs::enableCopySaves(bool b)
{
copySaves = b;
}
void InstanceCopyPrefs::enableKeepPlaytime(bool b)
{
keepPlaytime = b;
}
void InstanceCopyPrefs::enableCopyGameOptions(bool b)
{
copyGameOptions = b;
}
void InstanceCopyPrefs::enableCopyResourcePacks(bool b)
{
copyResourcePacks = b;
}
void InstanceCopyPrefs::enableCopyShaderPacks(bool b)
{
copyShaderPacks = b;
}
void InstanceCopyPrefs::enableCopyServers(bool b)
{
copyServers = b;
}
void InstanceCopyPrefs::enableCopyMods(bool b)
{
copyMods = b;
}
void InstanceCopyPrefs::enableCopyScreenshots(bool b)
{
copyScreenshots = b;
}

View File

@ -0,0 +1,41 @@
//
// Created by marcelohdez on 10/22/22.
//
#pragma once
#include <QStringList>
struct InstanceCopyPrefs {
public:
[[nodiscard]] bool allTrue() const;
[[nodiscard]] QString getSelectedFiltersAsRegex() const;
// Getters
[[nodiscard]] bool isCopySavesEnabled() const;
[[nodiscard]] bool isKeepPlaytimeEnabled() const;
[[nodiscard]] bool isCopyGameOptionsEnabled() const;
[[nodiscard]] bool isCopyResourcePacksEnabled() const;
[[nodiscard]] bool isCopyShaderPacksEnabled() const;
[[nodiscard]] bool isCopyServersEnabled() const;
[[nodiscard]] bool isCopyModsEnabled() const;
[[nodiscard]] bool isCopyScreenshotsEnabled() const;
// Setters
void enableCopySaves(bool b);
void enableKeepPlaytime(bool b);
void enableCopyGameOptions(bool b);
void enableCopyResourcePacks(bool b);
void enableCopyShaderPacks(bool b);
void enableCopyServers(bool b);
void enableCopyMods(bool b);
void enableCopyScreenshots(bool b);
protected: // data
bool copySaves = true;
bool keepPlaytime = true;
bool copyGameOptions = true;
bool copyResourcePacks = true;
bool copyShaderPacks = true;
bool copyServers = true;
bool copyMods = true;
bool copyScreenshots = true;
};

View File

@ -5,15 +5,17 @@
#include "pathmatcher/RegexpMatcher.h"
#include <QtConcurrentRun>
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime)
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs)
{
m_origInstance = origInstance;
m_keepPlaytime = keepPlaytime;
m_keepPlaytime = prefs.isKeepPlaytimeEnabled();
if(!copySaves)
QString filters = prefs.getSelectedFiltersAsRegex();
if (!filters.isEmpty())
{
// Set regex filter:
// FIXME: get this from the original instance type...
auto matcherReal = new RegexpMatcher("[.]?minecraft/saves");
auto matcherReal = new RegexpMatcher(filters);
matcherReal->caseSensitive(false);
m_matcher.reset(matcherReal);
}

View File

@ -1,20 +1,21 @@
#pragma once
#include "tasks/Task.h"
#include "net/NetJob.h"
#include <QUrl>
#include <QFuture>
#include <QFutureWatcher>
#include "settings/SettingsObject.h"
#include "BaseVersion.h"
#include <QUrl>
#include "BaseInstance.h"
#include "BaseVersion.h"
#include "InstanceCopyPrefs.h"
#include "InstanceTask.h"
#include "net/NetJob.h"
#include "settings/SettingsObject.h"
#include "tasks/Task.h"
class InstanceCopyTask : public InstanceTask
{
Q_OBJECT
public:
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime);
explicit InstanceCopyTask(InstancePtr origInstance, const InstanceCopyPrefs& prefs);
protected:
//! Entry point for tasks.
@ -22,7 +23,8 @@ protected:
void copyFinished();
void copyAborted();
private: /* data */
private:
/* data */
InstancePtr m_origInstance;
QFuture<bool> m_copyFuture;
QFutureWatcher<bool> m_copyFutureWatcher;

View File

@ -36,7 +36,7 @@
#include "JavaCommon.h"
#include "java/JavaUtils.h"
#include "ui/dialogs/CustomMessageBox.h"
#include <MMCStrings.h>
#include <QRegularExpression>
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)

View File

@ -1,8 +0,0 @@
#pragma once
#include <QString>
namespace Strings
{
int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
}

View File

@ -1,26 +1,28 @@
#include "MMCStrings.h"
#include "StringUtils.h"
/// If you're wondering where these came from exactly, then know you're not the only one =D
/// TAKEN FROM Qt, because it doesn't expose it intelligently
static inline QChar getNextChar(const QString &s, int location)
static inline QChar getNextChar(const QString& s, int location)
{
return (location < s.length()) ? s.at(location) : QChar();
}
/// TAKEN FROM Qt, because it doesn't expose it intelligently
int Strings::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
int StringUtils::naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs)
{
for (int l1 = 0, l2 = 0; l1 <= s1.count() && l2 <= s2.count(); ++l1, ++l2)
{
int l1 = 0, l2 = 0;
while (l1 <= s1.count() && l2 <= s2.count()) {
// skip spaces, tabs and 0's
QChar c1 = getNextChar(s1, l1);
while (c1.isSpace())
c1 = getNextChar(s1, ++l1);
QChar c2 = getNextChar(s2, l2);
while (c2.isSpace())
c2 = getNextChar(s2, ++l2);
if (c1.isDigit() && c2.isDigit())
{
if (c1.isDigit() && c2.isDigit()) {
while (c1.digitValue() == 0)
c1 = getNextChar(s1, ++l1);
while (c2.digitValue() == 0)
@ -30,11 +32,8 @@ int Strings::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensit
int lookAheadLocation2 = l2;
int currentReturnValue = 0;
// find the last digit, setting currentReturnValue as we go if it isn't equal
for (QChar lookAhead1 = c1, lookAhead2 = c2;
(lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
lookAhead1 = getNextChar(s1, ++lookAheadLocation1),
lookAhead2 = getNextChar(s2, ++lookAheadLocation2))
{
for (QChar lookAhead1 = c1, lookAhead2 = c2; (lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
lookAhead1 = getNextChar(s1, ++lookAheadLocation1), lookAhead2 = getNextChar(s2, ++lookAheadLocation2)) {
bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
if (!is1ADigit && !is2ADigit)
@ -43,14 +42,10 @@ int Strings::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensit
return -1;
if (!is2ADigit)
return 1;
if (currentReturnValue == 0)
{
if (lookAhead1 < lookAhead2)
{
if (currentReturnValue == 0) {
if (lookAhead1 < lookAhead2) {
currentReturnValue = -1;
}
else if (lookAhead1 > lookAhead2)
{
} else if (lookAhead1 > lookAhead2) {
currentReturnValue = 1;
}
}
@ -58,19 +53,24 @@ int Strings::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensit
if (currentReturnValue != 0)
return currentReturnValue;
}
if (cs == Qt::CaseInsensitive)
{
if (cs == Qt::CaseInsensitive) {
if (!c1.isLower())
c1 = c1.toLower();
if (!c2.isLower())
c2 = c2.toLower();
}
int r = QString::localeAwareCompare(c1, c2);
if (r < 0)
return -1;
if (r > 0)
return 1;
l1 += 1;
l2 += 1;
}
// The two strings are the same (02 == 2) so fall back to the normal sort
return QString::compare(s1, s2, cs);
}

32
launcher/StringUtils.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <QString>
namespace StringUtils {
#if defined Q_OS_WIN32
using string = std::wstring;
inline string toStdString(QString s)
{
return s.toStdWString();
}
inline QString fromStdString(string s)
{
return QString::fromStdWString(s);
}
#else
using string = std::string;
inline string toStdString(QString s)
{
return s.toStdString();
}
inline QString fromStdString(string s)
{
return QString::fromStdString(s);
}
#endif
int naturalCompare(const QString& s1, const QString& s2, Qt::CaseSensitivity cs);
} // namespace StringUtils

View File

@ -1,9 +1,10 @@
#include "JavaInstall.h"
#include <MMCStrings.h>
#include "StringUtils.h"
bool JavaInstall::operator<(const JavaInstall &rhs)
{
auto archCompare = Strings::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive);
auto archCompare = StringUtils::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive);
if(archCompare != 0)
return archCompare < 0;
if(id < rhs.id)
@ -14,7 +15,7 @@ bool JavaInstall::operator<(const JavaInstall &rhs)
{
return false;
}
return Strings::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0;
return StringUtils::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0;
}
bool JavaInstall::operator==(const JavaInstall &rhs)

View File

@ -41,7 +41,6 @@
#include "java/JavaInstallList.h"
#include "java/JavaCheckerJob.h"
#include "java/JavaUtils.h"
#include "MMCStrings.h"
#include "minecraft/VersionFilterData.h"
JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent)
@ -73,7 +72,7 @@ void JavaInstallList::load()
}
}
const BaseVersionPtr JavaInstallList::at(int i) const
const BaseVersion::Ptr JavaInstallList::at(int i) const
{
return m_vlist.at(i);
}
@ -122,7 +121,7 @@ BaseVersionList::RoleList JavaInstallList::providesRoles() const
}
void JavaInstallList::updateListData(QList<BaseVersionPtr> versions)
void JavaInstallList::updateListData(QList<BaseVersion::Ptr> versions)
{
beginResetModel();
m_vlist = versions;
@ -137,7 +136,7 @@ void JavaInstallList::updateListData(QList<BaseVersionPtr> versions)
m_loadTask.reset();
}
bool sortJavas(BaseVersionPtr left, BaseVersionPtr right)
bool sortJavas(BaseVersion::Ptr left, BaseVersion::Ptr right)
{
auto rleft = std::dynamic_pointer_cast<JavaInstall>(right);
auto rright = std::dynamic_pointer_cast<JavaInstall>(left);
@ -210,11 +209,11 @@ void JavaListLoadTask::javaCheckerFinished()
}
}
QList<BaseVersionPtr> javas_bvp;
QList<BaseVersion::Ptr> javas_bvp;
for (auto java : candidates)
{
//qDebug() << java->id << java->arch << " at " << java->path;
BaseVersionPtr bp_java = std::dynamic_pointer_cast<BaseVersion>(java);
BaseVersion::Ptr bp_java = std::dynamic_pointer_cast<BaseVersion>(java);
if (bp_java)
{

View File

@ -42,7 +42,7 @@ public:
Task::Ptr getLoadTask() override;
bool isLoaded() override;
const BaseVersionPtr at(int i) const override;
const BaseVersion::Ptr at(int i) const override;
int count() const override;
void sortVersions() override;
@ -50,7 +50,7 @@ public:
RoleList providesRoles() const override;
public slots:
void updateListData(QList<BaseVersionPtr> versions) override;
void updateListData(QList<BaseVersion::Ptr> versions) override;
protected:
void load();
@ -59,7 +59,7 @@ protected:
protected:
Status m_status = Status::NotDone;
shared_qobject_ptr<JavaListLoadTask> m_loadTask;
QList<BaseVersionPtr> m_vlist;
QList<BaseVersion::Ptr> m_vlist;
};
class JavaListLoadTask : public Task

View File

@ -439,19 +439,28 @@ QList<QString> JavaUtils::FindJavaPaths()
javas.append(FS::PathCombine(prefix, "bin/java"));
}
};
// java installed in a snap is installed in the standard directory, but underneath $SNAP
auto snap = qEnvironmentVariable("SNAP");
auto scanJavaDirs = [&](const QString & dirPath)
{
scanJavaDir(dirPath);
if (!snap.isNull()) {
scanJavaDir(snap + dirPath);
}
};
// oracle RPMs
scanJavaDir("/usr/java");
scanJavaDirs("/usr/java");
// general locations used by distro packaging
scanJavaDir("/usr/lib/jvm");
scanJavaDir("/usr/lib64/jvm");
scanJavaDir("/usr/lib32/jvm");
scanJavaDirs("/usr/lib/jvm");
scanJavaDirs("/usr/lib64/jvm");
scanJavaDirs("/usr/lib32/jvm");
// javas stored in Prism Launcher's folder
scanJavaDir("java");
scanJavaDirs("java");
// manually installed JDKs in /opt
scanJavaDir("/opt/jdk");
scanJavaDir("/opt/jdks");
scanJavaDirs("/opt/jdk");
scanJavaDirs("/opt/jdks");
// flatpak
scanJavaDir("/app/jdk");
scanJavaDirs("/app/jdk");
javas = addJavasFromEnv(javas);
javas.removeDuplicates();
return javas;

View File

@ -1,5 +1,6 @@
#include "JavaVersion.h"
#include <MMCStrings.h>
#include "StringUtils.h"
#include <QRegularExpression>
#include <QString>
@ -98,12 +99,12 @@ bool JavaVersion::operator<(const JavaVersion &rhs)
else if(thisPre && rhsPre)
{
// both are prereleases - use natural compare...
return Strings::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0;
return StringUtils::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0;
}
// neither is prerelease, so they are the same -> this cannot be less than rhs
return false;
}
else return Strings::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0;
else return StringUtils::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0;
}
bool JavaVersion::operator==(const JavaVersion &rhs)

View File

@ -37,7 +37,6 @@
#include "launch/LaunchTask.h"
#include "MessageLevel.h"
#include "MMCStrings.h"
#include "java/JavaChecker.h"
#include "tasks/Task.h"
#include <QDebug>

View File

@ -84,11 +84,14 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(OSX);
Q_INIT_RESOURCE(iOS);
Q_INIT_RESOURCE(flat);
Q_INIT_RESOURCE(flat_white);
return app.exec();
}
case Application::Failed:
return 1;
case Application::Succeeded:
return 0;
default:
return -1;
}
}

View File

@ -24,7 +24,7 @@ Index::Index(QObject *parent)
: QAbstractListModel(parent)
{
}
Index::Index(const QVector<VersionListPtr> &lists, QObject *parent)
Index::Index(const QVector<VersionList::Ptr> &lists, QObject *parent)
: QAbstractListModel(parent), m_lists(lists)
{
for (int i = 0; i < m_lists.size(); ++i)
@ -41,7 +41,7 @@ QVariant Index::data(const QModelIndex &index, int role) const
return QVariant();
}
VersionListPtr list = m_lists.at(index.row());
VersionList::Ptr list = m_lists.at(index.row());
switch (role)
{
case Qt::DisplayRole:
@ -81,9 +81,9 @@ bool Index::hasUid(const QString &uid) const
return m_uids.contains(uid);
}
VersionListPtr Index::get(const QString &uid)
VersionList::Ptr Index::get(const QString &uid)
{
VersionListPtr out = m_uids.value(uid, nullptr);
VersionList::Ptr out = m_uids.value(uid, nullptr);
if(!out)
{
out = std::make_shared<VersionList>(uid);
@ -92,7 +92,7 @@ VersionListPtr Index::get(const QString &uid)
return out;
}
VersionPtr Index::get(const QString &uid, const QString &version)
Version::Ptr Index::get(const QString &uid, const QString &version)
{
auto list = get(uid);
return list->getVersion(version);
@ -105,7 +105,7 @@ void Index::parse(const QJsonObject& obj)
void Index::merge(const std::shared_ptr<Index> &other)
{
const QVector<VersionListPtr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists;
const QVector<VersionList::Ptr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists;
// initial load, no need to merge
if (m_lists.isEmpty())
{
@ -120,7 +120,7 @@ void Index::merge(const std::shared_ptr<Index> &other)
}
else
{
for (const VersionListPtr &list : lists)
for (const VersionList::Ptr &list : lists)
{
if (m_uids.contains(list->uid()))
{
@ -138,7 +138,7 @@ void Index::merge(const std::shared_ptr<Index> &other)
}
}
void Index::connectVersionList(const int row, const VersionListPtr &list)
void Index::connectVersionList(const int row, const VersionList::Ptr &list)
{
connect(list.get(), &VersionList::nameChanged, this, [this, row]()
{

View File

@ -19,20 +19,19 @@
#include <memory>
#include "BaseEntity.h"
#include "meta/VersionList.h"
class Task;
namespace Meta
{
using VersionListPtr = std::shared_ptr<class VersionList>;
using VersionPtr = std::shared_ptr<class Version>;
class Index : public QAbstractListModel, public BaseEntity
{
Q_OBJECT
public:
explicit Index(QObject *parent = nullptr);
explicit Index(const QVector<VersionListPtr> &lists, QObject *parent = nullptr);
explicit Index(const QVector<VersionList::Ptr> &lists, QObject *parent = nullptr);
enum
{
@ -49,21 +48,21 @@ public:
QString localFilename() const override { return "index.json"; }
// queries
VersionListPtr get(const QString &uid);
VersionPtr get(const QString &uid, const QString &version);
VersionList::Ptr get(const QString &uid);
Version::Ptr get(const QString &uid, const QString &version);
bool hasUid(const QString &uid) const;
QVector<VersionListPtr> lists() const { return m_lists; }
QVector<VersionList::Ptr> lists() const { return m_lists; }
public: // for usage by parsers only
void merge(const std::shared_ptr<Index> &other);
void parse(const QJsonObject &obj) override;
private:
QVector<VersionListPtr> m_lists;
QHash<QString, VersionListPtr> m_uids;
QVector<VersionList::Ptr> m_lists;
QHash<QString, VersionList::Ptr> m_uids;
void connectVersionList(const int row, const VersionListPtr &list);
void connectVersionList(const int row, const VersionList::Ptr &list);
};
}

View File

@ -37,11 +37,11 @@ MetadataVersion currentFormatVersion()
static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj)
{
const QVector<QJsonObject> objects = requireIsArrayOf<QJsonObject>(obj, "packages");
QVector<VersionListPtr> lists;
QVector<VersionList::Ptr> lists;
lists.reserve(objects.size());
std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj)
{
VersionListPtr list = std::make_shared<VersionList>(requireString(obj, "uid"));
VersionList::Ptr list = std::make_shared<VersionList>(requireString(obj, "uid"));
list->setName(ensureString(obj, "name", QString()));
return list;
});
@ -49,9 +49,9 @@ static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj)
}
// Version
static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj)
static Version::Ptr parseCommonVersion(const QString &uid, const QJsonObject &obj)
{
VersionPtr version = std::make_shared<Version>(uid, requireString(obj, "version"));
Version::Ptr version = std::make_shared<Version>(uid, requireString(obj, "version"));
version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000);
version->setType(ensureString(obj, "type", QString()));
version->setRecommended(ensureBoolean(obj, QString("recommended"), false));
@ -63,9 +63,9 @@ static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj)
return version;
}
static std::shared_ptr<Version> parseVersionInternal(const QJsonObject &obj)
static Version::Ptr parseVersionInternal(const QJsonObject &obj)
{
VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj);
Version::Ptr version = parseCommonVersion(requireString(obj, "uid"), obj);
version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj),
QString("%1/%2.json").arg(version->uid(), version->version()),
@ -74,12 +74,12 @@ static std::shared_ptr<Version> parseVersionInternal(const QJsonObject &obj)
}
// Version list / package
static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject &obj)
static VersionList::Ptr parseVersionListInternal(const QJsonObject &obj)
{
const QString uid = requireString(obj, "uid");
const QVector<QJsonObject> versionsRaw = requireIsArrayOf<QJsonObject>(obj, "versions");
QVector<VersionPtr> versions;
QVector<Version::Ptr> versions;
versions.reserve(versionsRaw.size());
std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj)
{
@ -88,7 +88,7 @@ static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject &
return version;
});
VersionListPtr list = std::make_shared<VersionList>(uid);
VersionList::Ptr list = std::make_shared<VersionList>(uid);
list->setName(ensureString(obj, "name", QString()));
list->setVersions(versions);
return list;

View File

@ -54,7 +54,7 @@ void Meta::Version::parse(const QJsonObject& obj)
parseVersion(obj, this);
}
void Meta::Version::mergeFromList(const Meta::VersionPtr& other)
void Meta::Version::mergeFromList(const Meta::Version::Ptr& other)
{
if(other->m_providesRecommendations)
{
@ -85,7 +85,7 @@ void Meta::Version::mergeFromList(const Meta::VersionPtr& other)
}
}
void Meta::Version::merge(const VersionPtr &other)
void Meta::Version::merge(const Version::Ptr &other)
{
mergeFromList(other);
if(other->m_data)

View File

@ -30,13 +30,14 @@
namespace Meta
{
using VersionPtr = std::shared_ptr<class Version>;
class Version : public QObject, public BaseVersion, public BaseEntity
{
Q_OBJECT
public: /* con/des */
public:
using Ptr = std::shared_ptr<Version>;
explicit Version(const QString &uid, const QString &version);
virtual ~Version();
@ -78,8 +79,8 @@ public: /* con/des */
return m_data != nullptr;
}
void merge(const VersionPtr &other);
void mergeFromList(const VersionPtr &other);
void merge(const Version::Ptr &other);
void mergeFromList(const Version::Ptr &other);
void parse(const QJsonObject &obj) override;
QString localFilename() const override;
@ -113,4 +114,4 @@ private:
};
}
Q_DECLARE_METATYPE(Meta::VersionPtr)
Q_DECLARE_METATYPE(Meta::Version::Ptr)

View File

@ -40,7 +40,7 @@ bool VersionList::isLoaded()
return BaseEntity::isLoaded();
}
const BaseVersionPtr VersionList::at(int i) const
const BaseVersion::Ptr VersionList::at(int i) const
{
return m_versions.at(i);
}
@ -52,7 +52,7 @@ int VersionList::count() const
void VersionList::sortVersions()
{
beginResetModel();
std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b)
{
return *a.get() < *b.get();
});
@ -66,7 +66,7 @@ QVariant VersionList::data(const QModelIndex &index, int role) const
return QVariant();
}
VersionPtr version = m_versions.at(index.row());
Version::Ptr version = m_versions.at(index.row());
switch (role)
{
@ -129,9 +129,9 @@ QString VersionList::humanReadable() const
return m_name.isEmpty() ? m_uid : m_name;
}
VersionPtr VersionList::getVersion(const QString &version)
Version::Ptr VersionList::getVersion(const QString &version)
{
VersionPtr out = m_lookup.value(version, nullptr);
Version::Ptr out = m_lookup.value(version, nullptr);
if(!out)
{
out = std::make_shared<Version>(m_uid, version);
@ -143,7 +143,7 @@ VersionPtr VersionList::getVersion(const QString &version)
bool VersionList::hasVersion(QString version) const
{
auto ver = std::find_if(m_versions.constBegin(), m_versions.constEnd(),
[&](Meta::VersionPtr const& a){ return a->version() == version; });
[&](Meta::Version::Ptr const& a){ return a->version() == version; });
return (ver != m_versions.constEnd());
}
@ -153,11 +153,11 @@ void VersionList::setName(const QString &name)
emit nameChanged(name);
}
void VersionList::setVersions(const QVector<VersionPtr> &versions)
void VersionList::setVersions(const QVector<Version::Ptr> &versions)
{
beginResetModel();
m_versions = versions;
std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
std::sort(m_versions.begin(), m_versions.end(), [](const Version::Ptr &a, const Version::Ptr &b)
{
return a->rawTime() > b->rawTime();
});
@ -168,7 +168,7 @@ void VersionList::setVersions(const QVector<VersionPtr> &versions)
}
// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; });
auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const Version::Ptr &ptr) { return ptr->type() == "release"; });
m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt;
endResetModel();
}
@ -179,7 +179,7 @@ void VersionList::parse(const QJsonObject& obj)
}
// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b)
static const Meta::Version::Ptr &getBetterVersion(const Meta::Version::Ptr &a, const Meta::Version::Ptr &b)
{
if(!a)
return b;
@ -194,7 +194,7 @@ static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const
return (a->type() == "release" ? a : b);
}
void VersionList::mergeFromIndex(const VersionListPtr &other)
void VersionList::mergeFromIndex(const VersionList::Ptr &other)
{
if (m_name != other->m_name)
{
@ -202,7 +202,7 @@ void VersionList::mergeFromIndex(const VersionListPtr &other)
}
}
void VersionList::merge(const VersionListPtr &other)
void VersionList::merge(const VersionList::Ptr &other)
{
if (m_name != other->m_name)
{
@ -216,7 +216,7 @@ void VersionList::merge(const VersionListPtr &other)
{
qWarning() << "Empty list loaded ...";
}
for (const VersionPtr &version : other->m_versions)
for (const Version::Ptr &version : other->m_versions)
{
// we already have the version. merge the contents
if (m_lookup.contains(version->version()))
@ -235,7 +235,7 @@ void VersionList::merge(const VersionListPtr &other)
endResetModel();
}
void VersionList::setupAddedVersion(const int row, const VersionPtr &version)
void VersionList::setupAddedVersion(const int row, const Version::Ptr &version)
{
// FIXME: do not disconnect from everythin, disconnect only the lambdas here
version->disconnect();
@ -244,7 +244,7 @@ void VersionList::setupAddedVersion(const int row, const VersionPtr &version)
connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TypeRole); });
}
BaseVersionPtr VersionList::getRecommended() const
BaseVersion::Ptr VersionList::getRecommended() const
{
return m_recommended;
}

View File

@ -20,10 +20,10 @@
#include <QJsonObject>
#include <memory>
#include "meta/Version.h"
namespace Meta
{
using VersionPtr = std::shared_ptr<class Version>;
using VersionListPtr = std::shared_ptr<class VersionList>;
class VersionList : public BaseVersionList, public BaseEntity
{
@ -33,6 +33,8 @@ class VersionList : public BaseVersionList, public BaseEntity
public:
explicit VersionList(const QString &uid, QObject *parent = nullptr);
using Ptr = std::shared_ptr<VersionList>;
enum Roles
{
UidRole = Qt::UserRole + 100,
@ -43,11 +45,11 @@ public:
Task::Ptr getLoadTask() override;
bool isLoaded() override;
const BaseVersionPtr at(int i) const override;
const BaseVersion::Ptr at(int i) const override;
int count() const override;
void sortVersions() override;
BaseVersionPtr getRecommended() const override;
BaseVersion::Ptr getRecommended() const override;
QVariant data(const QModelIndex &index, int role) const override;
RoleList providesRoles() const override;
@ -65,38 +67,38 @@ public:
}
QString humanReadable() const;
VersionPtr getVersion(const QString &version);
Version::Ptr getVersion(const QString &version);
bool hasVersion(QString version) const;
QVector<VersionPtr> versions() const
QVector<Version::Ptr> versions() const
{
return m_versions;
}
public: // for usage only by parsers
void setName(const QString &name);
void setVersions(const QVector<VersionPtr> &versions);
void merge(const VersionListPtr &other);
void mergeFromIndex(const VersionListPtr &other);
void setVersions(const QVector<Version::Ptr> &versions);
void merge(const VersionList::Ptr &other);
void mergeFromIndex(const VersionList::Ptr &other);
void parse(const QJsonObject &obj) override;
signals:
void nameChanged(const QString &name);
protected slots:
void updateListData(QList<BaseVersionPtr>) override
void updateListData(QList<BaseVersion::Ptr>) override
{
}
private:
QVector<VersionPtr> m_versions;
QHash<QString, VersionPtr> m_lookup;
QVector<Version::Ptr> m_versions;
QHash<QString, Version::Ptr> m_lookup;
QString m_uid;
QString m_name;
VersionPtr m_recommended;
Version::Ptr m_recommended;
void setupAddedVersion(const int row, const VersionPtr &version);
void setupAddedVersion(const int row, const Version::Ptr &version);
};
}
Q_DECLARE_METATYPE(Meta::VersionListPtr)
Q_DECLARE_METATYPE(Meta::VersionList::Ptr)

View File

@ -43,7 +43,6 @@
#include "settings/SettingsObject.h"
#include "Application.h"
#include "MMCStrings.h"
#include "pathmatcher/RegexpMatcher.h"
#include "pathmatcher/MultiMatcher.h"
#include "FileSystem.h"

View File

@ -7,7 +7,7 @@
#include "minecraft/PackProfile.h"
#include "settings/INISettingsObject.h"
VanillaCreationTask::VanillaCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loader_version)
VanillaCreationTask::VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version)
: InstanceCreationTask(), m_version(std::move(version)), m_using_loader(true), m_loader(std::move(loader)), m_loader_version(std::move(loader_version))
{}

View File

@ -7,16 +7,16 @@
class VanillaCreationTask final : public InstanceCreationTask {
Q_OBJECT
public:
VanillaCreationTask(BaseVersionPtr version) : InstanceCreationTask(), m_version(std::move(version)) {}
VanillaCreationTask(BaseVersionPtr version, QString loader, BaseVersionPtr loader_version);
VanillaCreationTask(BaseVersion::Ptr version) : InstanceCreationTask(), m_version(std::move(version)) {}
VanillaCreationTask(BaseVersion::Ptr version, QString loader, BaseVersion::Ptr loader_version);
bool createInstance() override;
private:
// Version to update to / create of the instance.
BaseVersionPtr m_version;
BaseVersion::Ptr m_version;
bool m_using_loader = false;
QString m_loader;
BaseVersionPtr m_loader_version;
BaseVersion::Ptr m_loader_version;
};

View File

@ -71,5 +71,7 @@ void VerifyJavaInstall::executeTask() {
{
emit logLine(tr("Java version %1").arg(major), MessageLevel::Error);
}
emit logLine(tr("Go to instance Java settings to change your Java version or disable the Java compatibility check if you know what you're doing."), MessageLevel::Error);
emitFailed(QString("Incompatible Java major version"));
}

View File

@ -36,7 +36,7 @@ LocalModUpdateTask::LocalModUpdateTask(QDir index_dir, ModPlatform::IndexedPack&
}
#ifdef Q_OS_WIN32
SetFileAttributesA(index_dir.path().toStdString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
#endif
}

View File

@ -39,7 +39,7 @@
#include <QList>
#include <list>
#include "Version.h"
#include "../Version.h"
#include "net/NetJob.h"
namespace ModPlatform {

View File

@ -58,7 +58,7 @@
namespace ATLauncher {
static Meta::VersionPtr getComponentVersion(const QString& uid, const QString& version);
static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version);
PackInstallTask::PackInstallTask(UserInteractionSupport *support, QString packName, QString version, InstallMode installMode)
{
@ -1037,7 +1037,7 @@ void PackInstallTask::install()
emitSucceeded();
}
static Meta::VersionPtr getComponentVersion(const QString& uid, const QString& version)
static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version)
{
auto vlist = APPLICATION->metadataIndex()->get(uid);
if (!vlist)

View File

@ -68,7 +68,7 @@ public:
* Requests a user interaction to select a component version from a given version list
* and constrained to a given Minecraft version.
*/
virtual QString chooseVersion(Meta::VersionListPtr vlist, QString minecraftVersion) = 0;
virtual QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) = 0;
/**
* Requests a user interaction to display a message.
@ -137,8 +137,8 @@ private:
QString archivePath;
QStringList jarmods;
Meta::VersionPtr minecraftVersion;
QMap<QString, Meta::VersionPtr> componentsToInstall;
Meta::Version::Ptr minecraftVersion;
QMap<QString, Meta::Version::Ptr> componentsToInstall;
QFuture<std::optional<QStringList>> m_extractFuture;
QFutureWatcher<std::optional<QStringList>> m_extractFutureWatcher;

View File

@ -372,13 +372,20 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
auto results = m_mod_id_resolver->getResults();
// first check for blocked mods
QString text;
QList<QUrl> urls;
QList<BlockedMod> blocked_mods;
auto anyBlocked = false;
for (const auto& result : results.files.values()) {
if (!result.resolved || result.url.isEmpty()) {
text += QString("%1: <a href='%2'>%2</a><br/>").arg(result.fileName, result.websiteUrl);
urls.append(QUrl(result.websiteUrl));
BlockedMod blocked_mod;
blocked_mod.name = result.fileName;
blocked_mod.websiteUrl = result.websiteUrl;
blocked_mod.hash = result.hash;
blocked_mod.matched = false;
blocked_mod.localPath = "";
blocked_mods.append(blocked_mod);
anyBlocked = true;
}
}
@ -388,11 +395,12 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked mods found"),
tr("The following mods were blocked on third party launchers.<br/>"
"You will need to manually download them and add them to the modpack"),
text,
urls);
blocked_mods);
message_dialog->setModal(true);
if (message_dialog->exec()) {
qDebug() << "Post dialog blocked mods list: " << blocked_mods;
copyBlockedMods(blocked_mods);
setupDownloadJob(loop);
} else {
m_mod_id_resolver.reset();
@ -404,6 +412,38 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
}
}
/// @brief copy the matched blocked mods to the instance staging area
/// @param blocked_mods list of the blocked mods and their matched paths
void FlameCreationTask::copyBlockedMods(QList<BlockedMod> const& blocked_mods)
{
setStatus(tr("Copying Blocked Mods..."));
setAbortable(false);
int i = 0;
int total = blocked_mods.length();
setProgress(i, total);
for (auto const& mod : blocked_mods) {
if (!mod.matched) {
qDebug() << mod.name << "was not matched to a local file, skipping copy";
continue;
}
auto dest_path = FS::PathCombine(m_stagingPath, "minecraft", "mods", mod.name);
setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));
qDebug() << "Will try to copy" << mod.localPath << "to" << dest_path;
if (!FS::copy(mod.localPath, dest_path)()) {
qDebug() << "Copy of" << mod.localPath << "to" << dest_path << "Failed";
}
i++;
setProgress(i, total);
}
setAbortable(true);
}
void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
{
m_files_job = new NetJob(tr("Mod download"), APPLICATION->network());
@ -449,7 +489,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
m_files_job.reset();
setError(reason);
});
connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setProgress(current, total); });
connect(m_files_job.get(), &NetJob::progress, this, &FlameCreationTask::setProgress);
connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit);
setStatus(tr("Downloading mods..."));

View File

@ -10,6 +10,8 @@
#include "net/NetJob.h"
#include "ui/dialogs/BlockedModsDialog.h"
class FlameCreationTask final : public InstanceCreationTask {
Q_OBJECT
@ -29,6 +31,7 @@ class FlameCreationTask final : public InstanceCreationTask {
private slots:
void idResolverSucceeded(QEventLoop&);
void setupDownloadJob(QEventLoop&);
void copyBlockedMods(QList<BlockedMod> const& blocked_mods);
private:
QWidget* m_parent = nullptr;

View File

@ -4,6 +4,7 @@
#include <QFile>
#include "FileSystem.h"
#include "StringUtils.h"
#include <MurmurHash2.h>
@ -35,6 +36,18 @@ Hasher::Ptr createFlameHasher(QString file_path)
return new FlameHasher(file_path);
}
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider)
{
return new BlockedModHasher(file_path, provider);
}
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider, QString type)
{
auto hasher = new BlockedModHasher(file_path, provider);
hasher->useHashType(type);
return hasher;
}
void ModrinthHasher::executeTask()
{
QFile file(m_path);
@ -66,7 +79,7 @@ void FlameHasher::executeTask()
// CF-specific
auto should_filter_out = [](char c) { return (c == 9 || c == 10 || c == 13 || c == 32); };
std::ifstream file_stream(m_path.toStdString(), std::ifstream::binary);
std::ifstream file_stream(StringUtils::toStdString(m_path), std::ifstream::binary);
// TODO: This is very heavy work, but apparently QtConcurrent can't use move semantics, so we can't boop this to another thread.
// How do we make this non-blocking then?
m_hash = QString::number(MurmurHash2(std::move(file_stream), 4 * MiB, should_filter_out));
@ -78,4 +91,50 @@ void FlameHasher::executeTask()
}
}
BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::Provider provider)
: Hasher(file_path), provider(provider) {
setObjectName(QString("BlockedModHasher: %1").arg(file_path));
hash_type = ProviderCaps.hashType(provider).first();
}
void BlockedModHasher::executeTask()
{
QFile file(m_path);
try {
file.open(QFile::ReadOnly);
} catch (FS::FileSystemException& e) {
qCritical() << QString("Failed to open JAR file in %1").arg(m_path);
qCritical() << QString("Reason: ") << e.cause();
emitFailed("Failed to open file for hashing.");
return;
}
m_hash = ProviderCaps.hash(provider, &file, hash_type);
file.close();
if (m_hash.isEmpty()) {
emitFailed("Empty hash!");
} else {
emitSucceeded();
}
}
QStringList BlockedModHasher::getHashTypes() {
return ProviderCaps.hashType(provider);
}
bool BlockedModHasher::useHashType(QString type) {
auto types = ProviderCaps.hashType(provider);
if (types.contains(type)) {
hash_type = type;
return true;
}
qDebug() << "Bad hash type " << type << " for provider";
return false;
}
} // namespace Hashing

View File

@ -40,8 +40,23 @@ class ModrinthHasher : public Hasher {
void executeTask() override;
};
class BlockedModHasher : public Hasher {
public:
BlockedModHasher(QString file_path, ModPlatform::Provider provider);
void executeTask() override;
QStringList getHashTypes();
bool useHashType(QString type);
private:
ModPlatform::Provider provider;
QString hash_type;
};
Hasher::Ptr createHasher(QString file_path, ModPlatform::Provider provider);
Hasher::Ptr createFlameHasher(QString file_path);
Hasher::Ptr createModrinthHasher(QString file_path);
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider);
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider, QString type);
} // namespace Hashing

View File

@ -176,8 +176,6 @@ void PackInstallTask::resolveMods()
void PackInstallTask::onResolveModsSucceeded()
{
QString text;
QList<QUrl> urls;
auto anyBlocked = false;
Flame::Manifest results = m_mod_id_resolver_task->getResults();
@ -191,11 +189,16 @@ void PackInstallTask::onResolveModsSucceeded()
// First check for blocked mods
if (!results_file.resolved || results_file.url.isEmpty()) {
QString type(local_file.type);
type[0] = type[0].toUpper();
text += QString("%1: %2 - <a href='%3'>%3</a><br/>").arg(type, local_file.name, results_file.websiteUrl);
urls.append(QUrl(results_file.websiteUrl));
BlockedMod blocked_mod;
blocked_mod.name = local_file.name;
blocked_mod.websiteUrl = results_file.websiteUrl;
blocked_mod.hash = results_file.hash;
blocked_mod.matched = false;
blocked_mod.localPath = "";
m_blocked_mods.append(blocked_mod);
anyBlocked = true;
} else {
local_file.url = results_file.url.toString();
@ -210,13 +213,16 @@ void PackInstallTask::onResolveModsSucceeded()
auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked files found"),
tr("The following files are not available for download in third party launchers.<br/>"
"You will need to manually download them and add them to the instance."),
text,
urls);
m_blocked_mods);
if (message_dialog->exec() == QDialog::Accepted)
if (message_dialog->exec() == QDialog::Accepted) {
qDebug() << "Post dialog blocked mods list: " << m_blocked_mods;
createInstance();
else
}
else {
abort();
}
} else {
createInstance();
}
@ -320,6 +326,9 @@ void PackInstallTask::downloadPack()
void PackInstallTask::onModDownloadSucceeded()
{
m_net_job.reset();
if (!m_blocked_mods.isEmpty()) {
copyBlockedMods();
}
emitSucceeded();
}
@ -343,4 +352,35 @@ void PackInstallTask::onModDownloadFailed(QString reason)
emitFailed(reason);
}
/// @brief copy the matched blocked mods to the instance staging area
void PackInstallTask::copyBlockedMods()
{
setStatus(tr("Copying Blocked Mods..."));
setAbortable(false);
int i = 0;
int total = m_blocked_mods.length();
setProgress(i, total);
for (auto const& mod : m_blocked_mods) {
if (!mod.matched) {
qDebug() << mod.name << "was not matched to a local file, skipping copy";
continue;
}
auto dest_path = FS::PathCombine(m_stagingPath, ".minecraft", "mods", mod.name);
setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));
qDebug() << "Will try to copy" << mod.localPath << "to" << dest_path;
if (!FS::copy(mod.localPath, dest_path)()) {
qDebug() << "Copy of" << mod.localPath << "to" << dest_path << "Failed";
}
i++;
setProgress(i, total);
}
setAbortable(true);
}
} // namespace ModpacksCH

View File

@ -43,6 +43,7 @@
#include "QObjectPtr.h"
#include "modplatform/flame/FileResolvingTask.h"
#include "net/NetJob.h"
#include "ui/dialogs/BlockedModsDialog.h"
#include <QWidget>
@ -76,6 +77,7 @@ private:
void resolveMods();
void createInstance();
void downloadPack();
void copyBlockedMods();
private:
NetJob::Ptr m_net_job = nullptr;
@ -90,6 +92,7 @@ private:
Version m_version;
QMap<QString, QString> m_files_to_copy;
QList<BlockedMod> m_blocked_mods;
//FIXME: nuke
QWidget* m_parent;

View File

@ -140,7 +140,7 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion
for (auto file_iter : files) {
File indexed_file;
auto parent = Json::requireObject(file_iter);
auto is_primary = Json::ensureBoolean(parent, "primary", false);
auto is_primary = Json::ensureBoolean(parent, (const QString)QStringLiteral("primary"), false);
if (!is_primary) {
auto filename = Json::ensureString(parent, "filename");
// Checking suffix here is fine because it's the response from Modrinth,

View File

@ -22,10 +22,14 @@
#include <QDir>
#include <QObject>
#include <toml++/toml.h>
#include "FileSystem.h"
#include "StringUtils.h"
#include "minecraft/mod/Mod.h"
#include "modplatform/ModIndex.h"
#include <toml++/toml.h>
namespace Packwiz {
auto getRealIndexName(QDir& index_dir, QString normalized_fname, bool should_find_match) -> QString
@ -63,22 +67,22 @@ static inline auto indexFileName(QString const& mod_slug) -> QString
static ModPlatform::ProviderCapabilities ProviderCaps;
// Helper functions for extracting data from the TOML file
auto stringEntry(toml::table table, const std::string entry_name) -> QString
auto stringEntry(toml::table table, QString entry_name) -> QString
{
auto node = table[entry_name];
auto node = table[StringUtils::toStdString(entry_name)];
if (!node) {
qCritical() << QString::fromStdString("Failed to read str property '" + entry_name + "' in mod metadata.");
qCritical() << "Failed to read str property '" + entry_name + "' in mod metadata.";
return {};
}
return QString::fromStdString(node.value_or(""));
return node.value_or("");
}
auto intEntry(toml::table table, const std::string entry_name) -> int
auto intEntry(toml::table table, QString entry_name) -> int
{
auto node = table[entry_name];
auto node = table[StringUtils::toStdString(entry_name)];
if (!node) {
qCritical() << QString::fromStdString("Failed to read int property '" + entry_name + "' in mod metadata.");
qCritical() << "Failed to read int property '" + entry_name + "' in mod metadata.";
return {};
}
@ -145,6 +149,8 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod)
// they want to do!
if (index_file.exists()) {
index_file.remove();
} else {
FS::ensureFilePathExists(index_file.fileName());
}
if (!index_file.open(QIODevice::ReadWrite)) {
@ -228,14 +234,14 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod
toml::table table;
#if TOML_EXCEPTIONS
try {
table = toml::parse_file(index_dir.absoluteFilePath(real_fname).toStdString());
table = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname)));
} catch (const toml::parse_error& err) {
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
qWarning() << "Reason: " << QString(err.what());
return {};
}
#else
table = toml::parse_file(index_dir.absoluteFilePath(real_fname).toStdString());
table = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname)));
if (!table) {
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
qWarning() << "Reason: " << QString(table.error().what());

View File

@ -24,7 +24,6 @@
#include <QUrl>
#include <QVariant>
struct toml_table_t;
class QDir;
// Mod from launcher/minecraft/mod/Mod.h
@ -34,9 +33,6 @@ namespace Packwiz {
auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool should_match = false) -> QString;
auto stringEntry(toml_table_t* parent, const char* entry_name) -> QString;
auto intEntry(toml_table_t* parent, const char* entry_name) -> int;
class V1 {
public:
struct Mod {

View File

@ -242,7 +242,7 @@ void HttpMetaCache::Load()
foo->local_changed_timestamp = Json::ensureDouble(element_obj, "last_changed_timestamp");
foo->remote_changed_timestamp = Json::ensureString(element_obj, "remote_changed_timestamp");
foo->makeEternal(Json::ensureBoolean(element_obj, "eternal", false));
foo->makeEternal(Json::ensureBoolean(element_obj, (const QString)QStringLiteral("eternal"), false));
if (!foo->isEternal()) {
foo->current_age = Json::ensureDouble(element_obj, "current_age");
foo->max_age = Json::ensureDouble(element_obj, "max_age");

View File

@ -34,5 +34,10 @@
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
<file>scalable/worlds.svg</file>
<file>scalable/delete.svg</file>
<file>scalable/tag.svg</file>
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Calque_1"
x="0px"
y="0px"
viewBox="0 0 32 32"
enable-background="new 0 0 32 32"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs13" />
<rect
fill-rule="evenodd"
clip-rule="evenodd"
fill="none"
width="32"
height="32"
id="rect2" />
<path
fill="#B6B5B6"
d="M30,28H2c-1.1,0-2-0.9-2-2V8c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v18C32,27.1,31.1,28,30,28z"
id="path4" />
<path
fill="#FBFBFB"
d="M30,27H2c-1.1,0-2-0.9-2-2V8c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v17C32,26.1,31.1,27,30,27z"
id="path6" />
<g
id="g19002"
transform="matrix(0.61347029,0,0,0.61364877,6.1844752,6.6215364)"
style="stroke-width:1.62983"><g
id="g9250"
transform="matrix(0.97069724,0,0,1.1763237,-0.10468178,-4.8181425)"
style="stroke-width:1.52524"><path
style="color:#000000;fill:#585858;fill-opacity:1;stroke-width:1.52524;stroke-linecap:round;-inkscape-stroke:none"
d="m 6.7324219,10.556641 v 0.820312 15.230469 c 0,1.649975 1.3558838,3.003906 3.0058594,3.003906 H 23.443359 c 1.649976,0 3.00586,-1.353931 3.00586,-3.003906 V 10.556641 Z m 1.6386719,1.638672 H 24.810547 v 14.412109 c 0,0.764319 -0.602868,1.365234 -1.367188,1.365234 H 9.7382813 c -0.7643194,0 -1.3671876,-0.600915 -1.3671875,-1.365234 z"
id="rect2395" /><path
id="path8117"
style="fill:none;stroke:#585858;stroke-width:2.28785;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
d="m 13.353409,15.259086 v 9.466797 z m 6.474609,0.183594 v 9.466797 z" /></g><path
style="fill:none;fill-opacity:1;stroke:#585858;stroke-width:2.44476;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 3.0114815,4.6293617 H 28.988519"
id="path9281" /><path
style="fill:none;stroke:#585858;stroke-width:2.44476;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 10.431403,3.4038387 H 21.568596"
id="path9283" /></g></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Calque_1"
x="0px"
y="0px"
viewBox="0 0 32 32"
enable-background="new 0 0 32 32"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs7209" />
<rect
fill-rule="evenodd"
clip-rule="evenodd"
fill="none"
width="32"
height="32"
id="rect7195" />
<path
fill="#B6B5B6"
d="M30,28.4H2c-1.1,0-2-0.9-2-2v-18c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v18C32,27.5,31.1,28.4,30,28.4z"
id="path7197" />
<path
fill="#FBFBFB"
d="M30,27.4H2c-1.1,0-2-0.9-2-2v-17c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v17C32,26.5,31.1,27.4,30,27.4z"
id="path7199" />
<g
id="_x36__6_">
<g
id="g7203">
<path
fill="#585858"
d="M22,11.4h-7c0-1.1-0.9-2-2-2h-3c-1.1,0-2,0.9-2,2v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-10 C24,12.3,23.1,11.4,22,11.4z M23,23.4c0,0.6-0.4,1-1,1H10c-0.6,0-1-0.4-1-1v-8h14V23.4z M23,14.4H9v-3c0-0.6,0.4-1,1-1h3 c0.6,0,1,0.4,1,1v1h8c0.6,0,1,0.4,1,1V14.4z"
id="path7201" />
</g>
</g>
<g
id="g7346"
transform="matrix(0.60195183,0,0,0.60195183,6.3687707,6.8734131)"
style="fill:#585858;fill-opacity:1;stroke-width:1.66127"><g
id="_x36__4_"
style="fill:#585858;fill-opacity:1;stroke-width:1.66127">
<g
id="g849"
style="fill:#585858;fill-opacity:1;stroke-width:1.66127">
</g>
</g><g
id="g1052"
transform="rotate(-90,15.237227,22.237227)"
style="fill:#585858;fill-opacity:1;stroke-width:1.66127"><g
id="_x37__7_"
style="fill:#585858;fill-opacity:1;stroke-width:1.66127">
<g
id="g1038"
style="fill:#585858;fill-opacity:1;stroke-width:1.66127">
<path
d="m 21.7,25.4 c -0.4,-0.4 -1,-0.4 -1.4,0 L 17,28.7 V 15 c 0,-0.6 -0.4,-1 -1,-1 -0.6,0 -1,0.4 -1,1 v 13.6 l -3.3,-3.2 c -0.4,-0.4 -1,-0.4 -1.4,0 -0.4,0.4 -0.4,1 0,1.4 l 4.9,4.9 c 0.2,0.2 0.5,0.3 0.8,0.3 0.3,0 0.6,-0.1 0.8,-0.3 l 4.9,-4.9 c 0.4,-0.4 0.4,-1 0,-1.4 z"
id="path1036"
style="fill:#585858;fill-opacity:1;stroke-width:2.62304" />
</g>
</g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
id="Calque_1"
x="0px"
y="0px"
viewBox="0 0 32.099998 32"
enable-background="new 0 0 32 32"
xml:space="preserve"
width="32.099998"
height="32"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs45" />
<rect
fill-rule="evenodd"
clip-rule="evenodd"
fill="none"
width="32"
height="32"
id="rect1776"
x="0.1"
y="0" /><path
fill="#b6b5b6"
d="M 30,28.4 H 2 c -1.1,0 -2,-0.9 -2,-2 v -18 c 0,-1.1 0.9,-2 2,-2 h 28 c 1.1,0 2,0.9 2,2 v 18 c 0,1.1 -0.9,2 -2,2 z"
id="path1778" /><path
fill="#fbfbfb"
d="M 30,27.4 H 2 c -1.1,0 -2,-0.9 -2,-2 v -17 c 0,-1.1 0.9,-2 2,-2 h 28 c 1.1,0 2,0.9 2,2 v 17 c 0,1.1 -0.9,2 -2,2 z"
id="path1780" /><path
id="path11889"
style="color:#000000;fill:#585858;fill-opacity:1;stroke-width:0.999994;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill"
d="m 11.520289,8.4637512 c -0.06474,-0.00183 -0.129661,-0.00125 -0.194234,0.00117 C 9.7763279,8.5230552 8.3049,9.7900155 8.3049,11.461507 v 10.877094 c -6e-7,2.228655 2.616628,3.738089 4.545774,2.622156 l 9.398109,-5.436205 c 1.928423,-1.115516 1.928423,-4.133479 0,-5.248993 L 12.850674,8.839348 C 12.428673,8.595238 11.973493,8.4765655 11.520289,8.4637512 Z m -0.184873,1.2309276 c 0.307885,1.456e-4 0.612521,0.080796 0.882242,0.2363567 a 0.89871379,0.89871379 0 0 0 0.0012,0 l 9.398109,5.4362075 c 1.143234,0.659415 1.143234,2.406201 0,3.065618 l -9.398109,5.436206 a 0.89871379,0.89871379 0 0 0 -0.0012,0 C 11.076744,24.528497 9.5659235,23.656375 9.56625,22.338599 V 11.461504 c 3.043e-4,-0.851902 0.622381,-1.5925143 1.461434,-1.7399133 0.102209,-0.018038 0.205103,-0.026958 0.307732,-0.026912 z" /></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -93,4 +93,36 @@
inkscape:label="beak" />
</g>
</g>
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
</g>
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:title>Prism Launcher Logo</dc:title>
<dc:date>19/10/2022</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Prism Launcher</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
</cc:Agent>
</dc:contributor>
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
<dc:rights>
<cc:Agent>
<dc:title>CC BY-SA 4.0</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>Prism Launcher</dc:title>
</cc:Agent>
</dc:publisher>
</cc:Work>
</rdf:RDF>
</metadata>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
id="Calque_1"
x="0px"
y="0px"
viewBox="0 0 24 24"
enable-background="new 0 0 24 24"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs11868" />
<rect
fill="none"
width="24"
height="24"
id="rect11854" />
<g
id="g15058"
transform="matrix(1.2018036,0,0,1.2018036,9.1890033,-5.9659463)"
style="stroke-width:0.832083"><path
style="fill:#cccccc;fill-opacity:1;stroke:#585858;stroke-width:0.832083;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="m -4.635309,18.83508 -1.6867847,4.775149 4.7751492,-1.686784 z"
id="path14640" /><path
style="fill:#f2f2f2;fill-opacity:1;stroke:#585858;stroke-width:0.832083;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="M 7.6468491,6.2880897 -3.1410372,17.075975 0.21216023,20.429172 11.000046,9.6412872 Z"
id="rect291" /></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Calque_1"
x="0px"
y="0px"
viewBox="0 0 32 32"
enable-background="new 0 0 32 32"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs13" />
<rect
fill-rule="evenodd"
clip-rule="evenodd"
fill="none"
width="32"
height="32"
id="rect2" />
<path
fill="#B6B5B6"
d="M30,28H2c-1.1,0-2-0.9-2-2V8c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v18C32,27.1,31.1,28,30,28z"
id="path4" />
<path
fill="#FBFBFB"
d="M30,27H2c-1.1,0-2-0.9-2-2V8c0-1.1,0.9-2,2-2h28c1.1,0,2,0.9,2,2v17C32,26.1,31.1,27,30,27z"
id="path6" />
<path
style="fill:none;fill-opacity:1;stroke:#585858;stroke-width:1;stroke-dasharray:none;stroke-opacity:1"
d="m 15.90395,8.3243241 -8.037878,0.04174 -0.04175,8.0378789 8.752925,8.079624 7.406322,-7.406322 z m -3.366509,2.6932089 c 1.114988,0 2.019906,0.904918 2.019906,2.019906 0,1.114988 -0.904918,2.019906 -2.019906,2.019906 -1.114988,0 -2.019906,-0.904918 -2.019906,-2.019906 0,-1.114988 0.904918,-2.019906 2.019906,-2.019906"
class="ColorScheme-Text"
id="path4838" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -2,7 +2,16 @@
<RCC version="1.0">
<qresource prefix="/backgrounds">
<file alias="kitteh">Polly.png</file>
<file alias="catmas">PollyChristmas.png</file>
<file alias="cattiversary">PollyParty.png</file>
<file alias="kitteh-xmas">PollyChristmas.png</file>
<file alias="kitteh-bday">PollyParty.png</file>
<file alias="kitteh-spooky">kitteh-spooky.png</file>
<file alias="rory">rory.png</file>
<file alias="rory-xmas">rory-xmas.png</file>
<file alias="rory-bday">rory-bday.png</file>
<file alias="rory-spooky">rory-spooky.png</file>
<file alias="rory-flat">rory-flat.png</file>
<file alias="rory-flat-xmas">rory-flat-xmas.png</file>
<file alias="rory-flat-bday">rory-flat-bday.png</file>
<file alias="rory-flat-spooky">rory-flat-spooky.png</file>
</qresource>
</RCC>

View File

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View File

@ -42,5 +42,10 @@
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
<file>scalable/worlds.svg</file>
<file>scalable/delete.svg</file>
<file>scalable/tag.svg</file>
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1 @@
<svg fill="#757575" xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M13.05 42q-1.2 0-2.1-.9-.9-.9-.9-2.1V10.5H8v-3h9.4V6h13.2v1.5H40v3h-2.05V39q0 1.2-.9 2.1-.9.9-2.1.9Zm5.3-7.3h3V14.75h-3Zm8.3 0h3V14.75h-3Z"/></svg>

After

Width:  |  Height:  |  Size: 235 B

View File

@ -0,0 +1 @@
<svg fill="#757575" xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M24.65 33.35 32 26l-7.35-7.35-2.1 2.1 3.75 3.75H16v3h10.3l-3.75 3.75ZM7.05 40q-1.2 0-2.1-.925-.9-.925-.9-2.075V11q0-1.15.9-2.075Q5.85 8 7.05 8h14l3 3h17q1.15 0 2.075.925.925.925.925 2.075v23q0 1.15-.925 2.075Q42.2 40 41.05 40Z"/></svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
fill="#757575"
height="48"
width="48"
version="1.1"
id="svg24108"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs24112" />
<path
d="M 11.674384,43.35533 V 4.3446706 L 42.325617,23.850001 Z"
id="path24106"
style="stroke-width:1" />
</svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@ -93,4 +93,36 @@
inkscape:label="beak" />
</g>
</g>
<path d="m16.746 6.9737 2.8639 4.9609c0.33073 0 2.6991-1.3672 2.8644-1.6536 0.16536-0.28642 0.16536-3.0209 0-3.3073l-2.8644 1.6536z" fill="#dfdfdf" stroke-width=".26458"/>
</g>
<path d="m3.8299 4.8948c-0.14551 0.25205-0.14553 2.6584 0 2.9104 0.14553 0.25204 2.2292 1.4552 2.5203 1.4552v-2.9104z" fill="#d6d2d2" stroke-width=".26458"/>
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:title>Prism Launcher Logo</dc:title>
<dc:date>19/10/2022</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Prism Launcher</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke</dc:title>
</cc:Agent>
</dc:contributor>
<dc:source>https://github.com/PrismLauncher/PrismLauncher</dc:source>
<dc:rights>
<cc:Agent>
<dc:title>CC BY-SA 4.0</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>Prism Launcher</dc:title>
</cc:Agent>
</dc:publisher>
</cc:Work>
</rdf:RDF>
</metadata>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1 @@
<svg fill="#757575" xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="m39.7 14.7-6.4-6.4 2.1-2.1q.85-.85 2.125-.825 1.275.025 2.125.875L41.8 8.4q.85.85.85 2.1t-.85 2.1Zm-2.1 2.1L12.4 42H6v-6.4l25.2-25.2Z"/></svg>

After

Width:  |  Height:  |  Size: 230 B

View File

@ -0,0 +1 @@
<svg fill="#757575" xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M27.95 43.15q-.9.9-2.175.9t-2.175-.9L4.85 24.4q-.5-.5-.675-1.05Q4 22.8 4 22.2V7q0-1.3.85-2.15Q5.7 4 7 4h15.2q.6 0 1.2.175t1.1.675L43.15 23.5q.95.95.95 2.225 0 1.275-.95 2.225ZM12.25 14.8q1.05 0 1.825-.775.775-.775.775-1.825 0-1.05-.775-1.825Q13.3 9.6 12.25 9.6q-1.05 0-1.825.775-.775.775-.775 1.825 0 1.05.775 1.825.775.775 1.825.775Z"/></svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@ -0,0 +1,51 @@
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/icons/flat_white">
<file>index.theme</file>
<file>scalable/about.svg</file>
<file>scalable/accounts.svg</file>
<file>scalable/bug.svg</file>
<file>scalable/cat.svg</file>
<file>scalable/centralmods.svg</file>
<file>scalable/checkupdate.svg</file>
<file>scalable/copy.svg</file>
<file>scalable/coremods.svg</file>
<file>scalable/custom-commands.svg</file>
<file>scalable/discord.svg</file>
<file>scalable/externaltools.svg</file>
<file>scalable/help.svg</file>
<file>scalable/instance-settings.svg</file>
<file>scalable/jarmods.svg</file>
<file>scalable/java.svg</file>
<file>scalable/language.svg</file>
<file>scalable/launcher.svg</file>
<file>scalable/loadermods.svg</file>
<file>scalable/log.svg</file>
<file>scalable/minecraft.svg</file>
<file>scalable/new.svg</file>
<file>scalable/news.svg</file>
<file>scalable/notes.svg</file>
<file>scalable/packages.svg</file>
<file>scalable/proxy.svg</file>
<file>scalable/quickmods.svg</file>
<file>scalable/reddit-alien.svg</file>
<file>scalable/refresh.svg</file>
<file>scalable/resourcepacks.svg</file>
<file>scalable/shaderpacks.svg</file>
<file>scalable/screenshot-placeholder.svg</file>
<file>scalable/screenshots.svg</file>
<file>scalable/settings.svg</file>
<file>scalable/star.svg</file>
<file>scalable/status-bad.svg</file>
<file>scalable/status-good.svg</file>
<file>scalable/status-running.svg</file>
<file>scalable/status-yellow.svg</file>
<file>scalable/viewfolder.svg</file>
<file>scalable/worlds.svg</file>
<file>scalable/delete.svg</file>
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/tag.svg</file>
<file>scalable/launch.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,11 @@
[Icon Theme]
Name=Flat (White)
Comment=White version of the flat icons (dark mode)
Inherits=multimc
Directories=scalable
[scalable]
Size=48
Type=Scalable
MinSize=16
MaxSize=256

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z"/>
</svg>

After

Width:  |  Height:  |  Size: 321 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M16,13C15.71,13 15.38,13 15.03,13.05C16.19,13.89 17,15 17,16.5V19H23V16.5C23,14.17 18.33,13 16,13M8,13C5.67,13 1,14.17 1,16.5V19H15V16.5C15,14.17 10.33,13 8,13M8,11A3,3 0 0,0 11,8A3,3 0 0,0 8,5A3,3 0 0,0 5,8A3,3 0 0,0 8,11M16,11A3,3 0 0,0 19,8A3,3 0 0,0 16,5A3,3 0 0,0 13,8A3,3 0 0,0 16,11Z"/>
</svg>

After

Width:  |  Height:  |  Size: 412 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/>
</svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M12,8L10.67,8.09C9.81,7.07 7.4,4.5 5,4.5C5,4.5 3.03,7.46 4.96,11.41C4.41,12.24 4.07,12.67 4,13.66L2.07,13.95L2.28,14.93L4.04,14.67L4.18,15.38L2.61,16.32L3.08,17.21L4.53,16.32C5.68,18.76 8.59,20 12,20C15.41,20 18.32,18.76 19.47,16.32L20.92,17.21L21.39,16.32L19.82,15.38L19.96,14.67L21.72,14.93L21.93,13.95L20,13.66C19.93,12.67 19.59,12.24 19.04,11.41C20.97,7.46 19,4.5 19,4.5C16.6,4.5 14.19,7.07 13.33,8.09L12,8M9,11A1,1 0 0,1 10,12A1,1 0 0,1 9,13A1,1 0 0,1 8,12A1,1 0 0,1 9,11M15,11A1,1 0 0,1 16,12A1,1 0 0,1 15,13A1,1 0 0,1 14,12A1,1 0 0,1 15,11M11,14H13L12.3,15.39C12.5,16.03 13.06,16.5 13.75,16.5A1.5,1.5 0 0,0 15.25,15H15.75A2,2 0 0,1 13.75,17C13,17 12.35,16.59 12,16V16H12C11.65,16.59 11,17 10.25,17A2,2 0 0,1 8.25,15H8.75A1.5,1.5 0 0,0 10.25,16.5C10.94,16.5 11.5,16.03 11.7,15.39L11,14Z"/>
</svg>

After

Width:  |  Height:  |  Size: 914 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2.06 11L15 15.28 12.06 17l.78-3.33-2.59-2.24 3.41-.29L15 8l1.34 3.14 3.41.29-2.59 2.24.78 3.33z"/>
</svg>

After

Width:  |  Height:  |  Size: 303 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 424 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/>
</svg>

After

Width:  |  Height:  |  Size: 265 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M22,12A10,10,0,1,1,12,2,10,10,0,0,1,22,12ZM12,4a8,8,0,1,0,8,8A8,8,0,0,0,12,4Zm4.23,14-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18"/>
</svg>

After

Width:  |  Height:  |  Size: 296 B

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
fill="#D8DEE9"
height="24"
viewBox="0 0 24 24"
width="24"
version="1.1"
id="svg4"
sodipodi:docname="custom-commands.svg"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3440"
inkscape:window-height="1382"
id="namedview6"
showgrid="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="39.333333"
inkscape:cx="11.38983"
inkscape:cy="13.283898"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="1"
inkscape:current-layer="svg4"
inkscape:pagecheckerboard="0">
<inkscape:grid
type="xygrid"
id="grid981" />
<sodipodi:guide
position="-8,11.440678"
orientation="1,0"
id="guide1060"
inkscape:locked="false" />
<sodipodi:guide
position="-28.34375,24"
orientation="0,1"
id="guide1062"
inkscape:locked="false" />
</sodipodi:namedview>
<g
style="fill:#000000"
id="g821"
transform="matrix(0.0322459,0,0,0.0322459,-17.878956,30.647558)">
<g
style="fill:#000000"
id="g819" />
</g>
<g
id="g503">
<path
d="M 0,0 H 24 V 24 H 0 Z"
fill="none"
id="path491" />
<path
d="M 8.7,15.9 4.8,12 8.7,8.1 C 9.09,7.71 9.09,7.09 8.7,6.7 8.31,6.31 7.69,6.31 7.3,6.7 l -4.59,4.59 c -0.39,0.39 -0.39,1.02 0,1.41 l 4.59,4.6 c 0.39,0.39 1.01,0.39 1.4,0 0.39,-0.39 0.39,-1.01 0,-1.4 z m 6.6,0 3.9,-3.9 -3.9,-3.9 c -0.39,-0.39 -0.39,-1.01 0,-1.4 0.39,-0.39 1.01,-0.39 1.4,0 l 4.59,4.59 c 0.39,0.39 0.39,1.02 0,1.41 l -4.59,4.6 c -0.39,0.39 -1.01,0.39 -1.4,0 -0.39,-0.39 -0.39,-1.01 0,-1.4 z"
id="path493" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs8"/>
<path id="path5145" style="fill:#D8DEE9;fill-opacity:1;stroke:none;stroke-width:1.4;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none" d="M 7.1074219 0.96484375 L 7.1074219 2.7304688 L 2.6132812 2.7304688 L 2.6132812 4.4960938 L 21.386719 4.4960938 L 21.386719 2.7304688 L 16.892578 2.7304688 L 16.892578 0.96484375 L 7.1074219 0.96484375 z M 5.0058594 6.0839844 L 5.0058594 22.859375 L 18.994141 22.859375 L 18.994141 6.0839844 L 5.0058594 6.0839844 z M 7.9160156 9.0605469 L 10.193359 9.0605469 L 10.193359 19.882812 L 7.9160156 19.882812 L 7.9160156 9.0605469 z M 13.804688 9.0605469 L 16.085938 9.0605469 L 16.085938 19.882812 L 13.804688 19.882812 L 13.804688 9.0605469 z "/>
</svg>

After

Width:  |  Height:  |  Size: 943 B

View File

@ -0,0 +1,4 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M10.14,11.63a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,10.14,11.63Zm3.75,0a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,13.89,11.63Z"/>
<path d="M18.89,3H5.11A2.11,2.11,0,0,0,3,5.12V19a2.11,2.11,0,0,0,2.11,2.12H16.77l-.55-1.9,1.32,1.22,1.24,1.15,2.21,2V5.12A2.11,2.11,0,0,0,18.89,3Zm-4,13.43s-.37-.44-.68-.83a3.25,3.25,0,0,0,1.86-1.22,5.89,5.89,0,0,1-1.18.61,6.77,6.77,0,0,1-1.49.44,7.21,7.21,0,0,1-2.66,0A8.63,8.63,0,0,1,9.25,15a6,6,0,0,1-.75-.35l-.09-.05,0,0-.29-.17a3.2,3.2,0,0,0,1.8,1.21l-.69.85a3.73,3.73,0,0,1-3.14-1.56,13.77,13.77,0,0,1,1.48-6,5.09,5.09,0,0,1,2.89-1.08l.1.12A6.94,6.94,0,0,0,7.82,9.26s.23-.12.61-.3a7.72,7.72,0,0,1,2.33-.65l.17,0a8.7,8.7,0,0,1,2.08,0,8.38,8.38,0,0,1,3.1,1A6.85,6.85,0,0,0,13.55,8l.14-.16a5.09,5.09,0,0,1,2.89,1.08,13.77,13.77,0,0,1,1.48,6A3.76,3.76,0,0,1,14.92,16.43Z"/>
</svg>

After

Width:  |  Height:  |  Size: 921 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs8"/>
<path id="path2" d="M 4 4 C 2.9000011 4 2.0097656 4.9000011 2.0097656 6 L 2 18 C 2 19.099999 2.9000011 20 4 20 L 20 20 C 21.099999 20 22 19.099999 22 18 L 22 8 C 22 6.9000011 21.099999 6 20 6 L 12 6 L 10 4 L 4 4 z M 12.537109 9.9082031 L 13.185547 10.298828 L 17.554688 12.929688 L 13.185547 15.5625 L 12.537109 15.953125 L 11.755859 14.65625 L 12.404297 14.265625 L 13.349609 13.695312 L 6.4453125 13.695312 L 6.4453125 12.166016 L 13.351562 12.166016 L 12.404297 11.595703 L 11.755859 11.205078 L 12.537109 9.9082031 z "/>
</svg>

After

Width:  |  Height:  |  Size: 771 B

View File

@ -0,0 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z"/>
</svg>

After

Width:  |  Height:  |  Size: 329 B

Some files were not shown because too many files have changed in this diff Show More