mirror of
https://github.com/ModOrganizer2/modorganizer-basic_games.git
synced 2026-07-27 14:07:29 -07:00
114 lines
4.1 KiB
Python
114 lines
4.1 KiB
Python
from typing import Tuple
|
|
|
|
import mobase
|
|
|
|
from ..basic_features import BasicModDataChecker, GlobPatterns
|
|
from ..basic_game import BasicGame
|
|
|
|
|
|
class SilentHill2RemakeModDataChecker(BasicModDataChecker):
|
|
def __init__(self):
|
|
super().__init__(
|
|
GlobPatterns(
|
|
delete=[
|
|
"*.txt",
|
|
"*.md",
|
|
"manifest.json",
|
|
"icon.png",
|
|
],
|
|
)
|
|
)
|
|
self.mod_path = ["SHProto", "Content", "Paks", "~mod"]
|
|
self.mod_path_lower = [name.lower() for name in self.mod_path]
|
|
|
|
def _find_tree(
|
|
self, filetree: mobase.IFileTree
|
|
) -> Tuple[str | None, mobase.FileTreeEntry | None]:
|
|
"""
|
|
Search the given filetree for a directory name that matches any component
|
|
of self.mod_path (case-insensitive).
|
|
|
|
Returns:
|
|
(prefix, entry)
|
|
prefix: The missing part before the match (e.g. 'SHProto/Content/')
|
|
entry: The IFileTree entry that matched (e.g. the 'Paks' directory)
|
|
(None, None) if nothing matches.
|
|
"""
|
|
for entry in filetree:
|
|
if not entry.isDir():
|
|
continue
|
|
|
|
name_lower = entry.name().lower()
|
|
for i, component in enumerate(self.mod_path_lower):
|
|
if name_lower == component:
|
|
# Build the prefix string for everything *before* this match
|
|
prefix_parts = self.mod_path[:i]
|
|
prefix = "/".join(prefix_parts) + ("/" if prefix_parts else "")
|
|
return (prefix, entry)
|
|
# No matches found
|
|
return (None, None)
|
|
|
|
def dataLooksValid(
|
|
self, filetree: mobase.IFileTree
|
|
) -> mobase.ModDataChecker.CheckReturn:
|
|
# Check for fully valid layout
|
|
has_entry, _ = self._find_tree(filetree)
|
|
if has_entry is None:
|
|
# in this case we check to make sure there's a .pak file
|
|
for entry in filetree:
|
|
if entry.name().lower().endswith(".pak") and entry.isFile():
|
|
return mobase.ModDataChecker.FIXABLE
|
|
elif has_entry == "":
|
|
return mobase.ModDataChecker.VALID
|
|
else:
|
|
return mobase.ModDataChecker.FIXABLE
|
|
|
|
# Otherwise, not recognizable
|
|
return mobase.ModDataChecker.INVALID
|
|
|
|
def fix(self, filetree: mobase.IFileTree) -> mobase.IFileTree:
|
|
filetree = super().fix(filetree)
|
|
prefix, item = self._find_tree(filetree)
|
|
if prefix is None:
|
|
foundAPak = False
|
|
# Move all top-level items to BepInEx/plugins/
|
|
items_to_move = list(filetree)
|
|
for cur_item in items_to_move:
|
|
if cur_item.name().lower().endswith(".pak"):
|
|
foundAPak = True
|
|
filetree.move(cur_item, f"SHProto/Content/Paks/~mod/{cur_item.name()}")
|
|
# foundAPack MUST be true because if 'prefix' returned None then
|
|
# there must be a .pak file or dataLooksValid wouldn't have returned
|
|
# a FIXABLE. This is therefore just a sanity check
|
|
assert foundAPak
|
|
return filetree
|
|
elif prefix == "":
|
|
return filetree
|
|
else:
|
|
# if prefix is not None then item cannot be None
|
|
assert item is not None
|
|
filetree.move(item, f"{prefix}{item.name()}")
|
|
return filetree
|
|
|
|
|
|
class SilentHill2RemakeGame(BasicGame):
|
|
def init(self, organizer: mobase.IOrganizer) -> bool:
|
|
super().init(organizer)
|
|
self._register_feature(SilentHill2RemakeModDataChecker())
|
|
return True
|
|
|
|
Name = "Silent Hill 2 Remake Support Plugin"
|
|
Author = "HomerSimpleton Returns"
|
|
Version = "1.0"
|
|
|
|
GameName = "Silent Hill 2 Remake"
|
|
GameShortName = "silenthill2"
|
|
GameNexusName = "silenthill2"
|
|
|
|
GameBinary = "SHProto/Binaries/Win64/SHProto-Win64-Shipping.exe"
|
|
GameLauncher = "SHProto.exe"
|
|
GameDataPath = "%GAME_PATH%"
|
|
GameSupportURL = "https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/Game:-Silent-Hill-2-Remake"
|
|
|
|
GameGogId = [1225972913, 2051029707]
|