Skip to content

Commit e9e83e0

Browse files
authored
Add files via upload
1 parent 1ff1ee4 commit e9e83e0

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

games/game_monsterhunterwilds.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import uuid
2+
import re
3+
from pathlib import Path
4+
from typing import Iterable
5+
6+
import mobase
7+
from PyQt6.QtCore import QDir
8+
9+
from ..basic_features import BasicModDataChecker, GlobPatterns
10+
from ..basic_game import BasicGame
11+
12+
13+
class MonsterHunterWildsModDataChecker(BasicModDataChecker):
14+
def __init__(self):
15+
super().__init__(
16+
GlobPatterns(
17+
valid=[
18+
"dinput8.dll",
19+
"*.pak",
20+
"natives",
21+
"reframework",
22+
],
23+
delete=[
24+
"modinfo.ini",
25+
"*.png",
26+
"*.jpg",
27+
"*.jpeg",
28+
"*.webp",
29+
],
30+
)
31+
)
32+
33+
34+
class MonsterHunterWildsGame(BasicGame):
35+
Name = "Monster Hunter: Wilds Support Plugin"
36+
Author = "Yashirow"
37+
Version = "1.0.1"
38+
39+
GameName = "Monster Hunter: Wilds"
40+
GameShortName = "monsterhunterwilds"
41+
GameBinary = "MonsterHunterWilds.exe"
42+
GameDataPath = "%GAME_PATH%"
43+
GameSaveExtension = "bin"
44+
GameNexusId = 6993
45+
GameSteamId = 2246340
46+
47+
_PAK_PATTERN = re.compile(
48+
r"re_chunk_000\.pak\.sub_000\.pak\.patch_(\d+)\.pak$", re.IGNORECASE
49+
)
50+
51+
def init(self, organizer: mobase.IOrganizer) -> bool:
52+
super().init(organizer)
53+
self._register_feature(MonsterHunterWildsModDataChecker())
54+
organizer.onAboutToRun(self._onAboutToRun)
55+
return True
56+
57+
def _game_root(self) -> Path:
58+
return Path(self.gameDirectory().absolutePath())
59+
60+
def _active_mod_paths(self) -> Iterable[Path]:
61+
mods_parent_path = Path(self._organizer.modsPath())
62+
modlist = self._organizer.modList().allModsByProfilePriority()
63+
for mod_name in modlist:
64+
if self._organizer.modList().state(mod_name) & mobase.ModState.ACTIVE:
65+
yield mods_parent_path / mod_name
66+
67+
def _overwrite_path(self) -> Path:
68+
return Path(self._organizer.overwritePath())
69+
70+
def _next_patch_number(self) -> int:
71+
max_patch = -1
72+
for pak_path in self._game_root().glob("*.pak"):
73+
match = self._PAK_PATTERN.fullmatch(pak_path.name)
74+
if match:
75+
max_patch = max(max_patch, int(match.group(1)))
76+
return max_patch + 1
77+
78+
def _root_paks(self, root_path: Path) -> list[Path]:
79+
return sorted(
80+
[
81+
child
82+
for child in root_path.iterdir()
83+
if child.is_file() and child.suffix.lower() == ".pak"
84+
],
85+
key=lambda path: path.name.casefold(),
86+
)
87+
88+
def _rename_paks(self):
89+
pak_files: list[tuple[Path, Path]] = []
90+
next_patch = self._next_patch_number()
91+
92+
for mod_path in self._active_mod_paths():
93+
for pak_path in self._root_paks(mod_path):
94+
target_name = (
95+
f"re_chunk_000.pak.sub_000.pak.patch_{next_patch:03d}.pak"
96+
)
97+
pak_files.append((pak_path, mod_path / target_name))
98+
next_patch += 1
99+
100+
overwrite_path = self._overwrite_path()
101+
if overwrite_path.exists():
102+
for pak_path in self._root_paks(overwrite_path):
103+
target_name = (
104+
f"re_chunk_000.pak.sub_000.pak.patch_{next_patch:03d}.pak"
105+
)
106+
pak_files.append((pak_path, overwrite_path / target_name))
107+
next_patch += 1
108+
109+
temporary_paths: list[tuple[Path, Path]] = []
110+
for source_path, target_path in pak_files:
111+
if source_path == target_path:
112+
continue
113+
temp_path = source_path.with_name(
114+
f"{source_path.stem}.{uuid.uuid4().hex}.tmp{source_path.suffix}"
115+
)
116+
source_path.rename(temp_path)
117+
temporary_paths.append((temp_path, target_path))
118+
119+
for temp_path, target_path in temporary_paths:
120+
temp_path.rename(target_path)
121+
122+
def _onAboutToRun(self, app_path_str: str, wd: QDir, args: str) -> bool:
123+
if Path(app_path_str) == self._game_root() / self.binaryName():
124+
self._rename_paks()
125+
return True
126+
127+

0 commit comments

Comments
 (0)