package net.vhati.modmanager.core;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
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.
*/
public static boolean isDatsDirValid( File d ) {
if ( !d.exists() || !d.isDirectory() ) return false;
if ( !new File(d, "data.dat").exists() ) return false;
if ( !new File(d, "resource.dat").exists() ) return false;
return true;
}
/**
* Returns the FTL resources dir, or null.
*/
public static File findDatsDir() {
String steamPath = "Steam/steamapps/common/FTL Faster Than Light/resources";
String gogPath = "GOG.com/Faster Than Light/resources";
String humblePath = "FTL/resources";
String xdgDataHome = System.getenv("XDG_DATA_HOME");
if ( xdgDataHome == null )
xdgDataHome = System.getProperty("user.home") +"/.local/share";
File[] candidates = new File[] {
// Windows - Steam
new File( new File(""+System.getenv("ProgramFiles(x86)")), steamPath ),
new File( new File(""+System.getenv("ProgramFiles")), steamPath ),
// Windows - GOG
new File( new File(""+System.getenv("ProgramFiles(x86)")), gogPath ),
new File( new File(""+System.getenv("ProgramFiles")), gogPath ),
// Windows - Humble Bundle
new File( new File(""+System.getenv("ProgramFiles(x86)")), humblePath ),
new File( new File(""+System.getenv("ProgramFiles")), humblePath ),
// Linux - Steam
new File( xdgDataHome +"/Steam/SteamApps/common/FTL Faster Than Light/data/resources" ),
new File( xdgDataHome +"/.steam/steam/SteamApps/common/FTL Faster Than Light/data/resources" ),
new File( System.getProperty("user.home") +"/.steam/steam/steamapps/common/FTL Faster Than Light/data/resources" ),
// OSX - Steam
new File( System.getProperty("user.home") +"/Library/Application Support/Steam/SteamApps/common/FTL Faster Than Light/FTL.app/Contents/Resources" ),
// OSX
new File( "/Applications/FTL.app/Contents/Resources" )
};
File result = null;
for ( File candidate : candidates ) {
if ( isDatsDirValid( candidate ) ) {
result = candidate;
break;
}
}
return result;
}
/**
* Modally prompts the user for the FTL resources dir.
*
* Reminder: GUI dialogs need to be in the event dispatch thread.
*
* @param parentComponent a parent for Swing dialogs, or null
*/
public static File promptForDatsDir( Component parentComponent ) {
File result = null;
String message = "";
message += "You will now be prompted to locate FTL manually.\n";
message += "Select '(FTL dir)/resources/data.dat'.\n";
message += "Or 'FTL.app', if you're on OSX.";
JOptionPane.showMessageDialog( parentComponent, message, "Find FTL", JOptionPane.INFORMATION_MESSAGE );
final JFileChooser fc = new JFileChooser();
fc.setDialogTitle( "Find data.dat or FTL.app" );
fc.setFileHidingEnabled( false );
fc.addChoosableFileFilter(new FileFilter() {
@Override
public String getDescription() {
return "FTL Data File - (FTL dir)/resources/data.dat";
}
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().equals("data.dat") || f.getName().equals("FTL.app");
}
});
fc.setMultiSelectionEnabled(false);
if ( fc.showOpenDialog( parentComponent ) == JFileChooser.APPROVE_OPTION ) {
File f = fc.getSelectedFile();
if ( f.getName().equals("data.dat") ) {
result = f.getParentFile();
}
else if ( f.getName().endsWith(".app") && f.isDirectory() ) {
File contentsPath = new File(f, "Contents");
if( contentsPath.exists() && contentsPath.isDirectory() && new File(contentsPath, "Resources").exists() )
result = new File(contentsPath, "Resources");
}
}
if ( result != null && isDatsDirValid( result ) ) {
return result;
}
return null;
}
/**
* Returns the executable that will launch FTL, or null.
*
* On Windows, FTLGame.exe is one dir above "resources/".
* On Linux, FTL is a script, one dir above "resources/".
* On OSX, FTL.app is the grandparent dir itself (a bundle).
*/
public static File findGameExe( File datsDir ) {
File result = null;
if ( System.getProperty("os.name").startsWith("Windows") ) {
File ftlDir = datsDir.getParentFile();
if ( ftlDir != null ) {
File exeFile = new File( ftlDir, "FTLGame.exe" );
if ( exeFile.exists() ) result = exeFile;
}
}
else if ( System.getProperty("os.name").equals("Linux") ) {
File ftlDir = datsDir.getParentFile();
if ( ftlDir != null ) {
File exeFile = new File( ftlDir, "FTL" );
if ( exeFile.exists() ) result = exeFile;
}
}
else if ( System.getProperty("os.name").contains("OS X") ) {
// FTL.app/Contents/Resources/
File contentsDir = datsDir.getParentFile();
if ( contentsDir != null ) {
File bundleDir = contentsDir.getParentFile();
if ( bundleDir != null ) {
if ( new File( bundleDir, "Contents/Info.plist" ).exists() ) {
result = bundleDir;
}
}
}
}
return result;
}
/**
* Returns the executable that will launch Steam, or null.
*
* 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 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") ) {
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() );
result = pb.start();
}
return result;
}
/**
* Returns the directory for user profiles and saved games, or null.
*/
public static File findUserDataDir() {
String xdgDataHome = System.getenv("XDG_DATA_HOME");
if ( xdgDataHome == null )
xdgDataHome = System.getProperty("user.home") +"/.local/share";
File[] candidates = new File[] {
// Windows XP
new File( System.getProperty("user.home") +"/My Documents/My Games/FasterThanLight" ),
// Windows Vista/7
new File( System.getProperty("user.home") +"/Documents/My Games/FasterThanLight" ),
// Linux
new File( xdgDataHome +"/FasterThanLight" ),
// OSX
new File( System.getProperty("user.home") +"/Library/Application Support/FasterThanLight" )
};
File result = null;
for ( File candidate : candidates ) {
if ( candidate.isDirectory() && candidate.exists() ) {
result = candidate;
break;
}
}
return result;
}
}