THE MEGA-FORMATTING COMMIT! TABS RULE, SPACES DROOL

This commit is contained in:
Wirlaburla 2024-07-22 18:19:38 -05:00
parent 6e292212fd
commit 408a52512b
15 changed files with 3084 additions and 3093 deletions

View File

@ -26,254 +26,254 @@ import java.io.*;
import java.util.ArrayList; import java.util.ArrayList;
public class Bert implements ActionListener { public class Bert implements ActionListener {
public JFrame frame = new JFrame(); public JFrame frame = new JFrame();
private JPanel frameContainer; private JPanel frameContainer;
private JButton cancelbtn; private JButton cancelbtn;
private JButton downloadbtn; private JButton downloadbtn;
private JCheckBox patchCheck; private JCheckBox patchCheck;
private JCheckBox baseCheck; private JCheckBox baseCheck;
private JCheckBox hdCheck; private JCheckBox hdCheck;
private JCheckBox furyCheck; private JCheckBox furyCheck;
private ButtonGroup radios = new ButtonGroup(); private ButtonGroup radios = new ButtonGroup();
private JFrame invoker; private JFrame invoker;
private boolean wilkinsDownloadFinished = false; private boolean wilkinsDownloadFinished = false;
public Bert(JFrame parent) { public Bert(JFrame parent) {
parent.setEnabled(false); parent.setEnabled(false);
this.invoker = parent; this.invoker = parent;
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
frame.setSize(600, 300); // 1280 800 frame.setSize(600, 300); // 1280 800
frame.setTitle("Download Assets"); frame.setTitle("Download Assets");
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(parent); frame.setLocationRelativeTo(parent);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
cancelbtn.addActionListener(this); cancelbtn.addActionListener(this);
downloadbtn.addActionListener(this); downloadbtn.addActionListener(this);
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
frame.setVisible(true); frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) public void windowClosing(WindowEvent e)
{ {
parent.setEnabled(true); parent.setEnabled(true);
e.getWindow().dispose(); e.getWindow().dispose();
} }
}); });
if (!new File(Main.inpath + "pkg2zip.exe").exists() || !new File(Main.inpath + "psvpfsparser.exe").exists()) { if (!new File(Main.inpath + "pkg2zip.exe").exists() || !new File(Main.inpath + "psvpfsparser.exe").exists()) {
JOptionPane.showMessageDialog(frame, "The decryption tool is missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "The decryption tool is missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
invoker.setEnabled(true); invoker.setEnabled(true);
frame.dispose(); frame.dispose();
} }
} }
public boolean reportWhenDownloaded(WilkinsCoffee setup) { public boolean reportWhenDownloaded(WilkinsCoffee setup) {
while (frame.isActive() || !wilkinsDownloadFinished) {} while (frame.isActive() || !wilkinsDownloadFinished) {}
if (wilkinsDownloadFinished) { // intellij please shut the everloving FUCK up DON'T do this again or i will skin you alive if (wilkinsDownloadFinished) { // intellij please shut the everloving FUCK up DON'T do this again or i will skin you alive
return true; return true;
} else { } else {
return false; return false;
} }
} }
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent.getSource() == cancelbtn) { if (actionEvent.getSource() == cancelbtn) {
invoker.setEnabled(true); invoker.setEnabled(true);
frame.dispose(); frame.dispose();
} else if (actionEvent.getSource() == downloadbtn) { } else if (actionEvent.getSource() == downloadbtn) {
ArrayList<Main.ArcTarget> arcs = new ArrayList<Main.ArcTarget>(); ArrayList<Main.ArcTarget> arcs = new ArrayList<Main.ArcTarget>();
ArrayList<Main.ArcKey> keys = new ArrayList<Main.ArcKey>(); ArrayList<Main.ArcKey> keys = new ArrayList<Main.ArcKey>();
if (baseCheck.isSelected()) { if (baseCheck.isSelected()) {
arcs.add(Main.ArcTarget.BASE); arcs.add(Main.ArcTarget.BASE);
keys.add(Main.ArcKey.BASE); keys.add(Main.ArcKey.BASE);
System.out.println("Begin download of data (Game version 1.0)"); System.out.println("Begin download of data (Game version 1.0)");
} }
if (patchCheck.isSelected()) { if (patchCheck.isSelected()) {
arcs.add(Main.ArcTarget.LATEST); arcs.add(Main.ArcTarget.LATEST);
keys.add(Main.ArcKey.LATEST); keys.add(Main.ArcKey.LATEST);
System.out.println("Begin download of data2 (Game version 1.04)"); System.out.println("Begin download of data2 (Game version 1.04)");
} }
if (hdCheck.isSelected()) { if (hdCheck.isSelected()) {
arcs.add(Main.ArcTarget.ADDON_HD); arcs.add(Main.ArcTarget.ADDON_HD);
keys.add(Main.ArcKey.ADDON_HD); keys.add(Main.ArcKey.ADDON_HD);
System.out.println("Begin download of dlc1 (HD DLC)"); System.out.println("Begin download of dlc1 (HD DLC)");
} }
if (furyCheck.isSelected()) { if (furyCheck.isSelected()) {
arcs.add(Main.ArcTarget.ADDON_HD_FURY); arcs.add(Main.ArcTarget.ADDON_HD_FURY);
keys.add(Main.ArcKey.ADDON_HD_FURY); keys.add(Main.ArcKey.ADDON_HD_FURY);
System.out.println("Begin download of dlc2 (Fury DLC)"); System.out.println("Begin download of dlc2 (Fury DLC)");
} }
if (arcs.isEmpty()) { if (arcs.isEmpty()) {
JOptionPane.showMessageDialog(invoker, "Select one or more asset packs.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(invoker, "Select one or more asset packs.", "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
frame.dispose(); frame.dispose();
invoker.setVisible(false); invoker.setVisible(false);
Thread downloaderPopupThread = new Thread(new Runnable() { // run on separate thread to prevent GUI freezing Thread downloaderPopupThread = new Thread(new Runnable() { // run on separate thread to prevent GUI freezing
@Override @Override
public void run() { public void run() {
for (Main.ArcTarget type : arcs) { for (Main.ArcTarget type : arcs) {
String key = ""; String key = "";
String arcname = ""; String arcname = "";
switch (type) { switch (type) {
case BASE : case BASE :
key = Main.ArcKey.BASE.toString(); key = Main.ArcKey.BASE.toString();
arcname = "Base game"; arcname = "Base game";
break; break;
case LATEST : case LATEST :
key = Main.ArcKey.LATEST.toString(); key = Main.ArcKey.LATEST.toString();
arcname = "Updates"; arcname = "Updates";
break; break;
case ADDON_HD : case ADDON_HD :
key = Main.ArcKey.ADDON_HD.toString(); key = Main.ArcKey.ADDON_HD.toString();
arcname = "HD Add-On Pack"; arcname = "HD Add-On Pack";
break; break;
case ADDON_HD_FURY : case ADDON_HD_FURY :
key = Main.ArcKey.ADDON_HD_FURY.toString(); key = Main.ArcKey.ADDON_HD_FURY.toString();
arcname = "Fury Add-On Pack"; arcname = "Fury Add-On Pack";
break; break;
} }
if (key.isEmpty()) { if (key.isEmpty()) {
System.out.println("Internal Error: Bert got dementia. Get a programmer!"); System.out.println("Internal Error: Bert got dementia. Get a programmer!");
JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
// download file // download file
Fozzie downloaderHandler = new Fozzie(); Fozzie downloaderHandler = new Fozzie();
boolean downloader = downloaderHandler.DownloadFile(type.toString(), Main.inpath, "asset.pkg", arcname); boolean downloader = downloaderHandler.DownloadFile(type.toString(), Main.inpath, "asset.pkg", arcname);
if (!downloader) { if (!downloader) {
// cleanup // cleanup
new File(Main.inpath + "asset.pkg").delete(); new File(Main.inpath + "asset.pkg").delete();
// restore controls // restore controls
invoker.setEnabled(true); invoker.setEnabled(true);
invoker.setVisible(true); invoker.setVisible(true);
invoker.toFront(); invoker.toFront();
invoker.repaint(); invoker.repaint();
return; return;
} }
// dump contents // dump contents
System.out.println("Extracting " + arcname); System.out.println("Extracting " + arcname);
Fozzie popup = new Fozzie(); Fozzie popup = new Fozzie();
popup.displayTextOnly("Extracting " + arcname + "...", "Extracting"); popup.displayTextOnly("Extracting " + arcname + "...", "Extracting");
try { try {
Process p = Main.exec(new String[]{"pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath); Process p = Main.exec(new String[]{"pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath);
InputStream debugin = new BufferedInputStream(p.getInputStream()); InputStream debugin = new BufferedInputStream(p.getInputStream());
OutputStream debugout = new BufferedOutputStream(System.out); OutputStream debugout = new BufferedOutputStream(System.out);
int c; int c;
while ((c = debugin.read()) != -1) { while ((c = debugin.read()) != -1) {
debugout.write(c); debugout.write(c);
} }
debugin.close(); debugin.close();
debugout.close(); debugout.close();
p.waitFor(); p.waitFor();
} catch (Exception e) { } catch (Exception e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
new File(Main.inpath + "asset.pkg").delete(); new File(Main.inpath + "asset.pkg").delete();
invoker.setEnabled(true); invoker.setEnabled(true);
invoker.setVisible(true); invoker.setVisible(true);
invoker.toFront(); invoker.toFront();
invoker.repaint(); invoker.repaint();
return; return;
} }
// decrypt // decrypt
System.out.println("Decrypting asset.pkg"); System.out.println("Decrypting asset.pkg");
String extracted; String extracted;
String name; String name;
if (type == Main.ArcTarget.BASE) { if (type == Main.ArcTarget.BASE) {
extracted = "app/PCSA00015"; extracted = "app/PCSA00015";
name = "data.psarc"; name = "data.psarc";
} else if (type == Main.ArcTarget.LATEST) { } else if (type == Main.ArcTarget.LATEST) {
extracted = "patch/PCSA00015"; extracted = "patch/PCSA00015";
name = "data2.psarc"; name = "data2.psarc";
} else if (type == Main.ArcTarget.ADDON_HD) { } else if (type == Main.ArcTarget.ADDON_HD) {
extracted = "addcont/PCSA00015/DLC1W2048PACKAGE"; extracted = "addcont/PCSA00015/DLC1W2048PACKAGE";
name = "dlc1.psarc"; name = "dlc1.psarc";
} else if (type == Main.ArcTarget.ADDON_HD_FURY) { // this is not "always true" - intellij is actually very dumj } else if (type == Main.ArcTarget.ADDON_HD_FURY) { // this is not "always true" - intellij is actually very dumj
extracted = "addcont/PCSA00015/DLC2W2048PACKAGE"; extracted = "addcont/PCSA00015/DLC2W2048PACKAGE";
name = "dlc2.psarc"; name = "dlc2.psarc";
} else { } else {
System.out.println("Internal Error: Bert got dementia. Get a programmer!"); System.out.println("Internal Error: Bert got dementia. Get a programmer!");
JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
new File(Main.inpath + "asset.pkg").delete(); new File(Main.inpath + "asset.pkg").delete();
Main.deleteDir(new File(Main.inpath + "app/")); Main.deleteDir(new File(Main.inpath + "app/"));
Main.deleteDir(new File(Main.inpath + "patch/")); Main.deleteDir(new File(Main.inpath + "patch/"));
Main.deleteDir(new File(Main.inpath + "addcont/")); Main.deleteDir(new File(Main.inpath + "addcont/"));
invoker.setEnabled(true); invoker.setEnabled(true);
invoker.setVisible(true); invoker.setVisible(true);
invoker.toFront(); invoker.toFront();
invoker.repaint(); invoker.repaint();
return; return;
} }
popup.setText("<html>Decrypting protected PFS:<br/>" + extracted + "</html>", "Decrypting"); popup.setText("<html>Decrypting protected PFS:<br/>" + extracted + "</html>", "Decrypting");
try { try {
Process p = Main.exec(new String[]{"psvpfsparser.exe", "-i", extracted, "-o", "./temp/", "-z", key.toString(), "-f", "cma.henkaku.xyz"}, Main.inpath); Process p = Main.exec(new String[]{"psvpfsparser.exe", "-i", extracted, "-o", "./temp/", "-z", key.toString(), "-f", "cma.henkaku.xyz"}, Main.inpath);
InputStream debugin = new BufferedInputStream(p.getInputStream()); InputStream debugin = new BufferedInputStream(p.getInputStream());
OutputStream debugout = new BufferedOutputStream(System.out); OutputStream debugout = new BufferedOutputStream(System.out);
int c; int c;
while ((c = debugin.read()) != -1) { while ((c = debugin.read()) != -1) {
debugout.write(c); debugout.write(c);
} }
debugin.close(); debugin.close();
debugout.close(); debugout.close();
p.waitFor(); p.waitFor();
} catch (Exception e) { } catch (Exception e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
new File(Main.inpath + "asset.pkg").delete(); new File(Main.inpath + "asset.pkg").delete();
Main.deleteDir(new File(Main.inpath + "app/")); Main.deleteDir(new File(Main.inpath + "app/"));
Main.deleteDir(new File(Main.inpath + "patch/")); Main.deleteDir(new File(Main.inpath + "patch/"));
Main.deleteDir(new File(Main.inpath + "addcont/")); Main.deleteDir(new File(Main.inpath + "addcont/"));
invoker.setEnabled(true); invoker.setEnabled(true);
invoker.setVisible(true); invoker.setVisible(true);
invoker.toFront(); invoker.toFront();
invoker.repaint(); invoker.repaint();
return; return;
} }
popup.setText("Deleting temporary files...", "Cleaning Up"); popup.setText("Deleting temporary files...", "Cleaning Up");
// stage & cleanup // stage & cleanup
System.out.println("Cleaning up"); System.out.println("Cleaning up");
new File(Main.inpath + "asset.pkg").delete(); new File(Main.inpath + "asset.pkg").delete();
new File(Main.inpath + "temp/PSP2/" + name).renameTo(new File(Main.inpath + name)); new File(Main.inpath + "temp/PSP2/" + name).renameTo(new File(Main.inpath + name));
Main.deleteDir(new File(Main.inpath + "app/")); Main.deleteDir(new File(Main.inpath + "app/"));
Main.deleteDir(new File(Main.inpath + "patch/")); Main.deleteDir(new File(Main.inpath + "patch/"));
Main.deleteDir(new File(Main.inpath + "addcont/")); Main.deleteDir(new File(Main.inpath + "addcont/"));
Main.deleteDir(new File(Main.inpath + "temp/")); Main.deleteDir(new File(Main.inpath + "temp/"));
popup.destroyDialog(); popup.destroyDialog();
} }
// restore controls // restore controls
JOptionPane.showMessageDialog(frame, "Assets downloaded successfully.", "Download Complete", JOptionPane.INFORMATION_MESSAGE); JOptionPane.showMessageDialog(frame, "Assets downloaded successfully.", "Download Complete", JOptionPane.INFORMATION_MESSAGE);
invoker.setEnabled(true); invoker.setEnabled(true);
invoker.setVisible(true); invoker.setVisible(true);
invoker.toFront(); invoker.toFront();
invoker.repaint(); invoker.repaint();
wilkinsDownloadFinished = true; wilkinsDownloadFinished = true;
} }
}); });
downloaderPopupThread.start(); downloaderPopupThread.start();
} }
} }
} }

View File

@ -33,217 +33,217 @@ import java.util.ArrayList;
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE; import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
public class Clifford implements ActionListener { public class Clifford implements ActionListener {
private JFrame frame = new JFrame(); private JFrame frame = new JFrame();
private JPanel frameContainer; private JPanel frameContainer;
private JTextField fName; private JTextField fName;
private JTextField fAuthor; private JTextField fAuthor;
private JTextField fVersion; private JTextField fVersion;
private JTextPane fDescription; private JTextPane fDescription;
private JButton savebtn; private JButton savebtn;
private JButton cancelbtn; private JButton cancelbtn;
JFrame invoker; JFrame invoker;
MissPiggy invokerPig; MissPiggy invokerPig;
boolean isPig = false; boolean isPig = false;
Main.Mod mod; Main.Mod mod;
int index; int index;
File directory; File directory;
boolean isSoundtrack = false; boolean isSoundtrack = false;
boolean creating; boolean creating;
public void Action(MissPiggy inv, int modindex) { public void Action(MissPiggy inv, int modindex) {
invokerPig = inv; invokerPig = inv;
invoker = invokerPig.frame; invoker = invokerPig.frame;
mod = Main.Mods.get(modindex); mod = Main.Mods.get(modindex);
index = modindex; index = modindex;
creating = false; creating = false;
isPig = true; isPig = true;
Action(invoker, modindex); Action(invoker, modindex);
} }
public void Action(MissPiggy inv, File dir) { public void Action(MissPiggy inv, File dir) {
invokerPig = inv; invokerPig = inv;
invoker = invokerPig.frame; invoker = invokerPig.frame;
directory = dir; directory = dir;
creating = true; creating = true;
isPig = true; isPig = true;
Action(invoker, dir); Action(invoker, dir);
} }
public void Action(JFrame inv, int modindex) { // Editor public void Action(JFrame inv, int modindex) { // Editor
invoker = inv; invoker = inv;
mod = Main.Mods.get(modindex); mod = Main.Mods.get(modindex);
index = modindex; index = modindex;
creating = false; creating = false;
frame.add(frameContainer); frame.add(frameContainer);
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
frame.setSize(600, 300); // 1280 800 frame.setSize(600, 300); // 1280 800
frame.setMinimumSize(new Dimension(200,100)); frame.setMinimumSize(new Dimension(200,100));
frame.setTitle("Options"); frame.setTitle("Options");
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(inv); frame.setLocationRelativeTo(inv);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
fName.setText(mod.friendlyName); fName.setText(mod.friendlyName);
fAuthor.setText(mod.author); fAuthor.setText(mod.author);
fVersion.setText(String.valueOf(mod.version)); fVersion.setText(String.valueOf(mod.version));
fDescription.setText(mod.description); fDescription.setText(mod.description);
cancelbtn.addActionListener(this); cancelbtn.addActionListener(this);
savebtn.addActionListener(this); savebtn.addActionListener(this);
frame.setVisible(true); frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) public void windowClosing(WindowEvent e)
{ {
invoker.setEnabled(true); invoker.setEnabled(true);
e.getWindow().dispose(); e.getWindow().dispose();
} }
}); });
} }
public void Action(JFrame inv, File dir) { // Generator public void Action(JFrame inv, File dir) { // Generator
invoker = inv; invoker = inv;
directory = dir; directory = dir;
creating = true; creating = true;
frame.add(frameContainer); frame.add(frameContainer);
frame.setSize(600, 200); // 1280 800 frame.setSize(600, 200); // 1280 800
frame.setMinimumSize(new Dimension(200,100)); frame.setMinimumSize(new Dimension(200,100));
frame.setTitle("Options"); frame.setTitle("Options");
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(null); frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
cancelbtn.addActionListener(this); cancelbtn.addActionListener(this);
savebtn.addActionListener(this); savebtn.addActionListener(this);
frame.setVisible(true); frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) public void windowClosing(WindowEvent e)
{ {
Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen
invoker.setEnabled(true); invoker.setEnabled(true);
e.getWindow().dispose(); e.getWindow().dispose();
} }
}); });
} }
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent.getSource() == cancelbtn) { if (actionEvent.getSource() == cancelbtn) {
Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen
invoker.setEnabled(true); invoker.setEnabled(true);
frame.dispose(); frame.dispose();
} else if (actionEvent.getSource() == savebtn && !creating) { } else if (actionEvent.getSource() == savebtn && !creating) {
try { try {
mod.version = Integer.parseInt(fVersion.getText()); mod.version = Integer.parseInt(fVersion.getText());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
mod.friendlyName = fName.getText(); mod.friendlyName = fName.getText();
mod.author = fAuthor.getText(); mod.author = fAuthor.getText();
mod.description = fDescription.getText(); mod.description = fDescription.getText();
JSONObject container = new JSONObject(); JSONObject container = new JSONObject();
if (mod.friendlyName.isEmpty()) { if (mod.friendlyName.isEmpty()) {
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
container.put("version", mod.version); container.put("version", mod.version);
container.put("friendlyName", mod.friendlyName); container.put("friendlyName", mod.friendlyName);
container.put("author", mod.author); container.put("author", mod.author);
container.put("description", mod.description); container.put("description", mod.description);
container.put("loaderversion", mod.loaderversion); container.put("loaderversion", mod.loaderversion);
container.put("game", mod.game); container.put("game", mod.game);
try { try {
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + mod.path.trim()).setComment(container.toString()); new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + mod.path.trim()).setComment(container.toString());
} catch (ZipException e) { } catch (ZipException e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
} }
Main.Mods.set(index, mod); Main.Mods.set(index, mod);
invoker.setEnabled(true); invoker.setEnabled(true);
if (isPig) {invokerPig.InitializeModListInGUI();} if (isPig) {invokerPig.InitializeModListInGUI();}
frame.dispose(); frame.dispose();
} else if (actionEvent.getSource() == savebtn && creating) { } else if (actionEvent.getSource() == savebtn && creating) {
if (fName.getText().isEmpty()) { if (fName.getText().isEmpty()) {
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
try { try {
Integer.parseInt(fVersion.getText()); Integer.parseInt(fVersion.getText());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileFilter(new FileNameExtensionFilter("Firestar Mod Package", "fstar")); fileChooser.setFileFilter(new FileNameExtensionFilter("Firestar Mod Package", "fstar"));
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) { if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
ZipFile zip = new ZipFile(fileChooser.getSelectedFile()); ZipFile zip = new ZipFile(fileChooser.getSelectedFile());
boolean hasScript = false; boolean hasScript = false;
try { try {
zip.addFolder(new File(directory.getAbsolutePath() + "/data")); zip.addFolder(new File(directory.getAbsolutePath() + "/data"));
if (new File(directory.getAbsolutePath() + "/delete.txt").exists()) { if (new File(directory.getAbsolutePath() + "/delete.txt").exists()) {
zip.addFile(new File(directory.getAbsolutePath() + "/delete.txt")); zip.addFile(new File(directory.getAbsolutePath() + "/delete.txt"));
} }
if (new File(directory.getAbsolutePath() + "/pack.png").exists()) { if (new File(directory.getAbsolutePath() + "/pack.png").exists()) {
zip.addFile(new File(directory.getAbsolutePath() + "/pack.png")); zip.addFile(new File(directory.getAbsolutePath() + "/pack.png"));
} }
if (new File(directory.getAbsolutePath() + "/fscript").exists()) { if (new File(directory.getAbsolutePath() + "/fscript").exists()) {
zip.addFile(new File(directory.getAbsolutePath() + "/fscript")); zip.addFile(new File(directory.getAbsolutePath() + "/fscript"));
hasScript = true; hasScript = true;
} }
JSONObject container = new JSONObject(); JSONObject container = new JSONObject();
container.put("version", Integer.parseInt(fVersion.getText())); container.put("version", Integer.parseInt(fVersion.getText()));
container.put("friendlyName", fName.getText()); container.put("friendlyName", fName.getText());
container.put("author", fAuthor.getText()); container.put("author", fAuthor.getText());
container.put("description", fDescription.getText()); container.put("description", fDescription.getText());
// todo later versions: handle logic for setting this depending on the fscript version too. // todo later versions: handle logic for setting this depending on the fscript version too.
// firestar 1.3 can't generate any version other than v1 so this is not necessary right now, but will become necessary when fscript features are added. // firestar 1.3 can't generate any version other than v1 so this is not necessary right now, but will become necessary when fscript features are added.
if (hasScript) { if (hasScript) {
container.put("loaderversion", 1); container.put("loaderversion", 1);
if (isSoundtrack) { if (isSoundtrack) {
ArrayList<boolean[]> requiresTemp = new ArrayList<>(); ArrayList<boolean[]> requiresTemp = new ArrayList<>();
requiresTemp.add(new boolean[]{false, true, false, false}); requiresTemp.add(new boolean[]{false, true, false, false});
requiresTemp.add(new boolean[]{true, false, false, false}); requiresTemp.add(new boolean[]{true, false, false, false});
container.put("requires", requiresTemp); // Pull localization files for patching. container.put("requires", requiresTemp); // Pull localization files for patching.
} }
} else { } else {
container.put("loaderversion", 0); container.put("loaderversion", 0);
} }
container.put("game", "2048"); container.put("game", "2048");
zip.setComment(container.toString()); zip.setComment(container.toString());
zip.close(); zip.close();
} catch (Exception e) { } catch (Exception e) {
fileChooser.getSelectedFile().delete(); //cleanup fileChooser.getSelectedFile().delete(); //cleanup
System.out.println(e.getMessage()); System.out.println(e.getMessage());
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
JOptionPane.showMessageDialog(frame, "Mod file created", "Success", JOptionPane.INFORMATION_MESSAGE); JOptionPane.showMessageDialog(frame, "Mod file created", "Success", JOptionPane.INFORMATION_MESSAGE);
Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen
invoker.setEnabled(true); invoker.setEnabled(true);
frame.dispose(); frame.dispose();
} }
} }
} }
} }

View File

@ -44,147 +44,145 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
public class Ernie implements ActionListener { public class Ernie implements ActionListener {
// Base URL for Gitea API // Base URL for Gitea API
public static final String gitapi = "https://git.worlio.com/api/v1/repos/bonkmaykr/firestar"; public static final String gitapi = "https://git.worlio.com/api/v1/repos/bonkmaykr/firestar";
public static final String changelog = "https://bonkmaykr.worlio.com/http/firestar/changelog.htm"; public static final String changelog = "https://bonkmaykr.worlio.com/http/firestar/changelog.htm";
private HttpURLConnection httpConn; private HttpURLConnection httpConn;
private int contentLength; private int contentLength;
private InputStream inputStream; private InputStream inputStream;
private JFrame frame = new JFrame(); private JFrame frame = new JFrame();
private JPanel frameContainer; private JPanel frameContainer;
private JEditorPane changelogDisplay; private JEditorPane changelogDisplay;
private JButton notnowbtn; private JButton notnowbtn;
private JButton surebtn; private JButton surebtn;
public boolean backgroundDone = false; public boolean backgroundDone = false;
private JFrame parent; private JFrame parent;
public Ernie(JFrame parent) { public Ernie(JFrame parent) {
this.parent = parent; this.parent = parent;
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
byte[] urlraw = getFile(gitapi+"/releases?draft=false&pre-release=false"); byte[] urlraw = getFile(gitapi+"/releases?draft=false&pre-release=false");
if (urlraw.length <= 0) { if (urlraw.length <= 0) {
JOptionPane.showMessageDialog(frame, "Internal Error: Couldn't check for updates.", "Fatal Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Internal Error: Couldn't check for updates.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
} else { } else {
try { try {
JSONArray releases = new JSONArray(new String(urlraw, Charset.forName("utf-8"))); JSONArray releases = new JSONArray(new String(urlraw, Charset.forName("utf-8")));
System.out.println("Updater: latest release is " + ((JSONObject)releases.get(0)).get("tag_name")); System.out.println("Updater: latest release is " + ((JSONObject)releases.get(0)).get("tag_name"));
if (releases.length() >= 1 && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag)) { if (releases.length() >= 1 && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag)) {
System.out.println("Updater: Your version is out of date."); System.out.println("Updater: Your version is out of date.");
frame.add(frameContainer); frame.add(frameContainer);
notnowbtn.addActionListener(this); notnowbtn.addActionListener(this);
surebtn.addActionListener(this); surebtn.addActionListener(this);
changelogDisplay.setEditable(false); changelogDisplay.setEditable(false);
changelogDisplay.setPage(changelog); changelogDisplay.setPage(changelog);
changelogDisplay.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf?? changelogDisplay.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf??
frame.setTitle("An update is available!"); frame.setTitle("An update is available!");
frame.setSize(450, 400); frame.setSize(450, 400);
frame.setResizable(false); frame.setResizable(false);
frame.setLocationRelativeTo(parent); frame.setLocationRelativeTo(parent);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
parent.setEnabled(false); parent.setEnabled(false);
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) public void windowClosing(WindowEvent e)
{ {
parent.setEnabled(true); parent.setEnabled(true);
e.getWindow().dispose(); e.getWindow().dispose();
} }
}); });
frame.setVisible(true); frame.setVisible(true);
} else { System.out.println("Updater: No updates."); } } else { System.out.println("Updater: No updates."); }
} catch (IOException ex) { } catch (IOException | JSONException ex) {
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
} catch (JSONException ex) { }
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent.getSource() == notnowbtn) {
parent.setEnabled(true);
frame.dispose();
} else
if (actionEvent.getSource() == surebtn) {
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
String releasepage = "https://git.worlio.com/bonkmaykr/firestar/releases";
try {
Desktop.getDesktop().browse(new URI(releasepage));
parent.setEnabled(true);
frame.dispose();
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Couldn't open your web browser!\nYou can check out the latest release at the URL below:\n"+releasepage, "Error", JOptionPane.ERROR_MESSAGE);
} }
}
} }
}
byte[] getFile(String url) { @Override
try { public void actionPerformed(ActionEvent actionEvent) {
URL fileURL = new URL(url); if (actionEvent.getSource() == notnowbtn) {
httpConn = (HttpURLConnection) fileURL.openConnection(); parent.setEnabled(true);
int response = httpConn.getResponseCode(); frame.dispose();
} else
if (actionEvent.getSource() == surebtn) {
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
String releasepage = "https://git.worlio.com/bonkmaykr/firestar/releases";
try {
Desktop.getDesktop().browse(new URI(releasepage));
parent.setEnabled(true);
frame.dispose();
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Couldn't open your web browser!\nYou can check out the latest release at the URL below:\n"+releasepage, "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
if (response == HttpURLConnection.HTTP_OK) { byte[] getFile(String url) {
contentLength = httpConn.getContentLength(); try {
inputStream = httpConn.getInputStream(); URL fileURL = new URL(url);
} else if (response == 404) { httpConn = (HttpURLConnection) fileURL.openConnection();
throw new IOException( int response = httpConn.getResponseCode();
"File missing from remote server.");
} else {
throw new IOException(
"Unexpected response; Server replied with " + response);
}
ErnieDownloader ed = new ErnieDownloader(this, url, httpConn.getContentLength());
ed.doInBackground();
while (!backgroundDone) {}
inputStream.close(); if (response == HttpURLConnection.HTTP_OK) {
httpConn.disconnect(); contentLength = httpConn.getContentLength();
frame.dispose(); inputStream = httpConn.getInputStream();
return ed.output; } else if (response == 404) {
} catch (MalformedURLException e) { throw new IOException(
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Ernie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE); "File missing from remote server.");
frame.dispose(); } else {
return new byte[]{}; throw new IOException(
} catch (Exception e) { "Unexpected response; Server replied with " + response);
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE); }
frame.dispose(); ErnieDownloader ed = new ErnieDownloader(this, url, httpConn.getContentLength());
return new byte[]{}; ed.doInBackground();
} while (!backgroundDone) {}
}
inputStream.close();
httpConn.disconnect();
frame.dispose();
return ed.output;
} catch (MalformedURLException e) {
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Ernie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.dispose();
return new byte[]{};
} catch (Exception e) {
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.dispose();
return new byte[]{};
}
}
} }
class ErnieDownloader extends SwingWorker<Void, Void> { class ErnieDownloader extends SwingWorker<Void, Void> {
private static final int BUFFER_SIZE = 4096; private static final int BUFFER_SIZE = 4096;
private String downloadURL; private String downloadURL;
private final Ernie gui; private final Ernie gui;
public byte[] output; public byte[] output;
public ErnieDownloader(Ernie gui, String downloadURL, long size) { public ErnieDownloader(Ernie gui, String downloadURL, long size) {
this.gui = gui; this.gui = gui;
this.downloadURL = downloadURL; this.downloadURL = downloadURL;
} }
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream()); BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] data = new byte[16384]; byte[] data = new byte[16384];
int x; int x;
while ((x = in.read(data, 0, data.length)) != -1) { while ((x = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, x); buffer.write(data, 0, x);
}
output = buffer.toByteArray();
in.close();
gui.backgroundDone = true;
return null;
} }
output = buffer.toByteArray();
in.close();
gui.backgroundDone = true;
return null;
}
} }

View File

@ -16,17 +16,16 @@
* along with this program. If not, see https://www.gnu.org/licenses/. * along with this program. If not, see https://www.gnu.org/licenses/.
*/ */
public class FirescriptFormatException extends Exception { public class FirescriptFormatException extends Exception {
public FirescriptFormatException() { public FirescriptFormatException() {
super(); super();
} }
public FirescriptFormatException(String msg) { public FirescriptFormatException(String msg) {
super(msg); super(msg);
} }
public FirescriptFormatException(String cmd, String msg) { public FirescriptFormatException(String cmd, String msg) {
super(cmd + ": " + msg); super(cmd + ": " + msg);
} }
} }

View File

@ -24,151 +24,151 @@ import java.net.URL;
import java.net.*; import java.net.*;
public class Fozzie { public class Fozzie {
private JFrame frame = new JFrame(); private JFrame frame = new JFrame();
public JProgressBar progressBar; public JProgressBar progressBar;
private JPanel frameContainer; private JPanel frameContainer;
private JLabel label; private JLabel label;
private HttpURLConnection httpConn; private HttpURLConnection httpConn;
private int contentLength; private int contentLength;
private InputStream inputStream; private InputStream inputStream;
public boolean backgroundDone = false; public boolean backgroundDone = false;
boolean DownloadFile(String url, String odir, String oname) { boolean DownloadFile(String url, String odir, String oname) {
return DownloadFile(url, odir, oname, oname); return DownloadFile(url, odir, oname, oname);
} }
boolean DownloadFile(String url, String odir, String oname, String dname) { boolean DownloadFile(String url, String odir, String oname, String dname) {
frame.add(frameContainer); frame.add(frameContainer);
frame.setSize(300, 100); frame.setSize(300, 100);
frame.setTitle("Download in Progress"); frame.setTitle("Download in Progress");
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(null); frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
frame.setVisible(true); frame.setVisible(true);
label.setText("Downloading \"" + dname + "\""); label.setText("Downloading \"" + dname + "\"");
try { try {
URL fileURL = new URL(url); URL fileURL = new URL(url);
httpConn = (HttpURLConnection) fileURL.openConnection(); httpConn = (HttpURLConnection) fileURL.openConnection();
int response = httpConn.getResponseCode(); int response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) { if (response == HttpURLConnection.HTTP_OK) {
String disposition = httpConn.getHeaderField("Content-Disposition"); String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType(); String contentType = httpConn.getContentType();
contentLength = httpConn.getContentLength(); contentLength = httpConn.getContentLength();
inputStream = httpConn.getInputStream(); inputStream = httpConn.getInputStream();
} else if (response == 404) { } else if (response == 404) {
throw new IOException( throw new IOException(
"File missing from remote server."); "File missing from remote server.");
} else { } else {
throw new IOException( throw new IOException(
"Unexpected response; Server replied with " + response); "Unexpected response; Server replied with " + response);
} }
new FozzieDownloader(this, url, odir, oname, httpConn.getContentLength()).doInBackground(); new FozzieDownloader(this, url, odir, oname, httpConn.getContentLength()).doInBackground();
while (!backgroundDone) {} while (!backgroundDone) {}
inputStream.close(); inputStream.close();
httpConn.disconnect(); httpConn.disconnect();
frame.dispose(); frame.dispose();
return true; return true;
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Fozzie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Fozzie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.dispose(); frame.dispose();
return false; return false;
} catch (Exception e) { } catch (Exception e) {
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.dispose(); frame.dispose();
return false; return false;
} }
} }
public void displayTextOnly(String text, String title) { public void displayTextOnly(String text, String title) {
frame.add(frameContainer); frame.add(frameContainer);
frame.setSize(300, 100); frame.setSize(300, 100);
frame.setTitle(title); frame.setTitle(title);
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(null); frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
frame.setVisible(true); frame.setVisible(true);
label.setText(text); label.setText(text);
progressBar.setVisible(false); progressBar.setVisible(false);
} }
public void setText(String text, String title) { public void setText(String text, String title) {
label.setText(text); label.setText(text);
frame.setTitle(title); frame.setTitle(title);
} }
public void destroyDialog() { public void destroyDialog() {
frame.setVisible(false); frame.setVisible(false);
frame.dispose(); frame.dispose();
} }
public void disconnect() throws IOException { public void disconnect() throws IOException {
inputStream.close(); inputStream.close();
httpConn.disconnect(); httpConn.disconnect();
} }
public int getContentLength() { public int getContentLength() {
return this.contentLength; return this.contentLength;
} }
public InputStream getInputStream() { public InputStream getInputStream() {
return this.inputStream; return this.inputStream;
} }
} }
class FozzieDownloader extends SwingWorker<Void, Void> { class FozzieDownloader extends SwingWorker<Void, Void> {
private static final int BUFFER_SIZE = 4096; private static final int BUFFER_SIZE = 4096;
private String downloadURL; private String downloadURL;
private String saveDirectory; private String saveDirectory;
private String saveName; private String saveName;
private final Fozzie gui; private final Fozzie gui;
private final long completeSize; private final long completeSize;
public FozzieDownloader(Fozzie gui, String downloadURL, String saveDirectory, String saveName, long size) { public FozzieDownloader(Fozzie gui, String downloadURL, String saveDirectory, String saveName, long size) {
this.gui = gui; this.gui = gui;
this.downloadURL = downloadURL; this.downloadURL = downloadURL;
this.saveDirectory = saveDirectory; this.saveDirectory = saveDirectory;
this.saveName = saveName; this.saveName = saveName;
this.completeSize = size; this.completeSize = size;
} }
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
long downloadedSize = 0; long downloadedSize = 0;
File downloadLocationDir = new File(saveDirectory); File downloadLocationDir = new File(saveDirectory);
File downloadLocation = new File(saveDirectory + "/" + saveName); File downloadLocation = new File(saveDirectory + "/" + saveName);
downloadLocationDir.mkdirs(); downloadLocationDir.mkdirs();
if (!downloadLocation.isFile()) { if (!downloadLocation.isFile()) {
downloadLocation.createNewFile(); downloadLocation.createNewFile();
} }
BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream()); BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream());
FileOutputStream fos = new FileOutputStream(saveDirectory + "/" + saveName); FileOutputStream fos = new FileOutputStream(saveDirectory + "/" + saveName);
BufferedOutputStream out = new BufferedOutputStream(fos,1024); BufferedOutputStream out = new BufferedOutputStream(fos,1024);
byte[] data = new byte[1024]; byte[] data = new byte[1024];
int x = 0; int x = 0;
while ((x = in.read(data,0,1024))>=0) { while ((x = in.read(data,0,1024))>=0) {
downloadedSize += x; downloadedSize += x;
int progress = (int) ((((double)downloadedSize) / ((double)completeSize)) * 100d); int progress = (int) ((((double)downloadedSize) / ((double)completeSize)) * 100d);
gui.progressBar.setValue(progress); gui.progressBar.setValue(progress);
out.write(data, 0, x); out.write(data, 0, x);
} }
out.close(); out.close();
in.close(); in.close();
gui.backgroundDone = true; gui.backgroundDone = true;
return null; return null;
} }
} }

View File

@ -16,9 +16,6 @@
* along with this program. If not, see https://www.gnu.org/licenses/. * along with this program. If not, see https://www.gnu.org/licenses/.
*/ */
import com.github.difflib.DiffUtils;
import com.github.difflib.UnifiedDiffUtils;
import com.github.difflib.patch.Patch;
import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.ZipFile;
import javax.swing.*; import javax.swing.*;
@ -35,337 +32,331 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
public class Gonzo { public class Gonzo {
JFrame frame = new JFrame(); JFrame frame = new JFrame();
private JPanel frameContainer; private JPanel frameContainer;
private JTextArea consoleDisplay; private JTextArea consoleDisplay;
private JScrollPane scrollPane; private JScrollPane scrollPane;
public boolean data0; public boolean data0;
public boolean data1; public boolean data1;
public boolean data2; public boolean data2;
public boolean dlc1; public boolean dlc1;
public boolean dlc2; public boolean dlc2;
private MissPiggy invoker; private MissPiggy invoker;
public String oArcTarget = "dlc2.psarc"; // which psarc to rebuild the assets in public String oArcTarget = "dlc2.psarc"; // which psarc to rebuild the assets in
// TODO 1.3: Implement requires boolean[] from Main.Mod // TODO 1.3: Implement requires boolean[] from Main.Mod
// Rework system to choose the last PSARC and then add more before it when called by requires[] // Rework system to choose the last PSARC and then add more before it when called by requires[]
// Instead of the current system where it simply grabs them all and bloats the file. // Instead of the current system where it simply grabs them all and bloats the file.
// //
// EDIT: requires[] is now an arraylist of booleans[], each a supported minimum combination of PSARCs. // EDIT: requires[] is now an arraylist of booleans[], each a supported minimum combination of PSARCs.
// if any one of them is met, gonzo may continue // if any one of them is met, gonzo may continue
// for example: // for example:
// [false, true, false, false], [true, false, false, false] // user only needs either base psarc or patches PSARC, one or the other (having both is OK) // [false, true, false, false], [true, false, false, false] // user only needs either base psarc or patches PSARC, one or the other (having both is OK)
// [true, true, false, false] // user needs both base and patches // [true, true, false, false] // user needs both base and patches
// [false, false, true, true] // user needs the HD DLC and the Fury DLC // [false, false, true, true] // user needs the HD DLC and the Fury DLC
// //
// if none is found, assume "new boolean[]{false, false, false, false}" (no PSARCs required) // if none is found, assume "new boolean[]{false, false, false, false}" (no PSARCs required)
// (at least one of any 4 psarcs will already be checked for by MissPiggy so this is an okay way to implement it.) // (at least one of any 4 psarcs will already be checked for by MissPiggy so this is an okay way to implement it.)
public void DeployMods(MissPiggy inv) { public void DeployMods(MissPiggy inv) {
invoker = inv; invoker = inv;
System.out.println("\n\nStarting mod deployment\n\n"); System.out.println("\n\nStarting mod deployment\n\n");
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
frame.setSize(800, 400); frame.setSize(800, 400);
frame.setMinimumSize(new Dimension(600,400)); frame.setMinimumSize(new Dimension(600,400));
frame.setTitle("Mod Installation"); frame.setTitle("Mod Installation");
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(inv.frame); frame.setLocationRelativeTo(inv.frame);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
frame.setVisible(true); frame.setVisible(true);
File psarcHandle = new File(Main.inpath + "data.psarc"); File psarcHandle = new File(Main.inpath + "data.psarc");
data0 = psarcHandle.isFile(); data0 = psarcHandle.isFile();
psarcHandle = new File(Main.inpath + "data1.psarc"); psarcHandle = new File(Main.inpath + "data1.psarc");
data1 = psarcHandle.isFile(); data1 = psarcHandle.isFile();
psarcHandle = new File(Main.inpath + "data2.psarc"); psarcHandle = new File(Main.inpath + "data2.psarc");
data2 = psarcHandle.isFile(); data2 = psarcHandle.isFile();
psarcHandle = new File(Main.inpath + "dlc1.psarc"); psarcHandle = new File(Main.inpath + "dlc1.psarc");
dlc1 = psarcHandle.isFile(); dlc1 = psarcHandle.isFile();
psarcHandle = new File(Main.inpath + "dlc2.psarc"); psarcHandle = new File(Main.inpath + "dlc2.psarc");
dlc2 = psarcHandle.isFile(); dlc2 = psarcHandle.isFile();
System.out.println("Source files discovered: data " + data0 + ", data1 " + data1 + ", data2 " + data2 + ", dlc1 " + dlc1 + ", dlc2 " + dlc2); System.out.println("Source files discovered: data " + data0 + ", data1 " + data1 + ", data2 " + data2 + ", dlc1 " + dlc1 + ", dlc2 " + dlc2);
final Thread managerThread = new Thread() { final Thread managerThread = new Thread() {
@Override @Override
public void run() { public void run() {
if (/*Main.repatch*/true) { //todo implement fast mode correctly or remove if (/*Main.repatch*/true) { //todo implement fast mode correctly or remove
CompatibilityRoutine(); CompatibilityRoutine();
} else { } else {
FastRoutine(); FastRoutine();
} }
} }
}; };
managerThread.start(); managerThread.start();
}
private void CompatibilityRoutine() {
// create temporary working area for asset dump
new File(System.getProperty("user.home") + "/.firestar/temp/").mkdirs();
// decide which files to dump
List<String> dumpThese = new ArrayList<String>();
if (data0) {dumpThese.add("data.psarc");oArcTarget = "data.psarc";}
if (data1) {dumpThese.add("data1.psarc");oArcTarget = "data1.psarc";}
if (data2) {dumpThese.add("data2.psarc");oArcTarget = "data2.psarc";}
if (dlc1) {dumpThese.add("dlc1.psarc");oArcTarget = "dlc1.psarc";}
if (dlc2) {dumpThese.add("dlc2.psarc");oArcTarget = "dlc2.psarc";}
// dump all assets to working area
for (String s : dumpThese) {
try {
System.out.println("Firestar is extracting " + s);
consoleDisplay.append("Firestar is extracting " + s + "\n");
//Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","aplay /home/bonkyboo/kittens_loop.wav"}); // DEBUG
Process p = Main.exec(new String[]{"../psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
final Thread ioThread = new Thread() {
@Override
public void run() {
try {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
consoleDisplay.append(line + "\n");
try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition. You can safely ignore this.\n" + e.getMessage());}
}
reader.close();
} catch (final Exception e) {
e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
}
}
};
ioThread.start();
p.waitFor();
} catch (IOException | InterruptedException e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
}
// overwrite assets with custom ones from each mod and/or perform operations as specified in mod's delete list
// todo: implement RegEx functions after delete.txt
for (Main.Mod m : Main.Mods) {
if (m.enabled) {
try {
System.out.println("Firestar is extracting " + m.friendlyName + " by " + m.author);
consoleDisplay.append("Firestar is extracting " + m.friendlyName + " by " + m.author + "\n");
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + m.path).extractAll(System.getProperty("user.home") + "/.firestar/temp/");
File fscript = new File(Main.inpath + "temp/fscript");
if (fscript.exists()) {
new Rizzo(new FileInputStream(fscript), Main.inpath + "temp/"); // Lets rizz this mod up
fscript.delete();
}
if (new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").isFile()) {
System.out.println("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author);
consoleDisplay.append("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author + "\n");
String deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/temp/delete.txt")));
if (Main.windows) {deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "\\.firestar\\temp\\delete.txt")));} // might be unnecessary
String[] dQarray = deleteQueue.split("\n");
Arrays.sort(dQarray);
System.out.println("The deletion queue is " + dQarray.length + " files long!"); //debug
for (String file : dQarray) {
if(file.contains("..")) { //todo: is this safe enough?
System.out.println("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!");
consoleDisplay.append("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!\n");
} else {
if (!Main.windows) {
System.out.println("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file);
consoleDisplay.append("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file + "\n");
new File(System.getProperty("user.home") + "/.firestar/temp/data" + file).delete();}
else {
System.out.println("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\"));
consoleDisplay.append("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\") + "\n");
new File(new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\")).delete();
}
}
}
// cleanup so we don't run it again for the next mod unless needed
// this is not necessary but good practice
new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").delete();
}
} catch (Exception e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
}
}
// Post fscript changes
try (InputStream is = Main.class.getResourceAsStream("/post.fscript")) {
new Rizzo(is, Main.inpath + "temp/");
} catch (IOException | FirescriptFormatException e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
} }
// create a list of the contents of data/ for psp2psarc.exe to read from private void CompatibilityRoutine() {
List<String> oFilesList = new ArrayList<String>(); // create temporary working area for asset dump
List<String> oFilesList2 = new ArrayList<String>(); new File(System.getProperty("user.home") + "/.firestar/temp/").mkdirs();
try {
listAllFiles(Paths.get(System.getProperty("user.home") + "/.firestar/temp/data/"), oFilesList);
for (String p : oFilesList) {
// We need to clean up the path here on Linux to avoid psp2psarc getting confused about where the hell "/" is.
// In WINE it should see it as Z: by default, but if it's somewhere else then I don't have an elegant way of knowing what drive letter it's on, so
// relative paths are kind of the only choice here. This can be extended to Windows too as it works there, though completely unnecessary.
if (!Main.windows) {oFilesList2.add(p.replace("\\", "/").split(new String(System.getProperty("user.home") + "/.firestar/temp/"))[1]);}
else {oFilesList2.add(p.split(new String(System.getProperty("user.home") + "\\.firestar\\temp\\").replace("\\", "\\\\"))[1]);} // path wont match regex unless adjusted for windows here
}
//oFilesList2.forEach(System.out::println); //debug
File oFilesListO = new File(System.getProperty("user.home") + "/.firestar/temp/list.txt");
if (oFilesListO.isFile()) {oFilesListO.delete();}
FileWriter oFilesListWr = new FileWriter(oFilesListO, true);
int i = 0;
for (String p : oFilesList2) {
oFilesListWr.append(p);
if (i != oFilesList2.size()) {
oFilesListWr.append("\n");
}
i++;
}
oFilesListWr.close();
} catch (Exception e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
// invoke psp2psarc.exe one final time to reconstruct the assets // decide which files to dump
try { List<String> dumpThese = new ArrayList<String>();
System.out.println("Firestar is compiling the final build"); if (data0) {dumpThese.add("data.psarc");oArcTarget = "data.psarc";}
consoleDisplay.append("Firestar is compiling the final build" + "\n"); if (data1) {dumpThese.add("data1.psarc");oArcTarget = "data1.psarc";}
Process p = Main.exec(new String[]{"../psp2psarc.exe", "create", "--skip-missing-files", "-j12", "-a", "-i", "-y", "--input-file=list.txt", "-o" + oArcTarget}, System.getProperty("user.home") + "/.firestar/temp/"); if (data2) {dumpThese.add("data2.psarc");oArcTarget = "data2.psarc";}
final Thread ioThread = new Thread() { if (dlc1) {dumpThese.add("dlc1.psarc");oArcTarget = "dlc1.psarc";}
@Override if (dlc2) {dumpThese.add("dlc2.psarc");oArcTarget = "dlc2.psarc";}
public void run() {
try {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
consoleDisplay.append(line + "\n");
try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition.\n" + e.getMessage());}
}
reader.close();
} catch (final Exception e) {
e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
}
}
};
ioThread.start();
p.waitFor();
} catch (IOException | InterruptedException e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
// cleanup // dump all assets to working area
boolean one = new File(Main.outpath).mkdirs(); for (String s : dumpThese) {
boolean two; try {
System.out.println("created export folder: " + one); System.out.println("Firestar is extracting " + s);
if (new File(Main.outpath + oArcTarget).exists()) {System.out.println("deleting existing file: " + Main.outpath + oArcTarget); new File(Main.outpath + oArcTarget).delete();} //hackjob consoleDisplay.append("Firestar is extracting " + s + "\n");
if (!Main.windows) {two = new File(System.getProperty("user.home") + "/.firestar/temp/" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));} //Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","aplay /home/bonkyboo/kittens_loop.wav"}); // DEBUG
else {two = new File(System.getProperty("user.home") + "\\.firestar\\temp\\" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));} Process p = Main.exec(new String[]{"../psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
System.out.println("moved file to destination: " + two); final Thread ioThread = new Thread() {
if (two) {System.out.println("file should be located at " + Main.outpath + oArcTarget);} else { @Override
System.out.println("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!"); public void run() {
consoleDisplay.append("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!"); try {
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!", "Fatal Error", JOptionPane.ERROR_MESSAGE); final BufferedReader reader = new BufferedReader(
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); new InputStreamReader(p.getInputStream()));
AllowExit(); String line = null;
return; while ((line = reader.readLine()) != null) {
} System.out.println(line);
try { consoleDisplay.append(line + "\n");
File tmp = new File(System.getProperty("user.home") + "/.firestar/temp/"); try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
Main.deleteDir(tmp); catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition. You can safely ignore this.\n" + e.getMessage());}
} catch (Exception e) { }
System.out.println("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage()); reader.close();
consoleDisplay.append("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage()); } catch (final Exception e) {
} e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
}
}
};
ioThread.start();
p.waitFor();
} catch (IOException | InterruptedException e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
}
// done! // overwrite assets with custom ones from each mod and/or perform operations as specified in mod's delete list
try { // todo: implement RegEx functions after delete.txt
TimeUnit.SECONDS.sleep(1); // avoid race condition when logging for (Main.Mod m : Main.Mods) {
} catch (InterruptedException e) { if (m.enabled) {
//ignore try {
} System.out.println("Firestar is extracting " + m.friendlyName + " by " + m.author);
consoleDisplay.append("Firestar is extracting " + m.friendlyName + " by " + m.author + "\n");
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + m.path).extractAll(System.getProperty("user.home") + "/.firestar/temp/");
((TitledBorder)scrollPane.getBorder()).setTitle("DONE! Close this pop-up to continue."); File fscript = new File(Main.inpath + "temp/fscript");
scrollPane.repaint(); if (fscript.exists()) {
new Rizzo(new FileInputStream(fscript), Main.inpath + "temp/"); // Lets rizz this mod up
fscript.delete();
}
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); if (new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").isFile()) {
AllowExit(); System.out.println("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author);
} consoleDisplay.append("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author + "\n");
private void FastRoutine() { String deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/temp/delete.txt")));
if (Main.windows) {deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "\\.firestar\\temp\\delete.txt")));} // might be unnecessary
String[] dQarray = deleteQueue.split("\n");
Arrays.sort(dQarray);
System.out.println("The deletion queue is " + dQarray.length + " files long!"); //debug
} for (String file : dQarray) {
if(file.contains("..")) { //todo: is this safe enough?
System.out.println("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!");
consoleDisplay.append("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!\n");
} else {
if (!Main.windows) {
System.out.println("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file);
consoleDisplay.append("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file + "\n");
new File(System.getProperty("user.home") + "/.firestar/temp/data" + file).delete();}
else {
System.out.println("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\"));
consoleDisplay.append("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\") + "\n");
new File(new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\")).delete();
}
}
}
public void AllowExit() { // cleanup so we don't run it again for the next mod unless needed
System.out.println("\n\nYou may now close the pop-up window."); // this is not necessary but good practice
consoleDisplay.append("\n\n\nYou may now close the pop-up window."); new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").delete();
try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {} //ignore }
scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum()); } catch (Exception e) {
frame.addWindowListener(new WindowAdapter() { System.out.println(e.getMessage());
@Override consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
public void windowClosing(WindowEvent e) JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
{ frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
invoker.wrapUpDeployment(); AllowExit();
e.getWindow().dispose(); return;
} }
}); }
} }
private static void listAllFiles(Path currentPath, List<String> allFiles) // Post fscript changes
throws IOException try (InputStream is = Main.class.getResourceAsStream("/post.fscript")) {
{ new Rizzo(is, Main.inpath + "temp/");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(currentPath)) } catch (IOException | FirescriptFormatException e) {
{ System.out.println(e.getMessage());
for (Path entry : stream) { consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
if (Files.isDirectory(entry)) { JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
listAllFiles(entry, allFiles); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
} else { AllowExit();
allFiles.add(entry.toString()); return;
} }
}
} // create a list of the contents of data/ for psp2psarc.exe to read from
} List<String> oFilesList = new ArrayList<String>();
List<String> oFilesList2 = new ArrayList<String>();
try {
listAllFiles(Paths.get(System.getProperty("user.home") + "/.firestar/temp/data/"), oFilesList);
for (String p : oFilesList) {
// We need to clean up the path here on Linux to avoid psp2psarc getting confused about where the hell "/" is.
// In WINE it should see it as Z: by default, but if it's somewhere else then I don't have an elegant way of knowing what drive letter it's on, so
// relative paths are kind of the only choice here. This can be extended to Windows too as it works there, though completely unnecessary.
if (!Main.windows) {oFilesList2.add(p.replace("\\", "/").split(new String(System.getProperty("user.home") + "/.firestar/temp/"))[1]);}
else {oFilesList2.add(p.split(new String(System.getProperty("user.home") + "\\.firestar\\temp\\").replace("\\", "\\\\"))[1]);} // path wont match regex unless adjusted for windows here
}
//oFilesList2.forEach(System.out::println); //debug
File oFilesListO = new File(System.getProperty("user.home") + "/.firestar/temp/list.txt");
if (oFilesListO.isFile()) {oFilesListO.delete();}
FileWriter oFilesListWr = new FileWriter(oFilesListO, true);
int i = 0;
for (String p : oFilesList2) {
oFilesListWr.append(p);
if (i != oFilesList2.size()) {
oFilesListWr.append("\n");
}
i++;
}
oFilesListWr.close();
} catch (Exception e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
// invoke psp2psarc.exe one final time to reconstruct the assets
try {
System.out.println("Firestar is compiling the final build");
consoleDisplay.append("Firestar is compiling the final build" + "\n");
Process p = Main.exec(new String[]{"../psp2psarc.exe", "create", "--skip-missing-files", "-j12", "-a", "-i", "-y", "--input-file=list.txt", "-o" + oArcTarget}, System.getProperty("user.home") + "/.firestar/temp/");
final Thread ioThread = new Thread() {
@Override
public void run() {
try {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
consoleDisplay.append(line + "\n");
try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition.\n" + e.getMessage());}
}
reader.close();
} catch (final Exception e) {
e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
}
}
};
ioThread.start();
p.waitFor();
} catch (IOException | InterruptedException e) {
System.out.println(e.getMessage());
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
// cleanup
boolean one = new File(Main.outpath).mkdirs();
boolean two;
System.out.println("created export folder: " + one);
if (new File(Main.outpath + oArcTarget).exists()) {System.out.println("deleting existing file: " + Main.outpath + oArcTarget); new File(Main.outpath + oArcTarget).delete();} //hackjob
if (!Main.windows) {two = new File(System.getProperty("user.home") + "/.firestar/temp/" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));}
else {two = new File(System.getProperty("user.home") + "\\.firestar\\temp\\" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));}
System.out.println("moved file to destination: " + two);
if (two) {System.out.println("file should be located at " + Main.outpath + oArcTarget);} else {
System.out.println("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!");
consoleDisplay.append("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!");
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
return;
}
try {
File tmp = new File(System.getProperty("user.home") + "/.firestar/temp/");
Main.deleteDir(tmp);
} catch (Exception e) {
System.out.println("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
consoleDisplay.append("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
}
// done!
try {
TimeUnit.SECONDS.sleep(1); // avoid race condition when logging
} catch (InterruptedException e) {
//ignore
}
((TitledBorder)scrollPane.getBorder()).setTitle("DONE! Close this pop-up to continue.");
scrollPane.repaint();
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
AllowExit();
}
private void FastRoutine() {
}
public void AllowExit() {
System.out.println("\n\nYou may now close the pop-up window.");
consoleDisplay.append("\n\n\nYou may now close the pop-up window.");
try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {} //ignore
scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e)
{
invoker.wrapUpDeployment();
e.getWindow().dispose();
}
});
}
private static void listAllFiles(Path currentPath, List<String> allFiles) throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(currentPath)) {
for (Path entry : stream) {
if (Files.isDirectory(entry)) {
listAllFiles(entry, allFiles);
} else {
allFiles.add(entry.toString());
}
}
}
}
} }

View File

@ -30,224 +30,224 @@ import javax.imageio.ImageIO;
import javax.swing.*; import javax.swing.*;
public class Main { public class Main {
// Build Information // Build Information
public static final String vstr = "Release 1.3"; public static final String vstr = "Release 1.3";
public static final String vcode = "Tetsuo"; public static final String vcode = "Tetsuo";
public static final String vtag = "tetsuo-1.3"; // set to dekka-1.1 for testing public static final String vtag = "tetsuo-1.3"; // set to dekka-1.1 for testing
public static final int vint = 1; public static final int vint = 1;
// User Settings // User Settings
public static String outpath = System.getProperty("user.home") + "/.firestar/out/"; //game assets location public static String outpath = System.getProperty("user.home") + "/.firestar/out/"; //game assets location
public final static String inpath = System.getProperty("user.home") + "/.firestar/"; //firestar folder -- do not change this public final static String inpath = System.getProperty("user.home") + "/.firestar/"; //firestar folder -- do not change this
public static boolean repatch; //are we in compat mode? public static boolean repatch; //are we in compat mode?
public static boolean windows; //True = windows public static boolean windows; //True = windows
public static int confvint = vint; public static int confvint = vint;
public static boolean checkUpdates = true; public static boolean checkUpdates = true;
//public static String psarc; //sdk location //public static String psarc; //sdk location
public enum ArcTarget { // install target for 2048, type used by downloader public enum ArcTarget { // install target for 2048, type used by downloader
BASE("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/NYEoaBGfiWymSEVZKxoyrKyBFsZNoFqxdyAIpZayZYuLLbCAArYrYXjPNhKCfXcONmhIZzZEeArycSrjiJOuNMWuWsDONUxMIQtMk.pkg"), BASE("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/NYEoaBGfiWymSEVZKxoyrKyBFsZNoFqxdyAIpZayZYuLLbCAArYrYXjPNhKCfXcONmhIZzZEeArycSrjiJOuNMWuWsDONUxMIQtMk.pkg"),
LATEST("http://gs.ww.np.dl.playstation.net/ppkg/np/PCSA00015/PCSA00015_T5/a4b7d9e35ed56e86/UP9000-PCSA00015_00-WIPEOUT2048BASE0-A0104-V0100-059564fcab8ce66d19b5a563e92677e581313205-PE.pkg"), LATEST("http://gs.ww.np.dl.playstation.net/ppkg/np/PCSA00015/PCSA00015_T5/a4b7d9e35ed56e86/UP9000-PCSA00015_00-WIPEOUT2048BASE0-A0104-V0100-059564fcab8ce66d19b5a563e92677e581313205-PE.pkg"),
ADDON_HD("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/JYMqGNXUKqHEyNLjbOgrWcJdnQJUMzgadRFWekbWFBXAwMeGikOyiHkXKogKIfqGhtNwKgmNWwwcrJORmRUTDzylBPwjGVnVjyDfh.pkg"), ADDON_HD("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/JYMqGNXUKqHEyNLjbOgrWcJdnQJUMzgadRFWekbWFBXAwMeGikOyiHkXKogKIfqGhtNwKgmNWwwcrJORmRUTDzylBPwjGVnVjyDfh.pkg"),
ADDON_HD_FURY("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/IAoJQaDpySenBmQCKiqecEPMzSdPfPcdXupxZXLTYYTuRgtsdTaHxbeejwGKRQpjJOKBdMMFzSoeEhsHYxNUasQrEzkZPeBxUEqnp.pkg"); ADDON_HD_FURY("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/IAoJQaDpySenBmQCKiqecEPMzSdPfPcdXupxZXLTYYTuRgtsdTaHxbeejwGKRQpjJOKBdMMFzSoeEhsHYxNUasQrEzkZPeBxUEqnp.pkg");
private final String value; private final String value;
ArcTarget(final String value) {this.value = value;} ArcTarget(final String value) {this.value = value;}
@Override @Override
public String toString() { public String toString() {
return value; return value;
} }
} }
public enum ArcKey { // decryption keys for 2048, type used by downloader public enum ArcKey { // decryption keys for 2048, type used by downloader
BASE("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"), BASE("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
LATEST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"), LATEST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
ADDON_HD("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsGG5kYGIR4Ojs7ejuis9/anXfuudVNvzgdu+9z1z+asJojA9uAACgRhTl"), ADDON_HD("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsGG5kYGIR4Ojs7ejuis9/anXfuudVNvzgdu+9z1z+asJojA9uAACgRhTl"),
ADDON_HD_FURY("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsFG5kYGIR4Ojs7ejuis9/3fydBRm3eCJX7biz/vVTm/2jMT64AQCCYhVy"); ADDON_HD_FURY("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsFG5kYGIR4Ojs7ejuis9/3fydBRm3eCJX7biz/vVTm/2jMT64AQCCYhVy");
private final String value; private final String value;
ArcKey(final String value) {this.value = value;} ArcKey(final String value) {this.value = value;}
@Override @Override
public String toString() { public String toString() {
return value; return value;
} }
} }
public class Mod { public class Mod {
public String path; // file name public String path; // file name
public int version = 1; public int version = 1;
public int priority = 0; //unused public int priority = 0; //unused
public String friendlyName; public String friendlyName;
public String description = ""; public String description = "";
public String game; //TODO for multi game support public String game; //TODO for multi game support
public int loaderversion = 0; //minimum required vint or feature level from Firestar public int loaderversion = 0; //minimum required vint or feature level from Firestar
public String author; // if null, "Author is unknown." public String author; // if null, "Author is unknown."
public boolean enabled = true; public boolean enabled = true;
public List<boolean[]> requires = new ArrayList<>(); // TODO: load optional "requires" array from mod meta if it exists. it will be base, patches, hd dlc, and fury dlc in that order. public List<boolean[]> requires = new ArrayList<>(); // TODO: load optional "requires" array from mod meta if it exists. it will be base, patches, hd dlc, and fury dlc in that order.
// TODO: save 'false true false false' in ost gen if necessary (patches change localization) // TODO: save 'false true false false' in ost gen if necessary (patches change localization)
} }
// Mods // Mods
public static List<Mod> Mods = new ArrayList<Mod>(); public static List<Mod> Mods = new ArrayList<Mod>();
// UI Global Assets // UI Global Assets
public static Font fExo2; public static Font fExo2;
public static BufferedImage windowIcon; public static BufferedImage windowIcon;
public static void main(String[] args) { public static void main(String[] args) {
// license string // license string
System.out.printf("FIRESTAR MOD MANAGER for WipEout 2048\nversion " + vstr + " (codename " + vcode + ") major " + vint + "\n" + System.out.printf("FIRESTAR MOD MANAGER for WipEout 2048\nversion " + vstr + " (codename " + vcode + ") major " + vint + "\n" +
"JVM host appears to be " + System.getProperty("os.name") + "JVM host appears to be " + System.getProperty("os.name") +
"\nRunning from " + System.getProperty("user.dir") + "\nRunning from " + System.getProperty("user.dir") +
"\nCopyright (C) 2024 bonkmaykr\n\nThis program is free software: you can redistribute it and/or modify\n" + "\nCopyright (C) 2024 bonkmaykr\n\nThis program is free software: you can redistribute it and/or modify\n" +
"it under the terms of the GNU General Public License as published by\n" + "it under the terms of the GNU General Public License as published by\n" +
"the Free Software Foundation, either version 3 of the License, or\n" + "the Free Software Foundation, either version 3 of the License, or\n" +
"(at your option) any later version.\n" + "(at your option) any later version.\n" +
"\n" + "\n" +
"This program is distributed in the hope that it will be useful,\n" + "This program is distributed in the hope that it will be useful,\n" +
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
"GNU General Public License for more details.\n" + "GNU General Public License for more details.\n" +
"\n" + "\n" +
"You should have received a copy of the GNU General Public License\n" + "You should have received a copy of the GNU General Public License\n" +
"along with this program. If not, see https://www.gnu.org/licenses/.\n\n\n\n"); "along with this program. If not, see https://www.gnu.org/licenses/.\n\n\n\n");
//begin //begin
// load global assets // load global assets
try { try {
fExo2 = Font.createFont(Font.TRUETYPE_FONT, Main.class.getResourceAsStream("/exo2.ttf")); fExo2 = Font.createFont(Font.TRUETYPE_FONT, Main.class.getResourceAsStream("/exo2.ttf"));
} catch (Exception e) { } catch (Exception e) {
System.out.println("Font \"Exo 2\" is missing!"); System.out.println("Font \"Exo 2\" is missing!");
fExo2 = new Font("Arial", Font.PLAIN, 12); fExo2 = new Font("Arial", Font.PLAIN, 12);
} }
// load global window icon // load global window icon
try { try {
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png")); windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Failed to find titleIcon.png. Window will not have an icon."); System.out.println("ERROR: Failed to find titleIcon.png. Window will not have an icon.");
} }
// check and load configs // check and load configs
File fConf = new File(System.getProperty("user.home") + "/.firestar/firestar.conf"); File fConf = new File(System.getProperty("user.home") + "/.firestar/firestar.conf");
if (!fConf.isFile()) { if (!fConf.isFile()) {
System.out.println("No configuration was found. Starting the initial setup"); System.out.println("No configuration was found. Starting the initial setup");
new WilkinsCoffee().setup(); new WilkinsCoffee().setup();
} else { } else {
new MissPiggy().Action(); // Quick! Start singing Firework by Katy Perry! (or open the main window i guess...) new MissPiggy().Action(); // Quick! Start singing Firework by Katy Perry! (or open the main window i guess...)
} }
} }
public static void writeConf(){ public static void writeConf(){
JSONObject container = new JSONObject(); JSONObject container = new JSONObject();
container.put("version", vint); container.put("version", vint);
container.put("2048path", outpath); container.put("2048path", outpath);
container.put("HDpath", "TODO"); // proposed hd/fury support for ps3, will use very simplified Fast Mode due to less difficulty installing container.put("HDpath", "TODO"); // proposed hd/fury support for ps3, will use very simplified Fast Mode due to less difficulty installing
container.put("safemode", repatch); container.put("safemode", repatch);
container.put("isWin32", windows); container.put("isWin32", windows);
container.put("checkUpdates", checkUpdates); container.put("checkUpdates", checkUpdates);
container.put("currentPlaylist", "TODO"); // proposed feature: store separate mod lists in lists/ to load/save later? container.put("currentPlaylist", "TODO"); // proposed feature: store separate mod lists in lists/ to load/save later?
try { try {
Files.write(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"), container.toString().getBytes()); Files.write(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"), container.toString().getBytes());
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public static void loadConf(){ public static void loadConf(){
try { try {
JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf")))); JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"))));
System.out.println(container.toString()); // debug System.out.println(container.toString()); // debug
confvint = (int) container.get("version"); // used for converting configs between program versions later down the line confvint = (int) container.get("version"); // used for converting configs between program versions later down the line
outpath = container.get("2048path").toString(); outpath = container.get("2048path").toString();
repatch = (boolean) container.get("safemode"); repatch = (boolean) container.get("safemode");
windows = (boolean) container.get("isWin32"); windows = (boolean) container.get("isWin32");
try { try {
checkUpdates = (boolean) container.get("checkUpdates"); checkUpdates = (boolean) container.get("checkUpdates");
} catch (JSONException e) { } catch (JSONException e) {
checkUpdates = true; checkUpdates = true;
} }
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Failed to load firestar.conf"); System.out.println("ERROR: Failed to load firestar.conf");
System.out.println(e.getMessage()); System.out.println(e.getMessage());
} }
} }
public static void loadConf(MissPiggy w){ public static void loadConf(MissPiggy w){
try { try {
JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf")))); JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"))));
System.out.println(container.toString()); // debug System.out.println(container.toString()); // debug
confvint = (int) container.get("version"); // used for converting configs between program versions later down the line confvint = (int) container.get("version"); // used for converting configs between program versions later down the line
outpath = container.get("2048path").toString(); outpath = container.get("2048path").toString();
repatch = (boolean) container.get("safemode"); repatch = (boolean) container.get("safemode");
windows = (boolean) container.get("isWin32"); windows = (boolean) container.get("isWin32");
try { try {
checkUpdates = (boolean) container.get("checkUpdates"); checkUpdates = (boolean) container.get("checkUpdates");
} catch (JSONException e) { } catch (JSONException e) {
checkUpdates = true; checkUpdates = true;
} }
} catch (Exception e) { } catch (Exception e) {
JOptionPane.showMessageDialog(w.frame, "Firestar couldn't load your config file. Tread lightly.\n\n" + e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(w.frame, "Firestar couldn't load your config file. Tread lightly.\n\n" + e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE);
System.out.println("ERROR: Failed to load firestar.conf"); System.out.println("ERROR: Failed to load firestar.conf");
System.out.println(e.getMessage()); System.out.println(e.getMessage());
} }
} }
public static void deleteDir(File file) { // https://stackoverflow.com/a/29175213/9259829 public static void deleteDir(File file) { // https://stackoverflow.com/a/29175213/9259829
File[] contents = file.listFiles(); File[] contents = file.listFiles();
if (contents != null) { if (contents != null) {
for (File f : contents) { for (File f : contents) {
if (! Files.isSymbolicLink(f.toPath())) { if (! Files.isSymbolicLink(f.toPath())) {
deleteDir(f); deleteDir(f);
} }
} }
} }
file.delete(); file.delete();
} }
public static void downloadDependenciesBeforeSetVisible(JFrame invoker) { public static void downloadDependenciesBeforeSetVisible(JFrame invoker) {
invoker.setVisible(false); invoker.setVisible(false);
Main.downloadDependencies(); Main.downloadDependencies();
invoker.setVisible(true); invoker.setVisible(true);
confvint = vint; confvint = vint;
Main.writeConf(); Main.writeConf();
} }
public static boolean downloadDependencies () { // todo: CHECKSUM!!!! THESE ARE EXECUTABLES!!!!!!!!!!! DON'T ALLOW MALWARE!!!! public static boolean downloadDependencies () { // todo: CHECKSUM!!!! THESE ARE EXECUTABLES!!!!!!!!!!! DON'T ALLOW MALWARE!!!!
boolean downloader = new Fozzie().DownloadFile("https://bonkmaykr.worlio.com/http/firestar/firesdk.zip", System.getProperty("user.home") + "/.firestar/", "firesdk.zip"); boolean downloader = new Fozzie().DownloadFile("https://bonkmaykr.worlio.com/http/firestar/firesdk.zip", System.getProperty("user.home") + "/.firestar/", "firesdk.zip");
if (!downloader) {return false;} if (!downloader) {return false;}
ZipFile sdk = new ZipFile(System.getProperty("user.home") + "/.firestar/firesdk.zip"); ZipFile sdk = new ZipFile(System.getProperty("user.home") + "/.firestar/firesdk.zip");
try { try {
sdk.extractAll(System.getProperty("user.home") + "/.firestar/"); sdk.extractAll(System.getProperty("user.home") + "/.firestar/");
} catch (ZipException e) { } catch (ZipException e) {
JOptionPane.showMessageDialog(new JFrame(), e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(new JFrame(), e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE);
System.out.println(e.getMessage()); System.out.println(e.getMessage());
return false; return false;
} }
sdk.getFile().delete(); // cleanup sdk.getFile().delete(); // cleanup
return true; return true;
} }
public static boolean callDownloaderStatically (String url, String folder, String name) { public static boolean callDownloaderStatically (String url, String folder, String name) {
return new Fozzie().DownloadFile(url, folder, name); return new Fozzie().DownloadFile(url, folder, name);
} }
public static Process exec(String[] cmd, String cwd) throws IOException { public static Process exec(String[] cmd, String cwd) throws IOException {
Process p; Process p;
String[] pcmd; String[] pcmd;
if (!Main.windows) { if (!Main.windows) {
pcmd = new String[cmd.length + 1]; pcmd = new String[cmd.length + 1];
pcmd[0] = "wine"; pcmd[0] = "wine";
System.arraycopy(cmd, 0, pcmd, 1, cmd.length); System.arraycopy(cmd, 0, pcmd, 1, cmd.length);
p = Runtime.getRuntime().exec(pcmd, null, new File(cwd)); p = Runtime.getRuntime().exec(pcmd, null, new File(cwd));
} else { } else {
p = Runtime.getRuntime().exec(cmd, null, new File(cwd.replace("/", "\\"))); p = Runtime.getRuntime().exec(cmd, null, new File(cwd.replace("/", "\\")));
}
return p;
} }
return p;
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -5,133 +5,132 @@ import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
/** /*
* Created by simon on 8/29/17. * Created by simon on 8/29/17.
* Copyright 2017 Simon Haoran Liang * Copyright 2017 Simon Haoran Liang
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including * associated documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
* following conditions: * following conditions:
* *
* The above copyright notice and this permission notice shall be included in all copies or substantial * The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software. * portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
public class ReplacingInputStream extends FilterInputStream { public class ReplacingInputStream extends FilterInputStream {
private Queue<Integer> inQueue, outQueue; private Queue<Integer> inQueue, outQueue;
private final byte[] search, replacement; private final byte[] search, replacement;
private boolean caseSensitive = true; private boolean caseSensitive = true;
public ReplacingInputStream(InputStream in, String search, String replacement) { public ReplacingInputStream(InputStream in, String search, String replacement) {
super(in); super(in);
this.inQueue = new LinkedList<>(); this.inQueue = new LinkedList<>();
this.outQueue = new LinkedList<>(); this.outQueue = new LinkedList<>();
this.search = search.getBytes(); this.search = search.getBytes();
this.replacement = replacement.getBytes(); this.replacement = replacement.getBytes();
} }
public ReplacingInputStream(InputStream in, String search, String replacement, boolean caseSensitive) { public ReplacingInputStream(InputStream in, String search, String replacement, boolean caseSensitive) {
super(in); super(in);
this.inQueue = new LinkedList<>(); this.inQueue = new LinkedList<>();
this.outQueue = new LinkedList<>(); this.outQueue = new LinkedList<>();
this.search = search.getBytes(); this.search = search.getBytes();
this.replacement = replacement.getBytes(); this.replacement = replacement.getBytes();
this.caseSensitive = caseSensitive; this.caseSensitive = caseSensitive;
} }
private boolean isMatchFound() { private boolean isMatchFound() {
Iterator<Integer> iterator = inQueue.iterator(); Iterator<Integer> iterator = inQueue.iterator();
for (byte b : search) { for (byte b : search) {
if (!iterator.hasNext()) return false; if (!iterator.hasNext()) return false;
Integer i = iterator.next(); Integer i = iterator.next();
if (caseSensitive && b != i) return false; if (caseSensitive && b != i) return false;
else if (Character.toLowerCase(b) != Character.toLowerCase(i.byteValue())) return false; else if (Character.toLowerCase(b) != Character.toLowerCase(i.byteValue())) return false;
} }
return true; return true;
} }
private void readAhead() throws IOException { private void readAhead() throws IOException {
// Work up some look-ahead. // Work up some look-ahead.
while (inQueue.size() < search.length) { while (inQueue.size() < search.length) {
int next = super.read(); int next = super.read();
inQueue.offer(next); inQueue.offer(next);
if (next == -1) { if (next == -1) {
break; break;
} }
} }
} }
@Override @Override
public int read() throws IOException { public int read() throws IOException {
// Next byte already determined. // Next byte already determined.
while (outQueue.isEmpty()) { while (outQueue.isEmpty()) {
readAhead(); readAhead();
if (isMatchFound()) { if (isMatchFound()) {
for (byte a : search) { for (byte a : search) {
inQueue.remove(); inQueue.remove();
} }
for (byte b : replacement) { for (byte b : replacement) {
outQueue.offer((int) b); outQueue.offer((int) b);
} }
} else { } else {
outQueue.add(inQueue.remove()); outQueue.add(inQueue.remove());
} }
} }
return outQueue.remove(); return outQueue.remove();
} }
@Override @Override
public int read(byte b[]) throws IOException { public int read(byte b[]) throws IOException {
return read(b, 0, b.length); return read(b, 0, b.length);
} }
// copied straight from InputStream inplementation, just needed to to use `read()` from this class // copied straight from InputStream inplementation, just needed to to use `read()` from this class
@Override @Override
public int read(byte b[], int off, int len) throws IOException { public int read(byte b[], int off, int len) throws IOException {
if (b == null) { if (b == null) {
throw new NullPointerException(); throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) { } else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} else if (len == 0) { } else if (len == 0) {
return 0; return 0;
} }
int c = read(); int c = read();
if (c == -1) { if (c == -1) {
return -1; return -1;
} }
b[off] = (byte)c; b[off] = (byte)c;
int i = 1; int i = 1;
try { try {
for (; i < len ; i++) { for (; i < len ; i++) {
c = read(); c = read();
if (c == -1) { if (c == -1) {
break; break;
} }
b[off + i] = (byte)c; b[off + i] = (byte)c;
} }
} catch (IOException ee) { } catch (IOException ee) { }
} return i;
return i; }
}
} }

View File

@ -56,397 +56,397 @@ import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
public class Rizzo { public class Rizzo {
private Scanner scanner; private Scanner scanner;
private final int maxVer = 1; private final int maxVer = 1;
private int ver = 1; private int ver = 1;
private String workingDir; private String workingDir;
public Rizzo(InputStream infile, String workingDir) throws FileNotFoundException, FirescriptFormatException { public Rizzo(InputStream infile, String workingDir) throws FileNotFoundException, FirescriptFormatException {
if (!workingDir.endsWith("/")) this.workingDir = workingDir + "/"; if (!workingDir.endsWith("/")) this.workingDir = workingDir + "/";
else this.workingDir = workingDir; else this.workingDir = workingDir;
scanner = new Scanner(infile); scanner = new Scanner(infile);
parseScript(null); parseScript(null);
}
private void parseScript(Object context) throws FirescriptFormatException {
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.startsWith("#") || line.length() < 1) continue;
if (!parseArgs(translateCommandline(line), context)) break;
} }
}
private boolean parseArgs(String[] args, Object context) throws FirescriptFormatException { private void parseScript(Object context) throws FirescriptFormatException {
System.out.println("Parsing Command: " + Arrays.toString(args)); while (scanner.hasNextLine()) {
if (args.length > 0) { String line = scanner.nextLine().trim();
if (context == null) { if (line.startsWith("#") || line.length() < 1) continue;
if (args[0].equalsIgnoreCase("fscript")) { if (!parseArgs(translateCommandline(line), context)) break;
ver = Integer.parseInt(args[1]); // We'll do shit with this later }
if (ver > maxVer) throw new FirescriptFormatException(args[0], "script too new"); }
} else if (args[0].equalsIgnoreCase("file")) {
File newCtx = new File(workingDir + args[1]);
System.out.println("Calling new parse: " + Arrays.toString(Arrays.copyOfRange(args, 2, args.length)));
parseArgs(Arrays.copyOfRange(args, 2, args.length), newCtx);
} else throw new FirescriptFormatException("fscript", "unknown command '" + args[0] + "'");
} else {
System.out.println("Using context: " + context.getClass().getName() + "@" + context.hashCode());
if (args[0].equals("{")) {
System.out.println("New context block: " + context.getClass().getName() + "@" + context.hashCode());
parseScript(context);
} else if (args[0].equals("}")) {
System.out.println("Ending context block: " + context.getClass().getName() + "@" + context.hashCode());
return false;
} else if (context instanceof File file) {
if (file.exists()) {
if (args[0].equalsIgnoreCase("delete")) {
System.out.println("Deleting: " + file.getPath());
if (file.getAbsolutePath().startsWith(workingDir)) {
if (file.isDirectory()) Main.deleteDir(file);
else file.delete();
}
} else if (args[0].equalsIgnoreCase("xml")) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// Mmmm, love me some INVALID XML corrections.
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(file), "\r\n", ""), "&", "&amp;"), "\n", "&#10;");
Document doc = docBuilder.parse(ris);
parseArgs(Arrays.copyOfRange(args, 1, args.length), doc);
try {
FileOutputStream output = new FileOutputStream(file);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StreamResult result = new StreamResult(new StringWriter()); private boolean parseArgs(String[] args, Object context) throws FirescriptFormatException {
DOMSource source = new DOMSource(doc); System.out.println("Parsing Command: " + Arrays.toString(args));
if (args.length > 0) {
if (context == null) {
if (args[0].equalsIgnoreCase("fscript")) {
ver = Integer.parseInt(args[1]); // We'll do shit with this later
if (ver > maxVer) throw new FirescriptFormatException(args[0], "script too new");
} else if (args[0].equalsIgnoreCase("file")) {
File newCtx = new File(workingDir + args[1]);
System.out.println("Calling new parse: " + Arrays.toString(Arrays.copyOfRange(args, 2, args.length)));
parseArgs(Arrays.copyOfRange(args, 2, args.length), newCtx);
} else throw new FirescriptFormatException("fscript", "unknown command '" + args[0] + "'");
} else {
System.out.println("Using context: " + context.getClass().getName() + "@" + context.hashCode());
if (args[0].equals("{")) {
System.out.println("New context block: " + context.getClass().getName() + "@" + context.hashCode());
parseScript(context);
} else if (args[0].equals("}")) {
System.out.println("Ending context block: " + context.getClass().getName() + "@" + context.hashCode());
return false;
} else if (context instanceof File file) {
if (file.exists()) {
if (args[0].equalsIgnoreCase("delete")) {
System.out.println("Deleting: " + file.getPath());
if (file.getAbsolutePath().startsWith(workingDir)) {
if (file.isDirectory()) Main.deleteDir(file);
else file.delete();
}
} else if (args[0].equalsIgnoreCase("xml")) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// Mmmm, love me some INVALID XML corrections.
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(file), "\r\n", ""), "&", "&amp;"), "\n", "&#10;");
Document doc = docBuilder.parse(ris);
parseArgs(Arrays.copyOfRange(args, 1, args.length), doc);
try {
FileOutputStream output = new FileOutputStream(file);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(source, result); StreamResult result = new StreamResult(new StringWriter());
// Look ma, I'm breaking XML standards! DOMSource source = new DOMSource(doc);
String xmlString = result.getWriter().toString()
.replace("&amp;", "&")
.replace("&#9;", "\t")
.replace("&#8;", "\b")
.replace("&#10;", "\n")
.replace("&#13;", "\r")
.replace("&#12;", "\f");
try (PrintStream ps = new PrintStream(output)) {
ps.print(xmlString);
}
} catch (TransformerException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (args[0].equalsIgnoreCase("str") || args[0].equalsIgnoreCase("xstr")) {
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayInputStream bais = new ByteArrayInputStream(fis.readAllBytes());
fis.close();
FileOutputStream fos = new FileOutputStream(file);
if (args[1].equalsIgnoreCase("append")) {
bais.transferTo(fos);
for (int s = 0; s < args[2].length(); s++) {
char c = args[2].charAt(s);
fos.write(c);
}
} else if (args[1].equalsIgnoreCase("replace") || args[1].equalsIgnoreCase("delete")) {
String replacement = "";
if (args[1].equalsIgnoreCase("replace")) replacement = args[3];
ReplacingInputStream ris;
if (args[0].equalsIgnoreCase("xstr")) ris = new ReplacingInputStream(bais, args[2], replacement, false);
else ris = new ReplacingInputStream(bais, args[2], replacement);
ris.transferTo(fos);
ris.close();
}
fos.flush();
fos.close();
} catch (IOException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (args[0].equalsIgnoreCase("binedit")) {
int offset = Integer.parseInt(args[1]);
String bytes = args[2];
if (bytes.length() % 2 != 0) throw new FirescriptFormatException(args[0], "invalid length of bytes");
try {
byte[] ba;
try (FileInputStream fis = new FileInputStream(file)) {
ba = fis.readAllBytes();
}
if (offset >= ba.length) throw new FirescriptFormatException(args[0], "offset is larger than file size");
else {
byte[] in = HexFormat.of().parseHex(bytes);
System.arraycopy(in, 0, ba, offset, in.length);
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(ba);
fos.flush();
}
}
} catch (IOException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (args[0].equalsIgnoreCase("patch")) {
try {
List<String> original = Files.readAllLines(file.toPath());
File patchFile = new File(workingDir + args[1]);
if (!patchFile.exists()) throw new FirescriptFormatException(args[0], "patch file doesn't exist");
List<String> patched = Files.readAllLines(patchFile.toPath());
Patch<String> patch = UnifiedDiffUtils.parseUnifiedDiff(patched); transformer.transform(source, result);
List<String> result = DiffUtils.patch(original, patch); // Look ma, I'm breaking XML standards!
String xmlString = result.getWriter().toString()
.replace("&amp;", "&")
.replace("&#9;", "\t")
.replace("&#8;", "\b")
.replace("&#10;", "\n")
.replace("&#13;", "\r")
.replace("&#12;", "\f");
try (PrintStream ps = new PrintStream(output)) {
ps.print(xmlString);
}
} catch (TransformerException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (args[0].equalsIgnoreCase("str") || args[0].equalsIgnoreCase("xstr")) {
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayInputStream bais = new ByteArrayInputStream(fis.readAllBytes());
fis.close();
FileOutputStream fos = new FileOutputStream(file);
if (args[1].equalsIgnoreCase("append")) {
bais.transferTo(fos);
for (int s = 0; s < args[2].length(); s++) {
char c = args[2].charAt(s);
fos.write(c);
}
} else if (args[1].equalsIgnoreCase("replace") || args[1].equalsIgnoreCase("delete")) {
String replacement = "";
if (args[1].equalsIgnoreCase("replace")) replacement = args[3];
ReplacingInputStream ris;
if (args[0].equalsIgnoreCase("xstr")) ris = new ReplacingInputStream(bais, args[2], replacement, false);
else ris = new ReplacingInputStream(bais, args[2], replacement);
ris.transferTo(fos);
ris.close();
}
fos.flush();
fos.close();
} catch (IOException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (args[0].equalsIgnoreCase("binedit")) {
int offset = Integer.parseInt(args[1]);
String bytes = args[2];
if (bytes.length() % 2 != 0) throw new FirescriptFormatException(args[0], "invalid length of bytes");
try {
byte[] ba;
try (FileInputStream fis = new FileInputStream(file)) {
ba = fis.readAllBytes();
}
if (offset >= ba.length) throw new FirescriptFormatException(args[0], "offset is larger than file size");
else {
byte[] in = HexFormat.of().parseHex(bytes);
System.arraycopy(in, 0, ba, offset, in.length);
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(ba);
fos.flush();
}
}
} catch (IOException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (args[0].equalsIgnoreCase("patch")) {
try {
List<String> original = Files.readAllLines(file.toPath());
File patchFile = new File(workingDir + args[1]);
if (!patchFile.exists()) throw new FirescriptFormatException(args[0], "patch file doesn't exist");
List<String> patched = Files.readAllLines(patchFile.toPath());
try (FileWriter fileWriter = new FileWriter(file)) { Patch<String> patch = UnifiedDiffUtils.parseUnifiedDiff(patched);
for (String str : result) { List<String> result = DiffUtils.patch(original, patch);
fileWriter.write(str + "\r\n");
} try (FileWriter fileWriter = new FileWriter(file)) {
} for (String str : result) {
} catch (FirescriptFormatException | PatchFailedException | IOException ex) { fileWriter.write(str + "\r\n");
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex); }
} }
} else throw new FirescriptFormatException("file", "unknown command '" + args[0] + "'"); } catch (FirescriptFormatException | PatchFailedException | IOException ex) {
} else System.out.println("fscript: file context not found, skipping."); Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
} else if (context instanceof Document document) { }
if (args[0].equalsIgnoreCase("modify")) { } else throw new FirescriptFormatException("file", "unknown command '" + args[0] + "'");
Element elem = (Element)traverse(document, args[1]); } else System.out.println("fscript: file context not found, skipping.");
parseArgs(Arrays.copyOfRange(args, 2, args.length), elem); } else if (context instanceof Document document) {
} else if (args[0].equalsIgnoreCase("create")) { if (args[0].equalsIgnoreCase("modify")) {
String newTag = args[1].substring(args[1].lastIndexOf(".")+1); Element elem = (Element)traverse(document, args[1]);
String newID = ""; parseArgs(Arrays.copyOfRange(args, 2, args.length), elem);
if (newTag.contains("#")) { } else if (args[0].equalsIgnoreCase("create")) {
newID = newTag.substring(newTag.indexOf("#")+1); String newTag = args[1].substring(args[1].lastIndexOf(".")+1);
newTag = newTag.substring(0, newTag.indexOf("#")); String newID = "";
if (newTag.contains("#")) {
newID = newTag.substring(newTag.indexOf("#")+1);
newTag = newTag.substring(0, newTag.indexOf("#"));
}
Element newElem = document.createElement(newTag);
if (newID != null && newID.length() > 0) newElem.setAttribute("id", newID);
traverse(document, args[1].substring(0, args[1].lastIndexOf("."))).appendChild(newElem);
parseArgs(Arrays.copyOfRange(args, 2, args.length), newElem);
} else if (args[0].equalsIgnoreCase("delete")) {
Element elem = (Element)traverse(document, args[1]);
elem.getParentNode().removeChild(elem);
} else if (args[0].equalsIgnoreCase("merge")) {
// We're basically copying the file context xml command but with another xml document.
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(new File(workingDir + args[1])), "\r\n", ""), "&", "&amp;"), "\n", "&#10;");
Document outDoc = docBuilder.parse(ris);
NamedNodeMap nnm = outDoc.getDocumentElement().getAttributes();
for (int x = 0; x < nnm.getLength(); x++) {
Attr importedNode = (Attr) document.importNode(nnm.item(x), true);
document.getDocumentElement().setAttributeNodeNS(importedNode);
}
NodeList cn = outDoc.getDocumentElement().getChildNodes();
for (int x = 0; x < cn.getLength(); x++) {
Node importedNode = document.importNode(cn.item(x), true);
document.getDocumentElement().appendChild(importedNode);
}
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else throw new FirescriptFormatException("xml", "unknown command '" + args[0] + "'");
} else if (context instanceof Element element) {
if (args[0].equalsIgnoreCase("set")) {
if (args[1].equalsIgnoreCase("attribute"))
// We replace newlines on XML write.
element.setAttribute(args[2], args[3].replace("\\n", "&#10;"));
else if (args[1].equalsIgnoreCase("value"))
element.setNodeValue(args[2]);
} else if (args[0].equalsIgnoreCase("create")) {
String finalTag = args[1];
String path = "";
if (finalTag.lastIndexOf(".") > 0) {
path = args[1].substring(0, finalTag.lastIndexOf("."));
finalTag = args[1].substring(finalTag.lastIndexOf(".")+1);
}
String id = "";
String name = "";
if (finalTag.contains("#")) {
id = finalTag.substring(finalTag.indexOf("#")+1);
finalTag = finalTag.substring(0, finalTag.indexOf("#"));
} else if (finalTag.contains("$")) {
name = finalTag.substring(finalTag.indexOf("$")+1);
finalTag = finalTag.substring(0, finalTag.indexOf("$"));
}
Element finalElem = element.getOwnerDocument().createElement(finalTag);
if (id != null && id.length() > 0) finalElem.setAttribute("id", id);
if (name != null && name.length() > 0) finalElem.setAttribute("name", name);
traverse(element, path).appendChild(finalElem);
parseArgs(Arrays.copyOfRange(args, 2, args.length), finalElem);
} else if (args[0].equalsIgnoreCase("create-at")) {
int index = Integer.parseInt(args[1]);
String finalTag = args[2];
String id = "";
String name = "";
if (finalTag.contains("#")) {
id = finalTag.substring(finalTag.indexOf("#")+1);
finalTag = finalTag.substring(0, finalTag.indexOf("#"));
} else if (finalTag.contains("$")) {
name = finalTag.substring(finalTag.indexOf("$")+1);
finalTag = finalTag.substring(0, finalTag.indexOf("$"));
}
Element finalElem = element.getOwnerDocument().createElement(finalTag);
if (id != null && id.length() > 0) finalElem.setAttribute("id", id);
if (name != null && name.length() > 0) finalElem.setAttribute("name", name);
element.insertBefore(finalElem, element.getChildNodes().item(index));
parseArgs(Arrays.copyOfRange(args, 3, args.length), finalElem);
} else throw new FirescriptFormatException("xml", "unknown element command '" + args[0] + "'");
} else throw new FirescriptFormatException("context is unknown");
} }
Element newElem = document.createElement(newTag); }
if (newID != null && newID.length() > 0) newElem.setAttribute("id", newID); return true;
traverse(document, args[1].substring(0, args[1].lastIndexOf("."))).appendChild(newElem); }
parseArgs(Arrays.copyOfRange(args, 2, args.length), newElem);
} else if (args[0].equalsIgnoreCase("delete")) {
Element elem = (Element)traverse(document, args[1]);
elem.getParentNode().removeChild(elem);
} else if (args[0].equalsIgnoreCase("merge")) {
// We're basically copying the file context xml command but with another xml document.
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(new File(workingDir + args[1])), "\r\n", ""), "&", "&amp;"), "\n", "&#10;");
Document outDoc = docBuilder.parse(ris);
NamedNodeMap nnm = outDoc.getDocumentElement().getAttributes(); private Node traverse(Node owner, String selector) throws FirescriptFormatException {
for (int x = 0; x < nnm.getLength(); x++) { if (selector == null || selector.length() == 0 || owner == null) {
Attr importedNode = (Attr) document.importNode(nnm.item(x), true); return owner;
document.getDocumentElement().setAttributeNodeNS(importedNode); }
} String[] elems = selector.split("\\.");
Node parent = owner;
for (String tag : elems) {
Node newParent = null;
int index = 0;
if (tag.contains("[")) {
index = Integer.parseInt(tag.substring(tag.indexOf("[")+1, tag.lastIndexOf("]")));
tag = tag.substring(0, tag.indexOf("["));
}
NodeList cn = outDoc.getDocumentElement().getChildNodes();
for (int x = 0; x < cn.getLength(); x++) {
Node importedNode = document.importNode(cn.item(x), true);
document.getDocumentElement().appendChild(importedNode);
}
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
}
} else throw new FirescriptFormatException("xml", "unknown command '" + args[0] + "'");
} else if (context instanceof Element element) {
if (args[0].equalsIgnoreCase("set")) {
if (args[1].equalsIgnoreCase("attribute"))
// We replace newlines on XML write.
element.setAttribute(args[2], args[3].replace("\\n", "&#10;"));
else if (args[1].equalsIgnoreCase("value"))
element.setNodeValue(args[2]);
} else if (args[0].equalsIgnoreCase("create")) {
String finalTag = args[1];
String path = "";
if (finalTag.lastIndexOf(".") > 0) {
path = args[1].substring(0, finalTag.lastIndexOf("."));
finalTag = args[1].substring(finalTag.lastIndexOf(".")+1);
}
String id = ""; String id = "";
if (tag.contains("#")) {
id = tag.substring(tag.indexOf("#")+1);
tag = tag.substring(0, tag.indexOf("#"));
}
String name = ""; String name = "";
if (finalTag.contains("#")) { if (tag.contains("$")) {
id = finalTag.substring(finalTag.indexOf("#")+1); name = tag.substring(tag.indexOf("$")+1);
finalTag = finalTag.substring(0, finalTag.indexOf("#")); tag = tag.substring(0, tag.indexOf("$"));
} else if (finalTag.contains("$")) {
name = finalTag.substring(finalTag.indexOf("$")+1);
finalTag = finalTag.substring(0, finalTag.indexOf("$"));
} }
Element finalElem = element.getOwnerDocument().createElement(finalTag); if (id.length() > 0) {
if (id != null && id.length() > 0) finalElem.setAttribute("id", id); NodeList ns;
if (name != null && name.length() > 0) finalElem.setAttribute("name", name); if (parent instanceof Document document)
traverse(element, path).appendChild(finalElem); ns = document.getElementsByTagName(tag);
parseArgs(Arrays.copyOfRange(args, 2, args.length), finalElem); else
} else if (args[0].equalsIgnoreCase("create-at")) { ns = ((Element)parent).getElementsByTagName(tag);
int index = Integer.parseInt(args[1]); for (int i = 0; i < ns.getLength(); i++) {
String finalTag = args[2]; Node n = ns.item(i);
String id = ""; if (n.getNodeName().equals("#text")) continue;
String name = ""; if (((Element)n).getAttribute("id").equals(id)) {
if (finalTag.contains("#")) { newParent = (Element)n;
id = finalTag.substring(finalTag.indexOf("#")+1); break;
finalTag = finalTag.substring(0, finalTag.indexOf("#")); }
} else if (finalTag.contains("$")) { }
name = finalTag.substring(finalTag.indexOf("$")+1); } else if (name.length() > 0) {
finalTag = finalTag.substring(0, finalTag.indexOf("$")); NodeList ns;
if (parent instanceof Document document)
ns = document.getChildNodes();
else
ns = ((Element)parent).getChildNodes();
for (int i = 0; i < ns.getLength(); i++) {
Node n = ns.item(i);
if (n.getNodeName().equals("#text")) continue;
if (((Element)n).getAttribute("name").equals(name)) {
newParent = (Element)n;
break;
}
}
} else {
if (parent instanceof Document document)
newParent = document.getElementsByTagName(tag).item(index);
else
newParent = ((Element)parent).getElementsByTagName(tag).item(index);
} }
Element finalElem = element.getOwnerDocument().createElement(finalTag); if (newParent == null) throw new FirescriptFormatException("xml: selector is invalid");
if (id != null && id.length() > 0) finalElem.setAttribute("id", id); else parent = newParent;
if (name != null && name.length() > 0) finalElem.setAttribute("name", name);
element.insertBefore(finalElem, element.getChildNodes().item(index));
parseArgs(Arrays.copyOfRange(args, 3, args.length), finalElem);
} else throw new FirescriptFormatException("xml", "unknown element command '" + args[0] + "'");
} else throw new FirescriptFormatException("context is unknown");
}
}
return true;
}
private Node traverse(Node owner, String selector) throws FirescriptFormatException {
if (selector == null || selector.length() == 0 || owner == null) {
return owner;
}
String[] elems = selector.split("\\.");
Node parent = owner;
for (String tag : elems) {
Node newParent = null;
int index = 0;
if (tag.contains("[")) {
index = Integer.parseInt(tag.substring(tag.indexOf("[")+1, tag.lastIndexOf("]")));
tag = tag.substring(0, tag.indexOf("["));
}
String id = "";
if (tag.contains("#")) {
id = tag.substring(tag.indexOf("#")+1);
tag = tag.substring(0, tag.indexOf("#"));
}
String name = "";
if (tag.contains("$")) {
name = tag.substring(tag.indexOf("$")+1);
tag = tag.substring(0, tag.indexOf("$"));
}
if (id.length() > 0) {
NodeList ns;
if (parent instanceof Document document)
ns = document.getElementsByTagName(tag);
else
ns = ((Element)parent).getElementsByTagName(tag);
for (int i = 0; i < ns.getLength(); i++) {
Node n = ns.item(i);
if (n.getNodeName().equals("#text")) continue;
if (((Element)n).getAttribute("id").equals(id)) {
newParent = (Element)n;
break;
}
} }
} else if (name.length() > 0) { return parent;
NodeList ns;
if (parent instanceof Document document)
ns = document.getChildNodes();
else
ns = ((Element)parent).getChildNodes();
for (int i = 0; i < ns.getLength(); i++) {
Node n = ns.item(i);
if (n.getNodeName().equals("#text")) continue;
if (((Element)n).getAttribute("name").equals(name)) {
newParent = (Element)n;
break;
}
}
} else {
if (parent instanceof Document document)
newParent = document.getElementsByTagName(tag).item(index);
else
newParent = ((Element)parent).getElementsByTagName(tag).item(index);
}
if (newParent == null) throw new FirescriptFormatException("xml: selector is invalid");
else parent = newParent;
}
return parent;
}
private static String[] translateCommandline(String line) throws FirescriptFormatException {
if (line == null || line.length() == 0) {
return new String[0];
} }
final int normal = 0; private static String[] translateCommandline(String line) throws FirescriptFormatException {
final int inQuote = 1; if (line == null || line.length() == 0) {
final int inDoubleQuote = 2; return new String[0];
int state = normal; }
final ArrayList<String> result = new ArrayList<String>();
final StringBuilder current = new StringBuilder();
boolean lastTokenHasBeenQuoted = false;
boolean lastTokenWasEscaped = false;
for (int i = 0; i < line.length(); i++) { final int normal = 0;
char nextTok = line.charAt(i); final int inQuote = 1;
switch (state) { final int inDoubleQuote = 2;
case inQuote -> { int state = normal;
if (nextTok == '\\') { final ArrayList<String> result = new ArrayList<String>();
lastTokenWasEscaped = true; final StringBuilder current = new StringBuilder();
} else if (nextTok == '\'' && !lastTokenWasEscaped) { boolean lastTokenHasBeenQuoted = false;
lastTokenHasBeenQuoted = true; boolean lastTokenWasEscaped = false;
state = normal;
} else { for (int i = 0; i < line.length(); i++) {
if (lastTokenWasEscaped) { char nextTok = line.charAt(i);
if (nextTok == 't') nextTok = '\t'; switch (state) {
if (nextTok == 'b') nextTok = '\b'; case inQuote -> {
if (nextTok == 'n') nextTok = '\n'; if (nextTok == '\\') {
if (nextTok == 'r') nextTok = '\r'; lastTokenWasEscaped = true;
if (nextTok == 'f') nextTok = '\f'; } else if (nextTok == '\'' && !lastTokenWasEscaped) {
lastTokenHasBeenQuoted = true;
state = normal;
} else {
if (lastTokenWasEscaped) {
if (nextTok == 't') nextTok = '\t';
if (nextTok == 'b') nextTok = '\b';
if (nextTok == 'n') nextTok = '\n';
if (nextTok == 'r') nextTok = '\r';
if (nextTok == 'f') nextTok = '\f';
}
current.append(nextTok);
lastTokenWasEscaped = false;
}
}
case inDoubleQuote -> {
if (nextTok == '\\') {
lastTokenWasEscaped = true;
} else if (nextTok == '\"' && !lastTokenWasEscaped) {
lastTokenHasBeenQuoted = true;
state = normal;
} else {
if (lastTokenWasEscaped) {
if (nextTok == 't') nextTok = '\t';
if (nextTok == 'b') nextTok = '\b';
if (nextTok == 'n') nextTok = '\n';
if (nextTok == 'r') nextTok = '\r';
if (nextTok == 'f') nextTok = '\f';
}
current.append(nextTok);
lastTokenWasEscaped = false;
}
}
default -> {
switch (nextTok) {
case '\\' -> lastTokenWasEscaped = true;
case '\'' -> state = inQuote;
case '\"' -> state = inDoubleQuote;
case ' ' -> {
if (!lastTokenWasEscaped && (lastTokenHasBeenQuoted || current.length() != 0)) {
result.add(current.toString());
current.setLength(0);
}
}
default -> {
if (lastTokenWasEscaped) {
if (nextTok == 't') nextTok = '\t';
if (nextTok == 'b') nextTok = '\b';
if (nextTok == 'n') nextTok = '\n';
if (nextTok == 'r') nextTok = '\r';
if (nextTok == 'f') nextTok = '\f';
lastTokenWasEscaped = false;
}
current.append(nextTok);
}
}
lastTokenHasBeenQuoted = false;
}
} }
current.append(nextTok);
lastTokenWasEscaped = false;
}
} }
case inDoubleQuote -> { if (lastTokenHasBeenQuoted || current.length() != 0) {
if (nextTok == '\\') { result.add(current.toString());
lastTokenWasEscaped = true;
} else if (nextTok == '\"' && !lastTokenWasEscaped) {
lastTokenHasBeenQuoted = true;
state = normal;
} else {
if (lastTokenWasEscaped) {
if (nextTok == 't') nextTok = '\t';
if (nextTok == 'b') nextTok = '\b';
if (nextTok == 'n') nextTok = '\n';
if (nextTok == 'r') nextTok = '\r';
if (nextTok == 'f') nextTok = '\f';
}
current.append(nextTok);
lastTokenWasEscaped = false;
}
} }
default -> { if (state == inQuote || state == inDoubleQuote) {
switch (nextTok) { throw new FirescriptFormatException("unbalanced quotes in " + line);
case '\\' -> lastTokenWasEscaped = true;
case '\'' -> state = inQuote;
case '\"' -> state = inDoubleQuote;
case ' ' -> {
if (!lastTokenWasEscaped && (lastTokenHasBeenQuoted || current.length() != 0)) {
result.add(current.toString());
current.setLength(0);
}
}
default -> {
if (lastTokenWasEscaped) {
if (nextTok == 't') nextTok = '\t';
if (nextTok == 'b') nextTok = '\b';
if (nextTok == 'n') nextTok = '\n';
if (nextTok == 'r') nextTok = '\r';
if (nextTok == 'f') nextTok = '\f';
lastTokenWasEscaped = false;
}
current.append(nextTok);
}
}
lastTokenHasBeenQuoted = false;
} }
} return result.toArray(new String[result.size()]);
} }
if (lastTokenHasBeenQuoted || current.length() != 0) {
result.add(current.toString());
}
if (state == inQuote || state == inDoubleQuote) {
throw new FirescriptFormatException("unbalanced quotes in " + line);
}
return result.toArray(new String[result.size()]);
}
} }

View File

@ -24,51 +24,51 @@ import java.io.IOException;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE; import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
public class Rowlf { public class Rowlf {
JFrame frame = new JFrame(); JFrame frame = new JFrame();
JPanel frameContainer; JPanel frameContainer;
Image logo; Image logo;
JLabel picLabel; JLabel picLabel;
private JTextField informationText; private JTextField informationText;
private JLabel versionLabel; private JLabel versionLabel;
private JLabel environmentLabel; private JLabel environmentLabel;
public Rowlf(JFrame parent) { public Rowlf(JFrame parent) {
try { try {
logo = ImageIO.read(Main.class.getResourceAsStream("/logo.png")).getScaledInstance(333, 100, Image.SCALE_SMOOTH); logo = ImageIO.read(Main.class.getResourceAsStream("/logo.png")).getScaledInstance(333, 100, Image.SCALE_SMOOTH);
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Failed to open About screen because we couldn't find an image needed to display the page."); System.out.println("ERROR: Failed to open About screen because we couldn't find an image needed to display the page.");
throw new RuntimeException(e); throw new RuntimeException(e);
} }
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
//frame.add(picLabel); //frame.add(picLabel);
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
picLabel.setIcon(new ImageIcon(logo));picLabel.setText(""); picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
informationText.getDocument().putProperty("filterNewlines", Boolean.FALSE); informationText.getDocument().putProperty("filterNewlines", Boolean.FALSE);
informationText.setHorizontalAlignment(JTextField.CENTER); informationText.setHorizontalAlignment(JTextField.CENTER);
informationText.setText("Created by bonkmaykr, a.k.a. \"Downforce Agent\"\n" + informationText.setText("Created by bonkmaykr, a.k.a. \"Downforce Agent\"\n" +
"\n" + "\n" +
"Special thanks to:\n" + "Special thanks to:\n" +
"ThatOneBonk, for Thallium and for modding help\n" + "ThatOneBonk, for Thallium and for modding help\n" +
"Wirlaburla, for web hosting and code assistance\n" + "Wirlaburla, for web hosting and code assistance\n" +
"Psygnosis, for making our favorite game ever\n" + "Psygnosis, for making our favorite game ever\n" +
"and to all the PSVita hackers who made this possible"); "and to all the PSVita hackers who made this possible");
informationText.setHighlighter(null); informationText.setHighlighter(null);
informationText.getCaret().setVisible(false); informationText.getCaret().setVisible(false);
informationText.setFocusable(false); informationText.setFocusable(false);
versionLabel.setText("Version " + Main.vstr + " (" + Main.vcode + ")"); versionLabel.setText("Version " + Main.vstr + " (" + Main.vcode + ")");
environmentLabel.setText("Running on Java " + System.getProperty("java.version") + " for " + System.getProperty("os.name")); environmentLabel.setText("Running on Java " + System.getProperty("java.version") + " for " + System.getProperty("os.name"));
// display window // display window
frame.setSize(400, 320); frame.setSize(400, 320);
frame.setTitle("About Firestar"); frame.setTitle("About Firestar");
frame.setResizable(false); frame.setResizable(false);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE); frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(parent); frame.setLocationRelativeTo(parent);
frame.setVisible(true); frame.setVisible(true);
} }
} }

View File

@ -20,57 +20,57 @@ import javax.swing.*;
import java.awt.*; import java.awt.*;
public class Scooter { public class Scooter {
private JFrame frame = new JFrame(); private JFrame frame = new JFrame();
public JProgressBar progressBar; public JProgressBar progressBar;
private JPanel frameContainer; private JPanel frameContainer;
private JLabel label; private JLabel label;
public void showDialog(String title) { public void showDialog(String title) {
frame.add(frameContainer); frame.add(frameContainer);
frame.setSize(300, 100); frame.setSize(300, 100);
frame.setTitle(title); frame.setTitle(title);
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(null); frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
progressBar.setStringPainted(true); progressBar.setStringPainted(true);
frame.setVisible(true); frame.setVisible(true);
} }
public void setProgressMin(int i) { public void setProgressMin(int i) {
progressBar.setMinimum(i); progressBar.setMinimum(i);
} }
public void setProgressValue(int i) { public void setProgressValue(int i) {
progressBar.setValue(i); progressBar.setValue(i);
} }
public void setProgressMax(int i) { public void setProgressMax(int i) {
progressBar.setMaximum(i); progressBar.setMaximum(i);
} }
public int getProgressMin() { public int getProgressMin() {
return progressBar.getMinimum(); return progressBar.getMinimum();
} }
public int getProgressValue() { public int getProgressValue() {
return progressBar.getValue(); return progressBar.getValue();
} }
public int getProgressMax() { public int getProgressMax() {
return progressBar.getMaximum(); return progressBar.getMaximum();
} }
public void setText(String text) { public void setText(String text) {
label.setText(text); label.setText(text);
} }
public void destroyDialog() { public void destroyDialog() {
frame.setVisible(false); frame.setVisible(false);
frame.dispose(); frame.dispose();
} }
} }

View File

@ -51,45 +51,45 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
public class Suggs implements ActionListener, ListSelectionListener { public class Suggs implements ActionListener, ListSelectionListener {
public JFrame frame = new JFrame(); public JFrame frame = new JFrame();
private JPanel frameContainer; private JPanel frameContainer;
private JList dSongList; private JList dSongList;
private JButton moveDownBtn; private JButton moveDownBtn;
private JButton saveBtn; private JButton saveBtn;
private JButton cancelBtn; private JButton cancelBtn;
private JTextField fTitle; private JTextField fTitle;
private JTextField fArtist; private JTextField fArtist;
private JLabel dTrackNo; private JLabel dTrackNo;
private JLabel dFileSize; private JLabel dFileSize;
private JButton frontendDemoChooseBtn; private JButton frontendDemoChooseBtn;
private JButton frontendMainChooseBtn; private JButton frontendMainChooseBtn;
private JButton deleteSongBtn; private JButton deleteSongBtn;
private JButton addSongBtn; private JButton addSongBtn;
private JButton moveUpBtn; private JButton moveUpBtn;
private JLabel dSTitle; private JLabel dSTitle;
private JLabel dMTitle; private JLabel dMTitle;
private JLabel dSSize; private JLabel dSSize;
private JLabel dMSize; private JLabel dMSize;
private JCheckBox checkAdditive; private JCheckBox checkAdditive;
private JButton spDeleteBtn; private JButton spDeleteBtn;
private JButton mpDeleteBtn; private JButton mpDeleteBtn;
private JCheckBox checkNormalize; private JCheckBox checkNormalize;
private Scooter progressDialog; private Scooter progressDialog;
JFrame parent; JFrame parent;
int curIndex = -1; int curIndex = -1;
boolean normalizeVolumes = false; boolean normalizeVolumes = false;
public class AudioTrack { public class AudioTrack {
public File path; // file name public File path; // file name
public String title; // audio title public String title; // audio title
public String artist; // audio artist public String artist; // audio artist
public long size; // file size in bytes public long size; // file size in bytes
public boolean noConvert; public boolean noConvert;
} }
private List<AudioTrack> tracklist = new ArrayList<AudioTrack>(); private List<AudioTrack> tracklist = new ArrayList<AudioTrack>();
private File sptrack; private File sptrack;
private File mptrack; private File mptrack;
DocumentListener id3TagEditorHandler = new DocumentListener() { DocumentListener id3TagEditorHandler = new DocumentListener() {
@Override @Override
@ -108,48 +108,48 @@ public class Suggs implements ActionListener, ListSelectionListener {
} }
}; };
public Suggs(JFrame parent) { public Suggs(JFrame parent) {
this.parent = parent; this.parent = parent;
parent.setEnabled(false); parent.setEnabled(false);
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
frame.setSize(700, 400); frame.setSize(700, 400);
frame.setMinimumSize(new Dimension(700,400)); frame.setMinimumSize(new Dimension(700,400));
frame.setTitle("Soundtrack Mod Generator"); frame.setTitle("Soundtrack Mod Generator");
frame.setResizable(true); frame.setResizable(true);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(parent); frame.setLocationRelativeTo(parent);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
cancelBtn.addActionListener(this); cancelBtn.addActionListener(this);
saveBtn.addActionListener(this); saveBtn.addActionListener(this);
addSongBtn.addActionListener(this); // file picker addSongBtn.addActionListener(this); // file picker
deleteSongBtn.addActionListener(this); // delete from list deleteSongBtn.addActionListener(this); // delete from list
moveUpBtn.addActionListener(this); moveUpBtn.addActionListener(this);
moveDownBtn.addActionListener(this); moveDownBtn.addActionListener(this);
fTitle.addActionListener(this); // automatically change selected item when changed & fTitle.addActionListener(this); // automatically change selected item when changed &
fArtist.addActionListener(this); // also update field when new item selected fArtist.addActionListener(this); // also update field when new item selected
frontendMainChooseBtn.addActionListener(this); // file picker for singleplayer campaign grid music frontendMainChooseBtn.addActionListener(this); // file picker for singleplayer campaign grid music
frontendDemoChooseBtn.addActionListener(this); // file picker for multiplayer lobby music frontendDemoChooseBtn.addActionListener(this); // file picker for multiplayer lobby music
spDeleteBtn.addActionListener(this); spDeleteBtn.addActionListener(this);
mpDeleteBtn.addActionListener(this); mpDeleteBtn.addActionListener(this);
dSongList.addListSelectionListener(this); dSongList.addListSelectionListener(this);
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) public void windowClosing(WindowEvent e)
{ {
if (!tracklist.isEmpty() || sptrack != null || mptrack != null) { if (!tracklist.isEmpty() || sptrack != null || mptrack != null) {
int result = JOptionPane.showConfirmDialog(frame, "Are you sure?\nAll unsaved changes will be lost.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); int result = JOptionPane.showConfirmDialog(frame, "Are you sure?\nAll unsaved changes will be lost.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (result == JOptionPane.NO_OPTION) {return;} if (result == JOptionPane.NO_OPTION) {return;}
} }
parent.setEnabled(true); parent.setEnabled(true);
e.getWindow().dispose(); e.getWindow().dispose();
} }
}); });
fTitle.setText(""); fTitle.setText("");
fArtist.setText(""); fArtist.setText("");
@ -161,53 +161,53 @@ public class Suggs implements ActionListener, ListSelectionListener {
fTitle.getDocument().addDocumentListener(id3TagEditorHandler); fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
fArtist.getDocument().addDocumentListener(id3TagEditorHandler); fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
frame.setVisible(true); frame.setVisible(true);
} }
private void haveSeggs() { // kill yourself private void haveSeggs() { // kill yourself
} }
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent.getSource() == cancelBtn) { if (actionEvent.getSource() == cancelBtn) {
if (!tracklist.isEmpty() || sptrack != null || mptrack != null) { if (!tracklist.isEmpty() || sptrack != null || mptrack != null) {
int result = JOptionPane.showConfirmDialog(frame, "Are you sure?\nAll unsaved changes will be lost.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); int result = JOptionPane.showConfirmDialog(frame, "Are you sure?\nAll unsaved changes will be lost.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (result == JOptionPane.NO_OPTION) {return;} if (result == JOptionPane.NO_OPTION) {return;}
} }
parent.setEnabled(true); parent.setEnabled(true);
frame.dispose(); frame.dispose();
} else } else
if (actionEvent.getSource() == addSongBtn) {addSong();} else if (actionEvent.getSource() == addSongBtn) {addSong();} else
if (actionEvent.getSource() == deleteSongBtn) {remove(curIndex);} else if (actionEvent.getSource() == deleteSongBtn) {remove(curIndex);} else
if (actionEvent.getSource() == moveUpBtn) {moveUp(curIndex);} else if (actionEvent.getSource() == moveUpBtn) {moveUp(curIndex);} else
if (actionEvent.getSource() == moveDownBtn) {moveDown(curIndex);} else if (actionEvent.getSource() == moveDownBtn) {moveDown(curIndex);} else
if (actionEvent.getSource() == frontendMainChooseBtn) {setSPMusic();} else if (actionEvent.getSource() == frontendMainChooseBtn) {setSPMusic();} else
if (actionEvent.getSource() == frontendDemoChooseBtn) {setMPMusic();} else if (actionEvent.getSource() == frontendDemoChooseBtn) {setMPMusic();} else
if (actionEvent.getSource() == saveBtn) { if (actionEvent.getSource() == saveBtn) {
if (tracklist.isEmpty() && sptrack == null && mptrack == null) { if (tracklist.isEmpty() && sptrack == null && mptrack == null) {
JOptionPane.showMessageDialog(frame, "Please add at least one song to the playlist.", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "Please add at least one song to the playlist.", "Error", JOptionPane.ERROR_MESSAGE);
return; return;
} else {
String deets;
if (tracklist.isEmpty()) {
deets = "no songs";
} else { } else {
deets = tracklist.size() + " songs"; String deets;
if (tracklist.isEmpty()) {
deets = "no songs";
} else {
deets = tracklist.size() + " songs";
}
if (sptrack != null && mptrack == null) {
deets = deets + " and a custom campaign menu track";
} else if (mptrack != null && sptrack == null) {
deets = deets + " and a custom lobby menu track";
} else if (mptrack != null && sptrack != null) {
deets = deets + ", a custom campaign menu track, and a custom lobby menu track";
}
int result = JOptionPane.showConfirmDialog(frame, "Your custom playlist with " + deets + " will be generated.\nPress YES to continue, or NO to continue editing.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
save();
}
} }
if (sptrack != null && mptrack == null) { } else
deets = deets + " and a custom campaign menu track";
} else if (mptrack != null && sptrack == null) {
deets = deets + " and a custom lobby menu track";
} else if (mptrack != null && sptrack != null) {
deets = deets + ", a custom campaign menu track, and a custom lobby menu track";
}
int result = JOptionPane.showConfirmDialog(frame, "Your custom playlist with " + deets + " will be generated.\nPress YES to continue, or NO to continue editing.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
save();
}
}
} else
if (actionEvent.getSource() == spDeleteBtn) { if (actionEvent.getSource() == spDeleteBtn) {
dSTitle.setText("no track"); dSTitle.setText("no track");
dSSize.setText("no size"); dSSize.setText("no size");
@ -220,40 +220,40 @@ public class Suggs implements ActionListener, ListSelectionListener {
mptrack = null; mptrack = null;
mpDeleteBtn.setVisible(false); mpDeleteBtn.setVisible(false);
} }
} }
@Override @Override
public void valueChanged(ListSelectionEvent listSelectionEvent) { public void valueChanged(ListSelectionEvent listSelectionEvent) {
fTitle.getDocument().removeDocumentListener(id3TagEditorHandler); fTitle.getDocument().removeDocumentListener(id3TagEditorHandler);
fArtist.getDocument().removeDocumentListener(id3TagEditorHandler); fArtist.getDocument().removeDocumentListener(id3TagEditorHandler);
curIndex = dSongList.getSelectedIndex(); curIndex = dSongList.getSelectedIndex();
if (curIndex >= 0) { if (curIndex >= 0) {
fTitle.setEnabled(true); fTitle.setEnabled(true);
fArtist.setEnabled(true); fArtist.setEnabled(true);
AudioTrack at = tracklist.get(curIndex); AudioTrack at = tracklist.get(curIndex);
fTitle.setText(at.title); fTitle.setText(at.title);
fArtist.setText(at.artist); fArtist.setText(at.artist);
dTrackNo.setText(String.format("MT_%02d", curIndex+1)); dTrackNo.setText(String.format("MT_%02d", curIndex+1));
dFileSize.setText(at.size + " B"); dFileSize.setText(at.size + " B");
if (at.size > 1023) { if (at.size > 1023) {
dFileSize.setText((at.size / 1024) + " KB"); dFileSize.setText((at.size / 1024) + " KB");
}
if (at.size > 1048575) {
dFileSize.setText((at.size / 1048576) + " MB");
}
fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
} else {
fTitle.setEnabled(false);
fArtist.setEnabled(false);
fTitle.setText("");
fArtist.setText("");
dTrackNo.setText("\u200E");
dFileSize.setText("\u200E");
fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
} }
if (at.size > 1048575) {
dFileSize.setText((at.size / 1048576) + " MB");
}
fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
} else {
fTitle.setEnabled(false);
fArtist.setEnabled(false);
fTitle.setText("");
fArtist.setText("");
dTrackNo.setText("\u200E");
dFileSize.setText("\u200E");
fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
} }
}
private void updateSelectionToMatchTextFields() { private void updateSelectionToMatchTextFields() {
tracklist.get(curIndex).title = fTitle.getText(); tracklist.get(curIndex).title = fTitle.getText();
@ -262,52 +262,56 @@ public class Suggs implements ActionListener, ListSelectionListener {
dSongList.setSelectedIndex(curIndex); dSongList.setSelectedIndex(curIndex);
} }
private void remove(int index) { private void remove(int index) {
if (index >= 0) { if (index >= 0) {
tracklist.remove(index); tracklist.remove(index);
InitializeSongListInGUI(); InitializeSongListInGUI();
} }
} }
private void moveUp(int index) { private void moveUp(int index) {
if (index > 0) { if (index > 0) {
Collections.swap(tracklist, index, index - 1); Collections.swap(tracklist, index, index - 1);
InitializeSongListInGUI(); InitializeSongListInGUI();
} }
} }
private void moveDown(int index) { private void moveDown(int index) {
if (index < (tracklist.size() - 1)) { if (index < (tracklist.size() - 1)) {
Collections.swap(tracklist, index, index + 1); Collections.swap(tracklist, index, index + 1);
InitializeSongListInGUI(); InitializeSongListInGUI();
} }
} }
private void InitializeSongListInGUI() { private void InitializeSongListInGUI() {
dSongList.removeListSelectionListener(this); // prevent weird bullshit dSongList.removeListSelectionListener(this); // prevent weird bullshit
dSongList.clearSelection(); dSongList.clearSelection();
dSongList.removeAll(); dSongList.removeAll();
dSongList.setVisibleRowCount(tracklist.size()); dSongList.setVisibleRowCount(tracklist.size());
dSongList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); dSongList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// add text entry for each // add text entry for each
int i = 0; int i = 0;
String[] contents = new String[tracklist.size()]; String[] contents = new String[tracklist.size()];
while (i < tracklist.size()) { while (i < tracklist.size()) {
String dTitleInList; // avoid editing the actual list String dTitleInList; // avoid editing the actual list
String dArtistInList; // otherwise we cause weird JTextField behavior String dArtistInList; // otherwise we cause weird JTextField behavior
if (tracklist.get(i).title == null || tracklist.get(i).title.isEmpty()) if (tracklist.get(i).title == null || tracklist.get(i).title.isEmpty())
{dTitleInList = tracklist.get(i).path.getName();} else {dTitleInList = tracklist.get(i).title;} dTitleInList = tracklist.get(i).path.getName();
if (tracklist.get(i).artist == null || tracklist.get(i).artist.isEmpty()) else
{dArtistInList = "Unknown Artist";} else {dArtistInList = tracklist.get(i).artist;} dTitleInList = tracklist.get(i).title;
contents[i] = dArtistInList + " - " + dTitleInList; if (tracklist.get(i).artist == null || tracklist.get(i).artist.isEmpty())
dArtistInList = "Unknown Artist";
else
dArtistInList = tracklist.get(i).artist;
contents[i] = dArtistInList + " - " + dTitleInList;
i++; i++;
} }
dSongList.setListData(contents); dSongList.setListData(contents);
dSongList.setSelectedIndex(curIndex); dSongList.setSelectedIndex(curIndex);
dSongList.addListSelectionListener(this); dSongList.addListSelectionListener(this);
} }
private JFileChooser commonSoundFilePicker(boolean multiselect) { private JFileChooser commonSoundFilePicker(boolean multiselect) {
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
@ -325,13 +329,13 @@ public class Suggs implements ActionListener, ListSelectionListener {
return fileChooser; return fileChooser;
} }
private void setSPMusic() { private void setSPMusic() {
JFileChooser fileChooser = commonSoundFilePicker(false); JFileChooser fileChooser = commonSoundFilePicker(false);
int result = fileChooser.showOpenDialog(frame); int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) { if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile(); File selectedFile = fileChooser.getSelectedFile();
sptrack = selectedFile; sptrack = selectedFile;
dSTitle.setText(selectedFile.getName()); dSTitle.setText(selectedFile.getName());
dSSize.setText(selectedFile.length() + " B"); dSSize.setText(selectedFile.length() + " B");
if (selectedFile.length() > 1023) { if (selectedFile.length() > 1023) {
dSSize.setText((selectedFile.length() / 1024) + " KB"); dSSize.setText((selectedFile.length() / 1024) + " KB");
@ -340,267 +344,267 @@ public class Suggs implements ActionListener, ListSelectionListener {
dSSize.setText((selectedFile.length() / 1048576) + " MB"); dSSize.setText((selectedFile.length() / 1048576) + " MB");
} }
spDeleteBtn.setVisible(true); spDeleteBtn.setVisible(true);
} }
} }
private void setMPMusic() { private void setMPMusic() {
JFileChooser fileChooser = commonSoundFilePicker(false); JFileChooser fileChooser = commonSoundFilePicker(false);
int result = fileChooser.showOpenDialog(frame); int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) { if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile(); File selectedFile = fileChooser.getSelectedFile();
mptrack = selectedFile; mptrack = selectedFile;
dMTitle.setText(selectedFile.getName()); dMTitle.setText(selectedFile.getName());
dMSize.setText(selectedFile.length() + " B"); dMSize.setText(selectedFile.length() + " B");
if (selectedFile.length() > 1023) { if (selectedFile.length() > 1023) {
dMSize.setText((selectedFile.length() / 1024) + " KB"); dMSize.setText((selectedFile.length() / 1024) + " KB");
}
if (selectedFile.length() > 1048575) {
dMSize.setText((selectedFile.length() / 1048576) + " MB");
}
mpDeleteBtn.setVisible(true);
}
}
private void addSong() {
JFileChooser fileChooser = commonSoundFilePicker(true);
int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
File[] selectedFiles = fileChooser.getSelectedFiles();
for (File f : selectedFiles) {
if (f.exists()) {
System.out.println("Importing audio file \"" + f.getName() + "\"");
AudioTrack track = new AudioTrack();
track.path = f;
String fname = f.getName();
if (fname.contains(" - ")) {
track.title = fname.substring(fname.indexOf(" - ")+3, fname.lastIndexOf("."));
track.artist = fname.substring(0, fname.indexOf(" - "));
} else track.title = fname;
track.size = f.length();
tracklist.add(track);
}
}
InitializeSongListInGUI();
}
}
private void save() {
frame.setEnabled(false);
frame.setAlwaysOnTop(false);
normalizeVolumes = checkNormalize.isSelected();
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/")); // starts with clean temp
new Thread(() -> {
int progressSize = tracklist.size()+(sptrack != null?1:0)+(mptrack != null?1:0)+1; // Accounting for processes
progressDialog = new Scooter();
progressDialog.showDialog("Soundtrack Mod Generator");
progressDialog.setText("Generating audio files...");
progressDialog.setProgressMax(progressSize);
progressDialog.setProgressValue(0);
progressDialog.progressBar.setStringPainted(false);
try {
new File(Main.inpath + "temp/data/audio/music").mkdirs();
FileOutputStream fos = new FileOutputStream(new File(Main.inpath + "temp/fscript"));
PrintStream ps = new PrintStream(fos);
ps.println("fscript 1");
ps.println("# AUTOGENERATED BY FIRESTAR");
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
for (int i = 0; i < tracklist.size(); i++) {
AudioTrack at = tracklist.get(i);
String trackno = String.format("%02d", i+1);
String oTitle;
if (at.title == null) {oTitle = "";} else {oTitle = at.title;}
String oArtist;
if (at.artist == null) {oArtist = "";} else {oArtist = at.artist;}
new File(Main.inpath + "temp/data/audio/music/" + trackno).mkdirs();
if (at.path.getName().endsWith(".at9")) {
progressDialog.setText("Copying track " + (i+1) + " out of " + tracklist.size() + "...");
try {
// Assume whoever made the AT9s knows what they're doing
System.out.println("Copying track #" + (i+1) + " \"" + at.artist + " - " + at.title + "\"...");
Files.copy(at.path.toPath(), Paths.get(Main.inpath + "temp/data/audio/music/" + trackno + "/music_stereo.at9"), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
} }
} else { if (selectedFile.length() > 1048575) {
progressDialog.setText("Encoding track " + (i+1) + " out of " + tracklist.size() + "..."); dMSize.setText((selectedFile.length() / 1048576) + " MB");
try { }
System.out.println("Encoding track #" + (i+1) + " \"" + oArtist + " - " + oTitle + "\"..."); mpDeleteBtn.setVisible(true);
if (!at.path.getName().endsWith(".wav") && !at.path.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet }
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "ffmpeg/" + at.path.getName() + ".wav"}, Main.inpath + "temp/"); }
p.waitFor();
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + ".wav"); private void addSong() {
JFileChooser fileChooser = commonSoundFilePicker(true);
int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
File[] selectedFiles = fileChooser.getSelectedFiles();
for (File f : selectedFiles) {
if (f.exists()) {
System.out.println("Importing audio file \"" + f.getName() + "\"");
AudioTrack track = new AudioTrack();
track.path = f;
String fname = f.getName();
if (fname.contains(" - ")) {
track.title = fname.substring(fname.indexOf(" - ")+3, fname.lastIndexOf("."));
track.artist = fname.substring(0, fname.indexOf(" - "));
} else track.title = fname;
track.size = f.length();
tracklist.add(track);
} }
if (normalizeVolumes) { // normalize tracks }
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "-filter", "loudnorm=linear=true:i=-5.0:lra=7.0:tp=0.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + at.path.getName() + "_normalized.wav"}, Main.inpath + "temp/"); InitializeSongListInGUI();
p.waitFor(); }
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + "_normalized.wav"); }
private void save() {
frame.setEnabled(false);
frame.setAlwaysOnTop(false);
normalizeVolumes = checkNormalize.isSelected();
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/")); // starts with clean temp
new Thread(() -> {
int progressSize = tracklist.size()+(sptrack != null?1:0)+(mptrack != null?1:0)+1; // Accounting for processes
progressDialog = new Scooter();
progressDialog.showDialog("Soundtrack Mod Generator");
progressDialog.setText("Generating audio files...");
progressDialog.setProgressMax(progressSize);
progressDialog.setProgressValue(0);
progressDialog.progressBar.setStringPainted(false);
try {
new File(Main.inpath + "temp/data/audio/music").mkdirs();
FileOutputStream fos = new FileOutputStream(new File(Main.inpath + "temp/fscript"));
PrintStream ps = new PrintStream(fos);
ps.println("fscript 1");
ps.println("# AUTOGENERATED BY FIRESTAR");
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
for (int i = 0; i < tracklist.size(); i++) {
AudioTrack at = tracklist.get(i);
String trackno = String.format("%02d", i+1);
String oTitle;
if (at.title == null) {oTitle = "";} else {oTitle = at.title;}
String oArtist;
if (at.artist == null) {oArtist = "";} else {oArtist = at.artist;}
new File(Main.inpath + "temp/data/audio/music/" + trackno).mkdirs();
if (at.path.getName().endsWith(".at9")) {
progressDialog.setText("Copying track " + (i+1) + " out of " + tracklist.size() + "...");
try {
// Assume whoever made the AT9s knows what they're doing
System.out.println("Copying track #" + (i+1) + " \"" + at.artist + " - " + at.title + "\"...");
Files.copy(at.path.toPath(), Paths.get(Main.inpath + "temp/data/audio/music/" + trackno + "/music_stereo.at9"), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
} }
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", at.path.getPath(), "data/audio/music/" + trackno + "/music_stereo.at9"}, Main.inpath + "temp/"); } else {
p.waitFor(); progressDialog.setText("Encoding track " + (i+1) + " out of " + tracklist.size() + "...");
} catch (IOException | InterruptedException ex) { try {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex); System.out.println("Encoding track #" + (i+1) + " \"" + oArtist + " - " + oTitle + "\"...");
} if (!at.path.getName().endsWith(".wav") && !at.path.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
} Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "ffmpeg/" + at.path.getName() + ".wav"}, Main.inpath + "temp/");
String ocmd = "modify"; p.waitFor();
if (i >= 12) ocmd = "create"; at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + ".wav");
String oArtistLine;
if (!oArtist.isEmpty()) {
oArtistLine = oArtist.replace("\"", "\\\"")+"\\n";
} else {
oArtistLine = "";
}
int i2 = 0;
while (i2 < 15 /*17 languages*/) {
String language = "INTERNAL_ERROR";
switch (i2) {
case 0 -> language = "american";
case 1 -> language = "danish";
case 2 -> language = "dutch";
case 3 -> language = "english";
case 4 -> language = "finnish";
case 5 -> language = "french";
case 6 -> language = "german";
case 7 -> language = "italian";
case 8 -> language = "japanese";
case 9 -> language = "norwegian";
case 10 -> language = "polish";
case 11 -> language = "portuguese";
case 12 -> language = "russian";
case 13 -> language = "spanish";
case 14 -> language = "swedish";
default -> {
int result = JOptionPane.showConfirmDialog(frame, "Firestar encountered an internal error.\nString 'language' exported to FSCRIPT was blank.", "Fatal Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
if (result == JOptionPane.OK_OPTION) {System.exit(1);} //user safety
} }
if (normalizeVolumes) { // normalize tracks
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "-filter", "loudnorm=linear=true:i=-5.0:lra=7.0:tp=0.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + at.path.getName() + "_normalized.wav"}, Main.inpath + "temp/");
p.waitFor();
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + "_normalized.wav");
}
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", at.path.getPath(), "data/audio/music/" + trackno + "/music_stereo.at9"}, Main.inpath + "temp/");
p.waitFor();
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
} }
//case 9: language = "korean"; break; }
//case 16: language = "traditionalchinese"; break; String ocmd = "modify";
ps.println("file \"data/plugins/languages/"+language+"/entries.xml\" xml "+ocmd+" StringTable.entry#MT_"+trackno+" set attribute \"string\" \""+oArtistLine+oTitle.replace("\"", "\\\"")+"\""); if (i >= 12) ocmd = "create";
i2++; String oArtistLine;
if (!oArtist.isEmpty()) {
oArtistLine = oArtist.replace("\"", "\\\"")+"\\n";
} else {
oArtistLine = "";
}
int i2 = 0;
while (i2 < 15 /*17 languages*/) {
String language = "INTERNAL_ERROR";
switch (i2) {
case 0 -> language = "american";
case 1 -> language = "danish";
case 2 -> language = "dutch";
case 3 -> language = "english";
case 4 -> language = "finnish";
case 5 -> language = "french";
case 6 -> language = "german";
case 7 -> language = "italian";
case 8 -> language = "japanese";
case 9 -> language = "norwegian";
case 10 -> language = "polish";
case 11 -> language = "portuguese";
case 12 -> language = "russian";
case 13 -> language = "spanish";
case 14 -> language = "swedish";
default -> {
int result = JOptionPane.showConfirmDialog(frame, "Firestar encountered an internal error.\nString 'language' exported to FSCRIPT was blank.", "Fatal Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
if (result == JOptionPane.OK_OPTION) {System.exit(1);} //user safety
}
}
//case 9: language = "korean"; break;
//case 16: language = "traditionalchinese"; break;
ps.println("file \"data/plugins/languages/"+language+"/entries.xml\" xml "+ocmd+" StringTable.entry#MT_"+trackno+" set attribute \"string\" \""+oArtistLine+oTitle.replace("\"", "\\\"")+"\"");
i2++;
}
ps.println("file \"data/audio/music/"+trackno+"/music_stereo.fft\" delete");
progressDialog.setProgressValue(i+1);
} }
ps.println("file \"data/audio/music/"+trackno+"/music_stereo.fft\" delete"); for (int s = tracklist.size(); s < 12; s++) {
progressDialog.setProgressValue(i+1); ps.println("file \"data/audio/music/"+String.format("%02d", s+1)+"/music_stereo.fft\" delete");
} }
for (int s = tracklist.size(); s < 12; s++) { if (sptrack != null) {
ps.println("file \"data/audio/music/"+String.format("%02d", s+1)+"/music_stereo.fft\" delete"); progressDialog.setText("Encoding singleplayer frontend track...");
} if (sptrack.exists()) {
if (sptrack != null) { try {
progressDialog.setText("Encoding singleplayer frontend track..."); System.out.println("Encoding singleplayer frontend track...");
if (sptrack.exists()) { if (!sptrack.getName().endsWith(".wav") && !sptrack.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "ffmpeg/" + sptrack.getName() + ".wav"}, Main.inpath + "temp/");
p.waitFor();
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + ".wav");
}
if (normalizeVolumes) { // normalize tracks
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "-filter", "loudnorm=linear=true:i=-10.0:lra=12.0:tp=-2.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + sptrack.getName() + "_normalized.wav"}, Main.inpath + "temp/");
p.waitFor();
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + "_normalized.wav");
}
new File(Main.inpath + "temp/data/audio/music/FEMusic").mkdirs();
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", sptrack.getPath(), "data/audio/music/FEMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/");
p.waitFor();
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
}
}
ps.println("file \"data/audio/music/FEMusic/frontend_stereo.fft\" delete");
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
}
if (mptrack != null) {
progressDialog.setText("Encoding multiplayer frontend track...");
try {
assert(mptrack.exists());
System.out.println("Encoding multiplayer frontend track...");
if (!mptrack.getName().endsWith(".wav") && !mptrack.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "ffmpeg/" + mptrack.getName() + ".wav"}, Main.inpath + "temp/");
p.waitFor();
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + ".wav");
}
if (normalizeVolumes) { // normalize tracks
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "-filter", "loudnorm=linear=true:i=-10.0:lra=12.0:tp=-2.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + mptrack.getName() + "_normalized.wav"}, Main.inpath + "temp/");
p.waitFor();
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + "_normalized.wav");
}
new File(Main.inpath + "temp/data/audio/music/FEDemoMusic").mkdirs();
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", mptrack.getPath(), "data/audio/music/FEDemoMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/");
p.waitFor();
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
}
ps.println("file \"data/audio/music/FEDemoMusic/frontend_stereo.fft\" delete");
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
}
System.out.println("Finished encoding.");
progressDialog.setText("Generating Music Definitions...");
try { try {
System.out.println("Encoding singleplayer frontend track..."); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
if (!sptrack.getName().endsWith(".wav") && !sptrack.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "ffmpeg/" + sptrack.getName() + ".wav"}, Main.inpath + "temp/");
p.waitFor(); Document defDoc = docBuilder.newDocument();
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + ".wav"); Element docScreen = defDoc.createElement("Screen");
docScreen.setAttribute("name", "Top");
for (int i = 0; i < tracklist.size(); i++) { // TODO: support for additive
AudioTrack at = tracklist.get(i);
String trackno = String.format("%02d", i+1);
Element trackElem = defDoc.createElement("PI_Music");
trackElem.setAttribute("name", trackno);
Element pathElem = defDoc.createElement("Values");
pathElem.setAttribute("location", "data\\audio\\music\\"+trackno);
trackElem.appendChild(pathElem);
Element artistElem = defDoc.createElement("Entry");
artistElem.setAttribute("Artist", at.artist);
trackElem.appendChild(artistElem);
Element titleElem = defDoc.createElement("Entry");
titleElem.setAttribute("Label", at.title);
trackElem.appendChild(titleElem);
docScreen.appendChild(trackElem);
System.out.println("Adding \"" + trackno + ". " + at.artist + " - " + at.title + "\" to Definition.xml");
} }
if (normalizeVolumes) { // normalize tracks defDoc.appendChild(docScreen);
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "-filter", "loudnorm=linear=true:i=-10.0:lra=12.0:tp=-2.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + sptrack.getName() + "_normalized.wav"}, Main.inpath + "temp/");
p.waitFor(); new File(Main.inpath + "temp/data/plugins/music/").mkdirs();
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + "_normalized.wav"); FileOutputStream output = new FileOutputStream(Main.inpath + "temp/data/plugins/music/Definition.xml");
} TransformerFactory transformerFactory = TransformerFactory.newInstance();
new File(Main.inpath + "temp/data/audio/music/FEMusic").mkdirs(); Transformer transformer = transformerFactory.newTransformer();
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", sptrack.getPath(), "data/audio/music/FEMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/"); DOMSource source = new DOMSource(defDoc);
p.waitFor(); StreamResult result = new StreamResult(output);
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex); transformer.transform(source, result);
} catch (IOException | ParserConfigurationException | TransformerException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
} }
} progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
ps.println("file \"data/audio/music/FEMusic/frontend_stereo.fft\" delete");
progressDialog.setProgressValue(progressDialog.getProgressValue()+1); progressDialog.setText("Finalizing script...");
} System.out.println("Finalizing Fscript...");
if (mptrack != null) { ps.println("# END FIRESTAR AUTOGENERATION");
progressDialog.setText("Encoding multiplayer frontend track..."); ps.close();
try { fos.close();
assert(mptrack.exists()); } catch (IOException ex) {
System.out.println("Encoding multiplayer frontend track...");
if (!mptrack.getName().endsWith(".wav") && !mptrack.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "ffmpeg/" + mptrack.getName() + ".wav"}, Main.inpath + "temp/");
p.waitFor();
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + ".wav");
}
if (normalizeVolumes) { // normalize tracks
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "-filter", "loudnorm=linear=true:i=-10.0:lra=12.0:tp=-2.0", /* force sample rate to prevent Random Stupid Bullshit™ */"-ar", "44100", "ffmpeg/" + mptrack.getName() + "_normalized.wav"}, Main.inpath + "temp/");
p.waitFor();
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + "_normalized.wav");
}
new File(Main.inpath + "temp/data/audio/music/FEDemoMusic").mkdirs();
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", mptrack.getPath(), "data/audio/music/FEDemoMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/");
p.waitFor();
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
} }
ps.println("file \"data/audio/music/FEDemoMusic/frontend_stereo.fft\" delete");
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
}
System.out.println("Finished encoding.");
progressDialog.setText("Generating Music Definitions..."); progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document defDoc = docBuilder.newDocument(); progressDialog.destroyDialog();
Element docScreen = defDoc.createElement("Screen"); frame.dispose();
docScreen.setAttribute("name", "Top"); Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
for (int i = 0; i < tracklist.size(); i++) { // TODO: support for additive Clifford saveDialog = new Clifford();
AudioTrack at = tracklist.get(i); saveDialog.isSoundtrack = true;
String trackno = String.format("%02d", i+1); saveDialog.Action(frame, new File(Main.inpath + "temp/"));
parent.setEnabled(true);
Element trackElem = defDoc.createElement("PI_Music"); }).start();
trackElem.setAttribute("name", trackno); }
Element pathElem = defDoc.createElement("Values");
pathElem.setAttribute("location", "data\\audio\\music\\"+trackno);
trackElem.appendChild(pathElem);
Element artistElem = defDoc.createElement("Entry");
artistElem.setAttribute("Artist", at.artist);
trackElem.appendChild(artistElem);
Element titleElem = defDoc.createElement("Entry");
titleElem.setAttribute("Label", at.title);
trackElem.appendChild(titleElem);
docScreen.appendChild(trackElem);
System.out.println("Adding \"" + trackno + ". " + at.artist + " - " + at.title + "\" to Definition.xml");
}
defDoc.appendChild(docScreen);
new File(Main.inpath + "temp/data/plugins/music/").mkdirs();
FileOutputStream output = new FileOutputStream(Main.inpath + "temp/data/plugins/music/Definition.xml");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(defDoc);
StreamResult result = new StreamResult(output);
transformer.transform(source, result);
} catch (IOException | ParserConfigurationException | TransformerException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
}
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
progressDialog.setText("Finalizing script...");
System.out.println("Finalizing Fscript...");
ps.println("# END FIRESTAR AUTOGENERATION");
ps.close();
fos.close();
} catch (IOException ex) {
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
}
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
progressDialog.destroyDialog();
frame.dispose();
Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
Clifford saveDialog = new Clifford();
saveDialog.isSoundtrack = true;
saveDialog.Action(frame, new File(Main.inpath + "temp/"));
parent.setEnabled(true);
}).start();
}
} }

View File

@ -28,128 +28,128 @@ import java.io.IOException;
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE; import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
public class Waldorf implements ActionListener { public class Waldorf implements ActionListener {
private JFrame frame = new JFrame(); private JFrame frame = new JFrame();
private JPanel frameContainer; private JPanel frameContainer;
private JButton okbtn; private JButton okbtn;
private JButton cancelbtn; private JButton cancelbtn;
private JLabel fOutpath; private JLabel fOutpath;
private JButton resetbtn; private JButton resetbtn;
private JButton bOpenFolder; private JButton bOpenFolder;
private JButton dwnSDKbtn; private JButton dwnSDKbtn;
private JButton dwnARCbtn; private JButton dwnARCbtn;
private JButton fOutpathChangebtn; private JButton fOutpathChangebtn;
private JCheckBox checkUpdatesToggle; private JCheckBox checkUpdatesToggle;
private JButton bDelArcs; private JButton bDelArcs;
MissPiggy invoker; MissPiggy invoker;
private String tOutPath = Main.outpath; private String tOutPath = Main.outpath;
public void Action(MissPiggy inv) { public void Action(MissPiggy inv) {
invoker = inv; invoker = inv;
frame.add(frameContainer); frame.add(frameContainer);
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
frame.setSize(600, 300); // 1280 800 frame.setSize(600, 300); // 1280 800
frame.setMinimumSize(new Dimension(200,100)); frame.setMinimumSize(new Dimension(200,100));
frame.setTitle("Options"); frame.setTitle("Options");
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(inv.frame); frame.setLocationRelativeTo(inv.frame);
frame.setAlwaysOnTop(true); frame.setAlwaysOnTop(true);
cancelbtn.addActionListener(this); cancelbtn.addActionListener(this);
okbtn.addActionListener(this); okbtn.addActionListener(this);
resetbtn.addActionListener(this); resetbtn.addActionListener(this);
bOpenFolder.addActionListener(this); bOpenFolder.addActionListener(this);
bDelArcs.addActionListener(this); bDelArcs.addActionListener(this);
dwnARCbtn.addActionListener(this); dwnARCbtn.addActionListener(this);
dwnSDKbtn.addActionListener(this); dwnSDKbtn.addActionListener(this);
fOutpathChangebtn.addActionListener(this); fOutpathChangebtn.addActionListener(this);
fOutpath.setText(Main.outpath); fOutpath.setText(Main.outpath);
checkUpdatesToggle.setSelected(Main.checkUpdates); checkUpdatesToggle.setSelected(Main.checkUpdates);
frame.setVisible(true); frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) public void windowClosing(WindowEvent e)
{ {
invoker.frame.setEnabled(true); invoker.frame.setEnabled(true);
e.getWindow().dispose(); e.getWindow().dispose();
} }
}); });
} }
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent.getSource() == cancelbtn) { if (actionEvent.getSource() == cancelbtn) {
invoker.frame.setEnabled(true); invoker.frame.setEnabled(true);
frame.dispose(); frame.dispose();
} else } else
if (actionEvent.getSource() == okbtn) { if (actionEvent.getSource() == okbtn) {
Main.outpath = tOutPath; Main.outpath = tOutPath;
Main.checkUpdates = checkUpdatesToggle.isSelected(); Main.checkUpdates = checkUpdatesToggle.isSelected();
Main.writeConf(); Main.writeConf();
Main.loadConf(); Main.loadConf();
invoker.frame.setEnabled(true); invoker.frame.setEnabled(true);
frame.dispose(); frame.dispose();
} else } else
if (actionEvent.getSource() == resetbtn) { if (actionEvent.getSource() == resetbtn) {
int result = JOptionPane.showConfirmDialog(frame,"Are you sure you want to redo the initial setup?", "Restore Default Settings", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); int result = JOptionPane.showConfirmDialog(frame,"Are you sure you want to redo the initial setup?", "Restore Default Settings", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (result == JOptionPane.YES_OPTION) { if (result == JOptionPane.YES_OPTION) {
System.out.println("Restoring default settings"); System.out.println("Restoring default settings");
new File(System.getProperty("user.home") + "/.firestar/firestar.conf").delete(); new File(System.getProperty("user.home") + "/.firestar/firestar.conf").delete();
int result2 = JOptionPane.showConfirmDialog(frame,"Firestar will now close.", "Restore Default Settings", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE); int result2 = JOptionPane.showConfirmDialog(frame,"Firestar will now close.", "Restore Default Settings", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
if (result2 == JOptionPane.OK_OPTION) { if (result2 == JOptionPane.OK_OPTION) {
System.exit(0); System.exit(0);
} }
} }
} else } else
if (actionEvent.getSource() == bOpenFolder) { if (actionEvent.getSource() == bOpenFolder) {
try { try {
Desktop.getDesktop().open(new File(Main.inpath)); Desktop.getDesktop().open(new File(Main.inpath));
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} else } else
if (actionEvent.getSource() == bDelArcs) { if (actionEvent.getSource() == bDelArcs) {
int result = JOptionPane.showConfirmDialog(frame, "All existing PSARC dumps will be deleted.\nDo you want to continue?", "Delete PSARCs", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); int result = JOptionPane.showConfirmDialog(frame, "All existing PSARC dumps will be deleted.\nDo you want to continue?", "Delete PSARCs", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (result == JOptionPane.NO_OPTION) {return;} if (result == JOptionPane.NO_OPTION) {return;}
System.out.println("User requested arc wipe, deleting existing PSARCs"); System.out.println("User requested arc wipe, deleting existing PSARCs");
new File(Main.inpath + "data.psarc").delete(); new File(Main.inpath + "data.psarc").delete();
new File(Main.inpath + "data1.psarc").delete(); new File(Main.inpath + "data1.psarc").delete();
new File(Main.inpath + "data2.psarc").delete(); new File(Main.inpath + "data2.psarc").delete();
new File(Main.inpath + "dlc1.psarc").delete(); new File(Main.inpath + "dlc1.psarc").delete();
new File(Main.inpath + "dlc2.psarc").delete(); new File(Main.inpath + "dlc2.psarc").delete();
JOptionPane.showMessageDialog(frame, "PSARC files purged.", "Delete PSARCs", JOptionPane.INFORMATION_MESSAGE); JOptionPane.showMessageDialog(frame, "PSARC files purged.", "Delete PSARCs", JOptionPane.INFORMATION_MESSAGE);
} else } else
if (actionEvent.getSource() == dwnARCbtn) { if (actionEvent.getSource() == dwnARCbtn) {
new Bert(invoker.frame); new Bert(invoker.frame);
frame.dispose(); frame.dispose();
} else } else
if (actionEvent.getSource() == dwnSDKbtn) { if (actionEvent.getSource() == dwnSDKbtn) {
Thread downloaderPopupThread = new Thread(new Runnable() { Thread downloaderPopupThread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
Main.downloadDependenciesBeforeSetVisible(invoker.frame); Main.downloadDependenciesBeforeSetVisible(invoker.frame);
invoker.frame.setEnabled(true); invoker.frame.setEnabled(true);
} }
}); });
downloaderPopupThread.start(); downloaderPopupThread.start();
frame.dispose(); frame.dispose();
} else } else
if (actionEvent.getSource() == fOutpathChangebtn) { if (actionEvent.getSource() == fOutpathChangebtn) {
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = fileChooser.showOpenDialog(frame); int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) { if (result == JFileChooser.APPROVE_OPTION) {
if (fileChooser.getSelectedFile().isDirectory()) { if (fileChooser.getSelectedFile().isDirectory()) {
tOutPath = fileChooser.getSelectedFile().getAbsolutePath()+"/"; tOutPath = fileChooser.getSelectedFile().getAbsolutePath()+"/";
fOutpath.setText(tOutPath); fOutpath.setText(tOutPath);
} }
} }
} }
} }
} }

View File

@ -31,176 +31,176 @@ import java.nio.file.Files;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE; import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
public class WilkinsCoffee implements ActionListener { public class WilkinsCoffee implements ActionListener {
Image logo; Image logo;
public Pages page; public Pages page;
public JFrame frame = new JFrame(); public JFrame frame = new JFrame();
private JPanel frameContainer; private JPanel frameContainer;
private JLabel picLabel; private JLabel picLabel;
private JEditorPane instructions; private JEditorPane instructions;
private JButton contBtn; private JButton contBtn;
private JPanel inputContainer; private JPanel inputContainer;
private JButton PSARC_downBtn; private JButton PSARC_downBtn;
private JButton PSARC_impBtn; private JButton PSARC_impBtn;
private JPanel inputContainer2; private JPanel inputContainer2;
private JButton EXPORT_openFolderBtn; private JButton EXPORT_openFolderBtn;
private JLabel pathDisplay; private JLabel pathDisplay;
private JPanel checklistContainer; private JPanel checklistContainer;
private JLabel checklistFury; private JLabel checklistFury;
private JLabel checklistHD; private JLabel checklistHD;
private JLabel checklistPatch2; private JLabel checklistPatch2;
private JLabel checklistPatch1; private JLabel checklistPatch1;
private JLabel checklistBase; private JLabel checklistBase;
public enum Pages { public enum Pages {
INTRO(0), INTRO(0),
PSARC(1), PSARC(1),
EXPORT_LOCATION(2), EXPORT_LOCATION(2),
DONE(3); DONE(3);
public final int value; public final int value;
private Pages(int i) { private Pages(int i) {
this.value = i; this.value = i;
} }
} }
private String outPathTemp = System.getProperty("user.home") + "/Documents/"; private String outPathTemp = System.getProperty("user.home") + "/Documents/";
private boolean sdkInstalled = false; private boolean sdkInstalled = false;
public void setup() { public void setup() {
page = Pages.INTRO; page = Pages.INTRO;
inputContainer.setVisible(false); inputContainer.setVisible(false);
checklistContainer.setVisible(false); checklistContainer.setVisible(false);
inputContainer2.setVisible(false); inputContainer2.setVisible(false);
// check if this is windows or not // check if this is windows or not
if(System.getProperty("os.name").contains("Windows")) {Main.windows = true;System.out.println("Assuming we should NOT use WINE based on known system variables.");} if(System.getProperty("os.name").contains("Windows")) {Main.windows = true;System.out.println("Assuming we should NOT use WINE based on known system variables.");}
else {Main.windows = false;System.out.println("Assuming we should use WINE based on known system variables.");} else {Main.windows = false;System.out.println("Assuming we should use WINE based on known system variables.");}
// reformat path slightly for windows // reformat path slightly for windows
if (Main.windows) {outPathTemp.replace("/", "\\");} if (Main.windows) {outPathTemp.replace("/", "\\");}
frame.setIconImage(Main.windowIcon); frame.setIconImage(Main.windowIcon);
try { try {
logo = ImageIO.read(Main.class.getResourceAsStream("/programIcon.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH); logo = ImageIO.read(Main.class.getResourceAsStream("/programIcon.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
picLabel.setIcon(new ImageIcon(logo));picLabel.setText(""); picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images."); System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
picLabel.setText(""); picLabel.setText("");
} }
String bodyRule = "html, body {margin:0px;} p#first-p {margin-top:-13px;} p {margin-left:-20px;}"; String bodyRule = "html, body {margin:0px;} p#first-p {margin-top:-13px;} p {margin-left:-20px;}";
((HTMLDocument)instructions.getDocument()).getStyleSheet().addRule(bodyRule); ((HTMLDocument)instructions.getDocument()).getStyleSheet().addRule(bodyRule);
instructions.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf?? instructions.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf??
contBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f)); contBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
PSARC_downBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f)); PSARC_downBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
PSARC_impBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f)); PSARC_impBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
EXPORT_openFolderBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f)); EXPORT_openFolderBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
contBtn.addActionListener(this); contBtn.addActionListener(this);
PSARC_downBtn.addActionListener(this); PSARC_downBtn.addActionListener(this);
PSARC_impBtn.addActionListener(this); PSARC_impBtn.addActionListener(this);
EXPORT_openFolderBtn.addActionListener(this); EXPORT_openFolderBtn.addActionListener(this);
frame.setSize(400, 400); frame.setSize(400, 400);
frame.setTitle("Firestar Setup"); frame.setTitle("Firestar Setup");
frame.setResizable(false); frame.setResizable(false);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(null); frame.setLocationRelativeTo(null);
frame.setVisible(true); frame.setVisible(true);
} }
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
WilkinsCoffee threadParent = this; WilkinsCoffee threadParent = this;
if (actionEvent.getSource() == PSARC_downBtn) { if (actionEvent.getSource() == PSARC_downBtn) {
Thread waiterThread = new Thread(new Runnable() {@Override Thread waiterThread = new Thread(new Runnable() {@Override
public void run() { public void run() {
if (new Bert(frame).reportWhenDownloaded(threadParent)) { if (new Bert(frame).reportWhenDownloaded(threadParent)) {
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
refreshChecklist(); refreshChecklist();
} }
}}); }});
waiterThread.start(); waiterThread.start();
} else } else
if (actionEvent.getSource() == PSARC_impBtn) { if (actionEvent.getSource() == PSARC_impBtn) {
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
FileFilter fileChooserFilter = new FileNameExtensionFilter("Sony Playstation Archive File", "psarc"); FileFilter fileChooserFilter = new FileNameExtensionFilter("Sony Playstation Archive File", "psarc");
fileChooser.setFileFilter(fileChooserFilter); fileChooser.setFileFilter(fileChooserFilter);
int result = fileChooser.showOpenDialog(frame); int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) { if (result == JFileChooser.APPROVE_OPTION) {
try { try {
Files.copy(fileChooser.getSelectedFile().toPath(), new File(Main.inpath + fileChooser.getSelectedFile().getName()).toPath()); Files.copy(fileChooser.getSelectedFile().toPath(), new File(Main.inpath + fileChooser.getSelectedFile().getName()).toPath());
refreshChecklist(); refreshChecklist();
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
} catch (IOException e) { } catch (IOException e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
} }
} }
} else } else
if (actionEvent.getSource() == EXPORT_openFolderBtn) { if (actionEvent.getSource() == EXPORT_openFolderBtn) {
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = fileChooser.showOpenDialog(frame); int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) { if (result == JFileChooser.APPROVE_OPTION) {
if (fileChooser.getSelectedFile().isDirectory()) { if (fileChooser.getSelectedFile().isDirectory()) {
outPathTemp = fileChooser.getSelectedFile().getAbsolutePath()+"/"; outPathTemp = fileChooser.getSelectedFile().getAbsolutePath()+"/";
pathDisplay.setText("Export path: " + outPathTemp); pathDisplay.setText("Export path: " + outPathTemp);
} }
} }
} else } else
if (actionEvent.getSource() == contBtn) { if (actionEvent.getSource() == contBtn) {
switch (page) { switch (page) {
case INTRO: case INTRO:
if (!new File(Main.inpath + "psp2psarc.exe").exists()) { // we may have been here before // nag if (!new File(Main.inpath + "psp2psarc.exe").exists()) { // we may have been here before // nag
frame.setEnabled(false); frame.setEnabled(false);
int result = JOptionPane.showConfirmDialog(frame, "Firestar needs to download additional software to function. Setup is automatic and will only take a few minutes.\nIf you select NO, you will have to download additional dependencies later on.\n\nContinue?", "Firestar Setup", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); int result = JOptionPane.showConfirmDialog(frame, "Firestar needs to download additional software to function. Setup is automatic and will only take a few minutes.\nIf you select NO, you will have to download additional dependencies later on.\n\nContinue?", "Firestar Setup", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) { if (result == JOptionPane.YES_OPTION) {
sdkInstalled = true; sdkInstalled = true;
Thread downloaderPopupThread = new Thread(new Runnable() { Thread downloaderPopupThread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
Main.downloadDependenciesBeforeSetVisible(frame); Main.downloadDependenciesBeforeSetVisible(frame);
frame.setEnabled(true); frame.setEnabled(true);
} }
}); });
downloaderPopupThread.start(); downloaderPopupThread.start();
} else { } else {
frame.setEnabled(true); frame.setEnabled(true);
} }
} else { } else {
sdkInstalled = true; sdkInstalled = true;
} }
page = Pages.PSARC; page = Pages.PSARC;
try { try {
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconPSARC.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH); logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconPSARC.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
picLabel.setIcon(new ImageIcon(logo));picLabel.setText(""); picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images."); System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
picLabel.setText(""); picLabel.setText("");
} }
contBtn.setEnabled(false); contBtn.setEnabled(false);
contBtn.setBackground(new Color(102, 74, 58)); //brown contBtn.setBackground(new Color(102, 74, 58)); //brown
refreshChecklist(); refreshChecklist();
inputContainer.setVisible(true); inputContainer.setVisible(true);
checklistContainer.setVisible(true); checklistContainer.setVisible(true);
if (!sdkInstalled) { if (!sdkInstalled) {
PSARC_downBtn.setEnabled(false); PSARC_downBtn.setEnabled(false);
PSARC_downBtn.setBackground(new Color(102, 74, 58)); //brown PSARC_downBtn.setBackground(new Color(102, 74, 58)); //brown
} }
instructions.setText("<html>\n" + instructions.setText("<html>\n" +
" <head>\n" + " <head>\n" +
" \n" + " \n" +
" </head>\n" + " </head>\n" +
" <body>\n" + " <body>\n" +
@ -213,24 +213,24 @@ public class WilkinsCoffee implements ActionListener {
" </body>\n" + " </body>\n" +
"</html>\n"); "</html>\n");
break; break;
case PSARC: case PSARC:
page = Pages.EXPORT_LOCATION; page = Pages.EXPORT_LOCATION;
try { try {
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconEXPORT.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH); logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconEXPORT.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
picLabel.setIcon(new ImageIcon(logo));picLabel.setText(""); picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images."); System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
picLabel.setText(""); picLabel.setText("");
} }
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
inputContainer.setVisible(false); inputContainer.setVisible(false);
checklistContainer.setVisible(false); checklistContainer.setVisible(false);
inputContainer2.setVisible(true); inputContainer2.setVisible(true);
instructions.setText("<html>\n" + instructions.setText("<html>\n" +
" <head>\n" + " <head>\n" +
" \n" + " \n" +
" </head>\n" + " </head>\n" +
" <body>\n" + " <body>\n" +
@ -243,25 +243,25 @@ public class WilkinsCoffee implements ActionListener {
" </body>\n" + " </body>\n" +
"</html>\n"); "</html>\n");
pathDisplay.setText("Export path: " + outPathTemp); pathDisplay.setText("Export path: " + outPathTemp);
break; break;
case EXPORT_LOCATION: case EXPORT_LOCATION:
page = Pages.DONE; page = Pages.DONE;
try { try {
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconDONE.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH); logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconDONE.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
picLabel.setIcon(new ImageIcon(logo));picLabel.setText(""); picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images."); System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
picLabel.setText(""); picLabel.setText("");
} }
inputContainer2.setVisible(false); inputContainer2.setVisible(false);
Main.outpath = outPathTemp; Main.outpath = outPathTemp;
Main.repatch = true; Main.repatch = true;
Main.writeConf(); Main.writeConf();
instructions.setText("<html>\n" + instructions.setText("<html>\n" +
" <head>\n" + " <head>\n" +
" \n" + " \n" +
" </head>\n" + " </head>\n" +
" <body>\n" + " <body>\n" +
@ -271,48 +271,48 @@ public class WilkinsCoffee implements ActionListener {
" </body>\n" + " </body>\n" +
"</html>\n"); "</html>\n");
break; break;
case DONE: case DONE:
frame.dispose(); frame.dispose();
new MissPiggy().Action(); new MissPiggy().Action();
break; break;
default: default:
throw new UnsupportedOperationException("ERROR: Setup page-flip event listener didn't drink any Wilkins Coffee. Get a programmer!"); throw new UnsupportedOperationException("ERROR: Setup page-flip event listener didn't drink any Wilkins Coffee. Get a programmer!");
} }
} }
} }
private void refreshChecklist() { private void refreshChecklist() {
ImageIcon positive = new ImageIcon(Main.class.getResource("/lightPositive.png")); ImageIcon positive = new ImageIcon(Main.class.getResource("/lightPositive.png"));
ImageIcon negative = new ImageIcon(Main.class.getResource("/lightNegative.png")); ImageIcon negative = new ImageIcon(Main.class.getResource("/lightNegative.png"));
// enabling the continue button here leaves the previous one redundant, // enabling the continue button here leaves the previous one redundant,
// but it's needed to ensure we don't force a redownload if the setup is interrupted // but it's needed to ensure we don't force a redownload if the setup is interrupted
if(new File(Main.inpath + "data.psarc").exists()) { if(new File(Main.inpath + "data.psarc").exists()) {
checklistBase.setIcon(positive); checklistBase.setIcon(positive);
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
} else {checklistBase.setIcon(negative);} } else {checklistBase.setIcon(negative);}
if(new File(Main.inpath + "data1.psarc").exists()) { if(new File(Main.inpath + "data1.psarc").exists()) {
checklistPatch1.setIcon(positive); checklistPatch1.setIcon(positive);
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
} else {checklistPatch1.setIcon(negative);} } else {checklistPatch1.setIcon(negative);}
if(new File(Main.inpath + "data2.psarc").exists()) { if(new File(Main.inpath + "data2.psarc").exists()) {
checklistPatch2.setIcon(positive); checklistPatch2.setIcon(positive);
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
} else {checklistPatch2.setIcon(negative);} } else {checklistPatch2.setIcon(negative);}
if(new File(Main.inpath + "dlc1.psarc").exists()) { if(new File(Main.inpath + "dlc1.psarc").exists()) {
checklistHD.setIcon(positive); checklistHD.setIcon(positive);
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
} else {checklistHD.setIcon(negative);} } else {checklistHD.setIcon(negative);}
if(new File(Main.inpath + "dlc2.psarc").exists()) { if(new File(Main.inpath + "dlc2.psarc").exists()) {
checklistFury.setIcon(positive); checklistFury.setIcon(positive);
contBtn.setEnabled(true); contBtn.setEnabled(true);
contBtn.setBackground(new Color(221, 88, 11)); //orange contBtn.setBackground(new Color(221, 88, 11)); //orange
} else {checklistFury.setIcon(negative);} } else {checklistFury.setIcon(negative);}
} }
} }