diff --git a/plugins/basic_games/games/game_sptaki.py b/plugins/basic_games/games/game_sptaki.py new file mode 100644 index 0000000..33ebfa5 --- /dev/null +++ b/plugins/basic_games/games/game_sptaki.py @@ -0,0 +1,131 @@ +# SPT plugin for ModOrganizer, coded by a moron: Me :) +# Note: This is highly incomplete, and will almost deffinitely break. +# Some inconveniences exist, such as the fact that every time you install a mod that does not auto handle, you have to create the user/mods or bepinex/plugins directory manually etc. +# I would like to expand those features, but it will probably happen slowly; I'm not a programmer. +# This script was made by cross referencing several other basic_game extensions. +# I sincerely hope somebody with actual experience comes along and decides to fix it up. But for now, this auto resolves the vast majority of mods on the hub :). +# Discord: Archon001 + +from typing import List, Tuple +from PyQt5.QtCore import QFileInfo +import mobase +from ..basic_game import BasicGame + + +class SPTAKIGame(BasicGame, mobase.IPluginFileMapper): + + Name = "SPT AKI Plugin" + Author = "Archon" + Version = "1.0.1a" + GameName = "SPT AKI" + GameShortName = "sptaki" + GameBinary = "aki.launcher.exe" + GameDataPath = "%GAME_PATH%" + GameSaveExtension = "json" + GameSavesDirectory = "%GAME_PATH%/user/profiles" + + def init(self, organizer: mobase.IOrganizer) -> bool: + super().init(organizer) + self._featureMap[mobase.ModDataChecker] = SPTAKIModDataChecker() + return True + + def executables(self) -> List[mobase.ExecutableInfo]: + execs = super().executables() + print(execs) + + """ + A bat script file to bridge the environment to server and launcher. + """ + workaroundPath = self._gamePath + "/sptvfsbridge.bat" + + try: + workaround = open(workaroundPath, "rt") + except FileNotFoundError: + with open(workaroundPath, "wt") as workaround: + workaround.write( + """ +@echo off +setlocal + +set "launcher_path=aki.launcher.exe" +set "server_path=aki.server.exe" + +REM Launch the server.exe +start "" "%server_path%" + +REM Wait for a moment to ensure the server.exe has started +timeout /t 5 /nobreak >nul + +REM Launch the launcher.exe +start "" "%launcher_path%" + +endlocal +""" + ) + workaround.close() + + execs.append( + mobase.ExecutableInfo("Launch SP Tarkov", QFileInfo(workaroundPath)) + ) + execs.pop(0) + print(execs) + return execs + + +class SPTAKIModDataChecker(mobase.ModDataChecker): + def __init__(self): + super().__init__() + + def get_plugins_and_mods( + self, tree: mobase.IFileTree + ) -> Tuple[List[mobase.FileTreeEntry], List[mobase.FileTreeEntry]]: + + plugins: List[mobase.FileTreeEntry] = [] + mods: List[mobase.FileTreeEntry] = [] + + for e in tree: + if e.isDir() and e.exists("package.json", mobase.IFileTree.FILE): + mods.append(e) + elif e.isFile() and e.suffix().lower() == "dll": + plugins.append(e) + elif e.isDir(): + has_dll = False + for file_entry in e: + if file_entry.isFile() and file_entry.suffix().lower() == "dll": + has_dll = True + break + if has_dll and not e.exists("package.json", mobase.IFileTree.FILE): + plugins.append(e) + + return plugins, mods + + def dataLooksValid( + self, tree: mobase.IFileTree + ) -> mobase.ModDataChecker.CheckReturn: + # Check if we have bepinex/plugins, user/mods folders or .json/.dll + plugins, mods = self.get_plugins_and_mods(tree) + + if not plugins and not mods: + if tree.exists("bepinex/plugins") or tree.exists("user/mods"): + return mobase.ModDataChecker.VALID + else: + return mobase.ModDataChecker.INVALID + + return mobase.ModDataChecker.FIXABLE + + def fix(self, tree: mobase.IFileTree) -> mobase.IFileTree: + plugins, mods = self.get_plugins_and_mods(tree) + toMove = [] + if mods: + for entry in tree: + toMove.append((entry, "/user/mods/")) + for (entry, path) in toMove: + tree.move(entry, path, policy=mobase.IFileTree.MERGE) + + if plugins: + for entry in tree: + toMove.append((entry, "/bepinex/plugins/")) + for (entry, path) in toMove: + tree.move(entry, path, policy=mobase.IFileTree.MERGE) + + return tree