From be8a84cd2e36fc019ccb2b4a81559ac88499ed35 Mon Sep 17 00:00:00 2001 From: Vhati Date: Mon, 23 Mar 2015 03:58:16 -0400 Subject: [PATCH] Added a config option to launch FTL via Steam, if possible (kartoFlane) --- skel_common/backup/auto_update.json | 7 ++ skel_common/readme_changelog.txt | 3 + .../net/vhati/modmanager/FTLModManager.java | 9 ++- .../vhati/modmanager/cli/SlipstreamCLI.java | 25 ++++++- .../vhati/modmanager/core/FTLUtilities.java | 73 +++++++++++++++++-- .../modmanager/core/SlipstreamConfig.java | 1 + .../net/vhati/modmanager/ui/ManagerFrame.java | 31 +++++++- .../modmanager/ui/SlipstreamConfigDialog.java | 6 ++ 8 files changed, 138 insertions(+), 17 deletions(-) diff --git a/skel_common/backup/auto_update.json b/skel_common/backup/auto_update.json index 06a355b..f849baa 100644 --- a/skel_common/backup/auto_update.json +++ b/skel_common/backup/auto_update.json @@ -11,6 +11,13 @@ "notice" : "Important: Return FTL to an unmodded state before switching to a new version." }, "changelog" : [ + { + "version" : "1.7", + "hidden" : "true", + "changes" : [ + "Added a config option to launch FTL via Steam, if possible" + ] + }, { "version" : "1.6", "hidden" : "false", diff --git a/skel_common/readme_changelog.txt b/skel_common/readme_changelog.txt index b57bb72..9db5df0 100644 --- a/skel_common/readme_changelog.txt +++ b/skel_common/readme_changelog.txt @@ -1,5 +1,8 @@ Changelog +1.7: +- Added a config option to launch FTL via Steam, if possible + 1.6: - Fixed modorder not being saved properly diff --git a/src/main/java/net/vhati/modmanager/FTLModManager.java b/src/main/java/net/vhati/modmanager/FTLModManager.java index f18de39..2b37f74 100644 --- a/src/main/java/net/vhati/modmanager/FTLModManager.java +++ b/src/main/java/net/vhati/modmanager/FTLModManager.java @@ -66,6 +66,7 @@ public class FTLModManager { Properties config = new Properties(); config.setProperty( "allow_zip", "false" ); config.setProperty( "ftl_dats_path", "" ); + config.setProperty( "run_steam_ftl", "false" ); config.setProperty( "never_run_ftl", "false" ); config.setProperty( "use_default_ui", "false" ); config.setProperty( "remember_geometry", "true" ); @@ -84,7 +85,7 @@ public class FTLModManager { writeConfig = true; // Create a new cfg, but only if necessary. } } - catch (IOException e) { + catch ( IOException e ) { log.error( "Error loading config.", e ); showErrorDialog( "Error loading config from "+ configFile.getPath() ); } @@ -101,7 +102,7 @@ public class FTLModManager { log.trace( "Using system Look and Feel" ); UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() ); } - catch (Exception e) { + catch ( Exception e ) { log.error( "Error setting system Look and Feel.", e ); log.info( "Setting 'useDefaultUI=true' in the config file will prevent this error." ); } @@ -195,14 +196,14 @@ public class FTLModManager { ManagerFrame frame = new ManagerFrame( appConfig, APP_NAME, APP_VERSION, APP_URL, APP_AUTHOR ); frame.init(); frame.setVisible(true); - } catch ( Exception e ) { + } + catch ( Exception e ) { log.error( "Exception while creating ManagerFrame.", e ); System.exit(1); } } - private static void showErrorDialog( String message ) { JOptionPane.showMessageDialog( null, message, "Error", JOptionPane.ERROR_MESSAGE ); } diff --git a/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java b/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java index 0f7bdd2..31e5bb9 100644 --- a/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java +++ b/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java @@ -291,17 +291,36 @@ public class SlipstreamCLI { if ( cmdline.hasOption( "runftl" ) ) { // Exits (0/1). log.info( "Running FTL..." ); - File exeFile = FTLUtilities.findGameExe( datsDir ); + File exeFile = null; + String[] exeArgs = null; + + if ( config.getProperty( "run_steam_ftl", "false" ).equals( "true" ) ) { + exeFile = FTLUtilities.findSteamExe(); + exeArgs = new String[] {"-applaunch", FTLUtilities.STEAM_APPID_FTL}; + + if ( exeFile == null ) { + log.warn( "Steam executable could not be found. FTL will be launched directly." ); + } + } + if ( exeFile == null ) { + exeFile = FTLUtilities.findGameExe( datsDir ); + exeArgs = new String[0]; + + if ( exeFile == null ) { + log.warn( "FTL executable could not be found." ); + } + } + if ( exeFile != null ) { try { - FTLUtilities.launchGame( exeFile ); + FTLUtilities.launchExe( exeFile, exeArgs ); } catch ( Exception e ) { log.error( "Error launching FTL.", e ); System.exit( 1 ); } } else { - log.error( "Could not find FTL's executable." ); + log.error( "No executables were found to launch FTL." ); System.exit( 1 ); } diff --git a/src/main/java/net/vhati/modmanager/core/FTLUtilities.java b/src/main/java/net/vhati/modmanager/core/FTLUtilities.java index 8f3bf05..0b625fc 100644 --- a/src/main/java/net/vhati/modmanager/core/FTLUtilities.java +++ b/src/main/java/net/vhati/modmanager/core/FTLUtilities.java @@ -10,6 +10,10 @@ import javax.swing.filechooser.FileFilter; public class FTLUtilities { + /** Steam's application ID for FTL. */ + public static final String STEAM_APPID_FTL = "212680"; + + /** * Confirms the FTL resources dir exists and contains the dat files. */ @@ -154,20 +158,77 @@ public class FTLUtilities { /** - * Spawns the game (FTLGame.exe or FTL.app). + * Returns the executable that will launch Steam, or null. * - * @param exeFile see findGameExe() + * On Windows, Steam.exe. + * On Linux, steam is a script. ( http://moritzmolch.com/815 ) + * On OSX, Steam.app is the grandparent dir itself (a bundle). + * + * The args to launch FTL are: ["-applaunch", STEAM_APPID_FTL] + */ + public static File findSteamExe() { + File result = null; + + if ( System.getProperty("os.name").startsWith("Windows") ) { + File[] candidates = new File[] { + new File( new File(""+System.getenv("ProgramFiles(x86)")), "Steam/Steam.exe" ), + new File( new File(""+System.getenv("ProgramFiles")), "Steam/Steam.exe" ) + }; + + for ( File candidate : candidates ) { + if ( candidate.exists() ) { + result = candidate; + break; + } + } + } + else if ( System.getProperty("os.name").equals("Linux") ) { + File candidate = new File( "/usr/bin/steam" ); + + if ( candidate.exists() ) result = candidate; + } + else if ( System.getProperty("os.name").contains("OS X") ) { + File candidate = new File( "/Applications/Steam.app" ); + + if ( candidate.exists() ) result = candidate; + } + + return result; + } + + + /** + * Launches an executable. + * + * On Windows, *.exe. + * On Linux, a binary or script. + * On OSX, an *.app bundle dir. + * + * @param exeFile see findGameExe() or findSteamExe() + * @param exeArgs arguments for the executable * @return a Process object, or null */ - public static Process launchGame( File exeFile ) throws IOException { + public static Process launchExe( File exeFile, String... exeArgs ) throws IOException { if ( exeFile == null ) return null; + if ( exeArgs == null ) exeArgs = new String[0]; Process result = null; ProcessBuilder pb = null; if ( System.getProperty("os.name").contains("OS X") ) { - pb = new ProcessBuilder( "open", "-a", exeFile.getAbsolutePath() ); - } else { - pb = new ProcessBuilder( exeFile.getAbsolutePath() ); + String[] args = new String[3 + exeArgs.length]; + args[0] = "open"; + args[1] = "-a"; + args[2] = exeFile.getAbsolutePath(); + System.arraycopy( exeArgs, 0, args, 3, exeArgs.length ); + + pb = new ProcessBuilder( args ); + } + else { + String[] args = new String[1 + exeArgs.length]; + + System.arraycopy( exeArgs, 0, args, 1, exeArgs.length ); + + pb = new ProcessBuilder( args ); } if ( pb != null ) { pb.directory( exeFile.getParentFile() ); diff --git a/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java b/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java index 4936afc..976dfdf 100644 --- a/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java +++ b/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java @@ -64,6 +64,7 @@ public class SlipstreamConfig { configComments += "\n"; configComments += " allow_zip - Sets whether to treat .zip files as .ftl files. Default: false.\n"; configComments += " ftl_dats_path - The path to FTL's resources folder. If invalid, you'll be prompted.\n"; + configComments += " run_steam_ftl - If true, SMM will use Steam to launch FTL, if possible. Default: false.\n"; configComments += " never_run_ftl - If true, there will be no offer to run FTL after patching. Default: false.\n"; configComments += " update_catalog - If a number greater than 0, check for new mod descriptions every N days.\n"; configComments += " update_app - If a number greater than 0, check for newer app versions every N days.\n"; diff --git a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java index 7a6a04a..a2a9574 100644 --- a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java +++ b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java @@ -677,9 +677,28 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse String neverRunFtl = appConfig.getProperty( "never_run_ftl", "false" ); if ( !neverRunFtl.equals("true") ) { - File exeFile = FTLUtilities.findGameExe( datsDir ); + File exeFile = null; + String[] exeArgs = null; + + if ( appConfig.getProperty( "run_steam_ftl", "false" ).equals( "true" ) ) { + exeFile = FTLUtilities.findSteamExe(); + exeArgs = new String[] {"-applaunch", FTLUtilities.STEAM_APPID_FTL}; + + if ( exeFile == null ) { + log.warn( "Steam executable could not be found. FTL will be launched directly." ); + } + } + if ( exeFile == null ) { + exeFile = FTLUtilities.findGameExe( datsDir ); + exeArgs = new String[0]; + + if ( exeFile == null ) { + log.warn( "FTL executable could not be found." ); + } + } + if ( exeFile != null ) { - patchDlg.setSuccessTask( new SpawnGameTask( exeFile ) ); + patchDlg.setSuccessTask( new SpawnGameTask( exeFile, exeArgs ) ); } } @@ -951,9 +970,13 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse private class SpawnGameTask implements Runnable { private final File exeFile; + private final String[] exeArgs; - public SpawnGameTask( File exeFile ) { + public SpawnGameTask( File exeFile, String... exeArgs ) { + if ( exeArgs == null ) exeArgs = new String[0]; this.exeFile = exeFile; + this.exeArgs = new String[exeArgs.length]; + System.arraycopy( exeArgs, 0, this.exeArgs, 0, exeArgs.length ); } @Override @@ -963,7 +986,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse if ( response == JOptionPane.YES_OPTION ) { log.info( "Running FTL..." ); try { - FTLUtilities.launchGame( exeFile ); + FTLUtilities.launchExe( exeFile, exeArgs ); } catch ( Exception e ) { log.error( "Error launching FTL.", e ); } diff --git a/src/main/java/net/vhati/modmanager/ui/SlipstreamConfigDialog.java b/src/main/java/net/vhati/modmanager/ui/SlipstreamConfigDialog.java index 99d43ed..487516e 100644 --- a/src/main/java/net/vhati/modmanager/ui/SlipstreamConfigDialog.java +++ b/src/main/java/net/vhati/modmanager/ui/SlipstreamConfigDialog.java @@ -28,6 +28,7 @@ import net.vhati.modmanager.ui.FieldEditorPanel.ContentType; public class SlipstreamConfigDialog extends JFrame implements ActionListener { protected static final String ALLOW_ZIP = "allow_zip"; + protected static final String RUN_STEAM_FTL = "run_steam_ftl"; protected static final String NEVER_RUN_FTL = "never_run_ftl"; protected static final String USE_DEFAULT_UI = "use_default_ui"; protected static final String REMEMBER_GEOMETRY = "remember_geometry"; @@ -53,6 +54,9 @@ public class SlipstreamConfigDialog extends JFrame implements ActionListener { editorPanel.addRow( ALLOW_ZIP, ContentType.BOOLEAN ); editorPanel.addTextRow( "Treat .zip files as .ftl files." ); editorPanel.addSeparatorRow(); + editorPanel.addRow( RUN_STEAM_FTL, ContentType.BOOLEAN ); + editorPanel.addTextRow( "Use Steam to run FTL, if possible." ); + editorPanel.addSeparatorRow(); editorPanel.addRow( NEVER_RUN_FTL, ContentType.BOOLEAN ); editorPanel.addTextRow( "Don't offer to run FTL after patching." ); editorPanel.addSeparatorRow(); @@ -77,6 +81,7 @@ public class SlipstreamConfigDialog extends JFrame implements ActionListener { editorPanel.addFillRow(); editorPanel.getBoolean( ALLOW_ZIP ).setSelected( appConfig.getProperty( ALLOW_ZIP, "false" ).equals( "true" ) ); + editorPanel.getBoolean( RUN_STEAM_FTL ).setSelected( appConfig.getProperty( RUN_STEAM_FTL, "false" ).equals( "true" ) ); editorPanel.getBoolean( NEVER_RUN_FTL ).setSelected( appConfig.getProperty( NEVER_RUN_FTL, "false" ).equals( "true" ) ); editorPanel.getBoolean( USE_DEFAULT_UI ).setSelected( appConfig.getProperty( USE_DEFAULT_UI, "false" ).equals( "true" ) ); editorPanel.getBoolean( REMEMBER_GEOMETRY ).setSelected( appConfig.getProperty( REMEMBER_GEOMETRY, "true" ).equals( "true" ) ); @@ -133,6 +138,7 @@ public class SlipstreamConfigDialog extends JFrame implements ActionListener { if ( source == applyBtn ) { String tmp; appConfig.setProperty( ALLOW_ZIP, editorPanel.getBoolean( ALLOW_ZIP ).isSelected() ? "true" : "false" ); + appConfig.setProperty( RUN_STEAM_FTL, editorPanel.getBoolean( RUN_STEAM_FTL ).isSelected() ? "true" : "false" ); appConfig.setProperty( NEVER_RUN_FTL, editorPanel.getBoolean( NEVER_RUN_FTL ).isSelected() ? "true" : "false" ); appConfig.setProperty( USE_DEFAULT_UI, editorPanel.getBoolean( USE_DEFAULT_UI ).isSelected() ? "true" : "false" ); appConfig.setProperty( REMEMBER_GEOMETRY, editorPanel.getBoolean( REMEMBER_GEOMETRY ).isSelected() ? "true" : "false" );