Skip to content

Commit

Permalink
Fix for Subnautica 2.0 (#140)
Browse files Browse the repository at this point in the history
* Fix subnautica starting in VR mode by default (adding seperate exe)
* Fix Subnautica 2.0, QMods deprecated
* Add use_qmods setting: Install */.dll mods in legacy QMods folder, instead of BepInEx/plugins (default).
* Version bump: Subnautica [Below Zero] v2.2
  • Loading branch information
ZashIn authored Mar 15, 2024
1 parent 4ecc67b commit 975506f
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 16 deletions.
18 changes: 7 additions & 11 deletions games/game_subnautica-below-zero.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
from __future__ import annotations

import mobase

from ..basic_features.basic_mod_data_checker import GlobPatterns
from ..basic_features import GlobPatterns
from . import game_subnautica # namespace to not load SubnauticaGame here, too!


class SubnauticaBelowZeroGame(game_subnautica.SubnauticaGame):
Name = "Subnautica Below Zero Support Plugin"
Author = "dekart811, Zash"
Version = "2.1"
Version = "2.2"

GameName = "Subnautica: Below Zero"
GameShortName = "subnauticabelowzero"
Expand All @@ -29,11 +27,9 @@ class SubnauticaBelowZeroGame(game_subnautica.SubnauticaGame):
r"\Subnautica Below Zero\SubnauticaZero\SavedGames"
]

def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = (
game_subnautica.SubnauticaModDataChecker(
GlobPatterns(unfold=["BepInExPack_BelowZero"])
)
def _set_mod_data_checker(
self, extra_patterns: GlobPatterns | None = None, use_qmod: bool | None = None
):
super()._set_mod_data_checker(
GlobPatterns(unfold=["BepInExPack_BelowZero"]), use_qmod
)
return True
103 changes: 98 additions & 5 deletions games/game_subnautica.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import fnmatch
import os
from collections.abc import Iterable
from enum import Enum
Expand All @@ -13,31 +14,74 @@
BasicGameSaveGame,
BasicGameSaveGameInfo,
)
from ..basic_features.utils import is_directory
from ..basic_game import BasicGame


class SubnauticaModDataChecker(BasicModDataChecker):
def __init__(self, patterns: GlobPatterns = GlobPatterns()):
use_qmods: bool = False

def __init__(
self, patterns: GlobPatterns = GlobPatterns(), use_qmods: bool = False
):
super().__init__(
GlobPatterns(
unfold=["BepInExPack_Subnautica"],
valid=["winhttp.dll", "doorstop_config.ini", "BepInEx", "QMods"],
valid=[
"BepInEx",
"doorstop_libs",
"doorstop_config.ini",
"run_bepinex.sh",
"winhttp.dll",
"QMods",
],
delete=[
"*.txt",
"*.md",
"icon.png",
"license",
"manifest.json",
],
move={"plugins": "BepInEx/", "patchers": "BepInEx/", "*": "QMods/"},
move={
"plugins": "BepInEx/",
"patchers": "BepInEx/",
"CustomCraft2SML": "QMods/" if use_qmods else "BepInEx/plugins/",
"CustomCraft3": "QMods/" if use_qmods else "BepInEx/plugins/",
},
).merge(patterns),
)
self.use_qmods = use_qmods

def dataLooksValid(
self, filetree: mobase.IFileTree
) -> mobase.ModDataChecker.CheckReturn:
check_return = super().dataLooksValid(filetree)
# A single unknown folder with a dll file in is to be moved to BepInEx/plugins/
if (
check_return is self.INVALID
and len(filetree) == 1
and is_directory(folder := filetree[0])
and any(fnmatch.fnmatch(entry.name(), "*.dll") for entry in folder)
):
return self.FIXABLE
return check_return

def fix(self, filetree: mobase.IFileTree) -> mobase.IFileTree:
filetree = super().fix(filetree)
if (
self.dataLooksValid(filetree) is self.FIXABLE
and len(filetree) == 1
and is_directory(folder := filetree[0])
and any(fnmatch.fnmatch(entry.name(), "*.dll") for entry in folder)
):
filetree.move(folder, "QMods/" if self.use_qmods else "BepInEx/plugins/")
return filetree


class SubnauticaGame(BasicGame, mobase.IPluginFileMapper):
Name = "Subnautica Support Plugin"
Author = "dekart811, Zash"
Version = "2.1.1"
Version = "2.2"

GameName = "Subnautica"
GameShortName = "subnautica"
Expand Down Expand Up @@ -81,12 +125,48 @@ def __init__(self):

def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = SubnauticaModDataChecker()
self._set_mod_data_checker()
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
lambda s: Path(s or "", "screenshot.jpg")
)

organizer.onPluginSettingChanged(self._settings_change_callback)
return True

def _set_mod_data_checker(
self, extra_patterns: GlobPatterns | None = None, use_qmod: bool | None = None
):
self._featureMap[mobase.ModDataChecker] = SubnauticaModDataChecker(
patterns=(GlobPatterns() if extra_patterns is None else extra_patterns),
use_qmods=(
bool(self._organizer.pluginSetting(self.name(), "use_qmods"))
if use_qmod is None
else use_qmod
),
)

def _settings_change_callback(
self,
plugin_name: str,
setting: str,
old: mobase.MoVariant,
new: mobase.MoVariant,
):
if plugin_name == self.name() and setting == "use_qmods":
self._set_mod_data_checker(use_qmod=bool(new))

def settings(self) -> list[mobase.PluginSetting]:
return [
mobase.PluginSetting(
"use_qmods",
(
"Install */.dll mods in legacy QMods folder,"
" instead of BepInEx/plugins (default)."
),
default_value=False,
)
]

def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]:
return [
BasicGameSaveGame(folder)
Expand All @@ -97,6 +177,19 @@ def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]:
for folder in Path(save_path).glob("slot*")
]

def executables(self) -> list[mobase.ExecutableInfo]:
binary = self.gameDirectory().absoluteFilePath(self.binaryName())
return [
mobase.ExecutableInfo(
self.gameName(),
binary,
).withArgument("-vrmode none"),
mobase.ExecutableInfo(
f"{self.gameName()} VR",
self.gameDirectory().absoluteFilePath(self.binaryName()),
),
]

def executableForcedLoads(self) -> list[mobase.ExecutableForcedLoadSetting]:
return [
mobase.ExecutableForcedLoadSetting(self.binaryName(), lib).withEnabled(True)
Expand Down

0 comments on commit 975506f

Please sign in to comment.