Merge branch 'PrismLauncher:develop' into instance-accounts
This commit is contained in:
commit
e0e3d4d8fe
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -546,11 +546,10 @@ jobs:
|
|||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
- name: Build Flatpak (Linux)
|
- name: Build Flatpak (Linux)
|
||||||
if: inputs.build_type == 'Debug'
|
if: inputs.build_type == 'Debug'
|
||||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v4
|
uses: flatpak/flatpak-github-actions/flatpak-builder@v5
|
||||||
with:
|
with:
|
||||||
bundle: "Prism Launcher.flatpak"
|
bundle: "Prism Launcher.flatpak"
|
||||||
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
|
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
|
||||||
cache-key: flatpak-${{ github.sha }}-x86_64
|
|
||||||
|
|
||||||
nix:
|
nix:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -268,6 +268,8 @@ if(NOT Launcher_FORCE_BUNDLED_LIBS)
|
|||||||
find_package(ghc_filesystem QUIET)
|
find_package(ghc_filesystem QUIET)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(ECMQtDeclareLoggingCategory)
|
||||||
|
|
||||||
####################################### Program Info #######################################
|
####################################### Program Info #######################################
|
||||||
|
|
||||||
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
|
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")
|
||||||
|
@ -551,6 +551,24 @@ set(ATLAUNCHER_SOURCES
|
|||||||
modplatform/atlauncher/ATLShareCode.h
|
modplatform/atlauncher/ATLShareCode.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
######## Logging categories ########
|
||||||
|
|
||||||
|
ecm_qt_declare_logging_category(CORE_SOURCES
|
||||||
|
HEADER Logging.h
|
||||||
|
IDENTIFIER authCredentials
|
||||||
|
CATEGORY_NAME "launcher.auth.credentials"
|
||||||
|
DEFAULT_SEVERITY Warning
|
||||||
|
DESCRIPTION "Secrets and credentials for debugging purposes"
|
||||||
|
EXPORT "${Launcher_Name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(KDE_INSTALL_LOGGINGCATEGORIESDIR) # only install if there is a standard path for this
|
||||||
|
ecm_qt_install_logging_categories(
|
||||||
|
EXPORT "${Launcher_Name}"
|
||||||
|
DESTINATION "${KDE_INSTALL_LOGGINGCATEGORIESDIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
################################ COMPILE ################################
|
################################ COMPILE ################################
|
||||||
|
|
||||||
set(LOGIC_SOURCES
|
set(LOGIC_SOURCES
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "Parsers.h"
|
#include "Parsers.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@ -75,9 +76,7 @@ bool getBool(QJsonValue value, bool & out) {
|
|||||||
|
|
||||||
bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) {
|
bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) {
|
||||||
qDebug() << "Parsing" << name <<":";
|
qDebug() << "Parsing" << name <<":";
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
if(jsonError.error) {
|
if(jsonError.error) {
|
||||||
@ -137,9 +136,7 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
|
|||||||
|
|
||||||
bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
|
bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
|
||||||
qDebug() << "Parsing Minecraft profile...";
|
qDebug() << "Parsing Minecraft profile...";
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -275,9 +272,7 @@ decoded base64 "value":
|
|||||||
|
|
||||||
bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
|
bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
|
||||||
qDebug() << "Parsing Minecraft profile...";
|
qDebug() << "Parsing Minecraft profile...";
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -389,9 +384,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
|
|||||||
|
|
||||||
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
|
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
|
||||||
qDebug() << "Parsing Minecraft entitlements...";
|
qDebug() << "Parsing Minecraft entitlements...";
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -424,9 +417,7 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output)
|
|||||||
|
|
||||||
bool parseRolloutResponse(QByteArray & data, bool& result) {
|
bool parseRolloutResponse(QByteArray & data, bool& result) {
|
||||||
qDebug() << "Parsing Rollout response...";
|
qDebug() << "Parsing Rollout response...";
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
@ -455,9 +446,7 @@ bool parseRolloutResponse(QByteArray & data, bool& result) {
|
|||||||
bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
|
bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
qDebug() << "Parsing Mojang response...";
|
qDebug() << "Parsing Mojang response...";
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
if(jsonError.error) {
|
if(jsonError.error) {
|
||||||
qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString();
|
qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
|
|
||||||
@ -41,9 +42,7 @@ void EntitlementsStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: check presence of same entitlementsRequestId?
|
// TODO: check presence of same entitlementsRequestId?
|
||||||
// TODO: validate JWTs?
|
// TODO: validate JWTs?
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
|
#include "minecraft/auth/AccountTask.h"
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "minecraft/auth/AccountTask.h"
|
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
|
|
||||||
LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {
|
LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {
|
||||||
@ -51,14 +52,10 @@ void LauncherLoginStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
if (error != QNetworkReply::NoError) {
|
if (error != QNetworkReply::NoError) {
|
||||||
qWarning() << "Reply error:" << error;
|
qWarning() << "Reply error:" << error;
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
if (Net::isApplicationError(error)) {
|
if (Net::isApplicationError(error)) {
|
||||||
emit finished(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
@ -76,9 +73,7 @@ void LauncherLoginStep::onRequestDone(
|
|||||||
|
|
||||||
if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
|
if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
|
||||||
qWarning() << "Could not parse login_with_xbox response...";
|
qWarning() << "Could not parse login_with_xbox response...";
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
emit finished(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
tr("Failed to parse the Minecraft access token response.")
|
tr("Failed to parse the Minecraft access token response.")
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
using OAuth2 = Katabasis::DeviceFlow;
|
using OAuth2 = Katabasis::DeviceFlow;
|
||||||
using Activity = Katabasis::Activity;
|
using Activity = Katabasis::Activity;
|
||||||
@ -117,14 +118,12 @@ void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) {
|
|||||||
// Succeeded or did not invalidate tokens
|
// Succeeded or did not invalidate tokens
|
||||||
emit hideVerificationUriAndCode();
|
emit hideVerificationUriAndCode();
|
||||||
QVariantMap extraTokens = m_oauth2->extraTokens();
|
QVariantMap extraTokens = m_oauth2->extraTokens();
|
||||||
#ifndef NDEBUG
|
|
||||||
if (!extraTokens.isEmpty()) {
|
if (!extraTokens.isEmpty()) {
|
||||||
qDebug() << "Extra tokens in response:";
|
qCDebug(authCredentials()) << "Extra tokens in response:";
|
||||||
foreach (QString key, extraTokens.keys()) {
|
foreach (QString key, extraTokens.keys()) {
|
||||||
qDebug() << "\t" << key << ":" << extraTokens.value(key);
|
qCDebug(authCredentials()) << "\t" << key << ":" << extraTokens.value(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
|
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -40,9 +41,7 @@ void MinecraftProfileStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
if (error == QNetworkReply::ContentNotFoundError) {
|
if (error == QNetworkReply::ContentNotFoundError) {
|
||||||
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
||||||
if(m_data->type == AccountType::Mojang) {
|
if(m_data->type == AccountType::Mojang) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -43,9 +44,7 @@ void MinecraftProfileStepMojang::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
if (error == QNetworkReply::ContentNotFoundError) {
|
if (error == QNetworkReply::ContentNotFoundError) {
|
||||||
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
|
||||||
if(m_data->type == AccountType::Mojang) {
|
if(m_data->type == AccountType::Mojang) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QJsonParseError>
|
#include <QJsonParseError>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -58,9 +59,7 @@ void XboxAuthorizationStep::onRequestDone(
|
|||||||
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
|
||||||
requestor->deleteLater();
|
requestor->deleteLater();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
if (error != QNetworkReply::NoError) {
|
if (error != QNetworkReply::NoError) {
|
||||||
qWarning() << "Reply error:" << error;
|
qWarning() << "Reply error:" << error;
|
||||||
if (Net::isApplicationError(error)) {
|
if (Net::isApplicationError(error)) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
#include "minecraft/auth/AuthRequest.h"
|
#include "minecraft/auth/AuthRequest.h"
|
||||||
#include "minecraft/auth/Parsers.h"
|
#include "minecraft/auth/Parsers.h"
|
||||||
#include "net/NetUtils.h"
|
#include "net/NetUtils.h"
|
||||||
@ -56,9 +56,7 @@ void XboxProfileStep::onRequestDone(
|
|||||||
|
|
||||||
if (error != QNetworkReply::NoError) {
|
if (error != QNetworkReply::NoError) {
|
||||||
qWarning() << "Reply error:" << error;
|
qWarning() << "Reply error:" << error;
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << data;
|
||||||
qDebug() << data;
|
|
||||||
#endif
|
|
||||||
if (Net::isApplicationError(error)) {
|
if (Net::isApplicationError(error)) {
|
||||||
emit finished(
|
emit finished(
|
||||||
AccountTaskState::STATE_FAILED_SOFT,
|
AccountTaskState::STATE_FAILED_SOFT,
|
||||||
@ -74,9 +72,7 @@ void XboxProfileStep::onRequestDone(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
qCDebug(authCredentials()) << "XBox profile: " << data;
|
||||||
qDebug() << "XBox profile: " << data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
emit finished(AccountTaskState::STATE_WORKING, tr("Got Xbox profile"));
|
emit finished(AccountTaskState::STATE_WORKING, tr("Got Xbox profile"));
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
#include "MetadataHandler.h"
|
#include "MetadataHandler.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
|
|
||||||
|
static ModPlatform::ProviderCapabilities ProviderCaps;
|
||||||
|
|
||||||
Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details()
|
Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details()
|
||||||
{
|
{
|
||||||
m_enabled = (file.suffix() != "disabled");
|
m_enabled = (file.suffix() != "disabled");
|
||||||
@ -91,6 +93,11 @@ std::pair<int, bool> Mod::compare(const Resource& other, SortType type) const
|
|||||||
if (this_ver < other_ver)
|
if (this_ver < other_ver)
|
||||||
return { -1, type == SortType::VERSION };
|
return { -1, type == SortType::VERSION };
|
||||||
}
|
}
|
||||||
|
case SortType::PROVIDER: {
|
||||||
|
auto compare_result = QString::compare(provider().value_or("Unknown"), cast_other->provider().value_or("Unknown"), Qt::CaseInsensitive);
|
||||||
|
if (compare_result != 0)
|
||||||
|
return { compare_result, type == SortType::PROVIDER };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return { 0, false };
|
return { 0, false };
|
||||||
}
|
}
|
||||||
@ -189,4 +196,11 @@ void Mod::finishResolvingWithDetails(ModDetails&& details)
|
|||||||
m_local_details = std::move(details);
|
m_local_details = std::move(details);
|
||||||
if (metadata)
|
if (metadata)
|
||||||
setMetadata(std::move(metadata));
|
setMetadata(std::move(metadata));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto Mod::provider() const -> std::optional<QString>
|
||||||
|
{
|
||||||
|
if (metadata())
|
||||||
|
return ProviderCaps.readableName(metadata()->provider);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "ModDetails.h"
|
#include "ModDetails.h"
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ public:
|
|||||||
auto description() const -> QString;
|
auto description() const -> QString;
|
||||||
auto authors() const -> QStringList;
|
auto authors() const -> QStringList;
|
||||||
auto status() const -> ModStatus;
|
auto status() const -> ModStatus;
|
||||||
|
auto provider() const -> std::optional<QString>;
|
||||||
|
|
||||||
auto metadata() -> std::shared_ptr<Metadata::ModStruct>;
|
auto metadata() -> std::shared_ptr<Metadata::ModStruct>;
|
||||||
auto metadata() const -> const std::shared_ptr<Metadata::ModStruct>;
|
auto metadata() const -> const std::shared_ptr<Metadata::ModStruct>;
|
||||||
|
@ -48,10 +48,11 @@
|
|||||||
|
|
||||||
#include "minecraft/mod/tasks/LocalModParseTask.h"
|
#include "minecraft/mod/tasks/LocalModParseTask.h"
|
||||||
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
|
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
|
||||||
|
#include "modplatform/ModIndex.h"
|
||||||
|
|
||||||
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed)
|
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed)
|
||||||
{
|
{
|
||||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE };
|
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ModFolderModel::data(const QModelIndex &index, int role) const
|
QVariant ModFolderModel::data(const QModelIndex &index, int role) const
|
||||||
@ -82,7 +83,15 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
case DateColumn:
|
case DateColumn:
|
||||||
return m_resources[row]->dateTimeChanged();
|
return m_resources[row]->dateTimeChanged();
|
||||||
|
case ProviderColumn: {
|
||||||
|
auto provider = at(row)->provider();
|
||||||
|
if (!provider.has_value()) {
|
||||||
|
//: Unknown mod provider (i.e. not Modrinth, CurseForge, etc...)
|
||||||
|
return tr("Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider.value();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -118,6 +127,8 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
|
|||||||
return tr("Version");
|
return tr("Version");
|
||||||
case DateColumn:
|
case DateColumn:
|
||||||
return tr("Last changed");
|
return tr("Last changed");
|
||||||
|
case ProviderColumn:
|
||||||
|
return tr("Provider");
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -133,6 +144,8 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
|
|||||||
return tr("The version of the mod.");
|
return tr("The version of the mod.");
|
||||||
case DateColumn:
|
case DateColumn:
|
||||||
return tr("The date and time this mod was last changed (or added).");
|
return tr("The date and time this mod was last changed (or added).");
|
||||||
|
case ProviderColumn:
|
||||||
|
return tr("Where the mod was downloaded from.");
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ public:
|
|||||||
NameColumn,
|
NameColumn,
|
||||||
VersionColumn,
|
VersionColumn,
|
||||||
DateColumn,
|
DateColumn,
|
||||||
|
ProviderColumn,
|
||||||
NUM_COLUMNS
|
NUM_COLUMNS
|
||||||
};
|
};
|
||||||
enum ModStatusAction {
|
enum ModStatusAction {
|
||||||
|
@ -20,7 +20,8 @@ enum class SortType {
|
|||||||
DATE,
|
DATE,
|
||||||
VERSION,
|
VERSION,
|
||||||
ENABLED,
|
ENABLED,
|
||||||
PACK_FORMAT
|
PACK_FORMAT,
|
||||||
|
PROVIDER
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EnableAction {
|
enum class EnableAction {
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ModListView.h"
|
#include "ModListView.h"
|
||||||
|
|
||||||
|
#include "minecraft/mod/ModFolderModel.h"
|
||||||
|
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
@ -62,4 +65,17 @@ void ModListView::setModel ( QAbstractItemModel* model )
|
|||||||
for(int i = 1; i < head->count(); i++)
|
for(int i = 1; i < head->count(); i++)
|
||||||
head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
head->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto real_model = model;
|
||||||
|
if (auto proxy_model = dynamic_cast<QSortFilterProxyModel*>(model); proxy_model)
|
||||||
|
real_model = proxy_model->sourceModel();
|
||||||
|
|
||||||
|
if (auto mod_model = dynamic_cast<ModFolderModel*>(real_model); mod_model) {
|
||||||
|
connect(mod_model, &ModFolderModel::updateFinished, this, [this, mod_model]{
|
||||||
|
auto mods = mod_model->allMods();
|
||||||
|
// Hide the 'Provider' column if no mod has a defined provider!
|
||||||
|
setColumnHidden(ModFolderModel::Columns::ProviderColumn,
|
||||||
|
std::none_of(mods.constBegin(), mods.constEnd(), [](auto const mod){ return mod->provider().has_value(); }));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,15 @@ set( katabasis_PUBLIC
|
|||||||
include/katabasis/RequestParameter.h
|
include/katabasis/RequestParameter.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ecm_qt_declare_logging_category(katabasis_PRIVATE
|
||||||
|
HEADER KatabasisLogging.h # NOTE: this won't be in src/, but CMAKE_BINARY_DIR/src isn't included by default so this should be fine
|
||||||
|
IDENTIFIER katabasisCredentials
|
||||||
|
CATEGORY_NAME "katabasis.credentials"
|
||||||
|
DEFAULT_SEVERITY Warning
|
||||||
|
DESCRIPTION "Secrets and credentials from Katabasis"
|
||||||
|
EXPORT "Katabasis"
|
||||||
|
)
|
||||||
|
|
||||||
add_library( Katabasis STATIC ${katabasis_PRIVATE} ${katabasis_PUBLIC} )
|
add_library( Katabasis STATIC ${katabasis_PRIVATE} ${katabasis_PUBLIC} )
|
||||||
target_link_libraries(Katabasis Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network)
|
target_link_libraries(Katabasis Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network)
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QLoggingCategory>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
@ -19,9 +19,11 @@
|
|||||||
#include "katabasis/PollServer.h"
|
#include "katabasis/PollServer.h"
|
||||||
#include "katabasis/Globals.h"
|
#include "katabasis/Globals.h"
|
||||||
|
|
||||||
|
#include "KatabasisLogging.h"
|
||||||
#include "JsonResponse.h"
|
#include "JsonResponse.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// ref: https://tools.ietf.org/html/rfc8628#section-3.2
|
// ref: https://tools.ietf.org/html/rfc8628#section-3.2
|
||||||
// Exception: Google sign-in uses "verification_url" instead of "*_uri" - we'll accept both.
|
// Exception: Google sign-in uses "verification_url" instead of "*_uri" - we'll accept both.
|
||||||
bool hasMandatoryDeviceAuthParams(const QVariantMap& params)
|
bool hasMandatoryDeviceAuthParams(const QVariantMap& params)
|
||||||
@ -333,9 +335,7 @@ QString DeviceFlow::refreshToken() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceFlow::setRefreshToken(const QString &v) {
|
void DeviceFlow::setRefreshToken(const QString &v) {
|
||||||
#ifndef NDEBUG
|
qCDebug(katabasisCredentials) << "new refresh token:" << v;
|
||||||
qDebug() << "DeviceFlow::setRefreshToken" << v << "...";
|
|
||||||
#endif
|
|
||||||
token_.refresh_token = v;
|
token_.refresh_token = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,38 +19,49 @@
|
|||||||
<p>Features:</p>
|
<p>Features:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Easily install game modifications, such as Fabric, Forge and Quilt</li>
|
<li>Easily install game modifications, such as Fabric, Forge and Quilt</li>
|
||||||
<li>Control your Java settings</li>
|
<li>Easily install and update modpacks from the Launcher</li>
|
||||||
|
<li>Control your Java settings, and enable Mangohud or Gamemode with a toggle</li>
|
||||||
<li>Manage worlds and resource packs from the launcher</li>
|
<li>Manage worlds and resource packs from the launcher</li>
|
||||||
<li>See logs and other details easily</li>
|
<li>See logs and other details easily through a dashboard</li>
|
||||||
<li>Kill Minecraft in case of a crash/freeze</li>
|
<li>Kill Minecraft in case of a crash/freeze</li>
|
||||||
<li>Isolate Minecraft instances to keep everything clean</li>
|
<li>Isolate Minecraft instances to keep everything clean</li>
|
||||||
<li>Install and update mods directly from the launcher</li>
|
<li>Install and update mods directly from the launcher</li>
|
||||||
|
<li>Customize the launcher with themes, and more</li>
|
||||||
|
<li>And cat :3</li>
|
||||||
</ul>
|
</ul>
|
||||||
</description>
|
</description>
|
||||||
<screenshots>
|
<screenshots>
|
||||||
<screenshot type="default">
|
<screenshot type="default">
|
||||||
<caption>The main Prism Launcher window</caption>
|
<caption>The main Prism Launcher window</caption>
|
||||||
<image type="source" width="976" height="764">https://prismlauncher.org/img/screenshots/LauncherDark.png</image>
|
<image type="source" width="1030" height="764">https://prismlauncher.org/img/screenshots/LauncherDark.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<caption>Modpack installation</caption>
|
<caption>Modpack installation</caption>
|
||||||
<image type="source" width="1103" height="954">https://prismlauncher.org/img/screenshots/ModpackInstallDark.png</image>
|
<image type="source" width="1126" height="850">https://prismlauncher.org/img/screenshots/ModpackInstallDark.png</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<caption>Modpack updating</caption>
|
||||||
|
<image type="source" width="930" height="677">https://prismlauncher.org/img/screenshots/ModpackUpdateDark.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<caption>Mod installation</caption>
|
<caption>Mod installation</caption>
|
||||||
<image type="source" width="1036" height="700">https://prismlauncher.org/img/screenshots/ModInstallDark.png</image>
|
<image type="source" width="848" height="558">https://prismlauncher.org/img/screenshots/ModInstallDark.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<caption>Mod updating</caption>
|
<caption>Mod updating</caption>
|
||||||
<image type="source" width="930" height="858">https://prismlauncher.org/img/screenshots/ModUpdateDark.png</image>
|
<image type="source" width="860" height="748">https://prismlauncher.org/img/screenshots/ModUpdateDark.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<caption>Instance management</caption>
|
<caption>Instance management</caption>
|
||||||
<image type="source" width="1083" height="735">https://prismlauncher.org/img/screenshots/PropertiesDark.png</image>
|
<image type="source" width="960" height="659">https://prismlauncher.org/img/screenshots/PropertiesDark.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<caption>Cat :)</caption>
|
<caption>Cat :3</caption>
|
||||||
<image type="source" width="931" height="759">https://prismlauncher.org/img/screenshots/LauncherCatDark.png</image>
|
<image type="source" width="1042" height="754">https://prismlauncher.org/img/screenshots/LauncherCatDark.png</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<caption>Customization</caption>
|
||||||
|
<image type="source" width="1040" height="752">https://prismlauncher.org/img/screenshots/CustomizeDark.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<releases>
|
<releases>
|
||||||
|
Loading…
Reference in New Issue
Block a user