diff --git a/.envrc b/.envrc
deleted file mode 100644
index 8392d15..0000000
--- a/.envrc
+++ /dev/null
@@ -1 +0,0 @@
-use flake
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9ab7d63..2b925ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,19 +5,18 @@ target/
*.bak
~$*
+
# Windows image file caches
Thumbs.db
# Windows folder config file
Desktop.ini
+
# Mac junk
.DS_Store
+
# IdeaJ
*.idea
*.iml
-
-# enviroemnt packages
-.direnv
-
diff --git a/flake.lock b/flake.lock
deleted file mode 100644
index 353863f..0000000
--- a/flake.lock
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "nodes": {
- "nixpkgs": {
- "locked": {
- "lastModified": 1754725699,
- "narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=",
- "rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054",
- "revCount": 841808,
- "type": "tarball",
- "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.841808%2Brev-85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054/01989280-4b63-70f9-95b3-49c511cb4d92/source.tar.gz"
- },
- "original": {
- "type": "tarball",
- "url": "https://flakehub.com/f/NixOS/nixpkgs/0.1"
- }
- },
- "root": {
- "inputs": {
- "nixpkgs": "nixpkgs"
- }
- }
- },
- "root": "root",
- "version": 7
-}
diff --git a/flake.nix b/flake.nix
deleted file mode 100644
index 2951bbe..0000000
--- a/flake.nix
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- description = "A Nix-flake-based Java development environment";
-
- inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1";
-
- outputs =
- inputs:
- let
- javaVersion = 17;
-
- supportedSystems = [
- "x86_64-linux"
- "aarch64-linux"
- "x86_64-darwin"
- "aarch64-darwin"
- ];
- forEachSupportedSystem =
- f:
- inputs.nixpkgs.lib.genAttrs supportedSystems (
- system:
- f {
- pkgs = import inputs.nixpkgs {
- inherit system;
- overlays = [ inputs.self.overlays.default ];
- };
- }
- );
- in
- {
- overlays.default =
- final: prev:
- let
- jdk = prev."jdk${toString javaVersion}";
- in
- {
- inherit jdk;
- maven = prev.maven.override { jdk_headless = jdk; };
- gradle = prev.gradle.override { java = jdk; };
- lombok = prev.lombok.override { inherit jdk; };
- };
-
- devShells = forEachSupportedSystem (
- { pkgs }:
- {
- default = pkgs.mkShell {
- packages = with pkgs; [
- gcc
- gradle
- jdk
- maven
- ncurses
- patchelf
- zlib
- ];
-
- shellHook =
- let
- loadLombok = "-javaagent:${pkgs.lombok}/share/java/lombok.jar";
- prev = "\${JAVA_TOOL_OPTIONS:+ $JAVA_TOOL_OPTIONS}";
- in
- ''
- export JAVA_TOOL_OPTIONS="${loadLombok}${prev}"
- '';
- };
- }
- );
- };
-}
-
diff --git a/pom.xml b/pom.xml
index 53264db..b235564 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,8 +11,8 @@
1.6
- 21
- 21
+ 1.6
+ 1.6
UTF-8
diff --git a/shell.nix b/shell.nix
deleted file mode 100644
index d7c46b9..0000000
--- a/shell.nix
+++ /dev/null
@@ -1,14 +0,0 @@
-(
- import
- (
- let
- lock = builtins.fromJSON (builtins.readFile ./flake.lock);
- in
- fetchTarball {
- url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
- sha256 = lock.nodes.flake-compat.locked.narHash;
- }
- )
- {src = ./.;}
-)
-.shellNix
diff --git a/skel_unix/modman-cli.sh b/skel_unix/modman-cli.sh
index 9c7124c..00104c8 100644
--- a/skel_unix/modman-cli.sh
+++ b/skel_unix/modman-cli.sh
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/bin/bash
# Get the absolute path to this script's folder.
if echo "$0" | awk '{exit(!/^\//);}'; then
diff --git a/skel_unix/modman.command b/skel_unix/modman.command
index 3b63900..1381d8f 100644
--- a/skel_unix/modman.command
+++ b/skel_unix/modman.command
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/bin/bash
# Get the script's name.
me=$(basename "$0");
diff --git a/src/main/java/net/vhati/modmanager/FTLModManager.java b/src/main/java/net/vhati/modmanager/FTLModManager.java
index c431262..b4fa76b 100644
--- a/src/main/java/net/vhati/modmanager/FTLModManager.java
+++ b/src/main/java/net/vhati/modmanager/FTLModManager.java
@@ -1,14 +1,19 @@
package net.vhati.modmanager;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
+import java.nio.charset.Charset;
import java.util.Date;
+import java.util.Properties;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
@@ -31,8 +36,8 @@ public class FTLModManager {
public static final String APP_NAME = "Slipstream Mod Manager";
public static final ComparableVersion APP_VERSION = new ComparableVersion( "1.9.1" );
- public static final String APP_URL = "TODO";
- public static final String APP_AUTHOR = "jan-leila";
+ public static final String APP_URL = "https://subsetgames.com/forum/viewtopic.php?f=12&t=17102";
+ public static final String APP_AUTHOR = "Vhati";
public static void main( String[] args ) {
@@ -48,7 +53,7 @@ public class FTLModManager {
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext( lc );
- encoder.setCharset(StandardCharsets.UTF_8);
+ encoder.setCharset( Charset.forName( "UTF-8" ) );
encoder.setPattern( "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" );
encoder.start();
@@ -71,7 +76,7 @@ public class FTLModManager {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException( Thread t, Throwable e ) {
- log.error("Uncaught exception in thread: {}", t.toString(), e);
+ log.error( "Uncaught exception in thread: "+ t.toString(), e );
}
});
@@ -81,15 +86,20 @@ public class FTLModManager {
}
// Ensure all popups are triggered from the event dispatch thread.
- SwingUtilities.invokeLater(FTLModManager::guiInit);
+
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ guiInit();
+ }
+ });
}
private static void guiInit() {
try {
- // TODO: get mods file from env var
// Nag if the jar was double-clicked.
- if (!new File("./mods/").exists()) {
+ if ( new File( "./mods/" ).exists() == false ) {
String currentPath = new File( "." ).getAbsoluteFile().getParentFile().getAbsolutePath();
log.error( String.format( "Slipstream could not find its own folder (Currently in \"%s\"), exiting...", currentPath ) );
@@ -98,13 +108,46 @@ public class FTLModManager {
throw new ExitException();
}
- // TODO: get config file from env var
File configFile = new File( "modman.cfg" );
- SlipstreamConfig appConfig = new SlipstreamConfig(configFile);
+ boolean writeConfig = false;
+ Properties props = new Properties();
+ props.setProperty( SlipstreamConfig.ALLOW_ZIP, "false" );
+ props.setProperty( SlipstreamConfig.FTL_DATS_PATH, "" ); // Prompt.
+ props.setProperty( SlipstreamConfig.STEAM_DISTRO, "" ); // Prompt.
+ props.setProperty( SlipstreamConfig.STEAM_EXE_PATH, "" ); // Prompt.
+ props.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "" ); // Prompt.
+ props.setProperty( SlipstreamConfig.NEVER_RUN_FTL, "false" );
+ props.setProperty( SlipstreamConfig.UPDATE_CATALOG, "" ); // Prompt.
+ props.setProperty( SlipstreamConfig.UPDATE_APP, "" ); // Prompt.
+ props.setProperty( SlipstreamConfig.USE_DEFAULT_UI, "false" );
+ props.setProperty( SlipstreamConfig.REMEMBER_GEOMETRY, "true" );
+ // "manager_geometry" doesn't have a default.
+
+ // Read the config file.
+ InputStream in = null;
+ try {
+ if ( configFile.exists() ) {
+ log.debug( "Loading config file" );
+ in = new FileInputStream( configFile );
+ props.load( new InputStreamReader( in, "UTF-8" ) );
+ } else {
+ writeConfig = true; // Create a new cfg, but only if necessary.
+ }
+ }
+ catch ( IOException e ) {
+ log.error( "Error loading config", e );
+ showErrorDialog( "Error loading config from "+ configFile.getPath() );
+ }
+ finally {
+ try {if ( in != null ) in.close();}
+ catch ( IOException e ) {}
+ }
+
+ SlipstreamConfig appConfig = new SlipstreamConfig( props, configFile );
// Look-and-Feel.
- boolean useDefaultUI = Boolean.parseBoolean(appConfig.getProperty(SlipstreamConfig.USE_DEFAULT_UI, "false"));
+ boolean useDefaultUI = "true".equals( appConfig.getProperty( SlipstreamConfig.USE_DEFAULT_UI, "false" ) );
if ( !useDefaultUI ) {
LookAndFeel defaultLaf = UIManager.getLookAndFeel();
@@ -114,7 +157,7 @@ public class FTLModManager {
log.debug( "Setting system look and feel: "+ UIManager.getSystemLookAndFeelClassName() );
// SystemLaf is risky. It may throw an exception, or lead to graphical bugs.
- // Problems are generally caused by custom Windows themes.
+ // Problems are geneally caused by custom Windows themes.
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
}
catch ( Exception e ) {
@@ -122,6 +165,7 @@ public class FTLModManager {
log.info( "Setting "+ SlipstreamConfig.USE_DEFAULT_UI +"=true in the config file to prevent this error..." );
appConfig.setProperty( SlipstreamConfig.USE_DEFAULT_UI, "true" );
+ writeConfig = true;
try {
UIManager.setLookAndFeel( defaultLaf );
@@ -176,6 +220,7 @@ public class FTLModManager {
if ( datsDir != null ) {
appConfig.setProperty( SlipstreamConfig.FTL_DATS_PATH, datsDir.getAbsolutePath() );
+ writeConfig = true;
log.info( "FTL dats located at: "+ datsDir.getAbsolutePath() );
}
}
@@ -192,9 +237,11 @@ public class FTLModManager {
int steamBasedResponse = JOptionPane.showConfirmDialog( null, "Was FTL installed via Steam?", "Confirm", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE );
if ( steamBasedResponse == JOptionPane.YES_OPTION ) {
appConfig.setProperty( SlipstreamConfig.STEAM_DISTRO, "true" );
+ writeConfig = true;
}
else {
appConfig.setProperty( SlipstreamConfig.STEAM_DISTRO, "false" );
+ writeConfig = true;
}
}
@@ -248,6 +295,7 @@ public class FTLModManager {
if ( steamExeFile != null ) {
appConfig.setProperty( SlipstreamConfig.STEAM_EXE_PATH, steamExeFile.getAbsolutePath() );
+ writeConfig = true;
log.info( "Steam located at: "+ steamExeFile.getAbsolutePath() );
}
}
@@ -260,9 +308,11 @@ public class FTLModManager {
int launchResponse = JOptionPane.showOptionDialog( null, "Would you prefer to launch FTL directly, or via Steam?", "How to Launch?", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, launchOptions, launchOptions[1] );
if ( launchResponse == 0 ) {
appConfig.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "false" );
+ writeConfig = true;
}
else if ( launchResponse == 1 ) {
appConfig.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "true" );
+ writeConfig = true;
}
}
}
@@ -290,6 +340,18 @@ public class FTLModManager {
appConfig.setProperty( SlipstreamConfig.UPDATE_CATALOG, "0" );
appConfig.setProperty( SlipstreamConfig.UPDATE_APP, "0" );
}
+ writeConfig = true;
+ }
+
+ if ( writeConfig ) {
+ try {
+ appConfig.writeConfig();
+ }
+ catch ( IOException e ) {
+ String errorMsg = String.format( "Error writing config to \"%s\"", configFile.getPath() );
+ log.error( errorMsg, e );
+ showErrorDialog( errorMsg );
+ }
}
ManagerFrame frame = null;
@@ -326,6 +388,8 @@ public class FTLModManager {
JOptionPane.showMessageDialog( null, message, "Error", JOptionPane.ERROR_MESSAGE );
}
+
+
private static class ExitException extends RuntimeException {
public ExitException() {
}
diff --git a/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java b/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java
index a10f407..3ad7f5b 100644
--- a/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java
+++ b/src/main/java/net/vhati/modmanager/cli/SlipstreamCLI.java
@@ -51,6 +51,7 @@ public class SlipstreamCLI {
private static Thread.UncaughtExceptionHandler exceptionHandler = null;
+
public static void main( String[] args ) {
exceptionHandler = new Thread.UncaughtExceptionHandler() {
@@ -82,117 +83,16 @@ public class SlipstreamCLI {
System.exit( 0 );
}
- if ( slipstreamCmd.validate ) {
- boolean success = validate(slipstreamCmd.modFileNames);
- System.exit( success ? 0 : 1);
- }
-
- File configFile = new File( "modman.cfg" );
- SlipstreamConfig appConfig = new SlipstreamConfig( configFile );
-
- if ( slipstreamCmd.listMods ) {
- listMods(appConfig);
- System.exit( 0 );
- }
-
- File datsDir = null;
- if ( slipstreamCmd.extractDatsDir != null ||
- slipstreamCmd.patch ||
- slipstreamCmd.runftl ) {
- datsDir = getDatsDir( appConfig );
- }
-
- if ( slipstreamCmd.extractDatsDir != null ) {
- extractDatsDir(slipstreamCmd, datsDir);
- System.exit( 0 );
- }
-
- if ( slipstreamCmd.patch ) {
- boolean success = patch(slipstreamCmd, datsDir);
- if (!success) {
- System.exit( 1 );
- }
- }
-
- if ( slipstreamCmd.runftl ) {
- boolean success = runFtl(appConfig, datsDir);
- System.exit(success ? 0 : 1 );
- }
-
- System.exit( 0 );
- }
-
- private static void extractDatsDir(SlipstreamCommand slipstreamCmd, File datsDir) {
- log.info( "Extracting dats..." );
-
- File extractDir = slipstreamCmd.extractDatsDir;
-
- FolderPack dstPack = null;
- List srcPacks = new ArrayList( 2 );
- InputStream is = null;
- try {
- File ftlDatFile = new File( datsDir, "ftl.dat" );
- File dataDatFile = new File( datsDir, "data.dat" );
- File resourceDatFile = new File( datsDir, "resource.dat" );
-
- if ( ftlDatFile.exists() ) { // FTL 1.6.1.
- AbstractPack ftlPack = new PkgPack( ftlDatFile, "r" );
- srcPacks.add( ftlPack );
- }
- else if ( dataDatFile.exists() && resourceDatFile.exists() ) { // FTL 1.01-1.5.13.
- AbstractPack dataPack = new FTLPack( dataDatFile, "r" );
- AbstractPack resourcePack = new FTLPack( resourceDatFile, "r" );
- srcPacks.add( dataPack );
- srcPacks.add( resourcePack );
- }
- else {
- throw new FileNotFoundException( String.format( "Could not find either \"%s\" or both \"%s\" and \"%s\"", ftlDatFile.getName(), dataDatFile.getName(), resourceDatFile.getName() ) );
- }
-
- if ( !extractDir.exists() ) extractDir.mkdirs();
-
- dstPack = new FolderPack( extractDir );
-
- for ( AbstractPack srcPack : srcPacks ) {
- List innerPaths = srcPack.list();
-
- for ( String innerPath : innerPaths ) {
- if ( dstPack.contains( innerPath ) ) {
- log.info( "While extracting resources, this file was overwritten: "+ innerPath );
- dstPack.remove( innerPath );
- }
- is = srcPack.getInputStream( innerPath );
- dstPack.add( innerPath, is );
- }
- srcPack.close();
- }
- }
- catch ( IOException e ) {
- log.error( "Error extracting dats", e );
- System.exit( 1 );
- }
- finally {
- try {if ( is != null ) is.close();}
- catch ( IOException ex ) {}
-
- try {if ( dstPack != null ) dstPack.close();}
- catch ( IOException ex ) {}
-
- for ( AbstractPack pack : srcPacks ) {
- try {pack.close();}
- catch ( IOException ex ) {}
- }
- }
- }
-
- private static boolean patch(SlipstreamCommand slipstreamCmd, File datsDir) {
- log.info( "Patching..." );
-
DelayedDeleteHook deleteHook = new DelayedDeleteHook();
Runtime.getRuntime().addShutdownHook( deleteHook );
- List modFiles = new ArrayList();
- if ( slipstreamCmd.modFileNames != null ) {
+ if ( slipstreamCmd.validate ) { // Exits (0/1).
+ log.info( "Validating..." );
+
+ StringBuilder resultBuf = new StringBuilder();
+ ReportFormatter formatter = new ReportFormatter();
+ boolean anyInvalid = false;
+
for ( String modFileName : slipstreamCmd.modFileNames ) {
File modFile = new File( modsDir, modFileName );
@@ -204,155 +104,270 @@ public class SlipstreamCLI {
}
catch ( IOException e ) {
log.error( String.format( "Error zipping dir: %s/", modFile.getName() ), e );
- return false;
+
+ List tmpMessages = new ArrayList();
+ tmpMessages.add( new ReportMessage( ReportMessage.SECTION, modFileName ) );
+ tmpMessages.add( new ReportMessage( ReportMessage.EXCEPTION, e.getMessage() ) );
+
+ formatter.format( tmpMessages, resultBuf, 0 );
+ resultBuf.append( "\n" );
+
+ anyInvalid = true;
+ continue;
+ }
+ }
+
+ Report validateReport = ModUtilities.validateModFile( modFile );
+
+ formatter.format( validateReport.messages, resultBuf, 0 );
+ resultBuf.append( "\n" );
+
+ if ( validateReport.outcome == false ) anyInvalid = true;
+ }
+ if ( resultBuf.length() == 0 ) {
+ resultBuf.append( "No mods were checked." );
+ }
+
+ System.out.println();
+ System.out.println( resultBuf.toString() );
+ System.exit( anyInvalid ? 1 : 0 );
+ }
+
+ File configFile = new File( "modman.cfg" );
+ SlipstreamConfig appConfig = getConfig( configFile );
+
+ if ( slipstreamCmd.listMods ) { // Exits.
+ log.info( "Listing mods..." );
+
+ boolean allowZip = appConfig.getProperty( SlipstreamConfig.ALLOW_ZIP, "false" ).equals( "true" );
+ File[] modFiles = modsDir.listFiles( new ModAndDirFileFilter( allowZip, true ) );
+ List dirList = new ArrayList();
+ List fileList = new ArrayList();
+ for ( File f : modFiles ) {
+ if ( f.isDirectory() )
+ dirList.add( f.getName() +"/" );
+ else
+ fileList.add( f.getName() );
+ }
+ Collections.sort( dirList );
+ Collections.sort( fileList );
+ for ( String s : dirList ) System.out.println( s );
+ for ( String s : fileList ) System.out.println( s );
+
+ System.exit( 0 );
+ }
+
+ File datsDir = null;
+ if ( slipstreamCmd.extractDatsDir != null ||
+ slipstreamCmd.patch ||
+ slipstreamCmd.runftl ) {
+ datsDir = getDatsDir( appConfig );
+ }
+
+ if ( slipstreamCmd.extractDatsDir != null ) { // Exits (0/1).
+ log.info( "Extracting dats..." );
+
+ File extractDir = slipstreamCmd.extractDatsDir;
+
+ FolderPack dstPack = null;
+ List srcPacks = new ArrayList( 2 );
+ InputStream is = null;
+ try {
+ File ftlDatFile = new File( datsDir, "ftl.dat" );
+ File dataDatFile = new File( datsDir, "data.dat" );
+ File resourceDatFile = new File( datsDir, "resource.dat" );
+
+ if ( ftlDatFile.exists() ) { // FTL 1.6.1.
+ AbstractPack ftlPack = new PkgPack( ftlDatFile, "r" );
+ srcPacks.add( ftlPack );
+ }
+ else if ( dataDatFile.exists() && resourceDatFile.exists() ) { // FTL 1.01-1.5.13.
+ AbstractPack dataPack = new FTLPack( dataDatFile, "r" );
+ AbstractPack resourcePack = new FTLPack( resourceDatFile, "r" );
+ srcPacks.add( dataPack );
+ srcPacks.add( resourcePack );
+ }
+ else {
+ throw new FileNotFoundException( String.format( "Could not find either \"%s\" or both \"%s\" and \"%s\"", ftlDatFile.getName(), dataDatFile.getName(), resourceDatFile.getName() ) );
+ }
+
+ if ( !extractDir.exists() ) extractDir.mkdirs();
+
+ dstPack = new FolderPack( extractDir );
+
+ for ( AbstractPack srcPack : srcPacks ) {
+ List innerPaths = srcPack.list();
+
+ for ( String innerPath : innerPaths ) {
+ if ( dstPack.contains( innerPath ) ) {
+ log.info( "While extracting resources, this file was overwritten: "+ innerPath );
+ dstPack.remove( innerPath );
+ }
+ is = srcPack.getInputStream( innerPath );
+ dstPack.add( innerPath, is );
+ }
+ srcPack.close();
+ }
+ }
+ catch ( IOException e ) {
+ log.error( "Error extracting dats", e );
+ System.exit( 1 );
+ }
+ finally {
+ try {if ( is != null ) is.close();}
+ catch ( IOException ex ) {}
+
+ try {if ( dstPack != null ) dstPack.close();}
+ catch ( IOException ex ) {}
+
+ for ( AbstractPack pack : srcPacks ) {
+ try {pack.close();}
+ catch ( IOException ex ) {}
+ }
+ }
+
+ System.exit( 0 );
+ }
+
+ if ( slipstreamCmd.patch ) { // Exits sometimes (1 on failure).
+ log.info( "Patching..." );
+
+ List modFiles = new ArrayList();
+ for ( String modFileName : slipstreamCmd.modFileNames ) {
+ File modFile = new File( modsDir, modFileName );
+
+ if ( modFile.isDirectory() ) {
+ log.info( String.format( "Zipping dir: %s/", modFile.getName() ) );
+ try {
+ modFile = createTempMod( modFile );
+ deleteHook.addDoomedFile( modFile );
+ }
+ catch ( IOException e ) {
+ log.error( String.format( "Error zipping dir: %s/", modFile.getName() ), e );
+ System.exit( 1 );
}
}
modFiles.add( modFile );
}
- }
- boolean globalPanic = slipstreamCmd.globalPanic;
+ boolean globalPanic = slipstreamCmd.globalPanic;
- SilentPatchObserver patchObserver = new SilentPatchObserver();
- ModPatchThread patchThread = new ModPatchThread( modFiles, datsDir, backupDir, globalPanic, patchObserver );
- patchThread.setDefaultUncaughtExceptionHandler( exceptionHandler );
- deleteHook.addWatchedThread( patchThread );
+ SilentPatchObserver patchObserver = new SilentPatchObserver();
+ ModPatchThread patchThread = new ModPatchThread( modFiles, datsDir, backupDir, globalPanic, patchObserver );
+ patchThread.setDefaultUncaughtExceptionHandler( exceptionHandler );
+ deleteHook.addWatchedThread( patchThread );
- patchThread.start();
- while ( patchThread.isAlive() ) {
- try {patchThread.join();}
- catch ( InterruptedException e ) {}
- }
-
- if ( !patchObserver.hasSucceeded() ) return false;
- return true;
- }
-
- private static boolean validate(String[] modFileNames) {
- DelayedDeleteHook deleteHook = new DelayedDeleteHook();
- Runtime.getRuntime().addShutdownHook( deleteHook );
-
- log.info( "Validating..." );
-
- StringBuilder resultBuf = new StringBuilder();
- ReportFormatter formatter = new ReportFormatter();
- boolean anyInvalid = false;
-
- for ( String modFileName : modFileNames ) {
- File modFile = new File( modsDir, modFileName );
-
- if ( modFile.isDirectory() ) {
- log.info( String.format( "Zipping dir: %s/", modFile.getName() ) );
- try {
- modFile = createTempMod( modFile );
- deleteHook.addDoomedFile( modFile );
- }
- catch ( IOException e ) {
- log.error( String.format( "Error zipping dir: %s/", modFile.getName() ), e );
-
- List tmpMessages = new ArrayList();
- tmpMessages.add( new ReportMessage( ReportMessage.SECTION, modFileName ) );
- tmpMessages.add( new ReportMessage( ReportMessage.EXCEPTION, e.getMessage() ) );
-
- formatter.format( tmpMessages, resultBuf, 0 );
- resultBuf.append( "\n" );
-
- anyInvalid = true;
- continue;
- }
+ patchThread.start();
+ while ( patchThread.isAlive() ) {
+ try {patchThread.join();}
+ catch ( InterruptedException e ) {}
}
- Report validateReport = ModUtilities.validateModFile( modFile );
-
- formatter.format( validateReport.messages, resultBuf, 0 );
- resultBuf.append( "\n" );
-
- if ( validateReport.outcome == false ) anyInvalid = true;
- }
- if ( resultBuf.length() == 0 ) {
- resultBuf.append( "No mods were checked." );
+ if ( !patchObserver.hasSucceeded() ) System.exit( 1 );
}
- System.out.println();
- System.out.println(resultBuf);
- return !anyInvalid;
- }
+ if ( slipstreamCmd.runftl ) { // Exits (0/1).
+ log.info( "Running FTL..." );
- private static void listMods(SlipstreamConfig appConfig) {
- log.info( "Listing mods..." );
+ File exeFile = null;
+ String[] exeArgs = null;
- boolean allowZip = appConfig.getProperty( SlipstreamConfig.ALLOW_ZIP, "false" ).equals( "true" );
- File[] modFiles = modsDir.listFiles( new ModAndDirFileFilter( allowZip, true ) );
- List dirList = new ArrayList();
- List fileList = new ArrayList();
- for ( File f : modFiles ) {
- if ( f.isDirectory() )
- dirList.add( f.getName() +"/" );
- else
- fileList.add( f.getName() );
- }
- Collections.sort( dirList );
- Collections.sort( fileList );
- for ( String s : dirList ) System.out.println( s );
- for ( String s : fileList ) System.out.println( s );
- }
+ // Try to run via Steam.
+ if ( "true".equals( appConfig.getProperty( SlipstreamConfig.RUN_STEAM_FTL, "false" ) ) ) {
- private static boolean runFtl(SlipstreamConfig appConfig, File datsDir) {
- log.info( "Running FTL..." );
+ String steamPath = appConfig.getProperty( SlipstreamConfig.STEAM_EXE_PATH );
+ if ( steamPath.length() > 0 ) {
+ exeFile = new File( steamPath );
- File exeFile = null;
- String[] exeArgs = null;
-
- // Try to run via Steam.
- if ( "true".equals( appConfig.getProperty( SlipstreamConfig.RUN_STEAM_FTL, "false" ) ) ) {
-
- String steamPath = appConfig.getProperty( SlipstreamConfig.STEAM_EXE_PATH );
- if ( steamPath.length() > 0 ) {
- exeFile = new File( steamPath );
-
- if ( exeFile.exists() ) {
- exeArgs = new String[] {"-applaunch", FTLUtilities.STEAM_APPID_FTL};
+ if ( exeFile.exists() ) {
+ exeArgs = new String[] {"-applaunch", FTLUtilities.STEAM_APPID_FTL};
+ }
+ else {
+ log.warn( String.format( "%s does not exist: %s", SlipstreamConfig.STEAM_EXE_PATH, exeFile.getAbsolutePath() ) );
+ exeFile = null;
+ }
}
- else {
- log.warn( String.format( "%s does not exist: %s", SlipstreamConfig.STEAM_EXE_PATH, exeFile.getAbsolutePath() ) );
- exeFile = null;
+
+ if ( exeFile == null ) {
+ log.warn( "Steam executable could not be found, so FTL will be launched directly" );
}
+
}
-
+ // Try to run directly.
if ( exeFile == null ) {
- log.warn( "Steam executable could not be found, so FTL will be launched directly" );
- }
+ exeFile = FTLUtilities.findGameExe( datsDir );
- }
- // Try to run directly.
- if ( exeFile == null ) {
- exeFile = FTLUtilities.findGameExe( datsDir );
+ if ( exeFile != null ) {
+ exeArgs = new String[0];
+ } else {
+ log.warn( "FTL executable could not be found" );
+ }
+ }
if ( exeFile != null ) {
- exeArgs = new String[0];
- } else {
- log.warn( "FTL executable could not be found" );
+ try {
+ FTLUtilities.launchExe( exeFile, exeArgs );
+ }
+ catch ( Exception e ) {
+ log.error( "Error launching FTL", e );
+ System.exit( 1 );
+ }
}
+ else {
+ log.error( "No executables were found to launch FTL" );
+ System.exit( 1 );
+ }
+
+ System.exit( 0 );
}
- if ( exeFile != null ) {
- try {
- FTLUtilities.launchExe( exeFile, exeArgs );
- }
- catch ( Exception e ) {
- log.error( "Error launching FTL", e );
- return false;
- }
- }
- else {
- log.error( "No executables were found to launch FTL" );
- return false;
- }
-
- return true;
+ System.exit( 0 );
}
+
+ /**
+ * Loads settings from a config file.
+ *
+ * If an error occurs, it'll be logged,
+ * and default settings will be returned.
+ */
+ private static SlipstreamConfig getConfig( File configFile ) {
+
+ Properties props = new Properties();
+ props.setProperty( SlipstreamConfig.ALLOW_ZIP, "false" );
+ props.setProperty( SlipstreamConfig.FTL_DATS_PATH, "" );
+ props.setProperty( SlipstreamConfig.STEAM_EXE_PATH, "" );
+ props.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "false" );
+ props.setProperty( SlipstreamConfig.NEVER_RUN_FTL, "false" );
+ props.setProperty( SlipstreamConfig.USE_DEFAULT_UI, "false" );
+ props.setProperty( SlipstreamConfig.REMEMBER_GEOMETRY, "true" );
+ // "update_catalog" doesn't have a default.
+ // "update_app" doesn't have a default.
+ // "manager_geometry" doesn't have a default.
+
+ // Read the config file.
+ InputStream in = null;
+ try {
+ if ( configFile.exists() ) {
+ log.trace( "Loading properties from config file" );
+ in = new FileInputStream( configFile );
+ props.load( new InputStreamReader( in, "UTF-8" ) );
+ }
+ }
+ catch ( IOException e ) {
+ log.error( "Error loading config", e );
+ }
+ finally {
+ try {if ( in != null ) in.close();}
+ catch ( IOException e ) {}
+ }
+
+ SlipstreamConfig appConfig = new SlipstreamConfig( props, configFile );
+ return appConfig;
+ }
+
+
/**
* Checks the validity of the config's dats path and returns it.
* Or exits if the path is invalid.
diff --git a/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java b/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java
index c6fa448..fe66234 100644
--- a/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java
+++ b/src/main/java/net/vhati/modmanager/core/SlipstreamConfig.java
@@ -1,21 +1,18 @@
package net.vhati.modmanager.core;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.swing.*;
-import java.io.*;
-import java.nio.charset.StandardCharsets;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.concurrent.atomic.AtomicBoolean;
public class SlipstreamConfig {
- private static final Logger log = LoggerFactory.getLogger( SlipstreamConfig.class );
public static final String ALLOW_ZIP = "allow_zip";
public static final String FTL_DATS_PATH = "ftl_dats_path";
@@ -29,35 +26,12 @@ public class SlipstreamConfig {
public static final String REMEMBER_GEOMETRY = "remember_geometry";
public static final String MANAGER_GEOMETRY = "manager_geometry";
- private final Properties config;
- private final File configFile;
+ private Properties config;
+ private File configFile;
- private final AtomicBoolean shutdownHookInitialized;
-
- public SlipstreamConfig(File configFile) {
- this.shutdownHookInitialized = new AtomicBoolean(false);
-
- config = getProperties();
-
- // Read the config file.
- InputStream in = null;
- try {
- if ( configFile.exists() ) {
- log.debug( "Loading config file" );
- in = new FileInputStream( configFile );
- config.load( new InputStreamReader( in, StandardCharsets.UTF_8) );
- scheduleShutdown();
- }
- }
- catch ( IOException e ) {
- log.error( "Error loading config", e );
- showErrorDialog( "Error loading config from "+ configFile.getPath() );
- }
- finally {
- try {if ( in != null ) in.close();}
- catch ( IOException ignored) {}
- }
+ public SlipstreamConfig( Properties config, File configFile ) {
+ this.config = config;
this.configFile = configFile;
}
@@ -68,23 +42,8 @@ public class SlipstreamConfig {
this.configFile = srcConfig.getConfigFile();
this.config = new Properties();
this.config.putAll( srcConfig.getConfig() );
- this.shutdownHookInitialized = srcConfig.shutdownHookInitialized;
}
- private static Properties getProperties() {
- Properties props = new Properties();
- props.setProperty( SlipstreamConfig.ALLOW_ZIP, "false" );
- props.setProperty( SlipstreamConfig.FTL_DATS_PATH, "" ); // Prompt.
- props.setProperty( SlipstreamConfig.STEAM_DISTRO, "" ); // Prompt.
- props.setProperty( SlipstreamConfig.STEAM_EXE_PATH, "" ); // Prompt.
- props.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "" ); // Prompt.
- props.setProperty( SlipstreamConfig.NEVER_RUN_FTL, "false" );
- props.setProperty( SlipstreamConfig.UPDATE_CATALOG, "" ); // Prompt.
- props.setProperty( SlipstreamConfig.UPDATE_APP, "" ); // Prompt.
- props.setProperty( SlipstreamConfig.USE_DEFAULT_UI, "false" );
- props.setProperty( SlipstreamConfig.REMEMBER_GEOMETRY, "true" );
- return props;
- }
public Properties getConfig() { return config; }
@@ -92,30 +51,9 @@ public class SlipstreamConfig {
public Object setProperty( String key, String value ) {
- scheduleShutdown();
return config.setProperty( key, value );
}
- private void scheduleShutdown() {
- if (!shutdownHookInitialized.compareAndExchange(false, true)) {
- Runtime.getRuntime().addShutdownHook(new Thread(() -> {
- try {
- this.writeConfig();
- } catch (IOException e) {
- String errorMsg = String.format( "Error writing config to \"%s\"", configFile.getPath() );
- log.error( errorMsg, e );
- // TODO: only show this error when in gui mode
- showErrorDialog( errorMsg );
- }
- }));
- }
-
- }
-
- private static void showErrorDialog( String message ) {
- JOptionPane.showMessageDialog( null, message, "Error", JOptionPane.ERROR_MESSAGE );
- }
-
public int getPropertyAsInt( String key, int defaultValue ) {
String s = config.getProperty( key );
if ( s != null && s.matches("^\\d+$") )
diff --git a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java
index 742e6f7..1bfcf30 100644
--- a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java
+++ b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java
@@ -1065,7 +1065,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
* Set this to false before an abnormal exit.
*/
public void setDisposeNormally( boolean b ) {
- disposeNormally = b;
+ disposeNormally = false;
}
@Override
diff --git a/src/main/java/net/vhati/modmanager/ui/ModPatchDialog.java b/src/main/java/net/vhati/modmanager/ui/ModPatchDialog.java
index bfa7932..80a2376 100644
--- a/src/main/java/net/vhati/modmanager/ui/ModPatchDialog.java
+++ b/src/main/java/net/vhati/modmanager/ui/ModPatchDialog.java
@@ -13,7 +13,7 @@ public class ModPatchDialog extends ProgressDialog implements ModPatchObserver {
public ModPatchDialog( Frame owner, boolean continueOnSuccess ) {
- super( owner, continueOnSuccess );
+ super( owner, true );
this.setTitle( "Patching..." );
this.setSize( 400, 160 );
diff --git a/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java b/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java
index 401ead3..8a07df2 100644
--- a/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java
+++ b/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java
@@ -524,33 +524,32 @@ public class ModXMLSandbox extends JFrame implements ActionListener {
*/
@SuppressWarnings("unchecked")
private void buildTreeFromString( DefaultTreeModel treeModel, String path ) {
-// Method commented out to get application to compile. Figure out what this did and fix it
-// DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)treeModel.getRoot();
-// DefaultMutableTreeNode currentNode = rootNode;
-//
-// String[] chunks = path.split( "/" );
-//
-// for ( int i=0; i < chunks.length; i++ ) {
-// String chunk = chunks[i];
-// if ( i < chunks.length-1 )
-// chunk += "/";
-//
-// boolean found = false;
-// Enumeration enumIt = currentNode.children();
-// while ( enumIt.hasMoreElements() ) {
-// DefaultMutableTreeNode tmpNode = enumIt.nextElement();
-// if ( chunk.equals( tmpNode.getUserObject() ) ) {
-// found = true;
-// currentNode = tmpNode;
-// break;
-// }
-// }
-// if ( !found ) {
-// DefaultMutableTreeNode newNode = new DefaultMutableTreeNode( chunk );
-// currentNode.insert( newNode, currentNode.getChildCount() );
-// currentNode = newNode;
-// }
-// }
+ DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)treeModel.getRoot();
+ DefaultMutableTreeNode currentNode = rootNode;
+
+ String[] chunks = path.split( "/" );
+
+ for ( int i=0; i < chunks.length; i++ ) {
+ String chunk = chunks[i];
+ if ( i < chunks.length-1 )
+ chunk += "/";
+
+ boolean found = false;
+ Enumeration enumIt = currentNode.children();
+ while ( enumIt.hasMoreElements() ) {
+ DefaultMutableTreeNode tmpNode = enumIt.nextElement();
+ if ( chunk.equals( tmpNode.getUserObject() ) ) {
+ found = true;
+ currentNode = tmpNode;
+ break;
+ }
+ }
+ if ( !found ) {
+ DefaultMutableTreeNode newNode = new DefaultMutableTreeNode( chunk );
+ currentNode.insert( newNode, currentNode.getChildCount() );
+ currentNode = newNode;
+ }
+ }
}