aboutsummaryrefslogtreecommitdiff
path: root/libs/basic_games/games/baldursgate3/plugins
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
commit7ee008e150bc5bcf76082d726f719ee0fdfda982 (patch)
tree27fb39be241fdb5ac2734c574de678977d1856d0 /libs/basic_games/games/baldursgate3/plugins
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 <noreply@anthropic.com>
Diffstat (limited to 'libs/basic_games/games/baldursgate3/plugins')
-rw-r--r--libs/basic_games/games/baldursgate3/plugins/__init__.py13
-rw-r--r--libs/basic_games/games/baldursgate3/plugins/bg3_tool_plugin.py49
-rw-r--r--libs/basic_games/games/baldursgate3/plugins/check_for_lslib_updates_plugin.py15
-rw-r--r--libs/basic_games/games/baldursgate3/plugins/convert_jsons_to_yaml_plugin.py58
-rw-r--r--libs/basic_games/games/baldursgate3/plugins/icons.py42
-rw-r--r--libs/basic_games/games/baldursgate3/plugins/reparse_pak_metadata_plugin.py17
6 files changed, 194 insertions, 0 deletions
diff --git a/libs/basic_games/games/baldursgate3/plugins/__init__.py b/libs/basic_games/games/baldursgate3/plugins/__init__.py
new file mode 100644
index 0000000..1b69faf
--- /dev/null
+++ b/libs/basic_games/games/baldursgate3/plugins/__init__.py
@@ -0,0 +1,13 @@
+import mobase
+
+from .check_for_lslib_updates_plugin import BG3ToolCheckForLsLibUpdates
+from .convert_jsons_to_yaml_plugin import BG3ToolConvertJsonsToYaml
+from .reparse_pak_metadata_plugin import BG3ToolReparsePakMetadata
+
+
+def createPlugins() -> list[mobase.IPluginTool]:
+ return [
+ BG3ToolCheckForLsLibUpdates(),
+ BG3ToolReparsePakMetadata(),
+ BG3ToolConvertJsonsToYaml(),
+ ]
diff --git a/libs/basic_games/games/baldursgate3/plugins/bg3_tool_plugin.py b/libs/basic_games/games/baldursgate3/plugins/bg3_tool_plugin.py
new file mode 100644
index 0000000..fc258a6
--- /dev/null
+++ b/libs/basic_games/games/baldursgate3/plugins/bg3_tool_plugin.py
@@ -0,0 +1,49 @@
+from PyQt6.QtCore import QCoreApplication
+from PyQt6.QtGui import QIcon, QPixmap
+
+import mobase
+
+
+class BG3ToolPlugin(mobase.IPluginTool, mobase.IPlugin):
+ desc = sub_name = ""
+ icon_bytes: bytes
+
+ def __init__(self):
+ mobase.IPluginTool.__init__(self)
+ mobase.IPlugin.__init__(self)
+ self._pluginName = self._displayName = "BG3 Tools"
+ self._pluginVersion = mobase.VersionInfo(1, 0, 0)
+ pixmap = QPixmap()
+ pixmap.loadFromData(self.icon_bytes, "SVG")
+ self.qicon = QIcon(pixmap)
+
+ def init(self, organizer: mobase.IOrganizer) -> bool:
+ self._organizer = organizer
+ return True
+
+ def version(self):
+ return self._pluginVersion
+
+ def author(self):
+ return "daescha"
+
+ def name(self):
+ return f"{self._pluginName}: {self.sub_name}"
+
+ def displayName(self):
+ return f"{self._displayName}/{self.sub_name}"
+
+ def tooltip(self):
+ return self.description()
+
+ def enabledByDefault(self):
+ return self._organizer.managedGame().name() == "Baldur's Gate 3 Plugin"
+
+ def settings(self) -> list[mobase.PluginSetting]:
+ return []
+
+ def icon(self) -> QIcon:
+ return self.qicon
+
+ def description(self) -> str:
+ return QCoreApplication.translate(self._pluginName, self.desc)
diff --git a/libs/basic_games/games/baldursgate3/plugins/check_for_lslib_updates_plugin.py b/libs/basic_games/games/baldursgate3/plugins/check_for_lslib_updates_plugin.py
new file mode 100644
index 0000000..b534e8a
--- /dev/null
+++ b/libs/basic_games/games/baldursgate3/plugins/check_for_lslib_updates_plugin.py
@@ -0,0 +1,15 @@
+from .bg3_tool_plugin import BG3ToolPlugin
+from .icons import download
+
+
+class BG3ToolCheckForLsLibUpdates(BG3ToolPlugin):
+ icon_bytes = download
+ sub_name = "Check For LsLib Updates"
+ desc = "Check to see if there has been a new release of LSLib and create download dialog if so."
+
+ def display(self):
+ from ...game_baldursgate3 import BG3Game
+
+ game_plugin = self._organizer.managedGame()
+ if isinstance(game_plugin, BG3Game):
+ game_plugin.utils.lslib_retriever.download_lslib_if_missing(True)
diff --git a/libs/basic_games/games/baldursgate3/plugins/convert_jsons_to_yaml_plugin.py b/libs/basic_games/games/baldursgate3/plugins/convert_jsons_to_yaml_plugin.py
new file mode 100644
index 0000000..fde3431
--- /dev/null
+++ b/libs/basic_games/games/baldursgate3/plugins/convert_jsons_to_yaml_plugin.py
@@ -0,0 +1,58 @@
+import json
+import os
+from pathlib import Path
+
+from PyQt6.QtCore import qInfo, qWarning
+from PyQt6.QtWidgets import QApplication
+
+from .bg3_tool_plugin import BG3ToolPlugin
+from .icons import exchange
+
+
+class BG3ToolConvertJsonsToYaml(BG3ToolPlugin):
+ icon_bytes = exchange
+ sub_name = "Convert JSONS to YAML"
+ desc = "Convert all jsons in active mods to yaml immediately."
+
+ def display(self):
+ from ...game_baldursgate3 import BG3Game
+
+ game_plugin = self._organizer.managedGame()
+ if not isinstance(game_plugin, BG3Game):
+ return
+ utils = game_plugin.utils
+ qInfo("converting all json files to yaml")
+ active_mods = utils.active_mods()
+ progress = utils.create_progress_window(
+ "Converting all json files to yaml", len(active_mods) + 1
+ )
+ for mod in active_mods:
+ _convert_jsons_in_dir_to_yaml(Path(mod.absolutePath()))
+ progress.setValue(progress.value() + 1)
+ QApplication.processEvents()
+ if progress.wasCanceled():
+ qWarning("conversion canceled by user")
+ return
+ _convert_jsons_in_dir_to_yaml(utils.overwrite_path)
+ progress.setValue(len(active_mods) + 1)
+ QApplication.processEvents()
+ progress.close()
+
+
+def _convert_jsons_in_dir_to_yaml(path: Path):
+ for file in list(path.rglob("*.json")):
+ converted_path = file.parent / file.name.replace(".json", ".yaml")
+ try:
+ if not converted_path.exists() or os.path.getmtime(file) > os.path.getmtime(
+ converted_path
+ ):
+ import yaml
+
+ with open(file, "r") as json_file:
+ with open(converted_path, "w") as yaml_file:
+ yaml.dump(
+ json.load(json_file), yaml_file, indent=2, sort_keys=False
+ )
+ qInfo(f"Converted {file} to YAML")
+ except OSError as e:
+ qWarning(f"Error accessing file {converted_path}: {e}")
diff --git a/libs/basic_games/games/baldursgate3/plugins/icons.py b/libs/basic_games/games/baldursgate3/plugins/icons.py
new file mode 100644
index 0000000..adc1023
--- /dev/null
+++ b/libs/basic_games/games/baldursgate3/plugins/icons.py
@@ -0,0 +1,42 @@
+refresh = b"""
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<!-- source: https://www.svgrepo.com/svg/168563/refresh -->
+<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 496.166 496.166" xml:space="preserve">
+ <path style="fill:#32BEA6;" d="M0.005,248.087C0.005,111.063,111.073,0,248.079,0c137.014,0,248.082,111.062,248.082,248.087
+ c0,137.002-111.068,248.079-248.082,248.079C111.073,496.166,0.005,385.089,0.005,248.087z"/>
+ <path style="fill:#F7F7F7;" d="M400.813,169.581c-2.502-4.865-14.695-16.012-35.262-5.891
+ c-20.564,10.122-10.625,32.351-10.625,32.351c7.666,15.722,11.98,33.371,11.98,52.046c0,65.622-53.201,118.824-118.828,118.824
+ c-65.619,0-118.82-53.202-118.82-118.824c0-61.422,46.6-111.946,106.357-118.173v30.793c0,0-0.084,1.836,1.828,2.999
+ c1.906,1.163,3.818,0,3.818,0l98.576-58.083c0,0,2.211-1.162,2.211-3.436c0-1.873-2.211-3.205-2.211-3.205l-98.248-57.754
+ c0,0-2.24-1.605-4.23-0.826c-1.988,0.773-1.744,3.481-1.744,3.481v32.993c-88.998,6.392-159.23,80.563-159.23,171.21
+ c0,94.824,76.873,171.696,171.693,171.696c94.828,0,171.707-76.872,171.707-171.696
+ C419.786,219.788,412.933,193.106,400.813,169.581z"/>
+</svg>
+"""
+
+exchange = b"""
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
+<!-- source: https://www.svgrepo.com/svg/449729/exchange-alt-s (edited color) -->
+<svg width="800px" height="800px" viewBox="-1 0 20 20" id="meteor-icon-kit__solid-exchange-alt-s" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <g id="SVGRepo_bgCarrier" stroke-width="0"/>
+ <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
+ <g id="SVGRepo_iconCarrier">
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M5.62132 6.5L6.06066 6.93934C6.64645 7.52513 6.64645 8.4749 6.06066 9.0607C5.47487 9.6464 4.52513 9.6464 3.93934 9.0607L0.93934 6.06066C0.35355 5.47487 0.35355 4.52513 0.93934 3.93934L3.93934 0.93934C4.52513 0.35355 5.47487 0.35355 6.06066 0.93934C6.64645 1.52513 6.64645 2.47487 6.06066 3.06066L5.62132 3.5H16C16.8284 3.5 17.5 4.17157 17.5 5V8C17.5 8.8284 16.8284 9.5 16 9.5C15.1716 9.5 14.5 8.8284 14.5 8V6.5H5.62132zM12.3787 13.5L11.9393 13.0607C11.3536 12.4749 11.3536 11.5251 11.9393 10.9393C12.5251 10.3536 13.4749 10.3536 14.0607 10.9393L17.0607 13.9393C17.6464 14.5251 17.6464 15.4749 17.0607 16.0607L14.0607 19.0607C13.4749 19.6464 12.5251 19.6464 11.9393 19.0607C11.3536 18.4749 11.3536 17.5251 11.9393 16.9393L12.3787 16.5H2C1.17157 16.5 0.5 15.8284 0.5 15V12C0.5 11.1716 1.17157 10.5 2 10.5C2.82843 10.5 3.5 11.1716 3.5 12V13.5H12.3787z" fill="#5046d2"/>
+ </g>
+</svg>
+"""
+
+download = b"""
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<!-- source: https://www.svgrepo.com/svg/243947/download -->
+<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve">
+ <polygon style="fill:#CFF09E;" points="319.666,253.182 319.666,95.093 192.334,95.093 192.334,253.182 131.742,253.182 256,416.907 380.258,253.182 "/>
+ <g>
+ <path style="fill:#507C5C;" d="M256,431.967c-4.709,0-9.148-2.203-11.996-5.954L119.748,262.287 c-3.458-4.555-4.036-10.678-1.492-15.8c2.543-5.123,7.769-8.364,13.488-8.364h45.533V95.092c0-8.315,6.742-15.059,15.059-15.059 h127.331c8.317,0,15.059,6.743,15.059,15.059v143.03h45.533c5.719,0,10.945,3.239,13.488,8.364 c2.543,5.122,1.965,11.244-1.492,15.8L267.997,426.011C265.148,429.764,260.709,431.967,256,431.967z M162.075,268.241L256,391.999 l93.925-123.758h-30.259c-8.317,0-15.059-6.743-15.059-15.059V110.151h-97.214v143.03c0,8.315-6.742,15.059-15.059,15.059h-30.259 V268.241z"/>
+ <path style="fill:#507C5C;" d="M256,512C114.842,512,0,397.158,0,256S114.842,0,256,0c8.317,0,15.059,6.743,15.059,15.059 S264.317,30.118,256,30.118C131.448,30.118,30.118,131.448,30.118,256S131.448,481.882,256,481.882S481.882,380.552,481.882,256 c0-68.911-30.874-133.183-84.706-176.34c-6.489-5.203-7.532-14.681-2.33-21.17c5.203-6.49,14.679-7.529,21.168-2.331 C477.015,105.064,512,177.903,512,256C512,397.158,397.158,512,256,512z"/>
+ </g>
+</svg>
+"""
diff --git a/libs/basic_games/games/baldursgate3/plugins/reparse_pak_metadata_plugin.py b/libs/basic_games/games/baldursgate3/plugins/reparse_pak_metadata_plugin.py
new file mode 100644
index 0000000..f32a8a0
--- /dev/null
+++ b/libs/basic_games/games/baldursgate3/plugins/reparse_pak_metadata_plugin.py
@@ -0,0 +1,17 @@
+from .bg3_tool_plugin import BG3ToolPlugin
+from .icons import refresh
+
+
+class BG3ToolReparsePakMetadata(BG3ToolPlugin):
+ icon_bytes = refresh
+ sub_name = "Reparse Pak Metadata"
+ desc = "Force reparsing mod metadata immediately."
+
+ def display(self):
+ from ...game_baldursgate3 import BG3Game
+
+ game_plugin = self._organizer.managedGame()
+ if isinstance(game_plugin, BG3Game):
+ game_plugin.utils.construct_modsettings_xml(
+ exec_path="bin/bg3", force_reparse_metadata=True
+ )