aboutsummaryrefslogtreecommitdiff
path: root/CMakeLists.txt
Commit message (Collapse)AuthorAgeFilesLines
* Fix FOMOD casing and VFS test coverageSulfurNitride2026-06-231-1/+2
|
* Prepare 0.3.0 releaseSulfurNitride2026-06-171-2/+2
|
* Prepare Nexus-safe release cleanupSulfurNitride2026-06-171-1/+0
|
* release: prepare 0.2.3 stableSulfurNitride2026-05-301-1/+1
|
* release: prepare 0.2.2 stableSulfurNitride2026-05-241-1/+1
|
* release: bump Fluorine version to 0.2.1SulfurNitride2026-05-191-1/+1
|
* updater: SLR auto-update + wire fluorine updater badge, bump 0.2.0SulfurNitride2026-05-021-2/+2
| | | | | | | | | | | | | | | | | | | | - OrganizerCore: add fluorineUpdater() getter + checkForSlrUpdates() fired from startup checkForUpdates(); detached thread runs downloadSlr when SLR already installed so steamrt4 BUILD_ID drift is picked up without a launch-time stall. - MainWindow: connect FluorineUpdater::updateAvailable to existing updateAvailable() slot so the statusbar badge + actionUpdate light up; on_actionUpdate_triggered routes to Settings -> Updates when a Fluorine update is pending (the MO2 self-updater path is no-op'd). - MainWindow launch path: drop !isSlrInstalled() short-circuit; fresh installs still get the progress dialog, up-to-date checks rely on the startup background pass. - SettingsDialog: selectTabByLabel() so MainWindow can open Updates tab. - Launcher: rm -rf update-staging/ once a new bundle has synced into bin/, so the in-app updater doesn't accumulate stale extracts. - CMakeLists.txt: 0.1.4 -> 0.2.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Fix meta.ini duplicate keys and SKSE Log Redirector mapped foldersSulfurNitride2026-05-011-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | meta.ini: Qt6 QSettings IniFormat is case-sensitive on Linux. Pre-existing CamelCase keys + lowercase setValue() left both casings in the file, so mods grew duplicate entries on every install. Added MetaIniUtils:: normalizeMetaIniCase() to fold keys to lowercase and dedupe per-section (keeping non-empty values) before any QSettings open in readMeta, saveMeta, doInstall, and createMod. SKSE Log Redirector: deployExternalMappings created per-file symlinks under the redirected destination, so any new log file the game wrote post-deploy ended up as a real file outside the mapping. For isDirectory && createTarget mappings, now publish a single directory symlink dst -> src when the destination is missing, an existing symlink, or empty. Falls back to per-file symlinks when dst already has real content (preserves user data). Cleanup removes the symlink, leaving no files behind. Tests under src/tests/ (gtest, opt-in via BUILD_TESTING): - test_metainiutils: 6 tests covering no-op cases, case-only dedup, multi-line continuations, per-section scoping, and end-to-end verification that QSettings duplication is fixed. - test_external_dir_mapping: 6 tests covering directory symlink deploy, flow-through writes, idempotency, empty-dir replacement, real-file fallback, and cleanup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Finalize Linux build cleanupSulfurNitride2026-04-291-1/+1
|
* Native port of SKSELogRedirector plugin family (sysdmp), default offSulfurNitride2026-04-281-0/+1
| | | | | | | | | | | | | | | | | | | | Three FileMapper variants — Steam SSE, GOG, VR — that redirect <docs>/My Games/<X> onto a sibling folder so SKSE writes logs to the right place. Only one applies per game; all default off so the user opts in to the matching variant. Layout mirrors game_bethesda: shared static lib in src/common/ with the QObject base (init/author/version/settings/enabledByDefault/mappings), three plugin .so subdirs each adding Q_PLUGIN_METADATA + their own name/description and destFolderName override. Q_PLUGIN_METADATA can only appear once per .so, hence the split. Paths preserved verbatim from the upstream .py — including the SSE variant's "Skyrim.INI" sibling folder, which is intentional: a Skyrim bug sometimes creates a directory of that name and the redirect makes SKSE find logs in SSE's docs folder. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Fix VFS rmdir, prefix/launch issues, add version + beta channelSulfurNitride2026-04-231-0/+42
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - VFS: add mo2_rmdir + OverwriteManager::removeDirectory so Wrye Bash shutil.rmtree stops failing with WinError 267 (issue #47). - FileRenamer: case-insensitive fallback via new resolvePathCaseInsensitive walks each path component; bulk hide in Conflict tab no longer dies with a misleading "Input/output error" when DirectoryEntry normalised parent dir case (issue #54). formatSystemMessage stops aliasing Windows error code 5 to errno 5 (EIO). - Versioning: FLUORINE_VERSION_* + fluorine_build_info.h generated from CMake; Linux createVersionInfo returns Fluorine's version. About dialog shows Fluorine version + MO2 engine + commit. Beta builds stamp "<semver>B<yyyymmddhhmm>" (issue #51). - CI: ci.yml determines channel from ref (v* tags = stable, main = beta), publishes a rolling `beta` GitHub release whose body carries a machine-parseable fluorine-meta block (timestamp, commit) for the in-app updater. - Updater: new FluorineUpdater polls GitHub API on startup, compares against embedded metadata, notifies on new release without auto-install. Channel toggle piggybacks on the existing "beta versions" checkbox. - Bethesda plugins: determineMyGamesPath no longer creates Documents/My Games/<GameName> for every possible title at plugin load; only games with a detected install path get their dirs created (issue #55). - Starfield: dataDirectory() on Linux now points at <game>/Data instead of My Games/Starfield/Data so the single FUSE mount lands where SFSE loads plugins; My Games Data becomes a secondary symlinked mapping (issue #56). - Prefix resolution: prefer Fluorine config, then explicit fluorine/prefix_path, then legacy Settings/* keys (with a warning) so auto-detected Heroic/Bottles prefixes can't silently override a user- configured Fluorine prefix (issue #52). compatDataPathFromPrefix no longer hands Proton the wrong parent dir for plain wine prefixes. - xrandr: ensureXrandrInstalled back-fills the helper for existing SLR installs, prefix init runs it before wineboot, SLR wrap exposes xrandr-bin via --filesystem= and prepends PATH inside the container (issue #49). - Process tracking: drop the wineserver-as-last-resort fallback that made MO2 hang on Proton's session manager after game exit. Rescan the prefix for matching game executables instead (covers reparented launcher children like f4se_loader → Fallout4.exe). Unlock button now kills wineserver for the prefix (SIGTERM then SIGKILL on timeout). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Symlink saves, rank prefixes by Steam app type, ntsync safeguardsSulfurNitride2026-04-171-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - Replace copy-in/copy-out save deployment with a direct symlink from the prefix's __MO_Saves to the profile's saves/. Writes land in the profile immediately; afterRun reverts the symlink + prefix INI so a vanilla launch outside MO2 uses the default Saves dir. - Parse Steam's binary appinfo.vdf (v41) via a new Rust FFI crate backed by steam-vdf-parser. Rank detected games by common.type so real Games beat Tools/Editors when multiple prefixes share a My Games folder name (fixes Creation Kit shadowing Skyrim SE). Top-ranked candidate overwrites stale symlinks from earlier runs. - Switch bundled Steam Linux Runtime downloader from sniper (steamrt3) to steamrt4 so Proton 11+ works out of the box. steamrt4 omits xrandr so we inject it from the Debian x11-xserver-utils .deb into a dedicated dir and prepend it to PATH via `env PATH=...` inside the pressure-vessel container (PATH env doesn't propagate). - Auto-kill stale wineboot/wineserver/pv-adverb processes still bound to the prefix before starting a new wineboot -u; match by /proc/<pid>/environ WINEPREFIX / STEAM_COMPAT_DATA_PATH since Wine cmdlines are Windows-style. Same sweep runs in destroyPrefix so a delete actually frees file handles. - Blacklist Proton 11 (Steam-bundled) — its current Wine tree deadlocks during wineboot -u on modern kernels via ntsync / futex_wait_multiple races. Use "waitforexitandrun" (not "run") for prefix init so use_sessions=1 Protons don't fork into a persistent session manager. - Drop WINEDEBUG=-all during prefix init so wineboot progress is visible. Suppress focus-stealing by setting WA_ShowWithoutActivating on the PrefixSetupDialog and SLR download progress dialogs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* VFS perf fixes, icon/stylesheet compat, download filename fixSulfurNitride2026-04-121-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | VFS: - Open backing fd at mo2_open time for read-only handles so mo2_read can splice without re-opening the file on every read call. - Bump RLIMIT_NOFILE at mount time to fit the resulting fd pressure when the game keeps hundreds of BSAs open. - Dedicated node_cache_mutex so resolveByInode / mo2_lookup stop racing unordered_map writes while multiple tree_mutex readers are active. - max_read=1MB + matching conn->max_read and raised max_readahead/max_write so the kernel merges Wine's small sequential reads into bigger FUSE requests. - Per-op wall-clock counters in mo2_init() logs so we can distinguish VFS latency from game-side work. Proton launch: - Write dxvk.conf to the prefix and set DXVK_CONFIG_FILE to force dxvk.enableGraphicsPipelineLibrary=False, avoiding long GPL compile stalls on first run. UI / plugin compat: - Clamp IconDelegate's per-icon width to [8, 16] so narrow content columns don't trigger QIcon::pixmap(0,0) returning null and logging "failed to load icon" every repaint. - Pre-create lowercase symlinks in the stylesheet directory so QSS files authored on Windows resolve url(foo.svg) when on-disk files are Foo.svg. - Flip content icons empty-chessboard.png and facegen.png to 8-bit RGBA so Qt's built-in PNG reader loads them uniformly. - Add mobase.Version.canonicalString shim for legacy Python plugins that still call the old VersionInfo method on appVersion()'s return. - BSPluginList: compare normalized plugin name lists instead of byte hashes so the post-run case-fix refresh stops spuriously firing the "load order changed" dialog. - BSPluginList disabled by default. Download manager: - Parse CDN URL with QUrl + QUrlQuery and read the filename from the response-content-disposition query param (RFC 6266 quoted / unquoted / ext-value forms), not QFileInfo on the raw URL. - When the API or URL gives us a CDN object key (no archive extension), prefer the actual Content-Disposition header from the live response in metaDataChanged and downloadFinished. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add NIF previewer plugin with Linux-specific fixesSulfurNitride2026-04-121-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | Vendored from github.com/Parapets/mo2-preview_nif and adapted for Linux: - BSA texture resolution via MO2 virtual tree with case-insensitive fallback walk (Linux FS is case-sensitive; NIFs reference textures with arbitrary case against files on disk) - Process-wide cached BSA candidate list, keyed by profile path, priority-sorted, filtering disabled mods - Path backslash normalization before loose-file lookup - Polygon offset on SLSF1_Decal-flagged shapes to break z-ties with coincident base meshes (road decals, moss overlays) - Opaque framebuffer via glColorMask alpha lock so alpha-blended shapes can't bleed the dialog background through the preview area - QMouseEvent::globalPosition().toPoint() for Qt6 compatibility Preview dialog behavior (organizercore.cpp): - Switch previewFile and previewFileWithAlternatives from stack-allocated exec() to heap + ApplicationModal + show() + WA_DeleteOnClose. - Parent passed as nullptr so preview lifetime is decoupled from the stack-allocated ModInfoDialog that spawns it. Nested exec() inside the enclosing dialog's exec() was softlocking on close. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove LOOT integration entirelySulfurNitride2026-04-121-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | The sort button was already hidden on Linux (setVisible(false)) and the LOOT feedback path (LootDialog -> addLootReport) has always been Windows-only, meaning the dirty/incompatibilities/missingMasters/messages tooltip bullets and the dirty-plugin icon could never fire on Linux. MO2 shipped lootcli + libloot for a load-order sort mechanism that was unreachable from the UI. Users who want LOOT can download it from https://github.com/loot/loot and run it against their instance directly. - Drop libs/lootcli/, libloot Dockerfile build step, and lootcli staging/patchelf in build-inner.sh - Drop src/src/loot.{cpp,h}, src/src/lootdialog.{cpp,h,ui} - Extract MarkdownDocument / MarkdownPage (used by UpdateDialog for its changelog view) into src/src/markdowndocument.{h,cpp} - Strip addLootReport, makeLootTooltip, Loot::Plugin field, LOOT icon checks, and LOOT tooltip/isProblematic/hasInfo paths from pluginlist - Delete sortButton widget, updateSortButton(), onSortButtonClicked(), and all m_didUpdateMasterList wiring - Delete lootLogLevel setting, combo box, and "Integrated LOOT" group from the diagnostics settings tab
* Add BethINI Pie tool pluginSulfurNitride2026-04-101-0/+1
| | | | | | | | | | | | | | | | Native IPluginTool that integrates BethINI Pie (performance INI editor) into the Tools menu. Auto-downloads the latest Linux build from GitHub releases, checks for updates via commit SHA, and pre-configures it for the current game and profile INI directory. Supports: Skyrim SE, Fallout 4, Fallout New Vegas, Starfield. Includes post-extraction fixes for PyInstaller bundle quirks: - Patches tm.tcl hardcoded Tcl module path - Symlinks apps/icons/fonts from _internal/ to executable directory - Sets TCL_LIBRARY/TK_LIBRARY env vars on launch Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove NaK/Rust dependency, port remaining functionality to native C++SulfurNitride2026-04-081-6/+1
| | | | | | | | | | | | | | | Replace NaK Rust crate and nak_ffi with native C++ implementations: - Game detection (Steam, Heroic, Bottles), VDF parser, icon extraction - Prefix symlinks, SLR manager, Steam path detection - Known games database Add FUSE VFS optimizations: zero-copy reads via fuse_reply_data, default_permissions mount option, FUSE_CAP_ASYNC_DIO, FUSE_CAP_EXPIRE_ONLY, lookup cache parent index, cached mode bits, increased I/O buffer sizes. Update build system, prefix setup, and various fixes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Bundle PBS Python 3.12 + PyQt6, restore Python plugins as .py filesSulfurNitride2026-03-131-6/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | - Replace portable Python approach with python-build-standalone 3.12.13 (20260310 release) bundled directly in the distribution. Python is now always available without user setup — removes the Python settings tab. - PyQt6 staged to plugins/libs/PyQt6/ with bundled Qt stripped out; patchelf'd to use our existing bundled Qt in lib/ instead of duplicating it. - Restored native-converted plugins back to .py files: Form43Checker, ScriptExtenderPluginChecker, DDSPreview, basic_games, rootbuilder, installer_omod. Removed all *_native CMake targets. - pythonrunner.cpp: removed venv/MO2_PYTHON_DIR lookup; always uses bundled Python at <exe_dir>/python, system Python as last-resort fallback. - plugincontainer.cpp: removed fluorine/python_enabled gate (Python always loads), demoted proxy loading log messages from warn to debug, silenced [plugin-diag] stderr spam. - Dockerfile: switched from uv venv to PBS install_only tarball; PBS Python used for both build-time pybind11 compilation and runtime distribution. - build-inner.sh: aggressive Python staging (strip test/tkinter/ensurepip/ distutils/lib2to3/idlelib; wipe build-time site-packages, restore psutil+vdf). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Replace wrestool with native Rust PE icon extraction (pelite)SulfurNitride2026-03-121-2/+3
| | | | | | | | | | | | | | | | | - Add icons.rs to nak crate: parses PE resource sections, extracts RT_GROUP_ICON/RT_ICON and builds ICO files in memory - Expose nak_extract_exe_icon() FFI for C++ consumption - Update iconForExecutable() to use Rust FFI instead of shelling out to wrestool; reads all ICO entries for correct color depth - Fix BasicGamePlugin::gameIcon() to call iconForExecutable() (was returning empty QIcon, causing placeholder icons for BG3/Cyberpunk) - Move app icon setup: setDesktopFileName + setWindowIcon to MOApplication constructor (fixes Wayland taskbar/decoration icon) - Move data/com.fluorine.* to data/icons/, install to XDG paths at launch for Wayland compositor icon resolution - Remove icoutils dependency from Docker image and build output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add native Root Builder and OMOD Installer pluginsSulfurNitride2026-03-121-0/+2
| | | | | | | | | | | | | | | - libs/rootbuilder_native/: Native C++ port of rootbuilder.py (IPluginTool) - Root/ dir scanning, copy (reflink/CoW) and symlink modes - JSON manifest tracking, backup/restore, auto-deploy hooks - Legacy migration and third-party conflict detection - libs/installer_omod_native/: Native C++ port of installer_omod.py - Handles .omod archives (Oblivion Mod Manager format) - Binary config parsing, .NET string format, CRC file parsing - zlib raw deflate and LZMA decompression - Repackages to zip for MO2's installation manager - Added both to build-inner.sh plugin packaging Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Replace Python plugins with native C++ .so, remove bundled Python (~95MB)SulfurNitride2026-03-121-0/+4
| | | | | | | | | | | | | | - Add native plugins: form43_checker, script_extender_checker, preview_dds, basic_games (75 game defs via IPluginProxy pattern with Steam/GOG detection) - Remove portable Python from Dockerfile and build-inner.sh - Add Python settings tab with venv support (system python3 + PyQt6) - Skip loading plugin_python.so when Python disabled (default: off) - Update pythonrunner.cpp to use venv at ~/.local/share/fluorine/python-venv/ - Preserve real file permissions in FUSE VFS (fixes native executable +x bits) - Add FUSE_SET_ATTR_MODE handler so chmod works through VFS - Fix desktop shortcut Exec= to use fluorine-manager launcher, not bare binary Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Remove FUSE passthrough (CAP_SYS_ADMIN incompatible with AppImage), remove ↵SulfurNitride2026-03-081-1/+0
| | | | | | | | | | | bsplugins, fix bsatk types - Remove FUSE passthrough code: requesting FUSE_CAP_PASSTHROUGH without CAP_SYS_ADMIN caused session cleanup crash on shutdown - Remove bsplugins library (unneeded port) - Fix bsatk: use uint32_t instead of unsigned long for BSAULong (LP64 compat) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Replace Python build deps with uv across all build pathsSulfurNitride2026-02-151-19/+19
| | | | | | | | | | | | | | | | | Use uv as the single Python package manager for Docker, source, and Flatpak builds. Python 3.13 and pybind11==2.13.6 are now consistent across all three paths. - Docker: install uv + build venv instead of python3-dev/pip/pybind11-dev - CMake: bootstrap pyvenv with uv (REQUIRED/FATAL_ERROR) when no explicit Python provided; pin pybind11==2.13.6, add sip - Flatpak: remove pybind11 cmake module, use uv pip install --target for build deps, uv for portable Python packages - build-inner.sh: use BUILD_PY throughout, uv pip install for portable runtime packages, simplify embed check to direct Python invocation - VFS helper: fall back to shared libfuse3 when static .a unavailable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Bootstrap Python venv with uv when system packages are missingSulfurNitride2026-02-151-5/+38
| | | | | | | | | If python3-dev/pybind11-dev aren't installed and uv is available, automatically create a local venv at build/pyvenv/ with Python 3.13 and pybind11. Also detects pybind11 cmake dir dynamically instead of hardcoding the Python version in the path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Migrate data paths to ~/.local/share/fluorine/, add native build, fix ↵SulfurNitride2026-02-141-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | %command% and system Proton scanning - All data paths migrated from ~/.var/app/com.fluorine.manager/ to ~/.local/share/fluorine/ so native and Flatpak builds share the same instances, plugins, and configs - New fluorinepaths.h/.cpp with fluorineDataDir() helper and one-time migration from old path (writes MOVED.txt breadcrumb) - New libs/nak/src/paths.rs as Rust equivalent (data_dir()) - Strip %command% tokens from launch wrapper in protonlauncher.cpp - Always scan /usr/share/steam/compatibilitytools.d/ for system Proton packages (Arch installs Proton there); add Flatpak filesystem permission - Native build (build-native.sh) installs to ~/.local/share/fluorine/ with desktop entry and ~/.local/bin symlink instead of portable zip - build-flatpak.sh wrapper for Flatpak builds - Fix container locale (LANG=C.UTF-8) for AutoUic warnings - Fix prefixExists() to handle both compatdata and pfx directory layouts - Fix globalInstancesRootPath() to use fluorineDataDir() on Linux - Fix umu-run Flatpak lookup to use fluorineDataDir() - Update README with build instructions and Arch dependency list Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add FUSE external mapping support, BG3/Oblivion Remastered fixes, fomod-plus ↵SulfurNitride2026-02-141-0/+1
| | | | | | | | | | | | | | | and NaK integration FUSE VFS now deploys non-data-dir mod mappings (Paks, OBSE, UE4SS, etc.) via real symlinks and injects file-level data-dir mappings (plugins.txt, loadorder.txt) into the VFS tree. Fixes game launches for Oblivion Remastered (Root Builder path resolution, script extender support) and BG3 (Wine prefix documents directory, file mapper symlinks on Linux). Vendors mo2-fomod-plus plugin and NaK crate for FOMOD installer and game finder/runtime support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fluorine Manager: full Linux port of Mod Organizer 2SulfurNitride2026-02-111-0/+204
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 <noreply@anthropic.com>