Added support for extracting/sandboxing FTL 1.6.1's resources (patching is WIP)

This commit is contained in:
Vhati 2017-12-05 15:27:21 -05:00
parent 34a71e0aa5
commit f0df7faab8
10 changed files with 344 additions and 198 deletions

View file

@ -2,8 +2,10 @@ package net.vhati.modmanager.ui;
import java.awt.Frame;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JDialog;
import javax.swing.SwingUtilities;
@ -11,6 +13,7 @@ import javax.swing.SwingUtilities;
import net.vhati.ftldat.AbstractPack;
import net.vhati.ftldat.FolderPack;
import net.vhati.ftldat.FTLPack;
import net.vhati.ftldat.PkgPack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -22,24 +25,24 @@ public class DatExtractDialog extends ProgressDialog {
private boolean started = false;
private File extractDir;
private File[] datFiles;
private File extractDir = null;
private File datsDir = null;
private DatExtractThread workerThread = null;
public DatExtractDialog( Frame owner, File extractDir, File[] datFiles ) {
public DatExtractDialog( Frame owner, File extractDir, File datsDir ) {
super( owner, false );
this.setTitle( "Extracting..." );
this.extractDir = extractDir;
this.datFiles = datFiles;
this.datsDir = datsDir;
this.setSize( 400, 160 );
this.setMinimumSize( this.getPreferredSize() );
this.setLocationRelativeTo( owner );
workerThread = new DatExtractThread( extractDir, datFiles );
workerThread = new DatExtractThread( extractDir, datsDir );
}
/**
@ -79,59 +82,79 @@ public class DatExtractDialog extends ProgressDialog {
private class DatExtractThread extends Thread {
private File extractDir;
private File[] datFiles;
private File extractDir = null;
private File datsDir = null;
public DatExtractThread( File extractDir, File[] datFiles ) {
public DatExtractThread( File extractDir, File datsDir ) {
this.extractDir = extractDir;
this.datFiles = datFiles;
this.datsDir = datsDir;
}
@Override
public void run() {
AbstractPack srcP = null;
AbstractPack dstP = null;
AbstractPack dstPack = null;
List<AbstractPack> srcPacks = new ArrayList<AbstractPack>( 2 );
InputStream is = null;
int progress = 0;
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();
dstP = new FolderPack( extractDir );
dstPack = new FolderPack( extractDir );
for ( File datFile : datFiles ) {
srcP = new FTLPack( datFile, "r" );
for ( AbstractPack srcPack : srcPacks ) {
progress = 0;
List<String> innerPaths = srcP.list();
List<String> innerPaths = srcPack.list();
setProgressLater( progress, innerPaths.size() );
for ( String innerPath : innerPaths ) {
setStatusTextLater( innerPath );
if ( dstP.contains( innerPath ) ) {
if ( dstPack.contains( innerPath ) ) {
log.info( "While extracting resources, this file was overwritten: "+ innerPath );
dstP.remove( innerPath );
dstPack.remove( innerPath );
}
is = srcP.getInputStream( innerPath );
dstP.add( innerPath, is );
is = srcPack.getInputStream( innerPath );
dstPack.add( innerPath, is );
setProgressLater( progress++ );
}
srcP.close();
srcPack.close();
}
setTaskOutcomeLater( true, null );
}
catch ( Exception e ) {
log.error( "Error extracting dats.", e );
log.error( "Error extracting dats", e );
setTaskOutcomeLater( false, e );
}
finally {
try {if ( is != null ) is.close();}
catch ( IOException e ) {}
try {if ( srcP != null ) srcP.close();}
try {if ( dstPack != null ) dstPack.close();}
catch ( IOException e ) {}
try {if ( dstP != null ) dstP.close();}
catch ( IOException e ) {}
for ( AbstractPack pack : srcPacks ) {
try {pack.close();}
catch ( IOException ex ) {}
}
}
}
}

View file

@ -60,7 +60,6 @@ import net.vhati.modmanager.core.ModDB;
import net.vhati.modmanager.core.ModFileInfo;
import net.vhati.modmanager.core.ModInfo;
import net.vhati.modmanager.core.ModPatchThread;
import net.vhati.modmanager.core.ModPatchThread.BackedUpDat;
import net.vhati.modmanager.core.ModsScanObserver;
import net.vhati.modmanager.core.ModsScanThread;
import net.vhati.modmanager.core.ModUtilities;
@ -666,13 +665,6 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) );
BackedUpDat dataDat = new BackedUpDat();
dataDat.datFile = new File( datsDir, "data.dat" );
dataDat.bakFile = new File( backupDir, "data.dat.bak" );
BackedUpDat resDat = new BackedUpDat();
resDat.datFile = new File( datsDir, "resource.dat" );
resDat.bakFile = new File( backupDir, "resource.dat.bak" );
ModPatchDialog patchDlg = new ModPatchDialog( this, true );
String neverRunFtl = appConfig.getProperty( "never_run_ftl", "false" );
@ -705,7 +697,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
log.info( "" );
log.info( "Patching..." );
log.info( "" );
ModPatchThread patchThread = new ModPatchThread( modFiles, dataDat, resDat, false, patchDlg );
ModPatchThread patchThread = new ModPatchThread( modFiles, datsDir, backupDir, false, patchDlg );
patchThread.setDefaultUncaughtExceptionHandler( this );
patchThread.start();
@ -780,11 +772,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
File extractDir = extractChooser.getSelectedFile();
File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) );
File dataDatFile = new File( datsDir, "data.dat" );
File resDatFile = new File( datsDir, "resource.dat" );
File[] datFiles = new File[] {dataDatFile, resDatFile};
DatExtractDialog extractDlg = new DatExtractDialog( this, extractDir, datFiles );
DatExtractDialog extractDlg = new DatExtractDialog( this, extractDir, datsDir );
extractDlg.getWorkerThread().setDefaultUncaughtExceptionHandler( this );
extractDlg.extract();
extractDlg.setVisible( true );
@ -792,9 +781,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
else if ( source == sandboxMenuItem ) {
setStatusText( "" );
File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) );
File dataDatFile = new File( datsDir, "data.dat" );
ModXMLSandbox sandboxFrame = new ModXMLSandbox( dataDatFile );
ModXMLSandbox sandboxFrame = new ModXMLSandbox( datsDir );
sandboxFrame.addWindowListener( nerfListener );
sandboxFrame.setSize( 800, 600 );
sandboxFrame.setLocationRelativeTo( null );

View file

@ -13,6 +13,7 @@ import java.awt.event.KeyEvent;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Enumeration;
@ -54,7 +55,9 @@ import javax.swing.tree.TreePath;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.UndoManager;
import net.vhati.ftldat.AbstractPack;
import net.vhati.ftldat.FTLPack;
import net.vhati.ftldat.PkgPack;
import net.vhati.modmanager.core.ModUtilities;
import net.vhati.modmanager.core.SloppyXMLOutputProcessor;
import net.vhati.modmanager.core.XMLPatcher;
@ -72,7 +75,7 @@ public class ModXMLSandbox extends JFrame implements ActionListener {
private UndoManager undoManager = new UndoManager();
private Document mainDoc = null;
private File dataDatFile;
private File datsDir;
private JTabbedPane areasPane;
private JScrollPane mainScroll;
@ -91,11 +94,11 @@ public class ModXMLSandbox extends JFrame implements ActionListener {
private JLabel statusLbl;
public ModXMLSandbox( File dataDatFile ) {
public ModXMLSandbox( File datsDir ) {
super( "Mod XML Sandbox" );
this.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
this.dataDatFile = dataDatFile;
this.datsDir = datsDir;
Font sandboxFont = new Font( "Monospaced", Font.PLAIN, 13 );
@ -319,17 +322,29 @@ public class ModXMLSandbox extends JFrame implements ActionListener {
private void open() {
messageArea.setText( "" );
FTLPack dataP = null;
AbstractPack pack = null;
InputStream is = null;
try {
dataP = new FTLPack( dataDatFile, "r" );
List<String> innerPaths = dataP.list();
File ftlDatFile = new File( datsDir, "ftl.dat" );
File dataDatFile = new File( datsDir, "data.dat" );
if ( ftlDatFile.exists() ) { // FTL 1.6.1.
pack = new PkgPack( ftlDatFile, "r" );
}
else if ( dataDatFile.exists() ) { // FTL 1.01-1.5.13.
pack = new FTLPack( dataDatFile, "r" );
}
else {
throw new FileNotFoundException( String.format( "Could not find either \"%s\" or \"%s\"", ftlDatFile.getName(), dataDatFile.getName() ) );
}
List<String> innerPaths = pack.list();
String innerPath = promptForInnerPath( innerPaths );
if ( innerPath == null ) return;
is = dataP.getInputStream( innerPath );
String mainText = ModUtilities.decodeText( is, dataDatFile.getName()+":"+innerPath ).text;
is = pack.getInputStream( innerPath );
String mainText = ModUtilities.decodeText( is, pack.getName()+":"+innerPath ).text;
is.close();
mainText = mainText.replaceFirst( "<[?]xml [^>]*?[?]>", "" );
@ -356,7 +371,7 @@ public class ModXMLSandbox extends JFrame implements ActionListener {
try {if ( is != null ) is.close();}
catch ( IOException f ) {}
try {if ( dataP != null ) dataP.close();}
try {if ( pack != null ) pack.close();}
catch ( IOException f ) {}
}
}