mirror of
https://github.com/ModOrganizer2/modorganizer-basic_games.git
synced 2026-07-27 14:07:29 -07:00
Subnautica: custom mapping to fix saving (saves in game dir)
This commit is contained in:
@@ -9,14 +9,14 @@ class SubnauticaBelowZeroGame(game_subnautica.SubnauticaGame):
|
||||
|
||||
Name = "Subnautica Below Zero Support Plugin"
|
||||
Author = "dekart811, Zash"
|
||||
Version = "2.0"
|
||||
Version = "2.1"
|
||||
|
||||
GameName = "Subnautica: Below Zero"
|
||||
GameShortName = "subnauticabelowzero"
|
||||
GameNexusName = "subnauticabelowzero"
|
||||
GameSteamId = 848450
|
||||
GameBinary = "SubnauticaZero.exe"
|
||||
GameDataPath = ""
|
||||
GameDataPath = "_ROOT"
|
||||
GameDocumentsDirectory = "%GAME_PATH%"
|
||||
GameSupportURL = (
|
||||
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5.QtCore import QDir
|
||||
from PyQt5.QtCore import QDir, qWarning
|
||||
|
||||
import mobase
|
||||
|
||||
@@ -30,11 +32,11 @@ class SubnauticaModDataChecker(BasicModDataChecker):
|
||||
}
|
||||
|
||||
|
||||
class SubnauticaGame(BasicGame):
|
||||
class SubnauticaGame(BasicGame, mobase.IPluginFileMapper):
|
||||
|
||||
Name = "Subnautica Support Plugin"
|
||||
Author = "dekart811, Zash"
|
||||
Version = "2.0"
|
||||
Version = "2.1"
|
||||
|
||||
GameName = "Subnautica"
|
||||
GameShortName = "subnautica"
|
||||
@@ -42,8 +44,8 @@ class SubnauticaGame(BasicGame):
|
||||
GameSteamId = 264710
|
||||
GameEpicId = "Jaguar"
|
||||
GameBinary = "Subnautica.exe"
|
||||
GameDataPath = ""
|
||||
GameDocumentsDirectory = "%GAME_PATH%"
|
||||
GameDataPath = "_ROOT" # Custom mappings to actual root folders below.
|
||||
GameDocumentsDirectory = r"%GAME_PATH%"
|
||||
GameSupportURL = (
|
||||
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
||||
"Game:-Subnautica"
|
||||
@@ -57,6 +59,25 @@ class SubnauticaGame(BasicGame):
|
||||
|
||||
_forced_libraries = ["winhttp.dll"]
|
||||
|
||||
_root_blacklist = {GameDataPath.casefold()}
|
||||
|
||||
class MapType(Enum):
|
||||
FILE = 0
|
||||
FOLDER = 1
|
||||
|
||||
_root_extra_overwrites: dict[str, MapType] = {
|
||||
"qmodmanager_log-Subnautica.txt": MapType.FILE,
|
||||
"qmodmanager-config.json": MapType.FILE,
|
||||
"BepInEx_Shim_Backup": MapType.FOLDER,
|
||||
}
|
||||
"""Extra files & folders created in game root by mods / BepInEx after game launch,
|
||||
but not included in the mod archives.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
mobase.IPluginFileMapper.__init__(self)
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer) -> bool:
|
||||
super().init(organizer)
|
||||
self._featureMap[mobase.ModDataChecker] = SubnauticaModDataChecker()
|
||||
@@ -80,3 +101,75 @@ class SubnauticaGame(BasicGame):
|
||||
mobase.ExecutableForcedLoadSetting(self.binaryName(), lib).withEnabled(True)
|
||||
for lib in self._forced_libraries
|
||||
]
|
||||
|
||||
def mappings(self) -> list[mobase.Mapping]:
|
||||
game = self._organizer.managedGame()
|
||||
game_path = Path(game.gameDirectory().absolutePath())
|
||||
overwrite_path = Path(self._organizer.overwritePath())
|
||||
|
||||
return [
|
||||
*(
|
||||
# Extra overwrites
|
||||
self._overwrite_mapping(
|
||||
overwrite_path / name,
|
||||
dest,
|
||||
is_dir=(map_type is self.MapType.FOLDER),
|
||||
)
|
||||
for name, map_type in self._root_extra_overwrites.items()
|
||||
if not (dest := game_path / name).exists()
|
||||
),
|
||||
*self._root_mappings(game_path, overwrite_path),
|
||||
]
|
||||
|
||||
def _root_mappings(
|
||||
self, game_path: Path, overwrite_path: Path
|
||||
) -> Iterable[mobase.Mapping]:
|
||||
for mod_path in self._active_mod_paths():
|
||||
mod_name = mod_path.name
|
||||
|
||||
for child in mod_path.iterdir():
|
||||
# Check blacklist
|
||||
if child.name.casefold() in self._root_blacklist:
|
||||
qWarning(f"Skipping {child.name} ({mod_name})")
|
||||
continue
|
||||
destination = game_path / child.name
|
||||
# Check existing
|
||||
if destination.exists():
|
||||
qWarning(
|
||||
f"Overwriting of existing game files/folders is not supported! "
|
||||
f"{destination.as_posix()} ({mod_name})"
|
||||
)
|
||||
continue
|
||||
# Mapping: mod -> root
|
||||
yield mobase.Mapping(
|
||||
source=str(child),
|
||||
destination=str(destination),
|
||||
is_directory=child.is_dir(),
|
||||
create_target=False,
|
||||
)
|
||||
if child.is_dir():
|
||||
# Mapping: overwrite <-> root
|
||||
yield self._overwrite_mapping(
|
||||
overwrite_path / child.name, destination, is_dir=True
|
||||
)
|
||||
|
||||
def _active_mod_paths(self) -> Iterable[Path]:
|
||||
mods_parent_path = Path(self._organizer.modsPath())
|
||||
modlist = self._organizer.modList().allModsByProfilePriority()
|
||||
for mod in modlist:
|
||||
if self._organizer.modList().state(mod) & mobase.ModState.ACTIVE:
|
||||
yield mods_parent_path / mod
|
||||
|
||||
def _overwrite_mapping(
|
||||
self, overwrite_source: Path, destination: Path, is_dir: bool
|
||||
) -> mobase.Mapping:
|
||||
"""Mapping: overwrite <-> root"""
|
||||
if is_dir:
|
||||
# Root folders in overwrite need to exits.
|
||||
overwrite_source.mkdir(parents=True, exist_ok=True)
|
||||
return mobase.Mapping(
|
||||
str(overwrite_source),
|
||||
str(destination),
|
||||
is_dir,
|
||||
create_target=True,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user