11from ..basic_game import BasicGame
22import mobase
3+ from ..basic_features import BasicModDataChecker , GlobPatterns
4+ from typing import Tuple
35
4- class SilentHill2RemakeModDataChecker (mobase . ModDataChecker ):
6+ class SilentHill2RemakeModDataChecker (BasicModDataChecker ):
57 def __init__ (self ):
6- super ().__init__ ()
7- self .validDirNames = [
8- "."
9- ]
8+ super ().__init__ (
9+ GlobPatterns (
10+ delete = [
11+ "*.txt" ,
12+ "*.md" ,
13+ "manifest.json" ,
14+ "icon.png" ,
15+ ],
16+ )
17+ )
18+ self .mod_path = ["SHProto" , "Content" , "Paks" , "~mod" ]
19+ self .mod_path_lower = [name .lower () for name in self .mod_path ]
1020
11- def dataLooksValid (self , filetree : mobase .IFileTree ) -> mobase .ModDataChecker .CheckReturn :
21+ def _find_tree (self , filetree : mobase .IFileTree ) -> Tuple [str | None , mobase .IFileTree | None ]:
22+ """
23+ Search the given filetree for a directory name that matches any component
24+ of self.mod_path (case-insensitive).
25+
26+ Returns:
27+ (prefix, entry)
28+ prefix: The missing part before the match (e.g. 'SHProto/Content/')
29+ entry: The IFileTree entry that matched (e.g. the 'Paks' directory)
30+ (None, None) if nothing matches.
31+ """
1232 for entry in filetree :
1333 if not entry .isDir ():
1434 continue
15- if entry .name ().casefold () in (name .casefold () for name in self .validDirNames ):
16- return mobase .ModDataChecker .VALID
35+
36+ name_lower = entry .name ().lower ()
37+ for i , component in enumerate (self .mod_path_lower ):
38+ if name_lower == component :
39+ # Build the prefix string for everything *before* this match
40+ prefix_parts = self .mod_path [:i ]
41+ prefix = "/" .join (prefix_parts ) + ("/" if prefix_parts else "" )
42+ return (prefix , entry )
43+
44+ # No matches found
45+ return (None , None )
46+
47+
48+ def dataLooksValid (self , filetree : mobase .IFileTree ) -> mobase .ModDataChecker .CheckReturn :
49+ # Check for fully valid layout
50+ has_entry ,_ = self ._find_tree (filetree )
51+ if has_entry is None :
52+ for entry in filetree :
53+ if entry .name ().lower ().endswith (".pak" ) and entry .isFile ():
54+ return mobase .ModDataChecker .FIXABLE
55+ elif has_entry is "" :
56+ return mobase .ModDataChecker .VALID
57+ else :
58+ return mobase .ModDataChecker .FIXABLE
59+
60+ # Otherwise, not recognizable
1761 return mobase .ModDataChecker .INVALID
62+
63+ def fix (self , filetree : mobase .IFileTree ) -> mobase .IFileTree :
64+ filetree = super ().fix (filetree )
65+ prefix , item = self ._find_tree (filetree )
66+ if prefix is None :
67+ foundAPak = False
68+ # Move all top-level items to BepInEx/plugins/
69+ items_to_move = list (filetree )
70+ for item in items_to_move :
71+ if item .name ().lower ().endswith (".pak" ):
72+ foundAPak = True
73+ filetree .move (item , f"SHProto/Content/Paks/~mod/{ item .name ()} " )
74+ return filetree if foundAPak else None
75+ elif prefix is "" :
76+ return filetree
77+ else :
78+ filetree .move (item , f"{ prefix } { item .name ()} " )
79+ return filetree
1880
1981class SilentHill2RemakeGame (BasicGame ):
2082 def init (self , organizer : mobase .IOrganizer ) -> bool :
@@ -32,19 +94,7 @@ def init(self, organizer: mobase.IOrganizer) -> bool:
3294
3395 GameBinary = "SHProto/Binaries/Win64/SHProto-Win64-Shipping.exe"
3496 GameLauncher = "SHProto.exe"
35- #GameDataPath = "%GAME_PATH%/SHProto/Content/Paks/~mods"
36- GameDataPath = "%GAME_PATH%/SHProto/Content"
97+ GameDataPath = "%GAME_PATH%"
3798 GameSupportURL = "https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/Game:-Silent-Hill-2-Remake"
3899
39- GameGogId = [1225972913 , 2051029707 ]
40-
41- # def executables(self):
42- # return [
43- # {
44- # "name": "Silent Hill 2 Remake",
45- # "binary": self.GameBinary,
46- # }
47- # ]
48-
49- # def dataDirectory(self):
50- # return self._gamePath + "/SHProto/Content/Paks"
100+ GameGogId = [1225972913 , 2051029707 ]
0 commit comments