2024-04-10 03:35:27 -04:00
/ *
* Firestar Mod Manager
* Copyright ( C ) 2024 bonkmaykr
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see https : //www.gnu.org/licenses/.
* /
2024-04-21 14:37:17 -04:00
import javax.imageio.ImageIO ;
2024-04-10 04:49:21 -04:00
import javax.swing.* ;
2024-04-19 19:06:52 -04:00
import javax.swing.event.ListSelectionListener ;
2024-06-29 01:54:00 -04:00
import javax.swing.filechooser.FileNameExtensionFilter ;
2024-04-12 00:26:26 -04:00
import java.awt.* ;
2024-04-12 11:21:51 -04:00
import java.awt.event.ActionEvent ;
import java.awt.event.ActionListener ;
2024-04-21 14:37:17 -04:00
import java.awt.image.BufferedImage ;
2024-06-29 01:54:00 -04:00
import java.io.BufferedWriter ;
2024-04-19 19:06:52 -04:00
import java.io.File ;
2024-06-29 01:54:00 -04:00
import java.io.FileWriter ;
2024-04-21 14:37:17 -04:00
import java.io.IOException ;
2024-04-19 19:06:52 -04:00
import java.math.RoundingMode ;
2024-06-29 14:41:56 -04:00
import java.net.URI ;
import java.net.URISyntaxException ;
2024-05-07 01:47:43 -04:00
import java.nio.file.* ;
2024-04-19 19:06:52 -04:00
import java.text.DecimalFormat ;
2024-06-29 05:47:55 -04:00
import java.util.ArrayList ;
2024-05-07 05:26:40 -04:00
import java.util.Arrays ;
2024-06-29 12:56:35 -04:00
import java.util.Collections ;
import java.util.List ;
2024-06-29 01:54:00 -04:00
import java.util.Random ;
2024-05-07 05:26:40 -04:00
import java.util.regex.Pattern ;
2024-05-07 01:47:43 -04:00
import net.lingala.zip4j.* ;
2024-05-07 06:26:54 -04:00
import net.lingala.zip4j.exception.ZipException ;
2024-06-30 10:09:52 -04:00
import org.json.JSONException ;
2024-05-07 06:26:54 -04:00
import org.json.JSONObject ;
2024-06-29 01:54:00 -04:00
import static java.nio.file.StandardCopyOption.* ;
2024-04-12 11:21:51 -04:00
2024-04-12 00:26:26 -04:00
import static javax.swing.WindowConstants.EXIT_ON_CLOSE ;
2024-04-10 04:49:21 -04:00
2024-04-12 11:21:51 -04:00
public class MissPiggy implements ActionListener {
2024-04-21 14:37:17 -04:00
BufferedImage windowIcon ;
2024-04-12 00:26:26 -04:00
JFrame frame = new JFrame ( ) ;
JPanel frameContainer ;
JPanel actionsContainer ;
JPanel descriptionContainer ;
2024-04-12 11:21:51 -04:00
//JPanel menuBarContainerPanel = new JPanel();
public JMenuBar menuBar ;
public JMenu fileMenu ;
public JMenu toolsMenu ;
public JMenu helpMenu ;
//JMenuItem menuItem;
2024-04-12 00:26:26 -04:00
JScrollPane modListScrollContainer ;
2024-04-19 19:06:52 -04:00
public JList < String > modList ;
2024-04-12 00:26:26 -04:00
private JButton toggleButton ;
private JButton moveUpButton ;
private JButton deleteButton1 ;
private JButton moveDownButton ;
private JButton optionsButton ;
private JButton importButton ;
2024-04-12 11:21:51 -04:00
private JButton deployButton ;
2024-04-19 19:06:52 -04:00
private JTextPane descriptionField ;
2024-04-12 00:26:26 -04:00
2024-06-29 06:29:38 -04:00
//private int selectedItem;
2024-04-12 00:26:26 -04:00
2024-05-07 01:47:43 -04:00
public String priorityList ;
2024-06-29 15:23:21 -04:00
public String blackList ;
2024-05-07 01:47:43 -04:00
2024-06-29 12:56:35 -04:00
public boolean listenersAlreadySet = false ; // was written to troubleshoot a bug but this wasn't actually the cause
2024-04-12 00:26:26 -04:00
// Initialize the main window
public void Action ( /*Main entryPoint*/ ) {
2024-05-07 06:41:53 -04:00
System . out . println ( " Main window created " ) ;
2024-05-08 15:10:00 -04:00
System . out . println ( " Loading program configuration " ) ;
Main . loadConf ( this ) ;
2024-05-07 06:41:53 -04:00
// populate menu bar
2024-04-12 11:21:51 -04:00
menuBar = new JMenuBar ( ) ;
fileMenu = new JMenu ( " File " ) ;
toolsMenu = new JMenu ( " Tools " ) ;
helpMenu = new JMenu ( " Help " ) ;
2024-06-29 14:30:01 -04:00
fileMenu . add ( new JMenuItem ( " Deploy Mods " ) ) ;
fileMenu . add ( new JMenuItem ( " Import Mod from File " ) ) ;
2024-06-29 14:41:56 -04:00
//fileMenu.add(new JSeparator());
2024-06-29 14:30:01 -04:00
fileMenu . add ( new JMenuItem ( " Delete All " ) ) ;
2024-04-12 11:21:51 -04:00
fileMenu . add ( new JSeparator ( ) ) ;
fileMenu . add ( new JMenuItem ( " Options " ) ) ;
fileMenu . add ( new JMenuItem ( " Quit " ) ) ;
toolsMenu . add ( new JMenuItem ( " Edit Metadata " ) ) ; // disabled if a mod is not selected from the list
toolsMenu . add ( new JMenuItem ( " Generate New Mod from Folder... " ) ) ;
2024-05-07 01:47:43 -04:00
toolsMenu . add ( new JMenuItem ( " Create Soundtrack Mod... " ) ) ;
//toolsMenu.add(new JMenuItem("Download Mod from URL")); // TODO: implement. move option to File menu. should be ez
2024-04-12 11:21:51 -04:00
2024-06-30 16:23:46 -04:00
helpMenu . add ( new JMenuItem ( " Manual " ) ) ;
helpMenu . add ( new JSeparator ( ) ) ;
2024-06-29 14:41:56 -04:00
helpMenu . add ( new JMenuItem ( " Source Code " ) ) ; //replace with Website 'screwgravity.net' and 'Issue Tracker' gitea later
helpMenu . add ( new JMenuItem ( " License " ) ) ;
helpMenu . add ( new JSeparator ( ) ) ;
2024-04-12 11:21:51 -04:00
helpMenu . add ( new JMenuItem ( " About Firestar " ) ) ;
menuBar . add ( fileMenu ) ;
menuBar . add ( toolsMenu ) ;
menuBar . add ( helpMenu ) ;
menuBar . setVisible ( true ) ;
frame . setJMenuBar ( menuBar ) ;
2024-04-12 00:26:26 -04:00
frame . add ( frameContainer ) ; // initialize window contents -- will be handled by IntelliJ IDEA
2024-05-07 06:26:54 -04:00
InitializeModListStructure ( ) ;
2024-04-12 11:21:51 -04:00
InitializeModListInGUI ( ) ; // present mod list
2024-04-12 11:31:38 -04:00
fileMenu . getItem ( 0 ) . addActionListener ( this ) ;
fileMenu . getItem ( 1 ) . addActionListener ( this ) ;
2024-06-29 14:41:56 -04:00
fileMenu . getItem ( 2 ) . addActionListener ( this ) ;
fileMenu . getItem ( 4 ) . addActionListener ( this ) ;
2024-04-12 11:21:51 -04:00
fileMenu . getItem ( 5 ) . addActionListener ( this ) ;
2024-04-12 11:31:38 -04:00
toolsMenu . getItem ( 0 ) . addActionListener ( this ) ;
toolsMenu . getItem ( 1 ) . addActionListener ( this ) ;
2024-06-29 14:20:23 -04:00
toolsMenu . getItem ( 2 ) . addActionListener ( this ) ;
2024-04-12 11:31:38 -04:00
helpMenu . getItem ( 0 ) . addActionListener ( this ) ;
2024-06-30 16:23:46 -04:00
helpMenu . getItem ( 2 ) . addActionListener ( this ) ;
2024-06-29 14:41:56 -04:00
helpMenu . getItem ( 3 ) . addActionListener ( this ) ;
2024-06-30 16:23:46 -04:00
helpMenu . getItem ( 5 ) . addActionListener ( this ) ;
2024-06-29 01:54:00 -04:00
2024-05-08 15:10:00 -04:00
deployButton . addActionListener ( this ) ;
2024-06-29 01:54:00 -04:00
importButton . addActionListener ( this ) ;
deleteButton1 . addActionListener ( this ) ;
optionsButton . addActionListener ( this ) ;
moveUpButton . addActionListener ( this ) ;
moveDownButton . addActionListener ( this ) ;
toggleButton . addActionListener ( this ) ;
2024-04-12 11:21:51 -04:00
2024-04-19 19:06:52 -04:00
descriptionField . getDocument ( ) . putProperty ( " filterNewlines " , Boolean . FALSE ) ;
2024-04-12 11:21:51 -04:00
// display window
2024-04-21 14:37:17 -04:00
try {
windowIcon = ImageIO . read ( new File ( System . getProperty ( " user.dir " ) + " /resources/titleIcon.png " ) ) ;
frame . setIconImage ( windowIcon ) ;
} catch ( IOException e ) {
System . out . println ( " ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon. " ) ;
}
2024-04-12 00:26:26 -04:00
frame . setSize ( 800 , 600 ) ; // 1280 800
2024-04-19 19:06:52 -04:00
frame . setMinimumSize ( new Dimension ( 640 , 480 ) ) ;
2024-04-12 00:26:26 -04:00
frame . setTitle ( " Firestar Mod Manager " ) ;
frame . setResizable ( true ) ;
frame . setDefaultCloseOperation ( EXIT_ON_CLOSE ) ;
frame . setLayout ( new GridLayout ( ) ) ;
2024-04-13 11:04:35 -04:00
frame . setLocationRelativeTo ( null ) ;
2024-04-12 00:26:26 -04:00
frame . setVisible ( true ) ;
}
2024-05-07 06:26:54 -04:00
public void InitializeModListStructure ( ) {
2024-04-12 00:26:26 -04:00
// cleanup
2024-05-07 06:26:54 -04:00
Main . Mods . clear ( ) ;
2024-04-12 00:26:26 -04:00
2024-05-07 06:26:54 -04:00
// get current list of mods from file
// todo: rewrite when modpacks/playlists are added
2024-05-07 01:47:43 -04:00
try {
2024-05-07 05:26:40 -04:00
priorityList = new String ( Files . readAllBytes ( Paths . get ( System . getProperty ( " user.home " ) + " /.firestar/mods/index " ) ) ) ;
2024-05-07 01:47:43 -04:00
} catch ( IOException e ) {
2024-05-07 05:26:40 -04:00
File priorityListFileHandle = new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/index " ) ;
new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/ " ) . mkdirs ( ) ;
if ( ! priorityListFileHandle . isFile ( ) ) {
try {
priorityListFileHandle . createNewFile ( ) ;
} catch ( IOException ex ) {
throw new RuntimeException ( ex ) ;
}
}
2024-05-07 01:47:43 -04:00
priorityList = " " ;
}
2024-05-07 05:26:40 -04:00
// initialize data structures from each list entry
String [ ] pListArray = priorityList . split ( " \ n " ) ;
Arrays . sort ( pListArray ) ;
2024-05-07 06:26:54 -04:00
System . out . println ( " Initializing modList from file with length of " + pListArray . length + " units " ) ; //debug
2024-05-07 05:26:40 -04:00
for ( String s : pListArray ) {
2024-05-07 06:26:54 -04:00
/ *
Do nothing if the index number is not valid .
there probably is not a practical reason to do this , but I want to eliminate any undefined behaviors while we ' re here .
we ' ll also eliminate any syntax errors caused by the lack of a = sign
2024-06-29 01:54:00 -04:00
06 / 29 / 24 - also skip files that were manually removed but remain in the list
2024-05-07 06:26:54 -04:00
* /
2024-06-30 07:49:00 -04:00
2024-06-30 07:49:49 -04:00
File mod = new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/ " + s . substring ( s . indexOf ( " = " ) + 1 ) . trim ( ) ) ;
2024-06-30 07:49:00 -04:00
2024-06-29 01:54:00 -04:00
if ( s . split ( " = " ) [ 0 ] . matches ( " [0-9]+=* " ) & &
2024-06-30 07:49:00 -04:00
mod . exists ( ) ) {
2024-05-07 06:26:54 -04:00
//append mod to list from substring
Main . Mod m = new Main ( ) . new Mod ( ) ;
2024-06-30 07:58:15 -04:00
m . path = s . substring ( s . indexOf ( " = " ) + 1 ) . trim ( ) ;
2024-05-07 06:26:54 -04:00
System . out . println ( " found file " + m . path ) ;
//get json metadata from zip comment
JSONObject metadata ;
try {
2024-06-30 07:58:15 -04:00
metadata = new JSONObject ( new ZipFile ( System . getProperty ( " user.home " ) + " /.firestar/mods/ " + m . path ) . getComment ( ) ) ;
2024-06-29 01:54:00 -04:00
if ( metadata . has ( " friendlyName " ) ) { m . friendlyName = metadata . get ( " friendlyName " ) . toString ( ) ; } else { m . friendlyName = m . path ; }
if ( metadata . has ( " description " ) ) { m . description = metadata . get ( " description " ) . toString ( ) ; }
if ( metadata . has ( " version " ) ) { m . version = Integer . parseInt ( metadata . get ( " version " ) . toString ( ) ) ; }
if ( metadata . has ( " author " ) ) { m . author = metadata . get ( " author " ) . toString ( ) ; }
if ( metadata . has ( " loaderversion " ) ) { m . loaderversion = Integer . parseInt ( metadata . get ( " loaderversion " ) . toString ( ) ) ; }
if ( metadata . has ( " game " ) ) { m . game = metadata . get ( " game " ) . toString ( ) ; }
//send to list
Main . Mods . add ( m ) ;
} catch ( Exception e ) {
System . out . println ( " WARNING: mod entry for " + s + " was found but does not contain valid JSON metadata. skipping " ) ;
2024-06-30 07:49:00 -04:00
System . out . println ( e . getMessage ( ) ) ;
2024-05-07 06:26:54 -04:00
}
2024-06-29 01:54:00 -04:00
} else {
if ( ! s . isEmpty ( ) ) { System . out . println ( " WARNING: mod entry for " + s + " doesn't actually exist. skipping " ) ; }
2024-05-07 05:26:40 -04:00
}
}
2024-06-29 15:23:21 -04:00
try {
blackList = new String ( Files . readAllBytes ( Paths . get ( System . getProperty ( " user.home " ) + " /.firestar/mods/blacklist " ) ) ) ;
} catch ( IOException e ) {
File blackListFileHandle = new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/blacklist " ) ;
new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/ " ) . mkdirs ( ) ;
if ( ! blackListFileHandle . isFile ( ) ) {
try {
blackListFileHandle . createNewFile ( ) ;
} catch ( IOException ex ) {
throw new RuntimeException ( ex ) ;
}
}
blackList = " " ;
}
// initialize data structures from each list entry
String [ ] bListArray = blackList . split ( " \ n " ) ;
//Arrays.sort(bListArray);
System . out . println ( " Initializing blacklist from file with length of " + bListArray . length + " units " ) ; //debug
for ( String s : bListArray ) {
for ( Main . Mod m : Main . Mods ) {
2024-06-30 07:58:15 -04:00
if ( s . trim ( ) . equals ( m . path ) ) {
2024-06-29 15:23:21 -04:00
m . enabled = false ;
}
}
}
2024-05-07 06:26:54 -04:00
}
2024-06-29 12:56:35 -04:00
public void InitializeModListInGUI ( ) {
2024-05-07 06:26:54 -04:00
// cleanup
2024-06-29 12:56:35 -04:00
if ( listenersAlreadySet ) { modList . removeListSelectionListener ( modList . getListSelectionListeners ( ) [ 0 ] ) ; } // was written to troubleshoot a bug but this wasn't actually the cause
2024-05-07 06:26:54 -04:00
descriptionField . setText ( " Select a mod from the list on the right to view more details, or to make changes to your installation. " ) ;
modList . clearSelection ( ) ;
modList . removeAll ( ) ;
modList . setVisibleRowCount ( Main . Mods . size ( ) ) ;
modList . setSelectionMode ( ListSelectionModel . SINGLE_SELECTION ) ;
2024-05-07 05:26:40 -04:00
2024-04-12 00:26:26 -04:00
// add text entry for each
int i = 0 ;
2024-04-19 18:00:20 -04:00
/*JLabel[]*/ String [ ] contents = new String [ Main . Mods . size ( ) ] ;
2024-04-21 14:37:17 -04:00
System . out . println ( " Initializing modList to GUI with length of " + Main . Mods . size ( ) + " units " ) ; //debug
2024-04-12 00:26:26 -04:00
while ( i < Main . Mods . size ( ) ) {
2024-06-29 15:23:21 -04:00
if ( Main . Mods . get ( i ) . enabled ) { contents [ i ] = Main . Mods . get ( i ) . friendlyName ; }
else { contents [ i ] = Main . Mods . get ( i ) . friendlyName + " (Disabled) " ; }
2024-04-12 00:26:26 -04:00
//debug
2024-04-19 19:06:52 -04:00
String authorDisplay ;
if ( Main . Mods . get ( i ) . author = = null ) { authorDisplay = " Anonymous " ; } else { authorDisplay = " \" " + Main . Mods . get ( i ) . author + " \" " ; }
System . out . println ( " Added " + Main . Mods . get ( i ) . friendlyName + " by " + authorDisplay ) ;
2024-04-10 04:49:21 -04:00
2024-04-12 00:26:26 -04:00
i + + ;
}
2024-04-19 18:00:20 -04:00
modList . setListData ( contents ) ;
2024-06-29 06:54:04 -04:00
createSelectionEventListener ( ) ;
2024-04-10 03:35:27 -04:00
}
2024-04-12 11:21:51 -04:00
2024-04-19 19:06:52 -04:00
private ListSelectionListener whenItemSelected ( ) {
return null ;
}
2024-04-12 11:21:51 -04:00
@Override
public void actionPerformed ( ActionEvent actionEvent ) {
2024-06-29 14:41:56 -04:00
if ( actionEvent . getSource ( ) = = fileMenu . getItem ( 5 ) ) { System . exit ( 0 ) ; } else
2024-04-12 11:31:38 -04:00
if ( actionEvent . getSource ( ) = = fileMenu . getItem ( 0 ) ) { deployModGUI ( ) ; } else
2024-05-08 15:10:00 -04:00
if ( actionEvent . getSource ( ) = = deployButton ) { deployModGUI ( ) ; } else
2024-06-29 01:54:00 -04:00
if ( actionEvent . getSource ( ) = = importButton ) { importModGUI ( ) ; } else
2024-04-12 11:31:38 -04:00
if ( actionEvent . getSource ( ) = = fileMenu . getItem ( 1 ) ) { importModGUI ( ) ; } else
2024-06-29 14:41:56 -04:00
if ( actionEvent . getSource ( ) = = fileMenu . getItem ( 2 ) ) { removeAllGUI ( ) ; } else
2024-06-29 01:54:00 -04:00
if ( actionEvent . getSource ( ) = = optionsButton ) { optionsGUI ( ) ; } else
2024-06-29 14:41:56 -04:00
if ( actionEvent . getSource ( ) = = fileMenu . getItem ( 4 ) ) { optionsGUI ( ) ; } else
2024-06-29 01:54:00 -04:00
2024-06-29 12:56:35 -04:00
if ( actionEvent . getSource ( ) = = moveUpButton ) { moveUp ( modList . getSelectedIndex ( ) ) ; } else
if ( actionEvent . getSource ( ) = = moveDownButton ) { moveDown ( modList . getSelectedIndex ( ) ) ; } else
2024-06-29 15:23:21 -04:00
if ( actionEvent . getSource ( ) = = toggleButton ) { toggleSelected ( modList . getSelectedIndex ( ) ) ; } else
2024-06-29 12:56:35 -04:00
if ( actionEvent . getSource ( ) = = deleteButton1 ) { deleteSelected ( ) ; } else
2024-06-29 01:54:00 -04:00
2024-06-29 14:20:23 -04:00
if ( actionEvent . getSource ( ) = = toolsMenu . getItem ( 0 ) ) { throwUnimplemented ( ) ; } else
if ( actionEvent . getSource ( ) = = toolsMenu . getItem ( 1 ) ) { throwUnimplemented ( ) ; } else
if ( actionEvent . getSource ( ) = = toolsMenu . getItem ( 2 ) ) { throwUnimplemented ( ) ; } else
2024-06-29 14:41:56 -04:00
if ( actionEvent . getSource ( ) = = helpMenu . getItem ( 0 ) ) {
2024-06-30 16:23:46 -04:00
try {
Desktop . getDesktop ( ) . browse ( new URI ( " https://git.worlio.com/bonkmaykr/firestar/wiki/ " ) ) ;
} catch ( Exception e ) {
System . out . println ( e . getMessage ( ) ) ;
JOptionPane . showMessageDialog ( frame , e . getMessage ( ) , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
} else
if ( actionEvent . getSource ( ) = = helpMenu . getItem ( 2 ) ) {
2024-06-29 14:41:56 -04:00
try {
Desktop . getDesktop ( ) . browse ( new URI ( " https://git.worlio.com/bonkmaykr/firestar " ) ) ;
} catch ( Exception e ) {
System . out . println ( e . getMessage ( ) ) ;
JOptionPane . showMessageDialog ( frame , e . getMessage ( ) , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
} else
2024-06-30 16:23:46 -04:00
if ( actionEvent . getSource ( ) = = helpMenu . getItem ( 3 ) ) {
2024-06-29 14:41:56 -04:00
try {
Desktop . getDesktop ( ) . browse ( new URI ( " https://www.gnu.org/licenses/gpl-3.0.en.html " ) ) ;
} catch ( Exception e ) {
System . out . println ( e . getMessage ( ) ) ;
JOptionPane . showMessageDialog ( frame , e . getMessage ( ) , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
} else
2024-06-30 16:23:46 -04:00
if ( actionEvent . getSource ( ) = = helpMenu . getItem ( 5 ) ) { new Rowlf ( ) . displayAboutScreen ( ) ; }
2024-04-12 11:31:38 -04:00
}
// Will likely split the below functions into separate classes to work with intellij GUI designer.
public void deployModGUI ( ) {
2024-06-29 15:23:21 -04:00
int i = 0 ;
for ( Main . Mod m : Main . Mods ) {
if ( m . enabled ) { i + + ; }
}
if ( i > 0 ) {
int result = JOptionPane . showConfirmDialog ( frame , " A new PSARC will be generated. This can take several minutes. \ nDuring this time, your computer may be very busy or slow. \ n \ nAre you sure you want to continue? " , " Deploy Mods " , JOptionPane . YES_NO_OPTION , JOptionPane . QUESTION_MESSAGE ) ;
if ( result = = JOptionPane . YES_OPTION ) {
// prevent interruptions
frame . setDefaultCloseOperation ( WindowConstants . DO_NOTHING_ON_CLOSE ) ;
frame . setEnabled ( false ) ;
2024-05-07 09:44:26 -04:00
2024-06-29 15:23:21 -04:00
// start
new Gonzo ( ) . DeployMods ( this ) ;
}
} else {
JOptionPane . showMessageDialog ( frame , " Please add at least one mod file to continue. " , " Error " , JOptionPane . ERROR_MESSAGE ) ;
2024-06-29 14:30:01 -04:00
}
2024-05-07 09:44:26 -04:00
}
public void wrapUpDeployment ( ) {
// restore functionality to main window
frame . setDefaultCloseOperation ( EXIT_ON_CLOSE ) ;
frame . setEnabled ( true ) ;
2024-04-12 11:31:38 -04:00
}
public void importModGUI ( ) {
2024-06-28 17:11:15 -04:00
JFileChooser fileChooser = new JFileChooser ( ) ;
fileChooser . setCurrentDirectory ( new File ( System . getProperty ( " user.home " ) ) ) ;
2024-06-29 01:54:00 -04:00
//fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("All", "zip", "agr", "agrc", "agrf", "fstar"));
fileChooser . addChoosableFileFilter ( new FileNameExtensionFilter ( " ZIP Archive " , " zip " ) ) ;
2024-06-30 10:11:02 -04:00
fileChooser . addChoosableFileFilter ( new FileNameExtensionFilter ( " Firestar Mod Package " , " fstar " ) ) ;
2024-06-29 01:54:00 -04:00
2024-06-28 17:11:15 -04:00
int result = fileChooser . showOpenDialog ( frame ) ;
if ( result = = JFileChooser . APPROVE_OPTION ) {
File selectedFile = fileChooser . getSelectedFile ( ) ;
System . out . println ( " Importing selected mod file \" " + selectedFile . getName ( ) + " \" " ) ;
2024-06-30 10:09:52 -04:00
ZipFile zipImporterHandler = new ZipFile ( selectedFile . getAbsolutePath ( ) ) ;
2024-06-28 17:11:15 -04:00
if ( zipImporterHandler . isValidZipFile ( ) ) {
2024-06-29 01:54:00 -04:00
try {
2024-06-30 10:09:52 -04:00
new JSONObject ( new ZipFile ( selectedFile . getAbsolutePath ( ) ) . getComment ( ) ) ; // intentionally trigger exception if file is random BS
2024-06-29 01:54:00 -04:00
Path importDestination = Paths . get ( System . getProperty ( " user.home " ) + " /.firestar/mods/ "
+ selectedFile . getName ( ) + " _ " + Main . Mods . size ( ) + " .zip " ) ;
Files . copy ( Paths . get ( selectedFile . getPath ( ) ) , importDestination , StandardCopyOption . REPLACE_EXISTING ) ;
String importDestinationName = importDestination . toFile ( ) . getName ( ) ;
BufferedWriter bw = new BufferedWriter ( new FileWriter ( System . getProperty ( " user.home " ) + " /.firestar/mods/index " , true ) ) ;
bw . write ( Main . Mods . size ( ) + " = " + importDestinationName ) ;
bw . newLine ( ) ;
bw . close ( ) ;
InitializeModListStructure ( ) ;
InitializeModListInGUI ( ) ;
2024-06-30 10:09:52 -04:00
} catch ( JSONException e ) {
System . out . println ( " ERROR: File is not a valid ZIP archive with mod data. Aborting. " ) ;
JOptionPane . showMessageDialog ( frame , " Whoops, that's not a valid mod file. " , " Error " , JOptionPane . ERROR_MESSAGE ) ;
2024-06-29 01:54:00 -04:00
} catch ( Exception e ) {
System . out . println ( e . getMessage ( ) ) ;
JOptionPane . showMessageDialog ( frame , " An error has occured. \ n " + e . getMessage ( ) , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
2024-06-28 17:11:15 -04:00
} else {
2024-06-30 10:09:52 -04:00
System . out . println ( " ERROR: File is not a valid ZIP archive with mod data. Aborting. " ) ;
JOptionPane . showMessageDialog ( frame , " Whoops, that's not a valid mod file. " , " Error " , JOptionPane . ERROR_MESSAGE ) ;
2024-06-28 17:11:15 -04:00
}
}
2024-04-12 11:31:38 -04:00
}
public void removeAllGUI ( ) {
// todo warning dialog that nukes list when Yes is clicked
2024-06-29 05:47:55 -04:00
int result = JOptionPane . showConfirmDialog ( frame , " Do you really want to delete all mods? " , " Remove All " , JOptionPane . YES_NO_OPTION , JOptionPane . WARNING_MESSAGE ) ;
if ( result = = JOptionPane . YES_OPTION ) {
2024-06-30 08:15:48 -04:00
Main . deleteDir ( new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/ " ) ) ;
2024-06-29 14:30:01 -04:00
Main . Mods . clear ( ) ;
InitializeModListStructure ( ) ;
InitializeModListInGUI ( ) ;
}
2024-04-12 11:31:38 -04:00
}
public void optionsGUI ( ) {
2024-06-30 10:51:03 -04:00
new Waldorf ( ) . Action ( this ) ;
frame . setEnabled ( false ) ;
2024-04-12 11:31:38 -04:00
}
2024-06-29 06:29:38 -04:00
public void deleteSelected ( ) {
2024-06-29 14:20:23 -04:00
if ( modList . getSelectedIndex ( ) > = 0 ) {
File file = new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/ " + Main . Mods . get ( modList . getSelectedIndex ( ) ) . path ) ;
file . delete ( ) ;
System . out . println ( " Deleted " + Main . Mods . get ( modList . getSelectedIndex ( ) ) . friendlyName ) ; //debug
Main . Mods . remove ( modList . getSelectedIndex ( ) ) ;
regenerateModIndex ( true ) ;
} else {
JOptionPane . showMessageDialog ( frame , " Please select a mod to delete first. " , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
2024-06-29 06:29:38 -04:00
}
2024-04-12 11:31:38 -04:00
public void generatorGUI ( ) {
// todo mod packer
2024-06-29 01:55:16 -04:00
throwUnimplemented ( ) ;
2024-04-12 11:31:38 -04:00
}
public void metaEditorGUI ( ) {
// todo tag editor
2024-06-29 01:55:16 -04:00
throwUnimplemented ( ) ;
2024-04-12 11:31:38 -04:00
}
2024-06-29 12:56:35 -04:00
private void moveUp ( int index ) {
if ( index > 0 ) {
Collections . swap ( Main . Mods , index , index - 1 ) ;
System . out . println ( " Items moved, redeploying list " ) ;
InitializeModListInGUI ( ) ;
regenerateModIndex ( false ) ;
}
}
private void moveDown ( int index ) {
if ( index < ( Main . Mods . size ( ) - 1 ) ) {
Collections . swap ( Main . Mods , index , index + 1 ) ;
System . out . println ( " Items moved, redeploying list " ) ;
InitializeModListInGUI ( ) ;
regenerateModIndex ( false ) ;
}
}
2024-06-29 15:23:21 -04:00
private void toggleSelected ( int index ) {
if ( index > = 0 ) {
Main . Mods . get ( index ) . enabled = ! Main . Mods . get ( index ) . enabled ;
regenerateModBlacklist ( true ) ;
} else {
JOptionPane . showMessageDialog ( frame , " Please select a mod to toggle first. " , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
}
2024-06-29 01:54:00 -04:00
public void throwUnimplemented ( ) {
2024-06-29 13:14:26 -04:00
JOptionPane . showMessageDialog ( frame , " This feature is unimplemented and will be coming soon. \ nSee README at https://git.worlio.com/bonkmaykr/firestar " , " Unimplemented " , JOptionPane . INFORMATION_MESSAGE ) ;
2024-04-12 11:21:51 -04:00
}
2024-06-29 06:54:04 -04:00
public void createSelectionEventListener ( ) { // moved incase needs to be removed and re-added
2024-06-29 12:56:35 -04:00
listenersAlreadySet = true ; // was written to troubleshoot a bug but this wasn't actually the cause
2024-06-29 06:54:04 -04:00
modList . addListSelectionListener ( e - > {
2024-06-29 12:56:35 -04:00
if ( modList . getSelectedIndex ( ) > = 0 & & modList . getModel ( ) . getSize ( ) > = 1 ) { // avoid race OOB when reinitializing mod list
2024-06-29 06:54:04 -04:00
String authorDisplay ;
2024-06-29 13:04:21 -04:00
try { //debug
2024-06-30 07:58:15 -04:00
File pathReference = new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/ " + Main . Mods . get ( modList . getSelectedIndex ( ) ) . path ) ;
2024-06-29 06:54:04 -04:00
DecimalFormat df = new DecimalFormat ( " ##.## " ) ;
df . setRoundingMode ( RoundingMode . UP ) ;
float modFileSize = pathReference . length ( ) ; //precise units
String modFileSizeStr = String . valueOf ( modFileSize ) ;
String modFileSizeUnits = " bytes " ; //todo: don't show decimals for bytes
if ( pathReference . length ( ) > = 1024 ) {
modFileSizeStr = String . valueOf ( df . format ( modFileSize / 1024 ) ) ;
modFileSizeUnits = " Kilobytes " ;
}
if ( pathReference . length ( ) > = 1024 * 1024 ) {
modFileSizeStr = String . valueOf ( df . format ( modFileSize / ( 1024 * 1024 ) ) ) ;
modFileSizeUnits = " Megabytes " ;
}
if ( pathReference . length ( ) > = 1024 * 1024 * 1024 ) {
modFileSizeStr = String . valueOf ( df . format ( modFileSize / ( 1024 * 1024 * 1024 ) ) ) ;
modFileSizeUnits = " Gigabytes " ;
}
if ( Main . Mods . get ( modList . getSelectedIndex ( ) ) . author = = null ) {
authorDisplay = " an Unknown Author " ;
} else {
authorDisplay = Main . Mods . get ( modList . getSelectedIndex ( ) ) . author ;
}
descriptionField . setText (
" \" " + Main . Mods . get ( modList . getSelectedIndex ( ) ) . friendlyName + " \" \ n " +
" by " + authorDisplay + " \ n \ n " +
" Version " + Main . Mods . get ( modList . getSelectedIndex ( ) ) . version + " \ n " +
modFileSizeStr + " " + modFileSizeUnits + " in size " +
" \ n \ n " + Main . Mods . get ( modList . getSelectedIndex ( ) ) . description
) ; }
2024-06-29 13:04:21 -04:00
catch ( IndexOutOfBoundsException ex ) {
System . out . println ( ex . getMessage ( ) ) ;
System . out . println ( " mods " + Main . Mods . size ( ) ) ;
System . out . println ( " mod display " + modList . getModel ( ) . getSize ( ) ) ;
System . out . println ( " selection index " + modList . getSelectedIndex ( ) ) ;
2024-06-29 13:10:01 -04:00
int result = JOptionPane . showConfirmDialog ( frame , " Firestar encountered an internal error. \ n " + ex . getMessage ( ) , " Fatal Error " , JOptionPane . DEFAULT_OPTION , JOptionPane . ERROR_MESSAGE ) ;
if ( result = = JOptionPane . OK_OPTION ) { System . exit ( 1 ) ; } //user safety
2024-06-29 13:04:21 -04:00
}
}
2024-06-29 06:54:04 -04:00
} ) ;
}
2024-06-29 10:46:02 -04:00
2024-06-29 12:56:35 -04:00
public void regenerateModIndex ( boolean reload ) {
2024-06-29 10:46:02 -04:00
try {
System . out . println ( " Regenerating index... " ) ; //debug
new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/index " ) . delete ( ) ;
File priorityListFileHandle = new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/index " ) ;
priorityListFileHandle . createNewFile ( ) ;
BufferedWriter bw = new BufferedWriter ( new FileWriter ( System . getProperty ( " user.home " ) + " /.firestar/mods/index " , true ) ) ;
int i = 0 ;
for ( Main . Mod m : Main . Mods ) {
bw . write ( i + " = " + m . path ) ;
2024-06-29 12:56:35 -04:00
bw . newLine ( ) ;
2024-06-29 10:46:02 -04:00
i + + ;
}
bw . close ( ) ;
2024-06-29 15:23:21 -04:00
System . out . println ( " Mod index file regenerated. " ) ;
2024-06-29 10:46:02 -04:00
2024-06-29 12:56:35 -04:00
if ( reload ) {
2024-06-29 13:04:21 -04:00
Main . Mods . clear ( ) ; //cleanup
priorityList = " " ;
2024-06-29 12:56:35 -04:00
InitializeModListStructure ( ) ;
InitializeModListInGUI ( ) ;
}
2024-06-29 15:23:21 -04:00
} catch ( Exception e ) {
System . out . println ( e . getMessage ( ) ) ;
JOptionPane . showMessageDialog ( frame , " An error has occured. \ n " + e . getMessage ( ) , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
}
public void regenerateModBlacklist ( boolean reload ) {
try {
System . out . println ( " Regenerating blacklist... " ) ; //debug
new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/blacklist " ) . delete ( ) ;
File blackListFileHandle = new File ( System . getProperty ( " user.home " ) + " /.firestar/mods/blacklist " ) ;
blackListFileHandle . createNewFile ( ) ;
BufferedWriter bw2 = new BufferedWriter ( new FileWriter ( System . getProperty ( " user.home " ) + " /.firestar/mods/blacklist " , true ) ) ;
int i2 = 0 ;
for ( Main . Mod m : Main . Mods ) {
if ( ! m . enabled ) {
bw2 . write ( m . path ) ;
bw2 . newLine ( ) ;
i2 + + ;
}
}
bw2 . close ( ) ;
System . out . println ( " Mod blacklist file regenerated. " ) ;
if ( reload ) {
Main . Mods . clear ( ) ; //cleanup
blackList = " " ;
InitializeModListStructure ( ) ;
InitializeModListInGUI ( ) ;
}
2024-06-29 10:46:02 -04:00
} catch ( Exception e ) {
System . out . println ( e . getMessage ( ) ) ;
JOptionPane . showMessageDialog ( frame , " An error has occured. \ n " + e . getMessage ( ) , " Error " , JOptionPane . ERROR_MESSAGE ) ;
}
}
2024-04-10 03:35:27 -04:00
}