Compare commits
11 commits
19233266d0
...
ccd50b0275
Author | SHA1 | Date | |
---|---|---|---|
ccd50b0275 | |||
9e8e830ab1 | |||
9861d7242e | |||
8b344d2c53 | |||
c0795e234a | |||
![]() |
85cad4ffbe | ||
![]() |
dcec887f17 | ||
![]() |
4bb3a3ddb9 | ||
![]() |
23dbdc8ab2 | ||
![]() |
d89e53656e | ||
![]() |
871cbde44a |
14 changed files with 447 additions and 353 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -5,18 +5,19 @@ target/
|
||||||
*.bak
|
*.bak
|
||||||
~$*
|
~$*
|
||||||
|
|
||||||
|
|
||||||
# Windows image file caches
|
# Windows image file caches
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
# Windows folder config file
|
# Windows folder config file
|
||||||
Desktop.ini
|
Desktop.ini
|
||||||
|
|
||||||
|
|
||||||
# Mac junk
|
# Mac junk
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
|
||||||
# IdeaJ
|
# IdeaJ
|
||||||
*.idea
|
*.idea
|
||||||
*.iml
|
*.iml
|
||||||
|
|
||||||
|
# enviroemnt packages
|
||||||
|
.direnv
|
||||||
|
|
||||||
|
|
25
flake.lock
generated
Normal file
25
flake.lock
generated
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
69
flake.nix
Normal file
69
flake.nix
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
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}"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
4
pom.xml
4
pom.xml
|
@ -11,8 +11,8 @@
|
||||||
</prerequisites>
|
</prerequisites>
|
||||||
<properties>
|
<properties>
|
||||||
<jdk.version>1.6</jdk.version>
|
<jdk.version>1.6</jdk.version>
|
||||||
<maven.compiler.source>1.6</maven.compiler.source>
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
<maven.compiler.target>1.6</maven.compiler.target>
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
14
shell.nix
Normal file
14
shell.nix
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
(
|
||||||
|
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
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Get the absolute path to this script's folder.
|
# Get the absolute path to this script's folder.
|
||||||
if echo "$0" | awk '{exit(!/^\//);}'; then
|
if echo "$0" | awk '{exit(!/^\//);}'; then
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Get the script's name.
|
# Get the script's name.
|
||||||
me=$(basename "$0");
|
me=$(basename "$0");
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
package net.vhati.modmanager;
|
package net.vhati.modmanager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Properties;
|
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.UIManager.LookAndFeelInfo;
|
|
||||||
|
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
|
@ -36,8 +31,8 @@ public class FTLModManager {
|
||||||
|
|
||||||
public static final String APP_NAME = "Slipstream Mod Manager";
|
public static final String APP_NAME = "Slipstream Mod Manager";
|
||||||
public static final ComparableVersion APP_VERSION = new ComparableVersion( "1.9.1" );
|
public static final ComparableVersion APP_VERSION = new ComparableVersion( "1.9.1" );
|
||||||
public static final String APP_URL = "https://subsetgames.com/forum/viewtopic.php?f=12&t=17102";
|
public static final String APP_URL = "TODO";
|
||||||
public static final String APP_AUTHOR = "Vhati";
|
public static final String APP_AUTHOR = "jan-leila";
|
||||||
|
|
||||||
|
|
||||||
public static void main( String[] args ) {
|
public static void main( String[] args ) {
|
||||||
|
@ -53,7 +48,7 @@ public class FTLModManager {
|
||||||
|
|
||||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||||
encoder.setContext( lc );
|
encoder.setContext( lc );
|
||||||
encoder.setCharset( Charset.forName( "UTF-8" ) );
|
encoder.setCharset(StandardCharsets.UTF_8);
|
||||||
encoder.setPattern( "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" );
|
encoder.setPattern( "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" );
|
||||||
encoder.start();
|
encoder.start();
|
||||||
|
|
||||||
|
@ -76,7 +71,7 @@ public class FTLModManager {
|
||||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void uncaughtException( Thread t, Throwable e ) {
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,20 +81,15 @@ public class FTLModManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure all popups are triggered from the event dispatch thread.
|
// 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() {
|
private static void guiInit() {
|
||||||
try {
|
try {
|
||||||
|
// TODO: get mods file from env var
|
||||||
// Nag if the jar was double-clicked.
|
// Nag if the jar was double-clicked.
|
||||||
if ( new File( "./mods/" ).exists() == false ) {
|
if (!new File("./mods/").exists()) {
|
||||||
String currentPath = new File( "." ).getAbsoluteFile().getParentFile().getAbsolutePath();
|
String currentPath = new File( "." ).getAbsoluteFile().getParentFile().getAbsolutePath();
|
||||||
|
|
||||||
log.error( String.format( "Slipstream could not find its own folder (Currently in \"%s\"), exiting...", currentPath ) );
|
log.error( String.format( "Slipstream could not find its own folder (Currently in \"%s\"), exiting...", currentPath ) );
|
||||||
|
@ -108,46 +98,13 @@ public class FTLModManager {
|
||||||
throw new ExitException();
|
throw new ExitException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: get config file from env var
|
||||||
File configFile = new File( "modman.cfg" );
|
File configFile = new File( "modman.cfg" );
|
||||||
|
|
||||||
boolean writeConfig = false;
|
SlipstreamConfig appConfig = new SlipstreamConfig(configFile);
|
||||||
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.
|
// Look-and-Feel.
|
||||||
boolean useDefaultUI = "true".equals( appConfig.getProperty( SlipstreamConfig.USE_DEFAULT_UI, "false" ) );
|
boolean useDefaultUI = Boolean.parseBoolean(appConfig.getProperty(SlipstreamConfig.USE_DEFAULT_UI, "false"));
|
||||||
|
|
||||||
if ( !useDefaultUI ) {
|
if ( !useDefaultUI ) {
|
||||||
LookAndFeel defaultLaf = UIManager.getLookAndFeel();
|
LookAndFeel defaultLaf = UIManager.getLookAndFeel();
|
||||||
|
@ -157,7 +114,7 @@ public class FTLModManager {
|
||||||
log.debug( "Setting system look and feel: "+ UIManager.getSystemLookAndFeelClassName() );
|
log.debug( "Setting system look and feel: "+ UIManager.getSystemLookAndFeelClassName() );
|
||||||
|
|
||||||
// SystemLaf is risky. It may throw an exception, or lead to graphical bugs.
|
// SystemLaf is risky. It may throw an exception, or lead to graphical bugs.
|
||||||
// Problems are geneally caused by custom Windows themes.
|
// Problems are generally caused by custom Windows themes.
|
||||||
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
|
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
catch ( Exception e ) {
|
||||||
|
@ -165,7 +122,6 @@ public class FTLModManager {
|
||||||
log.info( "Setting "+ SlipstreamConfig.USE_DEFAULT_UI +"=true in the config file to prevent this error..." );
|
log.info( "Setting "+ SlipstreamConfig.USE_DEFAULT_UI +"=true in the config file to prevent this error..." );
|
||||||
|
|
||||||
appConfig.setProperty( SlipstreamConfig.USE_DEFAULT_UI, "true" );
|
appConfig.setProperty( SlipstreamConfig.USE_DEFAULT_UI, "true" );
|
||||||
writeConfig = true;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
UIManager.setLookAndFeel( defaultLaf );
|
UIManager.setLookAndFeel( defaultLaf );
|
||||||
|
@ -220,7 +176,6 @@ public class FTLModManager {
|
||||||
|
|
||||||
if ( datsDir != null ) {
|
if ( datsDir != null ) {
|
||||||
appConfig.setProperty( SlipstreamConfig.FTL_DATS_PATH, datsDir.getAbsolutePath() );
|
appConfig.setProperty( SlipstreamConfig.FTL_DATS_PATH, datsDir.getAbsolutePath() );
|
||||||
writeConfig = true;
|
|
||||||
log.info( "FTL dats located at: "+ datsDir.getAbsolutePath() );
|
log.info( "FTL dats located at: "+ datsDir.getAbsolutePath() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,11 +192,9 @@ public class FTLModManager {
|
||||||
int steamBasedResponse = JOptionPane.showConfirmDialog( null, "Was FTL installed via Steam?", "Confirm", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE );
|
int steamBasedResponse = JOptionPane.showConfirmDialog( null, "Was FTL installed via Steam?", "Confirm", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE );
|
||||||
if ( steamBasedResponse == JOptionPane.YES_OPTION ) {
|
if ( steamBasedResponse == JOptionPane.YES_OPTION ) {
|
||||||
appConfig.setProperty( SlipstreamConfig.STEAM_DISTRO, "true" );
|
appConfig.setProperty( SlipstreamConfig.STEAM_DISTRO, "true" );
|
||||||
writeConfig = true;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
appConfig.setProperty( SlipstreamConfig.STEAM_DISTRO, "false" );
|
appConfig.setProperty( SlipstreamConfig.STEAM_DISTRO, "false" );
|
||||||
writeConfig = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +248,6 @@ public class FTLModManager {
|
||||||
|
|
||||||
if ( steamExeFile != null ) {
|
if ( steamExeFile != null ) {
|
||||||
appConfig.setProperty( SlipstreamConfig.STEAM_EXE_PATH, steamExeFile.getAbsolutePath() );
|
appConfig.setProperty( SlipstreamConfig.STEAM_EXE_PATH, steamExeFile.getAbsolutePath() );
|
||||||
writeConfig = true;
|
|
||||||
log.info( "Steam located at: "+ steamExeFile.getAbsolutePath() );
|
log.info( "Steam located at: "+ steamExeFile.getAbsolutePath() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,11 +260,9 @@ 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] );
|
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 ) {
|
if ( launchResponse == 0 ) {
|
||||||
appConfig.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "false" );
|
appConfig.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "false" );
|
||||||
writeConfig = true;
|
|
||||||
}
|
}
|
||||||
else if ( launchResponse == 1 ) {
|
else if ( launchResponse == 1 ) {
|
||||||
appConfig.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "true" );
|
appConfig.setProperty( SlipstreamConfig.RUN_STEAM_FTL, "true" );
|
||||||
writeConfig = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,18 +290,6 @@ public class FTLModManager {
|
||||||
appConfig.setProperty( SlipstreamConfig.UPDATE_CATALOG, "0" );
|
appConfig.setProperty( SlipstreamConfig.UPDATE_CATALOG, "0" );
|
||||||
appConfig.setProperty( SlipstreamConfig.UPDATE_APP, "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;
|
ManagerFrame frame = null;
|
||||||
|
@ -388,8 +326,6 @@ public class FTLModManager {
|
||||||
JOptionPane.showMessageDialog( null, message, "Error", JOptionPane.ERROR_MESSAGE );
|
JOptionPane.showMessageDialog( null, message, "Error", JOptionPane.ERROR_MESSAGE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static class ExitException extends RuntimeException {
|
private static class ExitException extends RuntimeException {
|
||||||
public ExitException() {
|
public ExitException() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@ public class SlipstreamCLI {
|
||||||
|
|
||||||
private static Thread.UncaughtExceptionHandler exceptionHandler = null;
|
private static Thread.UncaughtExceptionHandler exceptionHandler = null;
|
||||||
|
|
||||||
|
|
||||||
public static void main( String[] args ) {
|
public static void main( String[] args ) {
|
||||||
|
|
||||||
exceptionHandler = new Thread.UncaughtExceptionHandler() {
|
exceptionHandler = new Thread.UncaughtExceptionHandler() {
|
||||||
|
@ -83,77 +82,16 @@ public class SlipstreamCLI {
|
||||||
System.exit( 0 );
|
System.exit( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
DelayedDeleteHook deleteHook = new DelayedDeleteHook();
|
if ( slipstreamCmd.validate ) {
|
||||||
Runtime.getRuntime().addShutdownHook( deleteHook );
|
boolean success = validate(slipstreamCmd.modFileNames);
|
||||||
|
System.exit( success ? 0 : 1);
|
||||||
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 );
|
|
||||||
|
|
||||||
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<ReportMessage> tmpMessages = new ArrayList<ReportMessage>();
|
|
||||||
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" );
|
File configFile = new File( "modman.cfg" );
|
||||||
SlipstreamConfig appConfig = getConfig( configFile );
|
SlipstreamConfig appConfig = new SlipstreamConfig( 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<String> dirList = new ArrayList<String>();
|
|
||||||
List<String> fileList = new ArrayList<String>();
|
|
||||||
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 );
|
|
||||||
|
|
||||||
|
if ( slipstreamCmd.listMods ) {
|
||||||
|
listMods(appConfig);
|
||||||
System.exit( 0 );
|
System.exit( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,75 +102,97 @@ public class SlipstreamCLI {
|
||||||
datsDir = getDatsDir( appConfig );
|
datsDir = getDatsDir( appConfig );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( slipstreamCmd.extractDatsDir != null ) { // Exits (0/1).
|
if ( slipstreamCmd.extractDatsDir != null ) {
|
||||||
log.info( "Extracting dats..." );
|
extractDatsDir(slipstreamCmd, datsDir);
|
||||||
|
|
||||||
File extractDir = slipstreamCmd.extractDatsDir;
|
|
||||||
|
|
||||||
FolderPack dstPack = null;
|
|
||||||
List<AbstractPack> srcPacks = new ArrayList<AbstractPack>( 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<String> 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 );
|
System.exit( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( slipstreamCmd.patch ) { // Exits sometimes (1 on failure).
|
if ( slipstreamCmd.patch ) {
|
||||||
log.info( "Patching..." );
|
boolean success = patch(slipstreamCmd, datsDir);
|
||||||
|
if (!success) {
|
||||||
|
System.exit( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<File> modFiles = new ArrayList<File>();
|
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<AbstractPack> srcPacks = new ArrayList<AbstractPack>( 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<String> 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<File> modFiles = new ArrayList<File>();
|
||||||
|
if ( slipstreamCmd.modFileNames != null ) {
|
||||||
for ( String modFileName : slipstreamCmd.modFileNames ) {
|
for ( String modFileName : slipstreamCmd.modFileNames ) {
|
||||||
File modFile = new File( modsDir, modFileName );
|
File modFile = new File( modsDir, modFileName );
|
||||||
|
|
||||||
|
@ -244,130 +204,155 @@ public class SlipstreamCLI {
|
||||||
}
|
}
|
||||||
catch ( IOException e ) {
|
catch ( IOException e ) {
|
||||||
log.error( String.format( "Error zipping dir: %s/", modFile.getName() ), e );
|
log.error( String.format( "Error zipping dir: %s/", modFile.getName() ), e );
|
||||||
System.exit( 1 );
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modFiles.add( modFile );
|
modFiles.add( modFile );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean globalPanic = slipstreamCmd.globalPanic;
|
|
||||||
|
|
||||||
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() ) System.exit( 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( slipstreamCmd.runftl ) { // Exits (0/1).
|
boolean globalPanic = slipstreamCmd.globalPanic;
|
||||||
log.info( "Running FTL..." );
|
|
||||||
|
|
||||||
File exeFile = null;
|
SilentPatchObserver patchObserver = new SilentPatchObserver();
|
||||||
String[] exeArgs = null;
|
ModPatchThread patchThread = new ModPatchThread( modFiles, datsDir, backupDir, globalPanic, patchObserver );
|
||||||
|
patchThread.setDefaultUncaughtExceptionHandler( exceptionHandler );
|
||||||
|
deleteHook.addWatchedThread( patchThread );
|
||||||
|
|
||||||
// Try to run via Steam.
|
patchThread.start();
|
||||||
if ( "true".equals( appConfig.getProperty( SlipstreamConfig.RUN_STEAM_FTL, "false" ) ) ) {
|
while ( patchThread.isAlive() ) {
|
||||||
|
try {patchThread.join();}
|
||||||
|
catch ( InterruptedException e ) {}
|
||||||
|
}
|
||||||
|
|
||||||
String steamPath = appConfig.getProperty( SlipstreamConfig.STEAM_EXE_PATH );
|
if ( !patchObserver.hasSucceeded() ) return false;
|
||||||
if ( steamPath.length() > 0 ) {
|
return true;
|
||||||
exeFile = new File( steamPath );
|
}
|
||||||
|
|
||||||
if ( exeFile.exists() ) {
|
private static boolean validate(String[] modFileNames) {
|
||||||
exeArgs = new String[] {"-applaunch", FTLUtilities.STEAM_APPID_FTL};
|
DelayedDeleteHook deleteHook = new DelayedDeleteHook();
|
||||||
}
|
Runtime.getRuntime().addShutdownHook( deleteHook );
|
||||||
else {
|
|
||||||
log.warn( String.format( "%s does not exist: %s", SlipstreamConfig.STEAM_EXE_PATH, exeFile.getAbsolutePath() ) );
|
log.info( "Validating..." );
|
||||||
exeFile = null;
|
|
||||||
}
|
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 );
|
||||||
|
|
||||||
if ( exeFile == null ) {
|
List<ReportMessage> tmpMessages = new ArrayList<ReportMessage>();
|
||||||
log.warn( "Steam executable could not be found, so FTL will be launched directly" );
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// Try to run directly.
|
|
||||||
|
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);
|
||||||
|
return !anyInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void listMods(SlipstreamConfig appConfig) {
|
||||||
|
log.info( "Listing mods..." );
|
||||||
|
|
||||||
|
boolean allowZip = appConfig.getProperty( SlipstreamConfig.ALLOW_ZIP, "false" ).equals( "true" );
|
||||||
|
File[] modFiles = modsDir.listFiles( new ModAndDirFileFilter( allowZip, true ) );
|
||||||
|
List<String> dirList = new ArrayList<String>();
|
||||||
|
List<String> fileList = new ArrayList<String>();
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean runFtl(SlipstreamConfig appConfig, File datsDir) {
|
||||||
|
log.info( "Running FTL..." );
|
||||||
|
|
||||||
|
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};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.warn( String.format( "%s does not exist: %s", SlipstreamConfig.STEAM_EXE_PATH, exeFile.getAbsolutePath() ) );
|
||||||
|
exeFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( exeFile == null ) {
|
if ( exeFile == null ) {
|
||||||
exeFile = FTLUtilities.findGameExe( datsDir );
|
log.warn( "Steam executable could not be found, so FTL will be launched directly" );
|
||||||
|
|
||||||
if ( exeFile != null ) {
|
|
||||||
exeArgs = new String[0];
|
|
||||||
} else {
|
|
||||||
log.warn( "FTL executable could not be found" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Try to run directly.
|
||||||
|
if ( exeFile == null ) {
|
||||||
|
exeFile = FTLUtilities.findGameExe( datsDir );
|
||||||
|
|
||||||
if ( exeFile != null ) {
|
if ( exeFile != null ) {
|
||||||
try {
|
exeArgs = new String[0];
|
||||||
FTLUtilities.launchExe( exeFile, exeArgs );
|
} else {
|
||||||
}
|
log.warn( "FTL executable could not be found" );
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
* Checks the validity of the config's dats path and returns it.
|
||||||
* Or exits if the path is invalid.
|
* Or exits if the path is invalid.
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
package net.vhati.modmanager.core;
|
package net.vhati.modmanager.core;
|
||||||
|
|
||||||
import java.io.File;
|
import org.slf4j.Logger;
|
||||||
import java.io.FileOutputStream;
|
import org.slf4j.LoggerFactory;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
import javax.swing.*;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
|
||||||
public class SlipstreamConfig {
|
public class SlipstreamConfig {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger( SlipstreamConfig.class );
|
||||||
|
|
||||||
public static final String ALLOW_ZIP = "allow_zip";
|
public static final String ALLOW_ZIP = "allow_zip";
|
||||||
public static final String FTL_DATS_PATH = "ftl_dats_path";
|
public static final String FTL_DATS_PATH = "ftl_dats_path";
|
||||||
|
@ -26,12 +29,35 @@ public class SlipstreamConfig {
|
||||||
public static final String REMEMBER_GEOMETRY = "remember_geometry";
|
public static final String REMEMBER_GEOMETRY = "remember_geometry";
|
||||||
public static final String MANAGER_GEOMETRY = "manager_geometry";
|
public static final String MANAGER_GEOMETRY = "manager_geometry";
|
||||||
|
|
||||||
private Properties config;
|
private final Properties config;
|
||||||
private File configFile;
|
private final 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;
|
this.configFile = configFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +68,23 @@ public class SlipstreamConfig {
|
||||||
this.configFile = srcConfig.getConfigFile();
|
this.configFile = srcConfig.getConfigFile();
|
||||||
this.config = new Properties();
|
this.config = new Properties();
|
||||||
this.config.putAll( srcConfig.getConfig() );
|
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; }
|
public Properties getConfig() { return config; }
|
||||||
|
|
||||||
|
@ -51,9 +92,30 @@ public class SlipstreamConfig {
|
||||||
|
|
||||||
|
|
||||||
public Object setProperty( String key, String value ) {
|
public Object setProperty( String key, String value ) {
|
||||||
|
scheduleShutdown();
|
||||||
return config.setProperty( key, value );
|
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 ) {
|
public int getPropertyAsInt( String key, int defaultValue ) {
|
||||||
String s = config.getProperty( key );
|
String s = config.getProperty( key );
|
||||||
if ( s != null && s.matches("^\\d+$") )
|
if ( s != null && s.matches("^\\d+$") )
|
||||||
|
|
|
@ -1065,7 +1065,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
* Set this to false before an abnormal exit.
|
* Set this to false before an abnormal exit.
|
||||||
*/
|
*/
|
||||||
public void setDisposeNormally( boolean b ) {
|
public void setDisposeNormally( boolean b ) {
|
||||||
disposeNormally = false;
|
disposeNormally = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class ModPatchDialog extends ProgressDialog implements ModPatchObserver {
|
||||||
|
|
||||||
|
|
||||||
public ModPatchDialog( Frame owner, boolean continueOnSuccess ) {
|
public ModPatchDialog( Frame owner, boolean continueOnSuccess ) {
|
||||||
super( owner, true );
|
super( owner, continueOnSuccess );
|
||||||
this.setTitle( "Patching..." );
|
this.setTitle( "Patching..." );
|
||||||
|
|
||||||
this.setSize( 400, 160 );
|
this.setSize( 400, 160 );
|
||||||
|
|
|
@ -524,32 +524,33 @@ public class ModXMLSandbox extends JFrame implements ActionListener {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void buildTreeFromString( DefaultTreeModel treeModel, String path ) {
|
private void buildTreeFromString( DefaultTreeModel treeModel, String path ) {
|
||||||
DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)treeModel.getRoot();
|
// Method commented out to get application to compile. Figure out what this did and fix it
|
||||||
DefaultMutableTreeNode currentNode = rootNode;
|
// DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)treeModel.getRoot();
|
||||||
|
// DefaultMutableTreeNode currentNode = rootNode;
|
||||||
String[] chunks = path.split( "/" );
|
//
|
||||||
|
// String[] chunks = path.split( "/" );
|
||||||
for ( int i=0; i < chunks.length; i++ ) {
|
//
|
||||||
String chunk = chunks[i];
|
// for ( int i=0; i < chunks.length; i++ ) {
|
||||||
if ( i < chunks.length-1 )
|
// String chunk = chunks[i];
|
||||||
chunk += "/";
|
// if ( i < chunks.length-1 )
|
||||||
|
// chunk += "/";
|
||||||
boolean found = false;
|
//
|
||||||
Enumeration<DefaultMutableTreeNode> enumIt = currentNode.children();
|
// boolean found = false;
|
||||||
while ( enumIt.hasMoreElements() ) {
|
// Enumeration<DefaultMutableTreeNode> enumIt = currentNode.children();
|
||||||
DefaultMutableTreeNode tmpNode = enumIt.nextElement();
|
// while ( enumIt.hasMoreElements() ) {
|
||||||
if ( chunk.equals( tmpNode.getUserObject() ) ) {
|
// DefaultMutableTreeNode tmpNode = enumIt.nextElement();
|
||||||
found = true;
|
// if ( chunk.equals( tmpNode.getUserObject() ) ) {
|
||||||
currentNode = tmpNode;
|
// found = true;
|
||||||
break;
|
// currentNode = tmpNode;
|
||||||
}
|
// break;
|
||||||
}
|
// }
|
||||||
if ( !found ) {
|
// }
|
||||||
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode( chunk );
|
// if ( !found ) {
|
||||||
currentNode.insert( newNode, currentNode.getChildCount() );
|
// DefaultMutableTreeNode newNode = new DefaultMutableTreeNode( chunk );
|
||||||
currentNode = newNode;
|
// currentNode.insert( newNode, currentNode.getChildCount() );
|
||||||
}
|
// currentNode = newNode;
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue