aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--CODE_OF_CONDUCT.md136
-rw-r--r--flake.nix12
-rw-r--r--launcher/Application.cpp67
-rw-r--r--launcher/LaunchController.cpp12
-rw-r--r--launcher/minecraft/auth/AccountData.cpp5
-rw-r--r--launcher/minecraft/auth/AccountData.h2
-rw-r--r--launcher/minecraft/auth/AccountList.cpp3
-rw-r--r--launcher/minecraft/auth/AccountTask.cpp8
-rw-r--r--launcher/minecraft/auth/AccountTask.h1
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.cpp3
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.cpp8
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.h1
-rw-r--r--launcher/ui/MainWindow.cpp2
-rw-r--r--packages/nix/polymc/default.nix13
15 files changed, 222 insertions, 53 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d4a27260..003aa65d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,7 +73,7 @@ set(Launcher_META_URL "https://meta.polymc.org/v1/" CACHE STRING "URL to fetch L
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
# MSA Client ID
-set(Launcher_MSA_CLIENT_ID "17b47edd-c884-4997-926d-9e7f9a6b4647" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
+set(Launcher_MSA_CLIENT_ID "549033b2-1532-4d4e-ae77-1bbaa46f9d74" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application")
# Bug tracker URL
set(Launcher_BUG_TRACKER_URL "https://github.com/PolyMC/PolyMC/issues" CACHE STRING "URL for the bug tracker.")
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..52a9f30a
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,136 @@
+# Contributor Covenant Code of Conduct
+This is a modified version of the Contributor Covenant.
+See commit history to see our changes.
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+* Trolling (antagonistic, inflammatory, insincere behaviour), insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement via email at
+[polymc-enforcement@scrumplex.net](mailto:polymc-enforcement@scrumplex.net) (Email
+address subject to change).
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
+
diff --git a/flake.nix b/flake.nix
index d809066a..5f95b4e6 100644
--- a/flake.nix
+++ b/flake.nix
@@ -16,11 +16,19 @@
};
outputs = args@{ self, nixpkgs, flake-utils, libnbtplusplus, quazip, ... }:
- {
+ let
+ systems = [
+ "aarch64-linux"
+ # "aarch64-darwin" # qtbase is currently broken
+ "i686-linux"
+ "x86_64-darwin"
+ "x86_64-linux"
+ ];
+ in {
overlay = final: prev: {
inherit (self.packages.${final.system}) polymc;
};
- } // flake-utils.lib.eachDefaultSystem (system:
+ } // flake-utils.lib.eachSystem systems (system:
let pkgs = import nixpkgs { inherit system; };
in {
packages = {
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index a3d6216e..e33df252 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -192,27 +192,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
#endif
startTime = QDateTime::currentDateTime();
-#ifdef Q_OS_LINUX
- {
- QFile osrelease("/proc/sys/kernel/osrelease");
- if (osrelease.open(QFile::ReadOnly | QFile::Text)) {
- QTextStream in(&osrelease);
- auto contents = in.readAll();
- if(
- contents.contains("WSL", Qt::CaseInsensitive) ||
- contents.contains("Microsoft", Qt::CaseInsensitive)
- ) {
- showFatalErrorMessage(
- "Unsupported system detected!",
- "Linux-on-Windows distributions are not supported.\n\n"
- "Please use the Windows binary when playing on Windows."
- );
- return;
- }
- }
- }
-#endif
-
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@@ -285,12 +264,21 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return;
}
}
+
m_instanceIdToLaunch = args["launch"].toString();
m_serverToJoin = args["server"].toString();
m_profileToUse = args["profile"].toString();
m_liveCheck = args["alive"].toBool();
m_zipToImport = args["import"].toUrl();
+ // error if --launch is missing with --server or --profile
+ if((!m_serverToJoin.isEmpty() || !m_profileToUse.isEmpty()) && m_instanceIdToLaunch.isEmpty())
+ {
+ std::cerr << "--server and --profile can only be used in combination with --launch!" << std::endl;
+ m_status = Application::Failed;
+ return;
+ }
+
QString origcwdPath = QDir::currentPath();
QString binPath = applicationDirPath();
QString adjustedBy;
@@ -359,20 +347,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return;
}
- if(m_instanceIdToLaunch.isEmpty() && !m_serverToJoin.isEmpty())
- {
- std::cerr << "--server can only be used in combination with --launch!" << std::endl;
- m_status = Application::Failed;
- return;
- }
-
- if(m_instanceIdToLaunch.isEmpty() && !m_profileToUse.isEmpty())
- {
- std::cerr << "--account can only be used in combination with --launch!" << std::endl;
- m_status = Application::Failed;
- return;
- }
-
#if defined(Q_OS_MAC)
// move user data to new location if on macOS and it still exists in Contents/MacOS
QDir fi(applicationDirPath());
@@ -566,26 +540,23 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "<> Paths set.";
}
- do // once
+ if(m_liveCheck)
{
- if(m_liveCheck)
+ QFile check(liveCheckFile);
+ if(check.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
- QFile check(liveCheckFile);
- if(!check.open(QIODevice::WriteOnly | QIODevice::Truncate))
- {
- qWarning() << "Could not open" << liveCheckFile << "for writing!";
- break;
- }
auto payload = appID.toString().toUtf8();
- if(check.write(payload) != payload.size())
+ if(check.write(payload) == payload.size())
{
+ check.close();
+ } else {
qWarning() << "Could not write into" << liveCheckFile << "!";
- check.remove();
- break;
+ check.remove(); // also closes file!
}
- check.close();
+ } else {
+ qWarning() << "Could not open" << liveCheckFile << "for writing!";
}
- } while(false);
+ }
// Initialize application settings
{
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 32fc99cb..40178b70 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -228,6 +228,18 @@ void LaunchController::login() {
emitFailed(errorString);
return;
}
+ case AccountState::Disabled: {
+ auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again.");
+ QMessageBox::warning(
+ m_parentWidget,
+ tr("Client identification changed"),
+ errorString,
+ QMessageBox::StandardButton::Ok,
+ QMessageBox::StandardButton::Ok
+ );
+ emitFailed(errorString);
+ return;
+ }
case AccountState::Gone: {
auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to.");
QMessageBox::warning(
diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp
index 9b84fe1a..f791db14 100644
--- a/launcher/minecraft/auth/AccountData.cpp
+++ b/launcher/minecraft/auth/AccountData.cpp
@@ -327,6 +327,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
}
if(type == AccountType::MSA) {
+ auto clientIDV = data.value("msa-client-id");
+ if (clientIDV.isString()) {
+ msaClientID = clientIDV.toString();
+ } // leave msaClientID empty if it doesn't exist or isn't a string
msaToken = tokenFromJSONV3(data, "msa");
userToken = tokenFromJSONV3(data, "utoken");
xboxApiToken = tokenFromJSONV3(data, "xrp-main");
@@ -360,6 +364,7 @@ QJsonObject AccountData::saveState() const {
}
else if (type == AccountType::MSA) {
output["type"] = "MSA";
+ output["msa-client-id"] = msaClientID;
tokenToJSONV3(output, msaToken, "msa");
tokenToJSONV3(output, userToken, "utoken");
tokenToJSONV3(output, xboxApiToken, "xrp-main");
diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h
index 606c1ad1..6749a471 100644
--- a/launcher/minecraft/auth/AccountData.h
+++ b/launcher/minecraft/auth/AccountData.h
@@ -47,6 +47,7 @@ enum class AccountState {
Offline,
Working,
Online,
+ Disabled,
Errored,
Expired,
Gone
@@ -81,6 +82,7 @@ struct AccountData {
bool legacy = false;
bool canMigrateToMSA = false;
+ QString msaClientID;
Katabasis::Token msaToken;
Katabasis::Token userToken;
Katabasis::Token xboxApiToken;
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index 04470e1c..e404cdda 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -291,6 +291,9 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
case AccountState::Expired: {
return tr("Expired", "Account status");
}
+ case AccountState::Disabled: {
+ return tr("Disabled", "Account status");
+ }
case AccountState::Gone: {
return tr("Gone", "Account status");
}
diff --git a/launcher/minecraft/auth/AccountTask.cpp b/launcher/minecraft/auth/AccountTask.cpp
index 98d8d94d..321b350f 100644
--- a/launcher/minecraft/auth/AccountTask.cpp
+++ b/launcher/minecraft/auth/AccountTask.cpp
@@ -43,6 +43,8 @@ QString AccountTask::getStateMessage() const
return tr("Authentication task succeeded.");
case AccountTaskState::STATE_OFFLINE:
return tr("Failed to contact the authentication server.");
+ case AccountTaskState::STATE_DISABLED:
+ return tr("Client ID has changed. New session needs to be created.");
case AccountTaskState::STATE_FAILED_SOFT:
return tr("Encountered an error during authentication.");
case AccountTaskState::STATE_FAILED_HARD:
@@ -78,6 +80,12 @@ bool AccountTask::changeState(AccountTaskState newState, QString reason)
emitFailed(reason);
return false;
}
+ case AccountTaskState::STATE_DISABLED: {
+ m_data->errorString = reason;
+ m_data->accountState = AccountState::Disabled;
+ emitFailed(reason);
+ return false;
+ }
case AccountTaskState::STATE_FAILED_SOFT: {
m_data->errorString = reason;
m_data->accountState = AccountState::Errored;
diff --git a/launcher/minecraft/auth/AccountTask.h b/launcher/minecraft/auth/AccountTask.h
index dac3f1b5..c2a5d86c 100644
--- a/launcher/minecraft/auth/AccountTask.h
+++ b/launcher/minecraft/auth/AccountTask.h
@@ -35,6 +35,7 @@ enum class AccountTaskState
STATE_CREATED,
STATE_WORKING,
STATE_SUCCEEDED,
+ STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn
STATE_FAILED_SOFT, //!< soft failure. authentication went through partially
STATE_FAILED_HARD, //!< hard failure. main tokens are invalid
STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists
diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index ffc81ed8..a604cadf 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -176,6 +176,9 @@ void MinecraftAccount::authFailed(QString reason)
{
switch (m_currentTask->taskState()) {
case AccountTaskState::STATE_OFFLINE:
+ case AccountTaskState::STATE_DISABLED: {
+ // NOTE: user will need to fix this themselves.
+ }
case AccountTaskState::STATE_FAILED_SOFT: {
// NOTE: this doesn't do much. There was an error of some sort.
}
diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp
index 779aee43..207d9373 100644
--- a/launcher/minecraft/auth/steps/MSAStep.cpp
+++ b/launcher/minecraft/auth/steps/MSAStep.cpp
@@ -12,9 +12,10 @@ using OAuth2 = Katabasis::DeviceFlow;
using Activity = Katabasis::Activity;
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
+ m_clientId = APPLICATION->getMSAClientID();
OAuth2::Options opts;
opts.scope = "XboxLive.signin offline_access";
- opts.clientIdentifier = APPLICATION->getMSAClientID();
+ opts.clientIdentifier = m_clientId;
opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
@@ -48,6 +49,10 @@ void MSAStep::rehydrate() {
void MSAStep::perform() {
switch(m_action) {
case Refresh: {
+ if (m_data->msaClientID != m_clientId) {
+ emit hideVerificationUriAndCode();
+ emit finished(AccountTaskState::STATE_DISABLED, tr("Microsoft user authentication failed - client identification has changed."));
+ }
m_oauth2->refresh();
return;
}
@@ -57,6 +62,7 @@ void MSAStep::perform() {
m_oauth2->setExtraRequestParams(extraOpts);
*m_data = AccountData();
+ m_data->msaClientID = m_clientId;
m_oauth2->login();
return;
}
diff --git a/launcher/minecraft/auth/steps/MSAStep.h b/launcher/minecraft/auth/steps/MSAStep.h
index 49ba3542..301e1465 100644
--- a/launcher/minecraft/auth/steps/MSAStep.h
+++ b/launcher/minecraft/auth/steps/MSAStep.h
@@ -29,4 +29,5 @@ private slots:
private:
Katabasis::DeviceFlow *m_oauth2 = nullptr;
Action m_action;
+ QString m_clientId;
};
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index 32b27afb..ad7227cc 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -588,7 +588,7 @@ public:
actionExportInstance = TranslatedAction(MainWindow);
actionExportInstance->setObjectName(QStringLiteral("actionExportInstance"));
actionExportInstance.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Export Instance"));
- // FIXME: missing tooltip
+ actionExportInstance.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Export the selected instance as a zip file."));
all_actions.append(&actionExportInstance);
instanceToolBar->addAction(actionExportInstance);
diff --git a/packages/nix/polymc/default.nix b/packages/nix/polymc/default.nix
index e65a7e34..a9610017 100644
--- a/packages/nix/polymc/default.nix
+++ b/packages/nix/polymc/default.nix
@@ -79,4 +79,17 @@ mkDerivation rec {
--set GAME_LIBRARY_PATH ${gameLibraryPath} \
--prefix PATH : ${lib.makeBinPath [ xorg.xrandr ]}
'';
+
+ meta = with lib; {
+ homepage = "https://polymc.org/";
+ description = "A free, open source launcher for Minecraft";
+ longDescription = ''
+ Allows you to have multiple, separate instances of Minecraft (each with
+ their own mods, texture packs, saves, etc) and helps you manage them and
+ their associated options with a simple interface.
+ '';
+ platforms = platforms.unix;
+ license = licenses.gpl3Plus;
+ maintainers = with maintainers; [ starcraft66 kloenk ];
+ };
}