diff --git a/lib/game.dart b/lib/game.dart index b0aa2f5..6cc6e96 100644 --- a/lib/game.dart +++ b/lib/game.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:crypto/crypto.dart'; +import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; import 'package:servermanager/autorestart.dart'; import 'package:servermanager/mod.dart'; @@ -12,6 +13,8 @@ import 'package:servermanager/statemachine.dart'; Future doDownloadMods(String modsFolder) async { Settings settings = Settings(); + if (!settings.inst!.downloadMods) return; + // Now, invoke SteamCmd to download the workshop mods. This is an authenticated action, and does require Scmd2fa String code = ""; if (settings.inst!.steam_creds!.has_2fa) { @@ -49,6 +52,44 @@ Future doDownloadMods(String modsFolder) async { print(result.stdout); } +Future doMigrateMods() async { + // Migrate the mods from the configured SteamLibrary path to the mods folder + Settings settings = Settings(); + await settings.createModFolderIfNotExists(); + + if (settings.inst!.downloadMods) return; + + // Copy the mods to their destination + for (Mod M in settings.inst!.mods) { + var ph = PathHelper.builder(settings.game_path) + .resolve("mods") + .resolve("steamapps") + .resolve("workshop") + .resolve("content") + .resolve("440900") + .resolve("${M.mod_id}") + .removeDir() + .mkdir(); + + var ph2 = PathHelper.builder(settings.inst!.conanExilesLibraryPath) + .resolve("steamapps") + .resolve("workshop") + .resolve("content") + .resolve("440900") + .resolve("${M.mod_id}"); + + Directory dir = new Directory(ph2.build()); + await for (var f in dir.list()) { + if (f is File && f.path.endsWith("pak")) { + String modDest = + ph.resolve(f.path.split(Platform.pathSeparator).last).build(); + + await f.copy(modDest); + } + } + } +} + Future> doScanMods(String modsFolder) async { Settings settings = Settings(); @@ -181,33 +222,55 @@ class GameServerPageState extends State { Navigator.pushNamed(context, "/server/mods"); }, ), - ListTile( - title: Text("Download Mods"), - subtitle: Text("Downloads the mods"), - leading: Icon(Icons.download_sharp), - onTap: () async { - setState(() { - downloading = true; - }); - await doDownloadMods(settings.getModPath()); + if (settings.inst!.downloadMods) + ListTile( + title: Text("Download Mods"), + subtitle: Text("Downloads the mods"), + leading: Icon(Icons.download_sharp), + onTap: () async { + setState(() { + downloading = true; + }); + await doDownloadMods(settings.getModPath()); - setState(() { - downloading = false; - }); + setState(() { + downloading = false; + }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Scanning mods..."))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Scanning mods..."))); - var mods = await doScanMods(settings.getModPath()); - setState(() { - settings.inst!.mods = mods; + var mods = await doScanMods(settings.getModPath()); + setState(() { + settings.inst!.mods = mods; - settings.Write(); - }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Mod scanning complete"))); - }, - ), + settings.Write(); + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Mod scanning complete"))); + }, + ), + if (!settings.inst!.downloadMods) + ListTile( + title: Text("Conan Exiles Install Path"), + subtitle: + Text("Set the Steam Library location of Conan Exiles"), + leading: Icon(Icons.folder), + onTap: () async { + // Open the folder select prompt + var path = await getDirectoryPath(); + setState(() { + settings.inst!.conanExilesLibraryPath = + path ?? settings.inst!.conanExilesLibraryPath; + + if (path == null) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + "You must select a valid SteamLibrary folder"))); + } + }); + }, + ), ListTile( title: Text("Configure AutoRestart"), leading: Icon(Icons.timer), @@ -227,6 +290,17 @@ class GameServerPageState extends State { }); }, ), + SwitchListTile( + value: settings.inst!.downloadMods, + onChanged: (value) { + setState(() { + settings.inst!.downloadMods = value; + }); + }, + title: Text("Automatic Download of Mods"), + subtitle: Text( + "If enabled, downloads mods using steamcmd, if disabled, you must configure the SteamLibrary folder location"), + ), ListTile( title: Text("Configure Server Ports"), leading: Icon(Icons.numbers), diff --git a/lib/pathtools.dart b/lib/pathtools.dart index 802e238..53d9fc6 100644 --- a/lib/pathtools.dart +++ b/lib/pathtools.dart @@ -17,6 +17,50 @@ class PathHelper { return this; } + PathHelper conditionalResolve(bool flag, String path) { + if (flag) pth += Platform.pathSeparator + path; + return this; + } + + bool deleteDirectory({bool recursive = false}) { + Directory dir = new Directory(build()); + try { + dir.deleteSync(recursive: recursive); + + return true; + } catch (E) { + return false; + } + } + + bool deleteFile() { + File file = new File(build()); + try { + file.deleteSync(recursive: true); + + return true; + } catch (E) { + return false; + } + } + + PathHelper removeDir() { + deleteDirectory(recursive: true); + return this; + } + + PathHelper removeFile() { + deleteFile(); + return this; + } + + PathHelper mkdir() { + Directory dir = new Directory(build()); + dir.createSync(recursive: true); + + return this; + } + String build() { return pth; } diff --git a/lib/settingsEntry.dart b/lib/settingsEntry.dart index 0d7fb65..2d110f9 100644 --- a/lib/settingsEntry.dart +++ b/lib/settingsEntry.dart @@ -28,4 +28,10 @@ class SettingsEntry { RconPort: 7779, GamePort: 7780, QueryPort: 7782); + + @HiveField(6, defaultValue: true) + bool downloadMods = true; + + @HiveField(7, defaultValue: "") + String conanExilesLibraryPath = ""; } diff --git a/lib/statemachine.dart b/lib/statemachine.dart index c0dcb7a..ed2e4dd 100644 --- a/lib/statemachine.dart +++ b/lib/statemachine.dart @@ -46,7 +46,10 @@ class StateMachine { // Server startup in progress Settings settings = Settings(); await settings.RunUpdate(valid: false); - await doDownloadMods(settings.getModPath()); + if (settings.inst!.downloadMods) + await doDownloadMods(settings.getModPath()); + else + await doMigrateMods(); settings.inst!.mods = await doScanMods(settings.getModPath()); await settings.writeOutModListFile();