| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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:
- 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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
bsatk:
- Archive::extractToMemory() extracts a file directly into a byte buffer
instead of a filesystem path, backed by a std::ostringstream sink.
- Archive::findFile() locates a file by relative path, case-insensitive
and separator-agnostic, walking the folder tree recursively.
- extractDirect/extractCompressed now take std::ostream& so both the
ofstream and ostringstream paths share the same implementation.
libbsarch: shim rewrite on Linux to map the Windows API surface onto
bsatk::Archive, enabling preview_bsa to open vanilla BSAs via the
same interface as other plugins.
preview_bsa: double-click on a file in the BSA tree now extracts the
bytes via extractToMemory() and hands them to IOrganizer::previewFileData
for nested preview rendering (e.g. NIF inside a BSA).
uibase + organizerproxy + organizercore: new IOrganizer::previewFileData
virtual that routes in-memory file bytes through the first registered
IPluginPreview matching the extension. Uses heap + WA_DeleteOnClose +
open() to avoid nested exec() softlock from mod info filetree ->
preview_bsa tree -> nif preview.
docker/build-inner.sh: stage preview_nif shaders into plugin_data/shaders
so ShaderManager can load them via IOrganizer::getPluginDataPath().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
actions/upload-artifact@v4 defaults include-hidden-files to false, so
.fluorine-manifest was getting stripped from the CI release artifact
and users saw the launcher bail with "can't find its bundle files"
despite the build log reporting "Wrote manifest: 10 entries".
Rename to fluorine-manifest.txt. Sidesteps the upload-artifact default
and also survives any user-side extractor that hides dotfiles.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previous sync ran `tar -cf - .` inside the launcher's HERE dir, which
slurped anything sitting next to the fluorine-manager script. If a user
extracted the release archive into ~/Downloads (alongside a 38 GB mod
stash), the launcher happily copied the whole lot into
~/.local/share/fluorine/bin/ on first run.
Write a `.fluorine-manifest` at build time listing the top-level entries
that belong to Fluorine, then have the launcher copy only those entries.
Also bail with a clear error if the manifest or ModOrganizer-core is
missing — catches "launcher dropped into some random folder" before any
damage is done.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Version fingerprint was stat -c '%i:%Y' which includes the inode number.
Re-extracting the same tarball produces new inodes, so the marker never
matched and the 237MB copy to ~/.local/share/fluorine/bin/ ran on every
launch — painful cross-drive (tarball on one disk, home on another).
Switch to '%s:%Y' (size + mtime). Survives re-extraction, still detects
real updates.
Also stage into bin.new/ and rename instead of rm -rf'ing bin/ before
the tar pipe. If the user Ctrl+C's mid-sync (or the copy fails), the
existing install stays intact instead of being left empty.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
| |
PyQt6 6.11.0 requires Qt_6.11 symbols not present in our bundled
Qt 6.10.2, causing all Python plugins to fail with ImportError.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Direct DLL extraction and installer execution instead of shelling out
to winetricks for all prefix dependencies. Fixes d3dcompiler_47 being
sourced from wrong SDK cabs (broke CommunityShaders), and eliminates
the fragile cabextract-in-pressure-vessel PATH issue.
- d3dcompiler_47: direct download from Mozilla fxc2 repo
- d3dcompiler_43, d3dx9, d3dx11_43: cabextract from DirectX June 2010
redist with correct system32/syswow64 mapping
- xact/xact_x64: cab extraction + batched regsvr32 registration
- vcrun2022: direct installer with msvcp140.dll workaround (Wine #57518)
- dotnet6/7/8, dotnetdesktop6: direct x86+x64 installer pairs
- Game detection: batched into single .reg file import
- All DLL overrides added to WINE_SETTINGS_REG
- SHA256 verification for downloaded files
- Winetricks kept only for win11 mode step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
Logs were being created in the current working directory (defaulting to
$HOME when launched from a desktop entry). Now uses the instance
directory passed to setLogDirectory() so each instance gets its own
logs/ folder. Removes unused FLUORINE_LAUNCH_DIR env var.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
visibility fix
Plugin loading:
- Remove symlink-based ensureBundledPluginsLinked(), replace with multi-dir
search (bundled dir takes priority, instance dir adds extras only)
- Auto-clean stale symlinks from instance plugins/ dirs on startup
- Add mergedProxyList() for proxy plugin discovery across both dirs
VFS Root Builder (replaces Python rootbuilder.py):
- Native C++ Root Builder integrated into FuseConnector
- Deploy mod Root/ files to game dir before FUSE mount, clear on unmount
- Per-instance toggle in Instance Manager (default: on)
- Root Builder path normalization in processrunner.cpp: rewrite binary and
start-in paths from mods/.../Root/ to Game Root for correct Wine path
resolution (fixes SKSE + EngineFixes versionlib lookup)
- Expose game dir and prefix to SLR pressure-vessel via --filesystem=
Wine registry check:
- Read/write Wine prefix system.reg (HKLM) with timestamp-aware parsing
- Auto-check game install path before launch, prompt to fix if mismatched
- Updates both Software\ and Wow6432Node\ registry keys
Column visibility fix:
- Guard updateGroupByProxy() during QHeaderView::restoreState() to prevent
sort indicator restoration from triggering setSourceModel() which resets
all columns to visible
Python proxy:
- Skip FixGameRegKey.py, crashlogtools, rootbuilder.py (Windows-only or
replaced by native implementations)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
Large modlists (e.g. Gate To Sovngarde) exceed the default 1024 fd
limit during FUSE VFS recursive directory iteration, causing
"Too many open files" errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
| |
Each launch creates a new mo_interface_YYYY-MM-DD_HH-MM-SS.log in a
logs/ folder next to where fluorine-manager was run from. Old logs are
cleaned up to keep only the 5 most recent. Launcher scripts export
FLUORINE_LAUNCH_DIR before cd'ing to the bin directory so the C++ side
knows the original working directory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
games
Steam injects 32-bit gameoverlayrenderer.so via LD_PRELOAD which causes
"wrong ELF class" errors for 64-bit Qt6 apps. Save and clear LD_PRELOAD
in both launcher and AppRun scripts, restore it in ProtonLauncher for
game processes.
Also hardens looksValid() with QFileInfo::exists() for absolute paths
(QDir::exists() has edge cases with relative subdirectory paths), adds
case-insensitive directory walking fallback, and adds debug logging to
both looksValid() and detectGame().
Adds ~/.steam/debian-installation to Python steam_utils.py candidates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
env var detection
Steam game mode injects its scout/soldier runtime into LD_LIBRARY_PATH,
which breaks Python extension modules and Qt internals that resolve
dependencies via LD_LIBRARY_PATH rather than RPATH. This caused all
Python-based basic_games plugins (Witcher 3, Oblivion Remastered, BG3,
etc.) to fail to load when launched through Steam.
Changes:
- Launcher script: set LD_LIBRARY_PATH to only bundled lib/ dir instead
of leaving Steam's runtime in the path
- AppRun: same fix — replace rather than append to LD_LIBRARY_PATH
- Deploy libbasic_games_native.so in tarball (was built but never copied)
so basic_games entries work without Python dependency
- Add STEAM_COMPAT_CLIENT_INSTALL_PATH env var check to Python
steam_utils.py (mirrors C++ fix from e41a79a) for game mode detection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Steam Linux Runtime:
- New Rust module (libs/nak/src/slr.rs): download SteamLinuxRuntime_sniper
from repo.steampowered.com, SHA256 verification, BUILD_ID update checks
- nak_ffi exports: nak_slr_is_installed, nak_slr_get_run_script, nak_download_slr
- ProtonLauncher: wraps Proton launch inside SLR pressure-vessel container
when enabled (run -- proton waitforexitandrun game.exe)
- Instance Manager: SLR checkbox (default on) beside Steam DRM checkbox
- Main window: pre-check downloads SLR before launch if needed
- Proton settings tab: "Download Steam Linux Runtime" button
- spawn.cpp: reads fluorine/use_slr per-instance INI key
- Logs "Final command:" showing full assembled launch command
Bug fixes:
- Fix Use Proton off by default for plugin executables (executableslist.cpp)
- Fix Use Proton off by default for file tree right-click (filetree.cpp)
- Fix Fedora 43 Qt platform plugin crash: explicit QT_QPA_PLATFORM_PLUGIN_PATH
- Add Qt6::Concurrent to CMakeLists for QtConcurrent background downloads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Qt platform plugins (libqxcb.so, libqxcb-glx-integration.so, etc.) kept
aqtinstall's hardcoded RPATH (/opt/qt6/6.10.2/gcc_64/lib) which doesn't
exist on user systems. The linker fell through to system Qt, loading the
wrong version into the process link map. When PyQt6 bindings later loaded
libQt6OpenGLWidgets, glibc reused the already-cached system version, causing
private-API symbol mismatches against our bundled Qt 6.10 (seen on Mint,
Bazzite, and likely all distros with system Qt installed).
All Qt plugins are one subdir deep under qt6plugins/, so
$ORIGIN/../../lib correctly resolves to our lib/ for all of them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
PyQt6 is staged after the main dep-collection loop, so its .so deps
(e.g. libQt6OpenGLWidgets) were never copied to lib/. The dynamic linker
then fell back to the host's Qt RPM build, which exports Qt_6.*_PRIVATE_API
version symbols that aqtinstall's Qt doesn't — causing a crash on Fedora-
based distros (Bazzite, etc.) whenever a Python plugin imported PyQt6 OpenGL.
Add a post-PyQt6 dep scan that bundles any Qt libs not yet present in lib/.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
Qt >= 6.5.0 requires libxcb-cursor0 to load the xcb platform plugin,
but it's frequently absent on user systems. All other libxcb libs are
skipped (must match host X server ABI), but libxcb-cursor is a pure
utility library safe to bundle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
| |
- Stage DDS/ package from source directly to plugins/data/DDS/ in
build-inner.sh (cmake MO2_STAGE_PYTHON_PLUGIN_PAYLOAD is OFF by
default so the cmake-sourced path was silently skipped)
- Stage winreg.py from libs/ directly as well (same root cause)
- Guard `import winreg` in gog_utils.py with try/except ImportError
and early-exit to Heroic GOG path if the shim is unavailable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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>
|
| |
|
|
|
|
|
|
| |
NixOS/Arch users have Qt 6.10 system-wide, causing Qt_6.10 symbol errors
when loading mobase.so against the bundled Qt 6.9. Switch Docker build to
install Qt 6.10.2 from aqtinstall instead of Ubuntu's Qt 6.9 packages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
mobase.so in plugins/libs/ couldn't find bundled Qt/uibase because the
RPATH was only one level up (plugins/lib/) instead of two (lib/). This
caused "initialization failed" on NixOS and potentially other distros.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
The Python proxy expects mobase.cpython-313-x86_64-linux-gnu.so in
plugins/libs/ but build-inner.sh was not copying it. This caused
"No module named 'mobase'" when loading Python plugins.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
self-destruct
- Remove initialScan() from mount and unmount — its heuristic ("file exists in
both overwrite and a mod") caused false-positive tracking of game-generated
config files. Tracking now only happens through explicit UI actions or
snapshot-based detectManualMoves().
- Prune stale tracked entries on load when mod folder no longer exists on disk.
- Store mod paths as relative (to JSON file parent) for instance portability;
legacy absolute paths auto-migrate on next save.
- Guard launcher sync against HERE==BIN_DST to prevent rm -rf self-destruct
when running directly from ~/.local/share/fluorine/bin/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
FUSE passthrough caused Wine DLL loading failures (ERROR_NOACCESS 0x3E6)
for all file types, not just executables. Root cause is a kernel-level
incompatibility between FUSE passthrough I/O and Wine's file access
patterns. Removed all passthrough code, the passthrough helper binary,
libcap dependency, and the settings UI toggle.
Also removed flake.nix (unused with Docker build system) and stopped
tar.gz'ing the build output since GitHub zips release assets automatically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
Negotiating passthrough without the capability caused Wine/Proton DLL
loading failures (SKSE plugins returning error 0x36). Now checks the
process's effective capability set via libcap before telling the kernel
we want passthrough. Also adds qt.conf for AT_SECURE compatibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
| |
The find glob only matched *.so, missing versioned shared libraries
like libproxy.so.1 which retained hardcoded Docker build paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Use fuse_passthrough_open/close API instead of raw fd assignment to
fi->backing_id, which caused EIO on every file open through the VFS
- Remove LD_LIBRARY_PATH from launcher script — DT_RPATH handles lib
resolution, and LD_LIBRARY_PATH triggers AT_SECURE which drops file
capabilities (cap_sys_admin) needed for passthrough
- Auto-detect missing cap_sys_admin at mount time and prompt via pkexec
to re-apply it (handles binary copy/update/extract losing the cap)
- Disable passthrough for session if fuse_passthrough_open fails, avoiding
"Operation not permitted" spam in terminal
- Fix Nix flake: tinyxml2 → tinyxml-2, xorg.lib* → top-level names
- CI: eliminate artifact zip round-trip for GitHub releases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
| |
The launcher now deploys the full application (not just Python) to the
central data directory on launch. Instance plugin symlinks always point
to this stable location instead of the tarball extraction dir, so they
survive moves/deletes of the original archive.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
- FUSE: disable AUTO_INVAL_DATA, enable readdirplus, 24h TTLs, clone_fd,
FUSE_USE_VERSION=312 — cuts game load time from 2:40 to 1:57
- Fix tracked writes going to wrong (lower-priority) mod in both
detectManualMoves and syncOverwrite
- Remove steam-run entirely (UI, C++, Rust layers)
- Build system: default to tarball, add installer/appimage as opt-in modes
- Add flake.nix for NixOS — builds from source with Rust crates as
separate pure derivations, FHS wrapper, NixOS module with FUSE passthrough
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Download LOOT AppImage from GitHub releases on first sort
- Pre-seed LOOT settings.toml with game type, path, and masterlist URL
- Mount FUSE VFS before launching LOOT, unmount after exit
- Copy plugins.txt/loadorder.txt to LOOT local path and back
- Fix VFS file timestamps (separate error_code for mtime)
- Add directory timestamps to FUSE (was showing 1969)
- Stamp plugin files with load-order-based incrementing timestamps
- Remove WebEngine dependency on Linux (QTextBrowser fallback)
- Enable LOOT sorting for FalloutNV and FalloutTTW
- Add unmountVFS() to OrganizerCore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
| |
The AppImage was missing libqsvg.so (Qt SVG imageformat plugin),
causing SVG-based theme icons and checkboxes to render as blank
squares. Add qt6-svg-dev and qt6-svg-plugins to the Docker image.
Also add explicit unchecked checkbox images to all vs15 Dark themes
for consistent rendering on Linux.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fix "Copy all" log truncation: the code unconditionally stripped 2
chars (\r\n) from formatted log messages, but on Linux spdlog only
appends \n. Every log message lost its last real character. Now
strips trailing \r and \n dynamically.
Enable ccache: it was installed in the Docker image but never
activated. build-inner.sh now auto-detects ccache and sets
CMAKE_*_COMPILER_LAUNCHER. build.sh mounts a persistent ccache
volume (~/.cache/fluorine-ccache) into the container. CI workflow
uses actions/cache to persist ccache across runs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Remove umu-run entirely (crashed due to pressure-vessel/FUSE
incompatibility) — use raw `proton run` instead
- Replace startDetached() with QProcess::start() so the game stays in
Fluorine's process tree. This lets Steam track the game lifetime and
makes the "close game" button work when Fluorine is added as a
non-Steam game.
- Add writeIniValueDirect/readIniValueDirect for safe Bethesda INI
handling without QSettings corruption
- Fix prefix_setup.rs to skip umu-run bootstrapping
- Clean up settings UI, build scripts, and docs for umu-run removal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
| |
The CI was failing because ghcr.io/SulfurNitride/fluorine-builder had
uppercase letters (GHCR requires lowercase). Instead of depending on a
pre-built GHCR image, CI now builds the Docker image from the Dockerfile
each run (matching build.sh), with registry-based layer caching for speed.
Also removes the duplicated inline AppImage logic in favor of build-inner.sh.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Add AppConfig::pluginsPath()/dllsPath() that respect MO2_PLUGINS_DIR
and MO2_DLLS_DIR env vars, fixing plugin discovery when plugins live
inside read-only AppImage squashfs (#22, game plugin not found errors)
- Preserve file modification times in save deploy/sync so games display
correct save timestamps instead of all showing the same time (#17)
- Replace QSettings INI reader in saves tab with direct line-by-line
parser to avoid backslash-as-line-continuation corruption of
sLocalSavePath=__MO_Saves\ (#22, saves tab showing wrong directory)
- Add diagnostic logging to plugin symlink creation, save backup/restore
operations to help diagnose silent failures through prefix symlinks
- Fix Python SONAME mismatch in AppImage build (patch portable Python
SONAME to match librunner.so DT_NEEDED, preventing dual libpython load)
- Bundle PyQt6 Qt dependencies, improve RPATH for lib/ and plugins/
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- python: switch Py_InitializeEx → Py_InitializeFromConfig for explicit
error reporting; add dladdr + fprintf diagnostics to trace which DSO
Python symbols resolve to and whether Py_IsInitialized succeeds
- python: log RTLD_NOLOAD vs fresh-load outcome when promoting libpython
to RTLD_GLOBAL
- build: add Docker-based AppImage build script (build.sh), update
Dockerfile and build-inner.sh for AppImage-only workflow
- build: remove Flatpak support entirely; move AppImage metadata
(desktop/metainfo/icon) from flatpak/ to data/
- Add Monster Hunter Wilds basic_games plugin
- .gitignore: exclude squashfs-root, build-source, flatpak-repo,
__pycache__, fomod-plus-settings.ini
- Various Linux port fixes across wineprefix, processrunner, proton
launcher, FUSE connector, instance manager, download manager,
sanitychecks, and NaK Rust paths/runtime_wrap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
logging, pybind11 warning
- Set $ORIGIN-relative RPATH on binaries so they find libs without
LD_LIBRARY_PATH (fixes #12)
- Check QDir::isAbsolutePath before concatenating instance paths to
prevent doubling of custom portable paths
- Canonicalize paths when matching Proton installations to handle
symlinks in /usr/share/steam/compatibilitytools.d/ (fixes #8)
- Add diagnostic logging for umu-run resolution showing preference,
bundled/system paths, and final selection (helps diagnose #8)
- Warn at CMake time if pybind11 >= 2.14 is detected (documents #9)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
%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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- New native Root Builder plugin (src/plugins/rootbuilder.py) with copy
and symlink deploy modes, auto-deploy hooks, backup/restore, and
third-party conflict detection that moves incompatible plugins to
DisabledPlugins/. In link mode, .exe/.dll are always copied to avoid
Wine/Proton path resolution issues with symlinked executables.
- Fix basic_games detection on Linux: steam_utils now checks native
Steam paths (~/.local/share/Steam, Flatpak, Snap), epic_utils uses
correct Linux Heroic config paths, gog_utils falls back to Heroic
GOG installed.json when Windows registry is unavailable.
- Fix OMOD installer crash: isArchiveSupported now handles both IFileTree
(from mod list refresh) and string (from install check) arguments.
- Add flatpak manifest step to copy source-tree Python plugins
(src/plugins/*.py) into the build output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
|
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>
|