11from __future__ import annotations
22
3+ import fnmatch
34import os
45from collections .abc import Iterable
56from enum import Enum
1314 BasicGameSaveGame ,
1415 BasicGameSaveGameInfo ,
1516)
17+ from ..basic_features .utils import is_directory
1618from ..basic_game import BasicGame
1719
1820
1921class SubnauticaModDataChecker (BasicModDataChecker ):
20- def __init__ (self , patterns : GlobPatterns = GlobPatterns ()):
22+ use_qmods : bool = False
23+
24+ def __init__ (
25+ self , patterns : GlobPatterns = GlobPatterns (), use_qmods : bool = False
26+ ):
2127 super ().__init__ (
2228 GlobPatterns (
2329 unfold = ["BepInExPack_Subnautica" ],
24- valid = ["winhttp.dll" , "doorstop_config.ini" , "BepInEx" , "QMods" ],
30+ valid = [
31+ "BepInEx" ,
32+ "doorstop_libs" ,
33+ "doorstop_config.ini" ,
34+ "run_bepinex.sh" ,
35+ "winhttp.dll" ,
36+ "QMods" ,
37+ ],
2538 delete = [
2639 "*.txt" ,
2740 "*.md" ,
2841 "icon.png" ,
2942 "license" ,
3043 "manifest.json" ,
3144 ],
32- move = {"plugins" : "BepInEx/" , "patchers" : "BepInEx/" , "*" : "QMods/" },
45+ move = {
46+ "plugins" : "BepInEx/" ,
47+ "patchers" : "BepInEx/" ,
48+ "CustomCraft2SML" : "QMods/" if use_qmods else "BepInEx/plugins/" ,
49+ "CustomCraft3" : "QMods/" if use_qmods else "BepInEx/plugins/" ,
50+ },
3351 ).merge (patterns ),
3452 )
53+ self .use_qmods = use_qmods
54+
55+ def dataLooksValid (
56+ self , filetree : mobase .IFileTree
57+ ) -> mobase .ModDataChecker .CheckReturn :
58+ check_return = super ().dataLooksValid (filetree )
59+ # A single unknown folder with a dll file in is to be moved to BepInEx/plugins/
60+ if (
61+ check_return is self .INVALID
62+ and len (filetree ) == 1
63+ and is_directory (folder := filetree [0 ])
64+ and any (fnmatch .fnmatch (entry .name (), "*.dll" ) for entry in folder )
65+ ):
66+ return self .FIXABLE
67+ return check_return
68+
69+ def fix (self , filetree : mobase .IFileTree ) -> mobase .IFileTree :
70+ filetree = super ().fix (filetree )
71+ if (
72+ self .dataLooksValid (filetree ) is self .FIXABLE
73+ and len (filetree ) == 1
74+ and is_directory (folder := filetree [0 ])
75+ and any (fnmatch .fnmatch (entry .name (), "*.dll" ) for entry in folder )
76+ ):
77+ filetree .move (folder , "QMods/" if self .use_qmods else "BepInEx/plugins/" )
78+ return filetree
3579
3680
3781class SubnauticaGame (BasicGame , mobase .IPluginFileMapper ):
3882 Name = "Subnautica Support Plugin"
3983 Author = "dekart811, Zash"
40- Version = "2.1.1 "
84+ Version = "2.2 "
4185
4286 GameName = "Subnautica"
4387 GameShortName = "subnautica"
@@ -81,12 +125,48 @@ def __init__(self):
81125
82126 def init (self , organizer : mobase .IOrganizer ) -> bool :
83127 super ().init (organizer )
84- self ._featureMap [ mobase . ModDataChecker ] = SubnauticaModDataChecker ()
128+ self ._set_mod_data_checker ()
85129 self ._featureMap [mobase .SaveGameInfo ] = BasicGameSaveGameInfo (
86130 lambda s : Path (s or "" , "screenshot.jpg" )
87131 )
132+
133+ organizer .onPluginSettingChanged (self ._settings_change_callback )
88134 return True
89135
136+ def _set_mod_data_checker (
137+ self , extra_patterns : GlobPatterns | None = None , use_qmod : bool | None = None
138+ ):
139+ self ._featureMap [mobase .ModDataChecker ] = SubnauticaModDataChecker (
140+ patterns = (GlobPatterns () if extra_patterns is None else extra_patterns ),
141+ use_qmods = (
142+ bool (self ._organizer .pluginSetting (self .name (), "use_qmods" ))
143+ if use_qmod is None
144+ else use_qmod
145+ ),
146+ )
147+
148+ def _settings_change_callback (
149+ self ,
150+ plugin_name : str ,
151+ setting : str ,
152+ old : mobase .MoVariant ,
153+ new : mobase .MoVariant ,
154+ ):
155+ if plugin_name == self .name () and setting == "use_qmods" :
156+ self ._set_mod_data_checker (use_qmod = bool (new ))
157+
158+ def settings (self ) -> list [mobase .PluginSetting ]:
159+ return [
160+ mobase .PluginSetting (
161+ "use_qmods" ,
162+ (
163+ "Install */.dll mods in legacy QMods folder,"
164+ " instead of BepInEx/plugins (default)."
165+ ),
166+ default_value = False ,
167+ )
168+ ]
169+
90170 def listSaves (self , folder : QDir ) -> list [mobase .ISaveGame ]:
91171 return [
92172 BasicGameSaveGame (folder )
@@ -97,6 +177,19 @@ def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]:
97177 for folder in Path (save_path ).glob ("slot*" )
98178 ]
99179
180+ def executables (self ) -> list [mobase .ExecutableInfo ]:
181+ binary = self .gameDirectory ().absoluteFilePath (self .binaryName ())
182+ return [
183+ mobase .ExecutableInfo (
184+ self .gameName (),
185+ binary ,
186+ ).withArgument ("-vrmode none" ),
187+ mobase .ExecutableInfo (
188+ f"{ self .gameName ()} VR" ,
189+ self .gameDirectory ().absoluteFilePath (self .binaryName ()),
190+ ),
191+ ]
192+
100193 def executableForcedLoads (self ) -> list [mobase .ExecutableForcedLoadSetting ]:
101194 return [
102195 mobase .ExecutableForcedLoadSetting (self .binaryName (), lib ).withEnabled (True )
0 commit comments