aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml8
-rw-r--r--CMakeLists.txt9
-rw-r--r--buildconfig/BuildConfig.cpp.in27
-rw-r--r--buildconfig/BuildConfig.h6
-rw-r--r--cmake/GetGitRevisionDescription.cmake246
-rw-r--r--cmake/GetGitRevisionDescription.cmake.in34
-rw-r--r--launcher/Application.cpp31
-rw-r--r--launcher/Application.h12
-rw-r--r--launcher/net/Download.cpp5
-rw-r--r--launcher/net/Download.h1
-rw-r--r--launcher/net/Upload.cpp43
-rw-r--r--launcher/net/Upload.h36
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.cpp33
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.h21
-rw-r--r--launcher/ui/dialogs/NewInstanceDialog.cpp27
-rw-r--r--launcher/ui/dialogs/NewInstanceDialog.h41
-rw-r--r--launcher/ui/pages/global/APIPage.cpp16
-rw-r--r--launcher/ui/pages/global/APIPage.ui6
-rw-r--r--launcher/ui/pages/global/AccountListPage.cpp2
-rw-r--r--launcher/ui/pages/modplatform/ImportPage.ui2
-rw-r--r--program_info/CMakeLists.txt23
-rw-r--r--program_info/polymc.6.scd61
-rw-r--r--program_info/polymc.6.txt64
23 files changed, 556 insertions, 198 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index fbbc1417..bc92f37f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -113,9 +113,9 @@ jobs:
uses: actions/cache@v3.0.2
with:
path: '${{ github.workspace }}\.ccache'
- key: ${{ matrix.os }}-${{ matrix.msystem }}
+ key: ${{ matrix.os }}--qt${{ matrix.qt_ver }}
restore-keys: |
- ${{ matrix.os }}-${{ matrix.msystem }}
+ ${{ matrix.os }}--qt${{ matrix.qt_ver }}
- name: Set short version
shell: bash
@@ -127,7 +127,7 @@ jobs:
if: runner.os == 'Linux'
run: |
sudo apt-get -y update
- sudo apt-get -y install ninja-build extra-cmake-modules
+ sudo apt-get -y install ninja-build extra-cmake-modules scdoc
- name: Install Dependencies (macOS)
if: runner.os == 'macOS'
@@ -138,7 +138,7 @@ jobs:
- name: Install Qt (Linux)
if: runner.os == 'Linux' && matrix.appimage != true
run: |
- sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 qt5-image-formats-plugins
+ sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
- name: Install Qt (macOS and AppImage)
if: matrix.qt_ver == 6 && runner.os != 'Windows'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fc9cdd31..c88a32ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -131,14 +131,16 @@ set(Launcher_MSA_CLIENT_ID "549033b2-1532-4d4e-ae77-1bbaa46f9d74" CACHE STRING "
# By using this key in your builds you accept the terms and conditions laid down in
# https://support.curseforge.com/en/support/solutions/articles/9000207405-curse-forge-3rd-party-api-terms-and-conditions
# NOTE: CurseForge requires you to change this if you make any kind of derivative work.
-set(Launcher_CURSEFORGE_API_KEY "$2a$10$1Oqr2MX3O4n/ilhFGc597u8tfI3L2Hyr9/rtWDAMRjghSQV2QUuxq" CACHE STRING "CurseForge API Key")
+set(Launcher_CURSEFORGE_API_KEY "$2a$10$1Oqr2MX3O4n/ilhFGc597u8tfI3L2Hyr9/rtWDAMRjghSQV2QUuxq" CACHE STRING "API key for the CurseForge platform")
#### Check the current Git commit and branch
include(GetGitRevisionDescription)
+git_get_exact_tag(Launcher_GIT_TAG)
get_git_head_revision(Launcher_GIT_REFSPEC Launcher_GIT_COMMIT)
message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
+message(STATUS "Git tag: ${Launcher_GIT_TAG}")
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
set(Launcher_RELEASE_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
@@ -263,7 +265,10 @@ elseif(UNIX)
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_SOURCE_DIR}/${Launcher_ManPage} DESTINATION ${LAUNCHER_MAN_DEST_DIR} RENAME "${Launcher_APP_BINARY_NAME}.6")
+
+ if(Launcher_ManPage)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${Launcher_ManPage} DESTINATION ${LAUNCHER_MAN_DEST_DIR})
+ endif()
# Install basic runner script if component "portable" is selected
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in
index 2d07bc58..7da66f36 100644
--- a/buildconfig/BuildConfig.cpp.in
+++ b/buildconfig/BuildConfig.cpp.in
@@ -70,12 +70,18 @@ Config::Config()
}
GIT_COMMIT = "@Launcher_GIT_COMMIT@";
+ GIT_TAG = "@Launcher_GIT_TAG@";
GIT_REFSPEC = "@Launcher_GIT_REFSPEC@";
- if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND"))
+
+ // Assume that builds outside of Git repos are "stable"
+ if (GIT_REFSPEC == QStringLiteral("GITDIR-NOTFOUND")
+ || GIT_TAG == QStringLiteral("GITDIR-NOTFOUND"))
{
- VERSION_CHANNEL = QStringLiteral("stable");
+ GIT_REFSPEC = "refs/heads/stable";
+ GIT_TAG = versionString();
}
- else if(GIT_REFSPEC.startsWith("refs/heads/"))
+
+ if (GIT_REFSPEC.startsWith("refs/heads/"))
{
VERSION_CHANNEL = GIT_REFSPEC;
VERSION_CHANNEL.remove("refs/heads/");
@@ -89,7 +95,7 @@ Config::Config()
}
else
{
- VERSION_CHANNEL = QObject::tr("unknown");
+ VERSION_CHANNEL = "unknown";
}
VERSION_STR = "@Launcher_VERSION_STRING@";
@@ -98,7 +104,7 @@ Config::Config()
HELP_URL = "@Launcher_HELP_URL@";
IMGUR_CLIENT_ID = "@Launcher_IMGUR_CLIENT_ID@";
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
- CURSEFORGE_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
+ FLAME_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
META_URL = "@Launcher_META_URL@";
BUG_TRACKER_URL = "@Launcher_BUG_TRACKER_URL@";
@@ -108,12 +114,17 @@ Config::Config()
SUBREDDIT_URL = "@Launcher_SUBREDDIT_URL@";
}
+QString Config::versionString() const
+{
+ return QString("%1.%2.%3").arg(VERSION_MAJOR).arg(VERSION_MINOR).arg(VERSION_HOTFIX);
+}
+
QString Config::printableVersionString() const
{
- QString vstr = QString("%1.%2.%3").arg(QString::number(VERSION_MAJOR), QString::number(VERSION_MINOR), QString::number(VERSION_HOTFIX));
+ QString vstr = versionString();
// If the build is not a main release, append the channel
- if(VERSION_CHANNEL != "stable")
+ if(VERSION_CHANNEL != "stable" && GIT_TAG != vstr)
{
vstr += "-" + VERSION_CHANNEL;
}
@@ -121,7 +132,7 @@ QString Config::printableVersionString() const
// if a build number is set, also add it to the end
if(VERSION_BUILD >= 0)
{
- vstr += "-" + QString::number(VERSION_BUILD);
+ vstr += "+build." + QString::number(VERSION_BUILD);
}
return vstr;
}
diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h
index e41d4ba0..95786d82 100644
--- a/buildconfig/BuildConfig.h
+++ b/buildconfig/BuildConfig.h
@@ -89,6 +89,9 @@ class Config {
/// The git commit hash of this build
QString GIT_COMMIT;
+ /// The git tag of this build
+ QString GIT_TAG;
+
/// The git refspec of this build
QString GIT_REFSPEC;
@@ -124,7 +127,7 @@ class Config {
/**
* Client API key for CurseForge
*/
- QString CURSEFORGE_API_KEY;
+ QString FLAME_API_KEY;
/**
* Metadata repository URL prefix
@@ -160,6 +163,7 @@ class Config {
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
+ QString versionString() const;
/**
* \brief Converts the Version to a string.
* \return The version number in string format (major.minor.revision.build).
diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake
index 39c2707b..4fbd90db 100644
--- a/cmake/GetGitRevisionDescription.cmake
+++ b/cmake/GetGitRevisionDescription.cmake
@@ -3,7 +3,7 @@
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
-# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
+# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
#
# Returns the refspec and sha hash of the current head revision
#
@@ -12,20 +12,33 @@
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
+# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
+#
+# Returns the results of git describe on the working tree (--dirty option),
+# and adjusting the output so that it tests false if an error occurs.
+#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
+# git_local_changes(<var>)
+#
+# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
+# Uses the return code of "git diff-index --quiet HEAD --".
+# Does not regard untracked files.
+#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
-# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
+# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
# http://academic.cleardefinition.com
-# Iowa State University HCI Graduate Program/VRAC
#
-# Copyright Iowa State University 2009-2010.
+# Copyright 2009-2013, Iowa State University.
+# Copyright 2013-2020, Ryan Pavlik
+# Copyright 2013-2020, Contributors
+# SPDX-License-Identifier: BSL-1.0
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
@@ -39,45 +52,124 @@ set(__get_git_revision_description YES)
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
-function(get_git_head_revision _refspecvar _hashvar)
- set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
- set(GIT_DIR "${GIT_PARENT_DIR}/.git")
- while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
- set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
- get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
- if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
+# Function _git_find_closest_git_dir finds the next closest .git directory
+# that is part of any directory in the path defined by _start_dir.
+# The result is returned in the parent scope variable whose name is passed
+# as variable _git_dir_var. If no .git directory can be found, the
+# function returns an empty string via _git_dir_var.
+#
+# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
+# neither foo nor bar contain a file/directory .git. This wil return
+# C:/bla/.git
+#
+function(_git_find_closest_git_dir _start_dir _git_dir_var)
+ set(cur_dir "${_start_dir}")
+ set(git_dir "${_start_dir}/.git")
+ while(NOT EXISTS "${git_dir}")
+ # .git dir not found, search parent directories
+ set(git_previous_parent "${cur_dir}")
+ get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
+ if(cur_dir STREQUAL git_previous_parent)
# We have reached the root directory, we are not in git
- set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
- set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
+ set(${_git_dir_var}
+ ""
+ PARENT_SCOPE)
return()
endif()
- set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+ set(git_dir "${cur_dir}/.git")
endwhile()
- # check if this is a submodule
+ set(${_git_dir_var}
+ "${git_dir}"
+ PARENT_SCOPE)
+endfunction()
+
+function(get_git_head_revision _refspecvar _hashvar)
+ _git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
+
+ if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
+ set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
+ else()
+ set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
+ endif()
+ if(NOT "${GIT_DIR}" STREQUAL "")
+ file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
+ "${GIT_DIR}")
+ if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
+ # We've gone above the CMake root dir.
+ set(GIT_DIR "")
+ endif()
+ endif()
+ if("${GIT_DIR}" STREQUAL "")
+ set(${_refspecvar}
+ "GITDIR-NOTFOUND"
+ PARENT_SCOPE)
+ set(${_hashvar}
+ "GITDIR-NOTFOUND"
+ PARENT_SCOPE)
+ return()
+ endif()
+
+ # Check if the current source dir is a git submodule or a worktree.
+ # In both cases .git is a file instead of a directory.
+ #
if(NOT IS_DIRECTORY ${GIT_DIR})
- file(READ ${GIT_DIR} submodule)
- string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
- get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
- get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
+ # The following git command will return a non empty string that
+ # points to the super project working tree if the current
+ # source dir is inside a git submodule.
+ # Otherwise the command will return an empty string.
+ #
+ execute_process(
+ COMMAND "${GIT_EXECUTABLE}" rev-parse
+ --show-superproject-working-tree
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ OUTPUT_VARIABLE out
+ ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT "${out}" STREQUAL "")
+ # If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
+ file(READ ${GIT_DIR} submodule)
+ string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
+ ${submodule})
+ string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
+ get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
+ get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
+ ABSOLUTE)
+ set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
+ else()
+ # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
+ file(READ ${GIT_DIR} worktree_ref)
+ # The .git directory contains a path to the worktree information directory
+ # inside the parent git repo of the worktree.
+ #
+ string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
+ ${worktree_ref})
+ string(STRIP ${git_worktree_dir} git_worktree_dir)
+ _git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
+ set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
+ endif()
+ else()
+ set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
- if(NOT EXISTS "${GIT_DIR}/HEAD")
+ if(NOT EXISTS "${HEAD_SOURCE_FILE}")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
- configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
+ configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
- "${GIT_DATA}/grabRef.cmake"
- @ONLY)
+ "${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
- set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
- set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
+ set(${_refspecvar}
+ "${HEAD_REF}"
+ PARENT_SCOPE)
+ set(${_hashvar}
+ "${HEAD_HASH}"
+ PARENT_SCOPE)
endfunction()
function(git_describe _var)
@@ -86,45 +178,107 @@ function(git_describe _var)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
- set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
+ set(${_var}
+ "GIT-NOTFOUND"
+ PARENT_SCOPE)
return()
endif()
if(NOT hash)
- set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
+ set(${_var}
+ "HEAD-HASH-NOTFOUND"
+ PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
- # (ARGN MATCHES "||") OR
- # (ARGN MATCHES "\\;"))
- # message("Please report the following error to the project!")
- # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
+ # (ARGN MATCHES "||") OR
+ # (ARGN MATCHES "\\;"))
+ # message("Please report the following error to the project!")
+ # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
- execute_process(COMMAND
- "${GIT_EXECUTABLE}"
- describe
- ${hash}
- ${ARGN}
- WORKING_DIRECTORY
- "${CMAKE_CURRENT_SOURCE_DIR}"
- RESULT_VARIABLE
- res
- OUTPUT_VARIABLE
- out
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(
+ COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ RESULT_VARIABLE res
+ OUTPUT_VARIABLE out
+ ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
- set(${_var} "${out}" PARENT_SCOPE)
+ set(${_var}
+ "${out}"
+ PARENT_SCOPE)
+endfunction()
+
+function(git_describe_working_tree _var)
+ if(NOT GIT_FOUND)
+ find_package(Git QUIET)
+ endif()
+ if(NOT GIT_FOUND)
+ set(${_var}
+ "GIT-NOTFOUND"
+ PARENT_SCOPE)
+ return()
+ endif()
+
+ execute_process(
+ COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ RESULT_VARIABLE res
+ OUTPUT_VARIABLE out
+ ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT res EQUAL 0)
+ set(out "${out}-${res}-NOTFOUND")
+ endif()
+
+ set(${_var}
+ "${out}"
+ PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
- set(${_var} "${out}" PARENT_SCOPE)
+ set(${_var}
+ "${out}"
+ PARENT_SCOPE)
+endfunction()
+
+function(git_local_changes _var)
+ if(NOT GIT_FOUND)
+ find_package(Git QUIET)
+ endif()
+ get_git_head_revision(refspec hash)
+ if(NOT GIT_FOUND)
+ set(${_var}
+ "GIT-NOTFOUND"
+ PARENT_SCOPE)
+ return()
+ endif()
+ if(NOT hash)
+ set(${_var}
+ "HEAD-HASH-NOTFOUND"
+ PARENT_SCOPE)
+ return()
+ endif()
+
+ execute_process(
+ COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ RESULT_VARIABLE res
+ OUTPUT_VARIABLE out
+ ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(res EQUAL 0)
+ set(${_var}
+ "CLEAN"
+ PARENT_SCOPE)
+ else()
+ set(${_var}
+ "DIRTY"
+ PARENT_SCOPE)
+ endif()
endfunction()
diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in
index 04db9a8e..116efc4e 100644
--- a/cmake/GetGitRevisionDescription.cmake.in
+++ b/cmake/GetGitRevisionDescription.cmake.in
@@ -8,10 +8,12 @@
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
-# Copyright Iowa State University 2009-2010.
+# Copyright 2009-2012, Iowa State University
+# Copyright 2011-2015, Contributors
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
+# SPDX-License-Identifier: BSL-1.0
set(HEAD_HASH)
@@ -19,23 +21,23 @@ file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
- # named branch
- string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
- if(EXISTS "@GIT_DIR@/${HEAD_REF}")
- configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
- else()
- configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
- file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
- if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
- set(HEAD_HASH "${CMAKE_MATCH_1}")
- endif()
- endif()
+ # named branch
+ string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
+ if(EXISTS "@GIT_DIR@/${HEAD_REF}")
+ configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
+ else()
+ configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
+ file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
+ if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
+ set(HEAD_HASH "${CMAKE_MATCH_1}")
+ endif()
+ endif()
else()
- # detached HEAD
- configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
+ # detached HEAD
+ configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
- file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
- string(STRIP "${HEAD_HASH}" HEAD_HASH)
+ file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
+ string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index f8c93259..2bd91fd7 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -711,9 +711,20 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings->registerSetting("CloseAfterLaunch", false);
m_settings->registerSetting("QuitAfterGameStop", false);
- // Custom MSA credentials
+ // Custom Microsoft Authentication Client ID
m_settings->registerSetting("MSAClientIDOverride", "");
- m_settings->registerSetting("CFKeyOverride", "");
+
+ // Custom Flame API Key
+ {
+ m_settings->registerSetting("CFKeyOverride", "");
+ m_settings->registerSetting("FlameKeyOverride", "");
+
+ QString flameKey = m_settings->get("CFKeyOverride").toString();
+
+ if (!flameKey.isEmpty())
+ m_settings->set("FlameKeyOverride", flameKey);
+ m_settings->reset("CFKeyOverride");
+ }
m_settings->registerSetting("UserAgentOverride", "");
// Init page provider
@@ -1553,6 +1564,16 @@ shared_qobject_ptr<Meta::Index> Application::metadataIndex()
return m_metadataIndex;
}
+Application::Capabilities Application::currentCapabilities()
+{
+ Capabilities c;
+ if (!getMSAClientID().isEmpty())
+ c |= SupportsMSA;
+ if (!getFlameAPIKey().isEmpty())
+ c |= SupportsFlame;
+ return c;
+}
+
QString Application::getJarPath(QString jarFile)
{
QStringList potentialPaths = {
@@ -1581,14 +1602,14 @@ QString Application::getMSAClientID()
return BuildConfig.MSA_CLIENT_ID;
}
-QString Application::getCurseKey()
+QString Application::getFlameAPIKey()
{
- QString keyOverride = m_settings->get("CFKeyOverride").toString();
+ QString keyOverride = m_settings->get("FlameKeyOverride").toString();
if (!keyOverride.isEmpty()) {
return keyOverride;
}
- return BuildConfig.CURSEFORGE_API_KEY;
+ return BuildConfig.FLAME_API_KEY;
}
QString Application::getUserAgent()
diff --git a/launcher/Application.h b/launcher/Application.h
index e3b4fced..019c3c3d 100644
--- a/launcher/Application.h
+++ b/launcher/Application.h
@@ -90,6 +90,14 @@ public:
Initialized
};
+ enum Capability {
+ None = 0,
+
+ SupportsMSA = 1 << 0,
+ SupportsFlame = 1 << 1,
+ };
+ Q_DECLARE_FLAGS(Capabilities, Capability)
+
public:
Application(int &argc, char **argv);
virtual ~Application();
@@ -154,6 +162,8 @@ public:
shared_qobject_ptr<Meta::Index> metadataIndex();
+ Capabilities currentCapabilities();
+
/*!
* Finds and returns the full path to a jar file.
* Returns a null-string if it could not be found.
@@ -161,7 +171,7 @@ public:
QString getJarPath(QString jarFile);
QString getMSAClientID();
- QString getCurseKey();
+ QString getFlameAPIKey();
QString getUserAgent();
QString getUserAgentUncached();
diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp
index 3061e32e..e6a6adcc 100644
--- a/launcher/net/Download.cpp
+++ b/launcher/net/Download.cpp
@@ -118,8 +118,9 @@ void Download::executeTask()
}
request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8());
- if (request.url().host().contains("api.curseforge.com")) {
- request.setRawHeader("x-api-key", APPLICATION->getCurseKey().toUtf8());
+ if (APPLICATION->currentCapabilities() & Application::SupportsFlame
+ && request.url().host().contains("api.curseforge.com")) {
+ request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8());
};
QNetworkReply* rep = m_network->get(request);
diff --git a/launcher/net/Download.h b/launcher/net/Download.h
index 20932944..1d264381 100644
--- a/launcher/net/Download.h
+++ b/launcher/net/Download.h
@@ -2,6 +2,7 @@
/*
* PolyMC - Minecraft Launcher
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp
index c9942a8d..12dd1e78 100644
--- a/launcher/net/Upload.cpp
+++ b/launcher/net/Upload.cpp
@@ -1,6 +1,38 @@
-//
-// Created by timoreo on 20/05/22.
-//
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * PolyMC - Minecraft Launcher
+ * Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "Upload.h"
@@ -174,8 +206,9 @@ namespace Net {
}
request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8());
- if (request.url().host().contains("api.curseforge.com")) {
- request.setRawHeader("x-api-key", APPLICATION->getCurseKey().toUtf8());
+ if (APPLICATION->currentCapabilities() & Application::SupportsFlame
+ && request.url().host().contains("api.curseforge.com")) {
+ request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8());
}
//TODO other types of post requests ?
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h
index ee784c6e..56687a31 100644
--- a/launcher/net/Upload.h
+++ b/launcher/net/Upload.h
@@ -1,3 +1,39 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * PolyMC - Minecraft Launcher
+ * Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#pragma once
#include "NetAction.h"
diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp
index f01c9c07..e4fc3ecc 100644
--- a/launcher/ui/dialogs/ModDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ModDownloadDialog.cpp
@@ -1,9 +1,28 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * PolyMC - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
#include "ModDownloadDialog.h"
#include <BaseVersion.h>
#include <icons/IconList.h>
#include <InstanceList.h>
+#include "Application.h"
#include "ProgressDialog.h"
#include "ReviewMessageBox.h"
@@ -100,13 +119,13 @@ void ModDownloadDialog::accept()
QList<BasePage *> ModDownloadDialog::getPages()
{
- modrinthPage = new ModrinthModPage(this, m_instance);
- flameModPage = new FlameModPage(this, m_instance);
- return
- {
- modrinthPage,
- flameModPage
- };
+ QList<BasePage *> pages;
+
+ pages.append(new ModrinthModPage(this, m_instance));
+ if (APPLICATION->currentCapabilities() & Application::SupportsFlame)
+ pages.append(new FlameModPage(this, m_instance));
+
+ return pages;
}
void ModDownloadDialog::addSelectedMod(const QString& name, ModDownloadTask* task)
diff --git a/launcher/ui/dialogs/ModDownloadDialog.h b/launcher/ui/dialogs/ModDownloadDialog.h
index 5c565ad3..1fa1f058 100644
--- a/launcher/ui/dialogs/ModDownloadDialog.h
+++ b/launcher/ui/dialogs/ModDownloadDialog.h
@@ -1,3 +1,21 @@
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * PolyMC - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
#pragma once
#include <QDialog>
@@ -48,9 +66,6 @@ private:
QDialogButtonBox * m_buttons = nullptr;
QVBoxLayout *m_verticalLayout = nullptr;
-
- ModrinthModPage *modrinthPage = nullptr;
- FlameModPage *flameModPage = nullptr;
QHash<QString, ModDownloadTask*> modTask;
BaseInstance *m_instance;
};
diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp
index 5b8ecc5b..35bba9be 100644
--- a/launcher/ui/dialogs/NewInstanceDialog.cpp
+++ b/launcher/ui/dialogs/NewInstanceDialog.cpp
@@ -150,20 +150,21 @@ void NewInstanceDialog::accept()
QList<BasePage *> NewInstanceDialog::getPages()
{
+ QList<BasePage *> pages;
+
importPage = new ImportPage(this);
- flamePage = new FlamePage(this);
- auto technicPage = new TechnicPage(this);
- return
- {
- new VanillaPage(this),
- importPage,
- new AtlPage(this),
- flamePage,
- new FtbPage(this),
- new LegacyFTB::Page(this),
- new ModrinthPage(this),
- technicPage
- };
+
+ pages.append(new VanillaPage(this));
+ pages.append(importPage);
+ pages.append(new AtlPage(this));
+ if (APPLICATION->currentCapabilities() & Application::SupportsFlame)
+ pages.append(new FlamePage(this));
+ pages.append(new FtbPage(this));
+ pages.append(new LegacyFTB::Page(this));
+ pages.append(new ModrinthPage(this));
+ pages.append(new TechnicPage(this));
+
+ return pages;
}
QString NewInstanceDialog::dialogTitle()
diff --git a/launcher/ui/dialogs/NewInstanceDialog.h b/launcher/ui/dialogs/NewInstanceDialog.h
index ef74634e..a3c8cd1c 100644
--- a/launcher/ui/dialogs/NewInstanceDialog.h
+++ b/launcher/ui/dialogs/NewInstanceDialog.h
@@ -1,16 +1,36 @@
-/* Copyright 2013-2021 MultiMC Contributors
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * PolyMC - Minecraft Launcher
+ * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#pragma once
@@ -69,7 +89,6 @@ private:
QString InstIconKey;
ImportPage *importPage = nullptr;
- FlamePage *flamePage = nullptr;
std::unique_ptr<InstanceTask> creationTask;
bool importIcon = false;
diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp
index b889e6f7..e3d30475 100644
--- a/launcher/ui/pages/global/APIPage.cpp
+++ b/launcher/ui/pages/global/APIPage.cpp
@@ -40,8 +40,10 @@
#include <QMessageBox>
#include <QFileDialog>
+#include <QRegularExpression>
#include <QStandardPaths>
#include <QTabBar>
+#include <QValidator>
#include <QVariant>
#include "settings/SettingsObject.h"
@@ -63,6 +65,10 @@ APIPage::APIPage(QWidget *parent) :
};
static QRegularExpression validUrlRegExp("https?://.+");
+ static QRegularExpression validMSAClientID(QRegularExpression::anchoredPattern(
+ "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"));
+ static QRegularExpression validFlameKey(QRegularExpression::anchoredPattern(
+ "\\$2[ayb]\\$.{56}"));
ui->setupUi(this);
@@ -75,6 +81,8 @@ APIPage::APIPage(QWidget *parent) :
// This function needs to be called even when the ComboBox's index is still in its default state.
updateBaseURLPlaceholder(ui->pasteTypeComboBox->currentIndex());
ui->baseURLEntry->setValidator(new QRegularExpressionValidator(validUrlRegExp, ui->baseURLEntry));
+ ui->msaClientID->setValidator(new QRegularExpressionValidator(validMSAClientID, ui->msaClientID));
+ ui->flameKey->setValidator(new QRegularExpressionValidator(validFlameKey, ui->flameKey));
ui->metaURL->setPlaceholderText(BuildConfig.META_URL);
ui->userAgentLineEdit->setPlaceholderText(BuildConfig.USER_AGENT);
@@ -137,8 +145,8 @@ void APIPage::loadSettings()
ui->msaClientID->setText(msaClientID);
QString metaURL = s->get("MetaURLOverride").toString();
ui->metaURL->setText(metaURL);
- QString curseKey = s->get("CFKeyOverride").toString();
- ui->curseKey->setText(curseKey);
+ QString flameKey = s->get("FlameKeyOverride").toString();
+ ui->flameKey->setText(flameKey);
QString customUserAgent = s->get("UserAgentOverride").toString();
ui->userAgentLineEdit->setText(customUserAgent);
}
@@ -167,8 +175,8 @@ void APIPage::applySettings()
}
s->set("MetaURLOverride", metaURL);
- QString curseKey = ui->curseKey->text();
- s->set("CFKeyOverride", curseKey);
+ QString flameKey = ui->flameKey->text();
+ s->set("FlameKeyOverride", flameKey);
s->set("UserAgentOverride", ui->userAgentLineEdit->text());
}
diff --git a/launcher/ui/pages/global/APIPage.ui b/launcher/ui/pages/global/APIPage.ui
index 5327771c..1ae788c7 100644
--- a/launcher/ui/pages/global/APIPage.ui
+++ b/launcher/ui/pages/global/APIPage.ui
@@ -196,7 +196,7 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox_curse">
+ <widget class="QGroupBox" name="groupBox_flame">
<property name="enabled">
<bool>true</bool>
</property>
@@ -214,7 +214,7 @@
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
- <string>Enter a custom API Key for CurseForge here. </string>
+ <string>Enter a custom API Key for CurseForge here.</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
@@ -228,7 +228,7 @@
</widget>
</item>
<item row="1" column="0">
- <widget class="QLineEdit" name="curseKey">
+ <widget class="QLineEdit" name="flameKey">
<property name="enabled">
<bool>true</bool>
</property>
diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp
index a608771e..fcc43add 100644
--- a/launcher/ui/pages/global/AccountListPage.cpp
+++ b/launcher/ui/pages/global/AccountListPage.cpp
@@ -96,7 +96,7 @@ AccountListPage::AccountListPage(QWidget *parent)
updateButtonStates();
// Xbox authentication won't work without a client identifier, so disable the button if it is missing
- if (APPLICATION->getMSAClientID().isEmpty()) {
+ if (~APPLICATION->currentCapabilities() & Application::SupportsMSA) {
ui->actionAddMicrosoft->setVisible(false);
ui->actionAddMicrosoft->setToolTip(tr("No Microsoft Authentication client ID was set."));
}
diff --git a/launcher/ui/pages/modplatform/ImportPage.ui b/launcher/ui/pages/modplatform/ImportPage.ui
index 77bc5da5..0a50e871 100644
--- a/launcher/ui/pages/modplatform/ImportPage.ui
+++ b/launcher/ui/pages/modplatform/ImportPage.ui
@@ -40,7 +40,7 @@
<item>
<widget class="QLabel" name="label_5">
<property name="text">
- <string>- Curseforge modpacks (ZIP)</string>
+ <string>- CurseForge modpacks (ZIP)</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
diff --git a/program_info/CMakeLists.txt b/program_info/CMakeLists.txt
index 8d835322..b1ba89df 100644
--- a/program_info/CMakeLists.txt
+++ b/program_info/CMakeLists.txt
@@ -1,3 +1,13 @@
+if(UNIX)
+ find_package(PkgConfig)
+ if(PkgConfig_FOUND)
+ pkg_search_module(SCDOC scdoc)
+ if(SCDOC_FOUND)
+ pkg_get_variable(SCDOC_SCDOC scdoc scdoc)
+ endif()
+ endif()
+endif()
+
set(Launcher_CommonName "PolyMC")
set(Launcher_Copyright "PolyMC Contributors\\n© 2012-2021 MultiMC Contributors")
@@ -12,7 +22,6 @@ set(Launcher_DesktopFileName "org.polymc.PolyMC.desktop" PARENT_SCOPE)
set(Launcher_Desktop "program_info/org.polymc.PolyMC.desktop" PARENT_SCOPE)
set(Launcher_MetaInfo "program_info/org.polymc.PolyMC.metainfo.xml" PARENT_SCOPE)
-set(Launcher_ManPage "program_info/polymc.6.txt" PARENT_SCOPE)
set(Launcher_SVG "program_info/org.polymc.PolyMC.svg" PARENT_SCOPE)
set(Launcher_Branding_ICNS "program_info/polymc.icns" PARENT_SCOPE)
set(Launcher_Branding_ICO "program_info/polymc.ico")
@@ -28,3 +37,15 @@ configure_file(polymc.rc.in polymc.rc @ONLY)
configure_file(polymc.manifest.in polymc.manifest @ONLY)
configure_file(polymc.ico polymc.ico COPYONLY)
configure_file(win_install.nsi.in win_install.nsi @ONLY)
+
+if(SCDOC_FOUND)
+ set(in_scd "${CMAKE_CURRENT_SOURCE_DIR}/polymc.6.scd")
+ set(out_man "${CMAKE_CURRENT_BINARY_DIR}/polymc.6")
+ add_custom_command(
+ DEPENDS "${in_scd}"
+ OUTPUT "${out_man}"
+ COMMAND ${SCDOC_SCDOC} < "${in_scd}" > "${out_man}"
+ )
+ add_custom_target(man ALL DEPENDS ${out_man})
+ set(Launcher_ManPage "program_info/polymc.6" PARENT_SCOPE)
+endif()
diff --git a/program_info/polymc.6.scd b/program_info/polymc.6.scd
new file mode 100644
index 00000000..f0628cc9
--- /dev/null
+++ b/program_info/polymc.6.scd
@@ -0,0 +1,61 @@
+polymc(6)
+
+
+# NAME
+
+polymc - a launcher and instance manager for Minecraft.
+
+
+# SYNOPSIS
+
+*polymc* [OPTIONS...]
+
+
+# DESCRIPTION
+
+PolyMC is a custom launcher for Minecraft that allows you to easily manage
+multiple installations of Minecraft at once. It also allows you to easily
+install and remove mods by simply dragging and dropping.
+Here are the current features of PolyMC.
+
+# OPTIONS
+
+*-d, --dir*=DIRECTORY
+ Use DIRECTORY as the PolyMC root.
+
+*-l, --launch*=INSTANCE_ID
+ Launch the instance specified by INSTANCE_ID.
+
+*--alive*
+ Write a small 'live.check' file after PolyMC starts.
+
+*-h, --help*
+ Display help text and exit.
+
+*-v, --version*
+ Display program version and exit.
+
+*-a, --profile*=PROFILE
+ Use the account specified by PROFILE (only valid in combination with --launch).
+
+# EXIT STATUS
+
+*0*
+ Success
+
+*1*
+ Failure (syntax or usage error; configuration error; unexpected error).
+
+# BUGS
+
+https://github.com/PolyMC/PolyMC/issues
+
+# RESOURCES
+
+GitHub: https://github.com/PolyMC/PolyMC
+
+Main website: https://polymc.org
+
+# AUTHORS
+
+PolyMC Contributors
diff --git a/program_info/polymc.6.txt b/program_info/polymc.6.txt
deleted file mode 100644
index 8f126cce..00000000
--- a/program_info/polymc.6.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-POLYMC(1)
-==========
-:doctype: manpage
-
-
-NAME
-----
-polymc - a launcher and instance manager for Minecraft.
-
-
-SYNOPSIS
---------
-*polymc* ['OPTIONS']
-
-
-DESCRIPTION
------------
-PolyMC is a custom launcher for Minecraft that allows you to easily manage
-multiple installations of Minecraft at once. It also allows you to easily
-install and remove mods by simply dragging and dropping.
-Here are the current features of PolyMC.
-
-OPTIONS
--------
-*-d, --dir*='DIRECTORY'::
- Use 'DIRECTORY' as the PolyMC root.
-
-*-l, --launch*='INSTANCE_ID'::
- Launch the instance specified by 'INSTANCE_ID'.
-
-*--alive*::
- Write a small 'live.check' file after PolyMC starts.
-
-*-h, --help*::
- Display help text and exit.
-
-*-v, --version*::
- Display program version and exit.
-*-a, --profile*='PROFILE'::
- Use the account specified by 'PROFILE' (only valid in combination with --launch).
-
-EXIT STATUS
------------
-*0*::
- Success
-
-*1*::
- Failure (syntax or usage error; configuration error; unexpected error).
-
-BUGS
-----
-<https://github.com/PolyMC/PolyMC/issues>
-
-RESOURCES
----------
-GitHub: <https://github.com/PolyMC/PolyMC>
-
-Main website: <https://polymc.org>
-
-AUTHORS
--------
-PolyMC Contributors
-
-// vim: syntax=asciidoc