Skip to content

Commit 503dc95

Browse files
committed
move file mapping definition to its own class
1 parent 8565599 commit 503dc95

2 files changed

Lines changed: 109 additions & 96 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import functools
2+
import json
3+
import os
4+
from pathlib import Path
5+
from typing import Callable, Optional
6+
7+
import mobase
8+
import yaml
9+
from PyQt6.QtCore import qInfo, qDebug, qWarning, QDir
10+
from PyQt6.QtWidgets import QApplication
11+
12+
from . import bg3_utils
13+
14+
15+
class BG3FileMapper(mobase.IPluginFileMapper):
16+
current_mappings: list[mobase.Mapping] = []
17+
18+
def __init__(self, utils: bg3_utils.BG3Utils, doc_dir: Callable[[], QDir]):
19+
super().__init__()
20+
self._utils = utils
21+
self.doc_dir = doc_dir
22+
23+
@functools.cached_property
24+
def doc_path(self):
25+
return Path(self.doc_dir().path())
26+
27+
def mappings(self) -> list[mobase.Mapping]:
28+
qInfo("creating custom bg3 mappings")
29+
self.current_mappings.clear()
30+
active_mods = self._utils.active_mods()
31+
doc_dir = Path(self.doc_dir().path())
32+
progress = self._utils.create_progress_window(
33+
"Mapping files to documents folder", len(active_mods) + 1
34+
)
35+
docs_path_mods = doc_dir / "Mods"
36+
docs_path_se = doc_dir / "Script Extender"
37+
for mod in active_mods:
38+
modpath = Path(mod.absolutePath())
39+
self.map_files(modpath, dest=docs_path_mods, pattern="*.pak", rel=False)
40+
self.map_files(modpath / "Script Extender", dest=docs_path_se)
41+
progress.setValue(progress.value() + 1)
42+
QApplication.processEvents()
43+
if progress.wasCanceled():
44+
qWarning("mapping canceled by user")
45+
return self.current_mappings
46+
self.map_files(self._utils.overwrite_path)
47+
self.create_mapping(
48+
self._utils.modsettings_path,
49+
doc_dir / "PlayerProfiles" / "Public" / self._utils.modsettings_path.name,
50+
)
51+
progress.setValue(len(active_mods) + 1)
52+
QApplication.processEvents()
53+
progress.close()
54+
return self.current_mappings
55+
56+
def map_files(
57+
self,
58+
path: Path,
59+
dest: Optional[Path] = None,
60+
pattern: str = "*",
61+
rel: bool = True,
62+
):
63+
dest = dest if dest else self.doc_path
64+
dest_func: Callable[[Path], str] = (
65+
(lambda f: os.path.relpath(f, path)) if rel else lambda f: f.name
66+
)
67+
found_jsons: set[Path] = set()
68+
for file in list(path.rglob(pattern)):
69+
if self._utils.convert_yamls_to_json and (
70+
file.name.endswith(".yaml") or file.name.endswith(".yml")
71+
):
72+
converted_path = file.parent / file.name.replace(
73+
".yaml", ".json"
74+
).replace(".yml", ".json")
75+
try:
76+
if not converted_path.exists() or os.path.getmtime(
77+
file
78+
) > os.path.getmtime(converted_path):
79+
with open(file, "r") as yaml_file:
80+
with open(converted_path, "w") as json_file:
81+
json.dump(
82+
yaml.safe_load(yaml_file), json_file, indent=2
83+
)
84+
qDebug(f"Converted {file} to JSON")
85+
found_jsons.add(converted_path)
86+
except OSError as e:
87+
qWarning(f"Error accessing file {converted_path}: {e}")
88+
elif file.name.endswith(".json"):
89+
found_jsons.add(file)
90+
else:
91+
self.create_mapping(file, dest / dest_func(file))
92+
for file in found_jsons:
93+
self.create_mapping(file, dest / dest_func(file))
94+
95+
def create_mapping(self, file: Path, dest: Path):
96+
self.current_mappings.append(
97+
mobase.Mapping(
98+
source=str(file),
99+
destination=str(dest),
100+
is_directory=file.is_dir(),
101+
create_target=True,
102+
)
103+
)

games/game_baldursgate3.py

Lines changed: 6 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,26 @@
11
import datetime
22
import difflib
3-
import json
43
import os
54
import shutil
65
from functools import cached_property
76
from pathlib import Path
8-
from typing import Any, Callable
7+
from typing import Any
98

109
import mobase
11-
import yaml
1210
from PyQt6.QtCore import (
1311
qDebug,
1412
qInfo,
15-
qWarning,
16-
)
17-
from PyQt6.QtWidgets import (
18-
QApplication,
1913
)
2014

15+
from .baldursgate3 import bg3_file_mapper
2116
from ..basic_features import (
2217
BasicGameSaveGameInfo,
2318
BasicLocalSavegames,
2419
)
2520
from ..basic_game import BasicGame
2621

2722

28-
class BG3Game(BasicGame, mobase.IPluginFileMapper):
23+
class BG3Game(BasicGame, bg3_file_mapper.BG3FileMapper):
2924
Name = "Baldur's Gate 3 Plugin"
3025
Author = "daescha"
3126
Version = "0.1.0"
@@ -47,10 +42,12 @@ class BG3Game(BasicGame, mobase.IPluginFileMapper):
4742

4843
def __init__(self):
4944
BasicGame.__init__(self)
50-
mobase.IPluginFileMapper.__init__(self)
5145
from .baldursgate3 import bg3_utils
5246

5347
self._utils = bg3_utils.BG3Utils(self.name())
48+
bg3_file_mapper.BG3FileMapper.__init__(
49+
self, self._utils, self.documentsDirectory
50+
)
5451

5552
def init(self, organizer: mobase.IOrganizer) -> bool:
5653
super().init(organizer)
@@ -192,93 +189,6 @@ def find_dlls(
192189
]
193190
return efls
194191

195-
def mappings(self) -> list[mobase.Mapping]:
196-
qInfo("creating custom bg3 mappings")
197-
mappings: list[mobase.Mapping] = []
198-
docs_path = Path(self.documentsDirectory().path())
199-
active_mods = self._utils.active_mods()
200-
201-
def map_files(
202-
path: Path,
203-
dest: Path = docs_path,
204-
pattern: str = "*",
205-
rel: bool = True,
206-
):
207-
dest_func: Callable[[Path], str] = (
208-
(lambda f: os.path.relpath(f, path)) if rel else lambda f: f.name
209-
)
210-
found_jsons: set[Path] = set()
211-
212-
def add_mapping(file: Path):
213-
mappings.append(
214-
mobase.Mapping(
215-
source=str(file),
216-
destination=str(dest / dest_func(file)),
217-
is_directory=file.is_dir(),
218-
create_target=True,
219-
)
220-
)
221-
222-
for file in list(path.rglob(pattern)):
223-
if self._utils.convert_yamls_to_json and (
224-
file.name.endswith(".yaml") or file.name.endswith(".yml")
225-
):
226-
converted_path = file.parent / file.name.replace(
227-
".yaml", ".json"
228-
).replace(".yml", ".json")
229-
try:
230-
if not converted_path.exists() or os.path.getmtime(
231-
file
232-
) > os.path.getmtime(converted_path):
233-
with open(file, "r") as yaml_file:
234-
with open(converted_path, "w") as json_file:
235-
json.dump(
236-
yaml.safe_load(yaml_file), json_file, indent=2
237-
)
238-
qDebug(f"Converted {file} to JSON")
239-
found_jsons.add(converted_path)
240-
except OSError as e:
241-
qWarning(f"Error accessing file {converted_path}: {e}")
242-
elif file.name.endswith(".json"):
243-
found_jsons.add(file)
244-
else:
245-
add_mapping(file)
246-
for file in found_jsons:
247-
add_mapping(file)
248-
249-
progress = self._utils.create_progress_window(
250-
"Mapping files to documents folder", len(active_mods) + 1
251-
)
252-
docs_path_mods = docs_path / "Mods"
253-
docs_path_se = docs_path / "Script Extender"
254-
for mod in active_mods:
255-
modpath = Path(mod.absolutePath())
256-
map_files(modpath, docs_path_mods, pattern="*.pak", rel=False)
257-
map_files(modpath / "Script Extender", docs_path_se)
258-
progress.setValue(progress.value() + 1)
259-
QApplication.processEvents()
260-
if progress.wasCanceled():
261-
qWarning("mapping canceled by user")
262-
return mappings
263-
map_files(self._utils.overwrite_path)
264-
mappings.append(
265-
mobase.Mapping(
266-
source=str(self._utils.modsettings_path),
267-
destination=str(
268-
docs_path
269-
/ "PlayerProfiles"
270-
/ "Public"
271-
/ self._utils.modsettings_path.name
272-
),
273-
is_directory=False,
274-
create_target=True,
275-
)
276-
)
277-
progress.setValue(len(active_mods) + 1)
278-
QApplication.processEvents()
279-
progress.close()
280-
return mappings
281-
282192
def loadOrderMechanism(self) -> mobase.LoadOrderMechanism:
283193
return mobase.LoadOrderMechanism.PLUGINS_TXT
284194

0 commit comments

Comments
 (0)