From 7ee008e150bc5bcf76082d726f719ee0fdfda982 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Wed, 11 Feb 2026 02:37:39 -0600 Subject: Fluorine Manager: full Linux port of Mod Organizer 2 Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 --- libs/installer_quick/.clang-format | 41 +++++ libs/installer_quick/.git-blame-ignore-revs | 1 + libs/installer_quick/.gitattributes | 7 + libs/installer_quick/.github/workflows/build.yml | 20 +++ libs/installer_quick/.github/workflows/linting.yml | 16 ++ libs/installer_quick/.gitignore | 5 + libs/installer_quick/.pre-commit-config.yaml | 20 +++ libs/installer_quick/CMakeLists.txt | 4 + libs/installer_quick/CMakePresets.json | 67 ++++++++ libs/installer_quick/src/CMakeLists.txt | 13 ++ libs/installer_quick/src/installer_quick_en.ts | 51 ++++++ libs/installer_quick/src/installerquick.cpp | 176 +++++++++++++++++++++ libs/installer_quick/src/installerquick.h | 77 +++++++++ libs/installer_quick/src/simpleinstalldialog.cpp | 69 ++++++++ libs/installer_quick/src/simpleinstalldialog.h | 72 +++++++++ libs/installer_quick/src/simpleinstalldialog.ui | 86 ++++++++++ libs/installer_quick/vcpkg.json | 15 ++ 17 files changed, 740 insertions(+) create mode 100644 libs/installer_quick/.clang-format create mode 100644 libs/installer_quick/.git-blame-ignore-revs create mode 100644 libs/installer_quick/.gitattributes create mode 100644 libs/installer_quick/.github/workflows/build.yml create mode 100644 libs/installer_quick/.github/workflows/linting.yml create mode 100644 libs/installer_quick/.gitignore create mode 100644 libs/installer_quick/.pre-commit-config.yaml create mode 100644 libs/installer_quick/CMakeLists.txt create mode 100644 libs/installer_quick/CMakePresets.json create mode 100644 libs/installer_quick/src/CMakeLists.txt create mode 100644 libs/installer_quick/src/installer_quick_en.ts create mode 100644 libs/installer_quick/src/installerquick.cpp create mode 100644 libs/installer_quick/src/installerquick.h create mode 100644 libs/installer_quick/src/simpleinstalldialog.cpp create mode 100644 libs/installer_quick/src/simpleinstalldialog.h create mode 100644 libs/installer_quick/src/simpleinstalldialog.ui create mode 100644 libs/installer_quick/vcpkg.json (limited to 'libs/installer_quick') diff --git a/libs/installer_quick/.clang-format b/libs/installer_quick/.clang-format new file mode 100644 index 0000000..6098e1f --- /dev/null +++ b/libs/installer_quick/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/libs/installer_quick/.git-blame-ignore-revs b/libs/installer_quick/.git-blame-ignore-revs new file mode 100644 index 0000000..c32a336 --- /dev/null +++ b/libs/installer_quick/.git-blame-ignore-revs @@ -0,0 +1 @@ +4b30cfb8a268d8c0472b148943dd588114916182 diff --git a/libs/installer_quick/.gitattributes b/libs/installer_quick/.gitattributes new file mode 100644 index 0000000..f869712 --- /dev/null +++ b/libs/installer_quick/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/libs/installer_quick/.github/workflows/build.yml b/libs/installer_quick/.github/workflows/build.yml new file mode 100644 index 0000000..4f109fe --- /dev/null +++ b/libs/installer_quick/.github/workflows/build.yml @@ -0,0 +1,20 @@ +name: Build Installer Quick + +on: + push: + branches: [master] + pull_request: + types: [opened, synchronize, reopened] + +env: + VCPKG_BINARY_SOURCES: clear;x-azblob,${{ vars.AZ_BLOB_VCPKG_URL }},${{ secrets.AZ_BLOB_SAS }},readwrite + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Installer Quick + id: build-installer-quick + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: uibase diff --git a/libs/installer_quick/.github/workflows/linting.yml b/libs/installer_quick/.github/workflows/linting.yml new file mode 100644 index 0000000..6b4d6c4 --- /dev/null +++ b/libs/installer_quick/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Installer Quick Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." diff --git a/libs/installer_quick/.gitignore b/libs/installer_quick/.gitignore new file mode 100644 index 0000000..cf71be7 --- /dev/null +++ b/libs/installer_quick/.gitignore @@ -0,0 +1,5 @@ +edit +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build diff --git a/libs/installer_quick/.pre-commit-config.yaml b/libs/installer_quick/.pre-commit-config.yaml new file mode 100644 index 0000000..eb8969c --- /dev/null +++ b/libs/installer_quick/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-merge-conflict + - id: check-case-conflict + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v21.1.8 + hooks: + - id: clang-format + 'types_or': [c++, c] + +ci: + autofix_commit_msg: "[pre-commit.ci] Auto fixes from pre-commit.com hooks." + autofix_prs: true + autoupdate_commit_msg: "[pre-commit.ci] Pre-commit autoupdate." + autoupdate_schedule: quarterly + submodules: false diff --git a/libs/installer_quick/CMakeLists.txt b/libs/installer_quick/CMakeLists.txt new file mode 100644 index 0000000..2d40abe --- /dev/null +++ b/libs/installer_quick/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) + +project(installer_quick) +add_subdirectory(src) diff --git a/libs/installer_quick/CMakePresets.json b/libs/installer_quick/CMakePresets.json new file mode 100644 index 0000000..5a63c77 --- /dev/null +++ b/libs/installer_quick/CMakePresets.json @@ -0,0 +1,67 @@ +{ + "configurePresets": [ + { + "errors": { + "deprecated": true + }, + "hidden": true, + "name": "cmake-dev", + "warnings": { + "deprecated": true, + "dev": true + } + }, + { + "cacheVariables": { + "VCPKG_MANIFEST_NO_DEFAULT_FEATURES": { + "type": "BOOL", + "value": "ON" + } + }, + "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "hidden": true, + "name": "vcpkg" + }, + { + "hidden": true, + "inherits": ["vcpkg"], + "name": "vcpkg-dev" + }, + { + "binaryDir": "${sourceDir}/vsbuild", + "architecture": { + "strategy": "set", + "value": "x64" + }, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "/EHsc /MP /W4", + "VCPKG_TARGET_TRIPLET": { + "type": "STRING", + "value": "x64-windows-static-md" + } + }, + "generator": "Visual Studio 17 2022", + "inherits": ["cmake-dev", "vcpkg-dev"], + "name": "vs2022-windows", + "toolset": "v143" + }, + { + "cacheVariables": { + "VCPKG_MANIFEST_FEATURES": { + "type": "STRING", + "value": "standalone" + } + }, + "inherits": "vs2022-windows", + "name": "vs2022-windows-standalone" + } + ], + "buildPresets": [ + { + "name": "vs2022-windows", + "resolvePackageReferences": "on", + "configurePreset": "vs2022-windows" + } + ], + "version": 4 +} diff --git a/libs/installer_quick/src/CMakeLists.txt b/libs/installer_quick/src/CMakeLists.txt new file mode 100644 index 0000000..050ddf0 --- /dev/null +++ b/libs/installer_quick/src/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.16) + +file(GLOB installer_quick_SOURCES CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/*.ui + ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc +) + +add_library(installer_quick SHARED ${installer_quick_SOURCES}) +mo2_configure_plugin(installer_quick NO_SOURCES WARNINGS 4) +target_link_libraries(installer_quick PRIVATE mo2::uibase) +mo2_install_plugin(installer_quick) diff --git a/libs/installer_quick/src/installer_quick_en.ts b/libs/installer_quick/src/installer_quick_en.ts new file mode 100644 index 0000000..f5aa081 --- /dev/null +++ b/libs/installer_quick/src/installer_quick_en.ts @@ -0,0 +1,51 @@ + + + + + InstallerQuick + + + Simple Installer + + + + + Installer for very simple archives + + + + + SimpleInstallDialog + + + Quick Install + + + + + Name + + + + + + Opens a Dialog that allows custom modifications. + + + + + Manual + + + + + OK + + + + + Cancel + + + + diff --git a/libs/installer_quick/src/installerquick.cpp b/libs/installer_quick/src/installerquick.cpp new file mode 100644 index 0000000..20b4b76 --- /dev/null +++ b/libs/installer_quick/src/installerquick.cpp @@ -0,0 +1,176 @@ +#include "installerquick.h" + +#include +#include + +#include +#include +#include + +#include "simpleinstalldialog.h" + +using namespace MOBase; + +InstallerQuick::InstallerQuick() : m_MOInfo(nullptr) {} + +bool InstallerQuick::init(IOrganizer* moInfo) +{ + m_MOInfo = moInfo; + // Note: Cannot retrieve the checker here because the game might + // not be initialized yet. + return true; +} + +QString InstallerQuick::name() const +{ + return "Simple Installer"; +} + +QString InstallerQuick::localizedName() const +{ + return tr("Simple Installer"); +} + +QString InstallerQuick::author() const +{ + return "Tannin"; +} + +QString InstallerQuick::description() const +{ + return tr("Installer for very simple archives"); +} + +VersionInfo InstallerQuick::version() const +{ + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); +} + +QList InstallerQuick::settings() const +{ + return {PluginSetting("silent", + "simple plugins will be installed without any user interaction", + QVariant(false))}; +} + +unsigned int InstallerQuick::priority() const +{ + return 50; +} + +bool InstallerQuick::isManualInstaller() const +{ + return false; +} + +bool InstallerQuick::isDataTextArchiveTopLayer(std::shared_ptr tree, + QString const& dataFolderName, + ModDataChecker*) const +{ + // A "DataText" archive is defined as having exactly one folder named like + // `dataFolderName` and one or more "useless" files (text files, pdf, or images). + static const std::set txtExtensions{ + "txt", "pdf", "md", "jpg", "jpeg", "png", "bmp"}; + bool dataFound = false; + bool txtFound = false; + for (auto entry : *tree) { + if (entry->isDir()) { + // If data was already found, or this is a directory not named "data", fail: + if (dataFound || entry->compare(dataFolderName) != 0) { + return false; + } + dataFound = true; + } else { + if (txtExtensions.count(entry->suffix()) == 0) { + return false; + } + txtFound = true; + } + } + return dataFound && txtFound; +} + +std::shared_ptr +InstallerQuick::getSimpleArchiveBase(std::shared_ptr dataTree, + QString const& dataFolderName, + ModDataChecker* checker) const +{ + if (!checker) { + return nullptr; + } + while (true) { + if (checker->dataLooksValid(dataTree) == ModDataChecker::CheckReturn::VALID || + isDataTextArchiveTopLayer(dataTree, dataFolderName, checker)) { + return dataTree; + } else if (dataTree->size() == 1 && dataTree->at(0)->isDir()) { + dataTree = dataTree->at(0)->astree(); + } else { + log::debug("Archive is not a simple archive."); + return nullptr; + } + } +} + +bool InstallerQuick::isArchiveSupported(std::shared_ptr tree) const +{ + auto checker = m_MOInfo->gameFeatures()->gameFeature(); + if (!checker) { + return false; + } + if (getSimpleArchiveBase(tree, m_MOInfo->managedGame()->dataDirectory().dirName(), + checker.get()) != nullptr) { + return true; + } + return checker->dataLooksValid(tree) == ModDataChecker::CheckReturn::FIXABLE; +} + +IPluginInstaller::EInstallResult +InstallerQuick::install(GuessedValue& modName, + std::shared_ptr& tree, QString&, int&) +{ + const QString dataFolderName = m_MOInfo->managedGame()->dataDirectory().dirName(); + auto checker = m_MOInfo->gameFeatures()->gameFeature(); + + auto base = std::const_pointer_cast( + getSimpleArchiveBase(tree, dataFolderName, checker.get())); + if (base == nullptr && + checker->dataLooksValid(tree) == ModDataChecker::CheckReturn::FIXABLE) { + tree = checker->fix(tree); + } else { + tree = base; + } + if (tree != nullptr) { + SimpleInstallDialog dialog(modName, parentWidget()); + if (m_MOInfo->pluginSetting(name(), "silent").toBool() || + dialog.exec() == QDialog::Accepted) { + modName.update(dialog.getName(), GUESS_USER); + + // If we have a data+txt archive, we move files to the data folder and + // switch to the data folder. We need to check that we actually have a + // checker here, otherwise it is anyway impossible that + // isDataTextArchiveTopLayer() returned true. + if (checker && isDataTextArchiveTopLayer(tree, dataFolderName, checker.get())) { + auto dataTree = tree->findDirectory(dataFolderName); + dataTree->detach(); + dataTree->merge(tree); + tree = dataTree; + } + return RESULT_SUCCESS; + } else { + if (dialog.manualRequested()) { + modName.update(dialog.getName(), GUESS_USER); + return RESULT_MANUALREQUESTED; + } else { + return RESULT_CANCELED; + } + } + } else { + // install shouldn't even have even have been called + qCritical("unsupported archive for quick installer"); + return RESULT_FAILED; + } +} + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +Q_EXPORT_PLUGIN2(installerQuick, InstallerQuick) +#endif diff --git a/libs/installer_quick/src/installerquick.h b/libs/installer_quick/src/installerquick.h new file mode 100644 index 0000000..5d9c910 --- /dev/null +++ b/libs/installer_quick/src/installerquick.h @@ -0,0 +1,77 @@ +#ifndef INSTALLERQUICK_H +#define INSTALLERQUICK_H + +#include +#include + +class InstallerQuick : public MOBase::IPluginInstallerSimple +{ + Q_OBJECT + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginInstaller MOBase::IPluginInstallerSimple) +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org.tannin.InstallerQuick") +#endif + +public: + InstallerQuick(); + + // Plugin functions: + virtual bool init(MOBase::IOrganizer* moInfo) override; + virtual QString name() const override; + virtual QString localizedName() const override; + virtual QString author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual QList settings() const override; + + // Installer functions: + virtual unsigned int priority() const override; + virtual bool isManualInstaller() const override; + virtual bool + isArchiveSupported(std::shared_ptr tree) const override; + + // Simple installer functions: + virtual EInstallResult install(MOBase::GuessedValue& modName, + std::shared_ptr& tree, + QString& version, int& modID) override; + +private: + /** + * @brief Check if the archive is a "DataText" archive. + * + * A "DataText" archive is defined as having exactly one folder named like the data + * folder of the game (`dataFolderName`) and one or more text or PDF files (standard + * package from french modding site). + * + * @param tree The tree to check. + * @param dataFolderName Name of the data folder (e.g., "data" for gamebryo games). + * @param checker The mod data checker, or a null pointer if none is available. + * + * @return true if the tree represents a "DataText" archive, false otherwise. + */ + bool isDataTextArchiveTopLayer(std::shared_ptr tree, + QString const& dataFolderName, + MOBase::ModDataChecker* checker) const; + + /** + * @brief Get the base of the archive. + * + * The base of the archive is either a "DataText" folder (i.e., a folder containing + * TXT or PDF files and a valid data folder), or an actual data folder. + * + * @param tree The tree to check. + * @param dataFolderName Name of the data folder (e.g., "data" for gamebryo games). + * @param checker The mod data checker, or a null pointer if none is available. + * + * @return the "base" of the archive, or a null pointer if none was found. + */ + std::shared_ptr + getSimpleArchiveBase(std::shared_ptr dataTree, + QString const& dataFolderName, + MOBase::ModDataChecker* checker) const; + +private: + const MOBase::IOrganizer* m_MOInfo; +}; + +#endif // INSTALLERQUICK_H diff --git a/libs/installer_quick/src/simpleinstalldialog.cpp b/libs/installer_quick/src/simpleinstalldialog.cpp new file mode 100644 index 0000000..b36b46e --- /dev/null +++ b/libs/installer_quick/src/simpleinstalldialog.cpp @@ -0,0 +1,69 @@ +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer 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, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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 Mod Organizer. If not, see . +*/ +#include "simpleinstalldialog.h" +#include "ui_simpleinstalldialog.h" + +#include + +#include +#include + +using namespace MOBase; + +SimpleInstallDialog::SimpleInstallDialog(const GuessedValue& preset, + QWidget* parent) + : QDialog(parent), ui(new Ui::SimpleInstallDialog), m_Manual(false) +{ + ui->setupUi(this); + + for (auto iter = preset.variants().begin(); iter != preset.variants().end(); ++iter) { + ui->nameCombo->addItem(*iter); + } + + ui->nameCombo->setCurrentIndex(ui->nameCombo->findText(preset)); + + setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); + ui->nameCombo->completer()->setCaseSensitivity(Qt::CaseSensitive); +} + +SimpleInstallDialog::~SimpleInstallDialog() +{ + delete ui; +} + +QString SimpleInstallDialog::getName() const +{ + return ui->nameCombo->currentText(); +} + +void SimpleInstallDialog::on_okBtn_clicked() +{ + this->accept(); +} + +void SimpleInstallDialog::on_cancelBtn_clicked() +{ + this->reject(); +} + +void SimpleInstallDialog::on_manualBtn_clicked() +{ + m_Manual = true; + this->reject(); +} diff --git a/libs/installer_quick/src/simpleinstalldialog.h b/libs/installer_quick/src/simpleinstalldialog.h new file mode 100644 index 0000000..e491438 --- /dev/null +++ b/libs/installer_quick/src/simpleinstalldialog.h @@ -0,0 +1,72 @@ +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer 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, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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 Mod Organizer. If not, see . +*/ + +#ifndef SIMPLEINSTALLDIALOG_H +#define SIMPLEINSTALLDIALOG_H + +#include +#include + +namespace Ui +{ +class SimpleInstallDialog; +} + +/** + * @brief Dialog for the installation of a simple archive + * a simple archive is one that doesn't require any manual changes to work correctly + **/ +class SimpleInstallDialog : public QDialog +{ + Q_OBJECT + +public: + /** + * @brief constructor + * + * @param preset suggested name for the mod + * @param parent parent widget + **/ + explicit SimpleInstallDialog(const MOBase::GuessedValue& preset, + QWidget* parent = 0); + ~SimpleInstallDialog(); + + /** + * @return true if the user requested the manual installation dialog + **/ + bool manualRequested() const { return m_Manual; } + /** + * @return the (user-modified) mod name + **/ + QString getName() const; + +private slots: + + void on_okBtn_clicked(); + + void on_cancelBtn_clicked(); + + void on_manualBtn_clicked(); + +private: + Ui::SimpleInstallDialog* ui; + bool m_Manual; +}; + +#endif // SIMPLEINSTALLDIALOG_H diff --git a/libs/installer_quick/src/simpleinstalldialog.ui b/libs/installer_quick/src/simpleinstalldialog.ui new file mode 100644 index 0000000..38a31ee --- /dev/null +++ b/libs/installer_quick/src/simpleinstalldialog.ui @@ -0,0 +1,86 @@ + + + SimpleInstallDialog + + + + 0 + 0 + 400 + 83 + + + + Quick Install + + + + + + + + Name + + + + + + + true + + + + + + + + + + + Opens a Dialog that allows custom modifications. + + + Opens a Dialog that allows custom modifications. + + + Manual + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + true + + + + + + + Cancel + + + + + + + + + + diff --git a/libs/installer_quick/vcpkg.json b/libs/installer_quick/vcpkg.json new file mode 100644 index 0000000..28051ad --- /dev/null +++ b/libs/installer_quick/vcpkg.json @@ -0,0 +1,15 @@ +{ + "features": { + "standalone": { + "description": "Build Standalone.", + "dependencies": ["mo2-cmake", "mo2-uibase"] + } + }, + "vcpkg-configuration": { + "default-registry": { + "kind": "git", + "repository": "https://github.com/ModOrganizer2/vcpkg-registry", + "baseline": "8beb2e0efa9c17dd6d17bb05288dd1e40727f673" + } + } +} -- cgit v1.3.1