diff --git a/.envrc b/.envrc index 3550a30f2..190b5b2b3 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ use flake +watch_file nix/*.nix diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 6bad57030..ad4016ff4 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v3 - uses: cachix/install-nix-action@v22 - - uses: DeterminateSystems/update-flake-lock@v19 + - uses: DeterminateSystems/update-flake-lock@v20 with: commit-msg: "chore(nix): update lockfile" pr-title: "chore(nix): update lockfile" diff --git a/flake.lock b/flake.lock index 28ef60f30..5599efe16 100644 --- a/flake.lock +++ b/flake.lock @@ -91,11 +91,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1692463654, - "narHash": "sha256-F8hZmsQINI+S6UROM4jyxAMbQLtzE44pI8Nk6NtMdao=", + "lastModified": 1693060755, + "narHash": "sha256-KNsbfqewEziFJEpPR0qvVz4rx0x6QXxw1CcunRhlFdk=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ca3c9ac9f4cdd4bea19f592b32bb59b74ab7d783", + "rev": "c66ccfa00c643751da2fd9290e096ceaa30493fc", "type": "github" }, "original": { diff --git a/launcher/Version.h b/launcher/Version.h index 92bff9ba9..9c043b013 100644 --- a/launcher/Version.h +++ b/launcher/Version.h @@ -103,14 +103,8 @@ class Version { QString m_fullString; - [[nodiscard]] inline bool isAppendix() const - { - return m_stringPart.startsWith('+'); - } - [[nodiscard]] inline bool isPreRelease() const - { - return m_stringPart.startsWith('-') && m_stringPart.length() > 1; - } + [[nodiscard]] inline bool isAppendix() const { return m_stringPart.startsWith('+'); } + [[nodiscard]] inline bool isPreRelease() const { return m_stringPart.startsWith('-') && m_stringPart.length() > 1; } inline bool operator==(const Section& other) const { @@ -156,14 +150,8 @@ class Version { return m_fullString < other.m_fullString; } - inline bool operator!=(const Section& other) const - { - return !(*this == other); - } - inline bool operator>(const Section& other) const - { - return !(*this < other || *this == other); - } + inline bool operator!=(const Section& other) const { return !(*this == other); } + inline bool operator>(const Section& other) const { return !(*this < other || *this == other); } }; private: diff --git a/launcher/launch/LogModel.h b/launcher/launch/LogModel.h index ba2e4054a..18e51d7e3 100644 --- a/launcher/launch/LogModel.h +++ b/launcher/launch/LogModel.h @@ -30,7 +30,7 @@ class LogModel : public QAbstractListModel { enum Roles { LevelRole = Qt::UserRole }; - private /* types */: + private /* types */: struct entry { MessageLevel::Enum level; QString line; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 280e70d7b..eed35615c 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -51,8 +51,13 @@ #include "Application.h" +#include "Json.h" #include "minecraft/mod/tasks/LocalModParseTask.h" +#include "minecraft/mod/tasks/LocalModUpdateTask.h" #include "minecraft/mod/tasks/ModFolderLoadTask.h" +#include "modplatform/ModIndex.h" +#include "modplatform/flame/FlameAPI.h" +#include "modplatform/flame/FlameModIndex.h" ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) @@ -309,3 +314,47 @@ void ModFolderModel::onParseSucceeded(int ticket, QString mod_id) emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); } + +static const FlameAPI flameAPI; +bool ModFolderModel::installMod(QString file_path, ModPlatform::IndexedVersion& vers) +{ + if (vers.addonId.isValid()) { + ModPlatform::IndexedPack pack{ + vers.addonId, + ModPlatform::ResourceProvider::FLAME, + }; + + QEventLoop loop; + + auto response = std::make_shared(); + auto job = flameAPI.getProject(vers.addonId.toString(), response); + + QObject::connect(job.get(), &Task::failed, [&loop] { loop.quit(); }); + QObject::connect(job.get(), &Task::aborted, &loop, &QEventLoop::quit); + QObject::connect(job.get(), &Task::succeeded, [response, this, &vers, &loop, &pack] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qDebug() << *response; + return; + } + try { + auto obj = Json::requireObject(Json::requireObject(doc), "data"); + FlameMod::loadIndexedPack(pack, obj); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading mod info: " << e.cause(); + } + LocalModUpdateTask update_metadata(indexDir(), pack, vers); + QObject::connect(&update_metadata, &Task::finished, &loop, &QEventLoop::quit); + update_metadata.start(); + }); + + job->start(); + + loop.exec(); + } + return ResourceFolderModel::installResource(file_path); +} diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 06fd78149..f1890e87e 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -48,6 +48,7 @@ #include "minecraft/mod/tasks/LocalModParseTask.h" #include "minecraft/mod/tasks/ModFolderLoadTask.h" +#include "modplatform/ModIndex.h" class LegacyInstance; class BaseInstance; @@ -75,6 +76,7 @@ class ModFolderModel : public ResourceFolderModel { [[nodiscard]] Task* createParseTask(Resource&) override; bool installMod(QString file_path) { return ResourceFolderModel::installResource(file_path); } + bool installMod(QString file_path, ModPlatform::IndexedVersion& vers); bool uninstallMod(const QString& filename, bool preserve_metadata = false); /// Deletes all the selected mods diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 7900e6c45..7a197f622 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -118,7 +118,9 @@ #include "minecraft/mod/TexturePackFolderModel.h" #include "minecraft/mod/tasks/LocalResourceParse.h" +#include "modplatform/ModIndex.h" #include "modplatform/flame/FlameAPI.h" +#include "modplatform/flame/FlameModIndex.h" #include "KonamiCode.h" @@ -923,6 +925,7 @@ void MainWindow::processURLs(QList urls) if (url.scheme().isEmpty()) url.setScheme("file"); + ModPlatform::IndexedVersion version; QMap extra_info; QUrl local_url; if (!url.isLocalFile()) { // download the remote resource and identify @@ -948,20 +951,19 @@ void MainWindow::processURLs(QList urls) auto api = FlameAPI(); auto job = api.getFile(addonId, fileId, array); - QString resource_name; - connect(job.get(), &Task::failed, this, [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(job.get(), &Task::succeeded, this, [this, array, addonId, fileId, &dl_url, &resource_name] { + connect(job.get(), &Task::succeeded, this, [this, array, addonId, fileId, &dl_url, &version] { qDebug() << "Returned CFURL Json:\n" << array->toStdString().c_str(); auto doc = Json::requireDocument(*array); auto data = Json::ensureObject(Json::ensureObject(doc.object()), "data"); // No way to find out if it's a mod or a modpack before here // And also we need to check if it ends with .zip, instead of any better way - auto fileName = Json::ensureString(data, "fileName"); + version = FlameMod::loadIndexedPackVersion(data); + auto fileName = version.fileName; // Have to use ensureString then use QUrl to get proper url encoding - dl_url = QUrl(Json::ensureString(data, "downloadUrl", "", "downloadUrl")); + dl_url = QUrl(version.downloadUrl); if (!dl_url.isValid()) { CustomMessageBox::selectable( this, tr("Error"), @@ -972,7 +974,6 @@ void MainWindow::processURLs(QList urls) } QFileInfo dl_file(dl_url.fileName()); - resource_name = Json::ensureString(data, "displayName", dl_file.completeBaseName(), "displayName"); }); { // drop stack @@ -1047,7 +1048,7 @@ void MainWindow::processURLs(QList urls) qWarning() << "Importing of Data Packs not supported at this time. Ignoring" << localFileName; break; case PackedResourceType::Mod: - minecraftInst->loaderModList()->installMod(localFileName); + minecraftInst->loaderModList()->installMod(localFileName, version); break; case PackedResourceType::ShaderPack: minecraftInst->shaderPackList()->installResource(localFileName); diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index b6f45da2e..0b6144522 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -151,10 +151,7 @@ class MainWindow : public QMainWindow { void deleteGroup(); void undoTrashInstance(); - inline void on_actionExportInstance_triggered() - { - on_actionExportInstanceZip_triggered(); - } + inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); void on_actionExportInstanceFlamePack_triggered(); diff --git a/launcher/ui/pages/global/JavaPage.cpp b/launcher/ui/pages/global/JavaPage.cpp index 45d8f0180..ac50319ec 100644 --- a/launcher/ui/pages/global/JavaPage.cpp +++ b/launcher/ui/pages/global/JavaPage.cpp @@ -185,6 +185,7 @@ void JavaPage::updateThresholds() { auto sysMiB = Sys::getSystemRam() / Sys::mebibyte; unsigned int maxMem = ui->maxMemSpinBox->value(); + unsigned int minMem = ui->minMemSpinBox->value(); QString iconName; @@ -194,6 +195,9 @@ void JavaPage::updateThresholds() } else if (maxMem > (sysMiB * 0.9)) { iconName = "status-yellow"; ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); + } else if (maxMem < minMem) { + iconName = "status-yellow"; + ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else { iconName = "status-good"; ui->labelMaxMemIcon->setToolTip(""); diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index d5dbb80b8..7aa6bd322 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -478,6 +478,7 @@ void InstanceSettingsPage::updateThresholds() { auto sysMiB = Sys::getSystemRam() / Sys::mebibyte; unsigned int maxMem = ui->maxMemSpinBox->value(); + unsigned int minMem = ui->minMemSpinBox->value(); QString iconName; @@ -487,6 +488,9 @@ void InstanceSettingsPage::updateThresholds() } else if (maxMem > (sysMiB * 0.9)) { iconName = "status-yellow"; ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); + } else if (maxMem < minMem) { + iconName = "status-yellow"; + ui->labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else { iconName = "status-good"; ui->labelMaxMemIcon->setToolTip(""); diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp index 6bf802e63..2142e6c9f 100644 --- a/launcher/ui/pages/instance/ServersPage.cpp +++ b/launcher/ui/pages/instance/ServersPage.cpp @@ -354,14 +354,8 @@ class ServersModel : public QAbstractListModel { } } - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override - { - return parent.isValid() ? 0 : m_servers.size(); - } - int columnCount(const QModelIndex& parent) const override - { - return parent.isValid() ? 0 : COLUMN_COUNT; - } + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override { return parent.isValid() ? 0 : m_servers.size(); } + int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : COLUMN_COUNT; } Server* at(int index) { @@ -445,10 +439,7 @@ class ServersModel : public QAbstractListModel { qDebug() << "Changed:" << path; load(); } - void fileChanged(const QString& path) - { - qDebug() << "Changed:" << path; - } + void fileChanged(const QString& path) { qDebug() << "Changed:" << path; } private slots: void save_internal() @@ -492,10 +483,7 @@ class ServersModel : public QAbstractListModel { m_saveTimer.stop(); } - bool saveIsScheduled() const - { - return m_dirty; - } + bool saveIsScheduled() const { return m_dirty; } void updateFSObserver() { diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 42279a663..d2d921918 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -186,12 +186,20 @@ QString JavaSettingsWidget::javaPath() const int JavaSettingsWidget::maxHeapSize() const { - return m_maxMemSpinBox->value(); + auto min = m_minMemSpinBox->value(); + auto max = m_maxMemSpinBox->value(); + if (max < min) + max = min; + return max; } int JavaSettingsWidget::minHeapSize() const { - return m_minMemSpinBox->value(); + auto min = m_minMemSpinBox->value(); + auto max = m_maxMemSpinBox->value(); + if (min > max) + min = max; + return min; } bool JavaSettingsWidget::permGenEnabled() const @@ -214,17 +222,9 @@ void JavaSettingsWidget::memoryValueChanged(int) if (obj == m_minMemSpinBox && min != observedMinMemory) { observedMinMemory = min; actuallyChanged = true; - if (min > max) { - observedMaxMemory = min; - m_maxMemSpinBox->setValue(min); - } } else if (obj == m_maxMemSpinBox && max != observedMaxMemory) { observedMaxMemory = max; actuallyChanged = true; - if (min > max) { - observedMinMemory = max; - m_minMemSpinBox->setValue(max); - } } else if (obj == m_permGenSpinBox && permgen != observedPermGenMemory) { observedPermGenMemory = permgen; actuallyChanged = true; @@ -361,8 +361,8 @@ void JavaSettingsWidget::checkJavaPath(const QString& path) setJavaStatus(JavaStatus::Pending); m_checker.reset(new JavaChecker()); m_checker->m_path = path; - m_checker->m_minMem = m_minMemSpinBox->value(); - m_checker->m_maxMem = m_maxMemSpinBox->value(); + m_checker->m_minMem = minHeapSize(); + m_checker->m_maxMem = maxHeapSize(); if (m_permGenSpinBox->isVisible()) { m_checker->m_permGen = m_permGenSpinBox->value(); } @@ -415,6 +415,9 @@ void JavaSettingsWidget::updateThresholds() } else if (observedMaxMemory > (m_availableMemory * 0.9)) { iconName = "status-yellow"; m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation approaches your system memory capacity.")); + } else if (observedMaxMemory < observedMinMemory) { + iconName = "status-yellow"; + m_labelMaxMemIcon->setToolTip(tr("Your maximum memory allocation is smaller than the minimum value")); } else { iconName = "status-good"; m_labelMaxMemIcon->setToolTip(""); diff --git a/libraries/LocalPeer/src/LocalPeer.cpp b/libraries/LocalPeer/src/LocalPeer.cpp index ab528c2a1..bd407042f 100644 --- a/libraries/LocalPeer/src/LocalPeer.cpp +++ b/libraries/LocalPeer/src/LocalPeer.cpp @@ -220,5 +220,5 @@ void LocalPeer::receiveConnection() socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; - emit messageReceived(uMsg); //### (might take a long time to return) + emit messageReceived(uMsg); // ### (might take a long time to return) } diff --git a/nix/dev.nix b/nix/dev.nix index c39e15653..a9c1dc65d 100644 --- a/nix/dev.nix +++ b/nix/dev.nix @@ -23,18 +23,13 @@ types_or = ["c" "c++" "java" "json" "objective-c"]; }; }; + + tools.clang-tools = pkgs.clang-tools_16; }; }; devShells.default = pkgs.mkShell { inherit (self.checks.${system}.pre-commit-check) shellHook; - packages = with pkgs; [ - nodePackages.markdownlint-cli - alejandra - deadnix - clang-tools - nil - ]; inputsFrom = [self.packages.${system}.prismlauncher-unwrapped]; buildInputs = with pkgs; [ccache ninja]; diff --git a/nix/package.nix b/nix/package.nix index 1dbadd405..074214c4b 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -1,6 +1,7 @@ { lib, stdenv, + canonicalize-jars-hook, cmake, cmark, Cocoa, @@ -26,7 +27,7 @@ assert lib.assertMsg (stdenv.isLinux || !gamemodeSupport) "gamemodeSupport is on src = lib.cleanSource self; - nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja]; + nativeBuildInputs = [extra-cmake-modules cmake jdk17 ninja canonicalize-jars-hook]; buildInputs = [ qtbase diff --git a/tests/FileSystem_test.cpp b/tests/FileSystem_test.cpp index e19410423..1d3cee85f 100644 --- a/tests/FileSystem_test.cpp +++ b/tests/FileSystem_test.cpp @@ -353,10 +353,7 @@ class FileSystemTest : public QObject { } } - void test_getDesktop() - { - QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); - } + void test_getDesktop() { QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); } void test_link() {