aboutsummaryrefslogtreecommitdiff
path: root/libs/basic_games/games/baldursgate3/bg3_file_mapper.py
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-14 02:45:12 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-14 02:45:25 -0600
commit817e8f5cd26739c69d930d21cd9dc4c0b6e4984e (patch)
tree52aed11d6751bb7d20b06acf197d56fac113203d /libs/basic_games/games/baldursgate3/bg3_file_mapper.py
parent51a9f8f197727f00896e5de44569b098923527dd (diff)
Add FUSE external mapping support, BG3/Oblivion Remastered fixes, fomod-plus 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>
Diffstat (limited to 'libs/basic_games/games/baldursgate3/bg3_file_mapper.py')
-rw-r--r--libs/basic_games/games/baldursgate3/bg3_file_mapper.py33
1 files changed, 33 insertions, 0 deletions
diff --git a/libs/basic_games/games/baldursgate3/bg3_file_mapper.py b/libs/basic_games/games/baldursgate3/bg3_file_mapper.py
index 0ae6ef8..e2c54e9 100644
--- a/libs/basic_games/games/baldursgate3/bg3_file_mapper.py
+++ b/libs/basic_games/games/baldursgate3/bg3_file_mapper.py
@@ -1,5 +1,6 @@
import functools
import os
+import platform
from pathlib import Path
from typing import Callable, Optional
@@ -10,9 +11,12 @@ import mobase
from . import bg3_utils
+_IS_LINUX = platform.system() != "Windows"
+
class BG3FileMapper(mobase.IPluginFileMapper):
current_mappings: list[mobase.Mapping] = []
+ _linux_symlinks: list[Path] = []
def __init__(self, utils: bg3_utils.BG3Utils, doc_dir: Callable[[], QDir]):
super().__init__()
@@ -26,6 +30,8 @@ class BG3FileMapper(mobase.IPluginFileMapper):
def mappings(self) -> list[mobase.Mapping]:
qInfo("creating custom bg3 mappings")
self.current_mappings.clear()
+ if _IS_LINUX:
+ self._cleanup_linux_symlinks()
active_mods = self._utils.active_mods()
if not active_mods:
return []
@@ -121,6 +127,18 @@ class BG3FileMapper(mobase.IPluginFileMapper):
def create_mapping(self, file: Path, dest: Path):
bg3_utils.create_dir_if_needed(dest)
+ # On Linux, FUSE cannot handle file mappings outside the game's data
+ # directory. Create real symlinks so the game (via Proton) can find
+ # mod files in the documents/prefix directory.
+ if _IS_LINUX and not file.is_dir():
+ try:
+ if dest.is_symlink() or dest.exists():
+ dest.unlink()
+ dest.symlink_to(file)
+ self._linux_symlinks.append(dest)
+ except OSError as e:
+ qWarning(f"BG3: failed to symlink {dest} -> {file}: {e}")
+
self.current_mappings.append(
mobase.Mapping(
source=str(file),
@@ -129,3 +147,18 @@ class BG3FileMapper(mobase.IPluginFileMapper):
create_target=True,
)
)
+
+ def _cleanup_linux_symlinks(self):
+ """Remove symlinks created by previous mappings() calls."""
+ for link in self._linux_symlinks:
+ try:
+ if link.is_symlink():
+ link.unlink()
+ except OSError:
+ pass
+ self._linux_symlinks.clear()
+
+ def cleanup(self):
+ """Public cleanup method — call from onFinishedRun."""
+ if _IS_LINUX:
+ self._cleanup_linux_symlinks()