Compare commits
36 Commits
3d91ebbbd7
...
tetsuo-1.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 9155493c0e | |||
| c32d45c63f | |||
| e53933200e | |||
|
|
8840a193a3 | ||
| c9a968d173 | |||
| b1f38400c3 | |||
| 889e99f301 | |||
| 9585f16f11 | |||
| f7c4603db1 | |||
| 9292d8db62 | |||
| b8dbfc9095 | |||
| f07a75276c | |||
| f336be5a0a | |||
| 841f8132bb | |||
| 5654fa0b9f | |||
| f21d05d245 | |||
| b5f2aa6925 | |||
| 12f01000dd | |||
| 168e536068 | |||
| 64230f5eb4 | |||
| 91a574bb04 | |||
| e877f5eaa6 | |||
| b3a949fe43 | |||
| a17f7d1b58 | |||
| efbf8585d2 | |||
| 3849a765e3 | |||
| 2bbf34bf70 | |||
| ca36fadad1 | |||
| a75f1ad06c | |||
| a54c1ea325 | |||
| 780a7d69b3 | |||
| 8dfed698bb | |||
| 040adf3b7e | |||
| 309aaec333 | |||
| 8af95d5287 | |||
| 9950188e0d |
2
.gitignore
vendored
@@ -28,6 +28,7 @@ out/
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
|
||||
### Binaries ###
|
||||
/firestar.zip
|
||||
/run-linux.sh
|
||||
/run-win32.bat
|
||||
@@ -37,3 +38,4 @@ out/
|
||||
/build/
|
||||
/.gradle/
|
||||
/gradle/
|
||||
!/gradle/wrapper/*
|
||||
10
.idea/artifacts/firestar_jar.xml
generated
@@ -6,10 +6,14 @@
|
||||
<element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
|
||||
</element>
|
||||
<element id="module-output" name="firestar.firestar.main" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.json/json/20240303/ebb88e8fb5122b7506d5cf1d69f1ccdb790d22a/json-20240303.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.lingala.zip4j/zip4j/2.11.5/4214e396e3891cb19eded3ce5e584cba9032fdc3/zip4j-2.11.5.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.java/java-gui-forms-rt/203.7148.30/f0dbca371a2592689e541be912de6005939f9c7c/java-gui-forms-rt-203.7148.30.jar" path-in-jar="/" />
|
||||
<element id="dir-copy" path="$PROJECT_DIR$/firestar/src/main/resources" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.java/java-gui-forms-rt/203.7148.30/f0dbca371a2592689e541be912de6005939f9c7c/java-gui-forms-rt-203.7148.30.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.github.java-diff-utils/java-diff-utils/4.12/1a712a91324d566eef39817fc5c9980eb10c21db/java-diff-utils-4.12.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.lingala.zip4j/zip4j/2.11.5/4214e396e3891cb19eded3ce5e584cba9032fdc3/zip4j-2.11.5.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.14.0/1ed471194b02f2c6cb734a0cd6f6f107c673afae/commons-lang3-3.14.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-text/1.12.0/66aa90dc099701c4d3b14bd256c328f592ccf0d6/commons-text-1.12.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.json/json/20240303/ebb88e8fb5122b7506d5cf1d69f1ccdb790d22a/json-20240303.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.netbeans.external/org-apache-commons-io/RELEASE113/815893df5f31da2ece4040fe0a12fd44b577afaf/org-apache-commons-io-RELEASE113.jar" path-in-jar="/" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
10
.idea/libraries/apache_commons_io.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="apache.commons.io" type="repository">
|
||||
<properties maven-id="commons-io:commons-io:2.16.1" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-io/commons-io/2.16.1/commons-io-2.16.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
11
.idea/libraries/apache_commons_text.xml
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="apache.commons.text" type="repository">
|
||||
<properties maven-id="org.apache.commons:commons-text:1.12.0" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-text/1.12.0/commons-text-1.12.0.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.14.0/commons-lang3-3.14.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
10
.idea/uiDesigner.xml
generated
@@ -32,17 +32,17 @@
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
|
||||
21
README.md
@@ -9,12 +9,12 @@
|
||||
# Installation
|
||||
The latest version of Firestar will always be available from [Releases](https://git.worlio.com/bonkmaykr/firestar/releases).
|
||||
If you aren't sure which file to get:
|
||||
- **Windows:** Download the latest installer [here](https://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_1.2_installer_windows.exe).
|
||||
- **Windows:** Download the latest installer [here](https://screwgravity.net/firestar/builds/stable/tetsuo/firestar_1.3_installer_winnt_x86-64.exe).
|
||||
- **Linux:** Install one of the packages from the [Releases](https://git.worlio.com/bonkmaykr/firestar/releases) page:
|
||||
- Ubuntu, Mint, PopOS: `sudo dpkg -i firestar_ver_arch.deb` or `gdebi firestar_ver_arch.deb`
|
||||
- Fedora, Mageia, OpenSUSE, AlmaLinux: `sudo rpm -i firestar-ver-arch.rpm`
|
||||
- Arch, EndeavourOS, CachyOS, Steam Deck: `sudo pacman -U firestar-ver-arch.pkg.tar.zst`
|
||||
- **All Platforms:** Grab the [Portable ZIP](https://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_dekka-1.2_portable.zip), extract it, and run the JAR file.
|
||||
- **All Platforms:** Grab the [JAR](https://screwgravity.net/firestar/builds/stable/tetsuo/firestar_1.3_portable.jar) and run it.
|
||||
|
||||
# System Requirements
|
||||
- Windows 8 or newer, Mac OS X 10.14 or older, any modern version of Linux/BSD
|
||||
@@ -50,7 +50,7 @@ Firestar uses the Gradle build system. We write our code and perform all our tes
|
||||
git clone https://git.worlio.com/bonkmaykr/firestar.git
|
||||
```
|
||||
|
||||
3. `cd` to `firestar/` and run `./gradlew build` to make a JAR or `./gradlew run` to test your code immediately.
|
||||
3. `cd` to `firestar/` and run `gradle build` to make a JAR or `gradle run` to test your code immediately.
|
||||
- On Windows systems make sure you're running `gradlew.bat` and not the Bash script instead.
|
||||
|
||||
# FAQ
|
||||
@@ -78,6 +78,21 @@ Firestar itself can run natively on the system, but it needs WINE in order to ha
|
||||
**If you are on Mac OS X you will need an older OS version that is still compatible with 32-bit applications.**
|
||||
|
||||
# Developer Commentary
|
||||
## Programmer SOP
|
||||
When adding new features to Firestar, the Screw Gravity! team (loosely) follows this procedure:
|
||||
1. The developer prototypes the feature, in part or in full, on a Linux system.
|
||||
2. After completion, a QEMU/KVM running Windows 10 w/ VC++ 2012 libs and the latest JDK is deployed to test Firestar on.
|
||||
3. Code refactoring is done to account for Windows bugs.
|
||||
4. The final commit is pushed.
|
||||
|
||||
Try to stick to these conventions:
|
||||
- Avoid allowing the user to interact with the main window (MissPiggy.java) while another menu is open that alters any data, and keep this window Always-on-top. This is usually done by passing the master JFrame as a parameter to the child and telling it to freeze the parent's JFrame until the user closes that menu.
|
||||
- Keep formatting consistent and readable.
|
||||
- `if` statements should have a space separating the conditions and code block.
|
||||
- Use tabs instead of repeat spaces for indentation where possible and keep one indentation per layer, avoid flattening unless appropriate.
|
||||
- Split up long equations and statements into new lines with an operator at the start of the new line.
|
||||
- Divide really long functions into paragraph for certain major steps.
|
||||
|
||||
## Third Party Code
|
||||
Firestar is built on top of the following additional software:
|
||||
- *[WINE](https://www.winehq.org/), for running the below applications across platforms.
|
||||
|
||||
@@ -18,6 +18,8 @@ dependencies {
|
||||
implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '2.11.5'
|
||||
implementation group: 'org.json', name: 'json', version: '20240303'
|
||||
implementation group: 'io.github.java-diff-utils', name: 'java-diff-utils', version: '4.12'
|
||||
implementation group: 'org.apache.commons', name: 'commons-text', version: '1.12.0'
|
||||
implementation group: 'org.netbeans.external', name: 'org-apache-commons-io', version: 'RELEASE113'
|
||||
|
||||
implementation 'com.jetbrains.intellij.java:java-gui-forms-rt:203.7148.30'
|
||||
antTask 'com.jetbrains.intellij.java:java-compiler-ant-tasks:203.7148.30'
|
||||
@@ -30,14 +32,15 @@ java {
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Main-Class': 'Main'
|
||||
)
|
||||
}
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
manifest {
|
||||
attributes(
|
||||
'Main-Class': 'Main'
|
||||
)
|
||||
}
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
|
||||
110
firestar/src/main/java/Beaker.form
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="Beaker">
|
||||
<grid id="27dc6" binding="frameContainer" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="772" height="129"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-2271221"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="20b72" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="8" bottom="0" right="8"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="-1" height="20"/>
|
||||
<preferred-size width="-1" height="80"/>
|
||||
<maximum-size width="-1" height="80"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusable value="false"/>
|
||||
<font size="8"/>
|
||||
<foreground color="-1"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="60002" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="9c218" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="© 2025 Canithesis Interactive"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="4c79f" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="6" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="This program is not endorsed by Sony Computer Entertainment."/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="da84a" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="c04e4" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="https://screwgravity.net/firestar/"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="b7dd0" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font size="10"/>
|
||||
<foreground color="-1"/>
|
||||
<text value="Developed and GNU'd by bonkmaykr. FScript thanx to Wirlaburla"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="19b7a" class="javax.swing.JLabel" binding="splashImg">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="640" height="400"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
59
firestar/src/main/java/Beaker.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Firestar Mod Manager
|
||||
* Copyright (C) 2025 Canithesis Interactive
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
|
||||
|
||||
public class Beaker {
|
||||
Image logo;
|
||||
private JLabel splashImg;
|
||||
JFrame frame = new JFrame();
|
||||
JPanel frameContainer;
|
||||
|
||||
public Beaker() throws InterruptedException {
|
||||
try {
|
||||
logo = ImageIO.read(Main.class.getResourceAsStream("/splash"+(int)(Math.random()*10)+".png")).getScaledInstance(640, 400, Image.SCALE_SMOOTH);
|
||||
} catch (IOException e) {
|
||||
System.out.println("ERROR: Uhhhhhhhhhhh........... what?");
|
||||
return;
|
||||
}
|
||||
|
||||
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
||||
splashImg.setIcon(new ImageIcon(logo));splashImg.setText("");
|
||||
|
||||
// display window
|
||||
frame.setSize(640, 450);
|
||||
frame.setTitle("Firestar Mod Manager");
|
||||
frame.setUndecorated(true);
|
||||
frame.setResizable(false);
|
||||
frame.setAlwaysOnTop(true);
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
frame.setLayout(new GridLayout());
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
|
||||
Thread.sleep(3000);
|
||||
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<text value=" If you add/remove DLC in the future, you will need to change this setting again."/>
|
||||
<text value="Downloading a game update will automatically download its previous versions."/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
@@ -108,7 +108,7 @@
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="1000f" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="1000f" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
@@ -120,55 +120,226 @@
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="ec9c0" class="javax.swing.JCheckBox" binding="patchCheck">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<text value="Updates"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="a6e9" class="javax.swing.JCheckBox" binding="baseCheck">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="6" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="10"/>
|
||||
<text value="Base game"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="f3723" class="javax.swing.JCheckBox" binding="hdCheck">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="10"/>
|
||||
<opaque value="false"/>
|
||||
<text value="HD Add-On Pack"/>
|
||||
<verticalTextPosition value="0"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5ed0c" class="javax.swing.JCheckBox" binding="furyCheck">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<opaque value="false"/>
|
||||
<selected value="false"/>
|
||||
<text value="Fury Add-On Pack"/>
|
||||
<verticalTextPosition value="0"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="afeb1" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="1" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="6337e" class="javax.swing.JRadioButton" binding="baseCheck">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="0"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<opaque value="false"/>
|
||||
<text value="Base Game"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5c733" class="javax.swing.JRadioButton" binding="patchCheck2">
|
||||
<constraints>
|
||||
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<label value="v1.04 (Latest)"/>
|
||||
<opaque value="false"/>
|
||||
<selected value="true"/>
|
||||
<text value="v1.04 (Latest)"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="f9b10" class="javax.swing.JRadioButton" binding="patchCheck1">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<opaque value="false"/>
|
||||
<text value="v1.01+"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="826d4" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<opaque value="false"/>
|
||||
<text value="Select Game Version:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="26170" class="javax.swing.JCheckBox" binding="skipBaseCheck">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<enabled value="false"/>
|
||||
<focusPainted value="false"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<label value="Don't redownload existing core game files"/>
|
||||
<text value="Don't redownload existing core game files"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="45b94" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-15128227"/>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<selected value="false"/>
|
||||
<text value="Fury Add-On Pack"/>
|
||||
<opaque value="false"/>
|
||||
<text value="Select DLC Packs:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="d53a4" binding="installedList" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="3" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="line" title="Installed Packs" title-justification="2" title-position="1">
|
||||
<font name="Exo 2"/>
|
||||
<title-color color="-1"/>
|
||||
<color color="-1"/>
|
||||
</border>
|
||||
<children>
|
||||
<grid id="e1f58" binding="installedListMargin" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="4" left="16" bottom="4" right="16"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<focusable value="false"/>
|
||||
<opaque value="false"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="74ba9" class="javax.swing.JLabel" binding="ipcBase">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Base Game"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="afce0" class="javax.swing.JLabel" binding="ipcPatch1">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Update v1.01"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="209d6" class="javax.swing.JLabel" binding="ipcPatch2">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Update v1.04"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="dbb59" class="javax.swing.JLabel" binding="ipcDlcHD">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="HD Add-On Pack"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="c1b3f" class="javax.swing.JLabel" binding="ipcDlcFury">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
<foreground color="-1"/>
|
||||
<horizontalAlignment value="2"/>
|
||||
<horizontalTextPosition value="11"/>
|
||||
<icon value="lightNegative.png"/>
|
||||
<text value="Fury Add-On Pack"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
|
||||
@@ -30,10 +30,19 @@ public class Bert implements ActionListener {
|
||||
private JPanel frameContainer;
|
||||
private JButton cancelbtn;
|
||||
private JButton downloadbtn;
|
||||
private JCheckBox patchCheck;
|
||||
private JCheckBox baseCheck;
|
||||
private JRadioButton baseCheck;
|
||||
private JRadioButton patchCheck1;
|
||||
private JRadioButton patchCheck2;
|
||||
private JCheckBox hdCheck;
|
||||
private JCheckBox furyCheck;
|
||||
private JCheckBox skipBaseCheck;
|
||||
private JPanel installedList;
|
||||
private JLabel ipcBase;
|
||||
private JLabel ipcPatch1;
|
||||
private JLabel ipcPatch2;
|
||||
private JLabel ipcDlcHD;
|
||||
private JLabel ipcDlcFury;
|
||||
private JPanel installedListMargin;
|
||||
private ButtonGroup radios = new ButtonGroup();
|
||||
|
||||
private JFrame invoker;
|
||||
@@ -54,8 +63,17 @@ public class Bert implements ActionListener {
|
||||
frame.setLocationRelativeTo(parent);
|
||||
frame.setAlwaysOnTop(true);
|
||||
|
||||
radios.add(baseCheck);
|
||||
radios.add(patchCheck1);
|
||||
radios.add(patchCheck2);
|
||||
|
||||
cancelbtn.addActionListener(this);
|
||||
downloadbtn.addActionListener(this);
|
||||
baseCheck.addActionListener(this);
|
||||
patchCheck1.addActionListener(this);
|
||||
patchCheck2.addActionListener(this);
|
||||
|
||||
refreshChecklist();
|
||||
|
||||
frame.setIconImage(Main.windowIcon);
|
||||
|
||||
@@ -74,6 +92,9 @@ public class Bert implements ActionListener {
|
||||
invoker.setEnabled(true);
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
if (new File(Main.inpath + "data2.psarc").exists())
|
||||
skipBaseCheck.setEnabled(true);
|
||||
}
|
||||
|
||||
public boolean reportWhenDownloaded(WilkinsCoffee setup) {
|
||||
@@ -87,34 +108,80 @@ public class Bert implements ActionListener {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
if (actionEvent.getSource() == baseCheck)
|
||||
skipBaseCheck.setEnabled(new File(Main.inpath + "data.psarc").exists()); else
|
||||
if (actionEvent.getSource() == patchCheck1)
|
||||
skipBaseCheck.setEnabled(new File(Main.inpath + "data1.psarc").exists()); else
|
||||
if (actionEvent.getSource() == patchCheck2)
|
||||
skipBaseCheck.setEnabled(new File(Main.inpath + "data2.psarc").exists()); else
|
||||
if (actionEvent.getSource() == cancelbtn) {
|
||||
invoker.setEnabled(true);
|
||||
frame.dispose();
|
||||
} else if (actionEvent.getSource() == downloadbtn) {
|
||||
ArrayList<Main.ArcTarget> arcs = new ArrayList<Main.ArcTarget>();
|
||||
ArrayList<Main.ArcKey> keys = new ArrayList<Main.ArcKey>();
|
||||
if (baseCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Begin download of data (Game version 1.0)");
|
||||
|
||||
// Always download predecessors to ensure no missing files
|
||||
// Probably not necessary since I will be adding selective extraction to Gonzo,
|
||||
// and throw errors when a lower PSARC doesn't exist, but there's no real reason not to.
|
||||
//
|
||||
// Of course, to avoid additional download times, we should probably
|
||||
// avoid adding to the download list if a file already exists, unless explicitly
|
||||
// selected (the exact radio button). The user can redownload one at a time
|
||||
// but Firestar will not overwrite existing PSARCs otherwise.
|
||||
if (baseCheck.isSelected()) { // I have the base game
|
||||
if (!skipBaseCheck.isSelected() || !new File(Main.inpath + "data.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Queued download of data (Game version 1.0)");
|
||||
}
|
||||
}
|
||||
if (patchCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.LATEST);
|
||||
keys.add(Main.ArcKey.LATEST);
|
||||
System.out.println("Begin download of data2 (Game version 1.04)");
|
||||
if (patchCheck1.isSelected()) { // I updated it once after it came out and then didn't turn my vita on for thousands of years
|
||||
if (!new File(Main.inpath + "data.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Queued download of data (Game version 1.0)");
|
||||
}
|
||||
if (!skipBaseCheck.isSelected() || !new File(Main.inpath + "data1.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.FIRST);
|
||||
keys.add(Main.ArcKey.FIRST);
|
||||
System.out.println("Queued download of data1 (Game version 1.01)");
|
||||
}
|
||||
}
|
||||
if (patchCheck2.isSelected()) { // I'm a normal fucking person
|
||||
if (!new File(Main.inpath + "data.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.BASE);
|
||||
keys.add(Main.ArcKey.BASE);
|
||||
System.out.println("Queued download of data (Game version 1.0)");
|
||||
}
|
||||
if (!new File(Main.inpath + "data1.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.FIRST);
|
||||
keys.add(Main.ArcKey.FIRST);
|
||||
System.out.println("Queued download of data1 (Game version 1.01)");
|
||||
}
|
||||
if (!skipBaseCheck.isSelected() || !new File(Main.inpath + "data2.psarc").exists()) {
|
||||
arcs.add(Main.ArcTarget.LATEST);
|
||||
keys.add(Main.ArcKey.LATEST);
|
||||
System.out.println("Queued download of data2 (Game version 1.04)");
|
||||
}
|
||||
}
|
||||
|
||||
// DLC are installed arbitrarily, separate of the game, and can remain as checkboxes with the old logic.
|
||||
// Likewise, the old overwrite policy applies. If the user selects these, it WILL download with no question.
|
||||
if (hdCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.ADDON_HD);
|
||||
keys.add(Main.ArcKey.ADDON_HD);
|
||||
System.out.println("Begin download of dlc1 (HD DLC)");
|
||||
System.out.println("Queued download of dlc1 (HD DLC)");
|
||||
}
|
||||
if (furyCheck.isSelected()) {
|
||||
arcs.add(Main.ArcTarget.ADDON_HD_FURY);
|
||||
keys.add(Main.ArcKey.ADDON_HD_FURY);
|
||||
System.out.println("Begin download of dlc2 (Fury DLC)");
|
||||
System.out.println("Queued download of dlc2 (Fury DLC)");
|
||||
}
|
||||
if (arcs.isEmpty()) {
|
||||
frame.setVisible(false);
|
||||
JOptionPane.showMessageDialog(invoker, "Select one or more asset packs.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
frame.setVisible(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,9 +199,13 @@ public class Bert implements ActionListener {
|
||||
key = Main.ArcKey.BASE.toString();
|
||||
arcname = "Base game";
|
||||
break;
|
||||
case FIRST :
|
||||
key = Main.ArcKey.FIRST.toString();
|
||||
arcname = "Update 1.01";
|
||||
break;
|
||||
case LATEST :
|
||||
key = Main.ArcKey.LATEST.toString();
|
||||
arcname = "Updates";
|
||||
arcname = "Update 1.04";
|
||||
break;
|
||||
case ADDON_HD :
|
||||
key = Main.ArcKey.ADDON_HD.toString();
|
||||
@@ -172,7 +243,7 @@ public class Bert implements ActionListener {
|
||||
Fozzie popup = new Fozzie();
|
||||
popup.displayTextOnly("Extracting " + arcname + "...", "Extracting");
|
||||
try {
|
||||
Process p = Main.exec(new String[]{"pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath);
|
||||
Process p = Main.exec(new String[]{Main.inpath + "pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath);
|
||||
InputStream debugin = new BufferedInputStream(p.getInputStream());
|
||||
OutputStream debugout = new BufferedOutputStream(System.out);
|
||||
int c;
|
||||
@@ -200,6 +271,9 @@ public class Bert implements ActionListener {
|
||||
if (type == Main.ArcTarget.BASE) {
|
||||
extracted = "app/PCSA00015";
|
||||
name = "data.psarc";
|
||||
} else if (type == Main.ArcTarget.FIRST) {
|
||||
extracted = "patch/PCSA00015";
|
||||
name = "data1.psarc";
|
||||
} else if (type == Main.ArcTarget.LATEST) {
|
||||
extracted = "patch/PCSA00015";
|
||||
name = "data2.psarc";
|
||||
@@ -226,7 +300,7 @@ public class Bert implements ActionListener {
|
||||
popup.setText("<html>Decrypting protected PFS:<br/>" + extracted + "</html>", "Decrypting");
|
||||
|
||||
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[]{Main.inpath + "psvpfsparser.exe", "-i", extracted, "-o", "./temp/", "-z", key.toString(), "-f", "cma.henkaku.xyz"}, Main.inpath);
|
||||
InputStream debugin = new BufferedInputStream(p.getInputStream());
|
||||
OutputStream debugout = new BufferedOutputStream(System.out);
|
||||
int c;
|
||||
@@ -276,4 +350,20 @@ public class Bert implements ActionListener {
|
||||
downloaderPopupThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshChecklist() {
|
||||
ImageIcon positive = new ImageIcon(Main.class.getResource("/lightPositive.png"));
|
||||
ImageIcon negative = new ImageIcon(Main.class.getResource("/lightNegative.png"));
|
||||
|
||||
if(new File(Main.inpath + "data.psarc").exists())
|
||||
ipcBase.setIcon(positive); else ipcBase.setIcon(negative);
|
||||
if(new File(Main.inpath + "data1.psarc").exists())
|
||||
ipcPatch1.setIcon(positive); else ipcPatch1.setIcon(negative);
|
||||
if(new File(Main.inpath + "data2.psarc").exists())
|
||||
ipcPatch2.setIcon(positive); else ipcPatch2.setIcon(negative);
|
||||
if(new File(Main.inpath + "dlc1.psarc").exists())
|
||||
ipcDlcHD.setIcon(positive); else ipcDlcHD.setIcon(negative);
|
||||
if(new File(Main.inpath + "dlc2.psarc").exists())
|
||||
ipcDlcFury.setIcon(positive); else ipcDlcFury.setIcon(negative);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,12 +163,15 @@ public class Clifford implements ActionListener {
|
||||
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
container.put("version", mod.version);
|
||||
container.put("friendlyName", mod.friendlyName);
|
||||
container.put("author", mod.author);
|
||||
container.put("description", mod.description);
|
||||
container.put("loaderversion", mod.loaderversion);
|
||||
container.put("game", mod.game);
|
||||
if (!mod.requires.isEmpty()) container.put("requires", mod.requires);
|
||||
if (!mod.extracts.isEmpty()) container.put("extracts", mod.extracts);
|
||||
|
||||
try {
|
||||
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + mod.path.trim()).setComment(container.toString());
|
||||
@@ -196,7 +199,9 @@ public class Clifford implements ActionListener {
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter("Firestar Mod Package", "fstar"));
|
||||
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
||||
ZipFile zip = new ZipFile(fileChooser.getSelectedFile());
|
||||
File modFile = fileChooser.getSelectedFile();
|
||||
if (!modFile.getName().endsWith(".fstar")) modFile = new File(modFile.toString() + ".fstar");
|
||||
ZipFile zip = new ZipFile(modFile);
|
||||
boolean hasScript = false;
|
||||
try {
|
||||
zip.addFolder(new File(directory.getAbsolutePath() + "/data"));
|
||||
@@ -211,21 +216,39 @@ public class Clifford implements ActionListener {
|
||||
hasScript = true;
|
||||
}
|
||||
|
||||
ArrayList<String> requires = new ArrayList<>();
|
||||
ArrayList<String> extracts = new ArrayList<>();
|
||||
if (isSoundtrack) {
|
||||
requires.add("data2.psarc");
|
||||
extracts.add("data/plugins/music/Definition.xml");
|
||||
extracts.add("data/plugins/languages/american/entries.xml");
|
||||
extracts.add("data/plugins/languages/danish/entries.xml");
|
||||
extracts.add("data/plugins/languages/dutch/entries.xml");
|
||||
extracts.add("data/plugins/languages/english/entries.xml");
|
||||
extracts.add("data/plugins/languages/finnish/entries.xml");
|
||||
extracts.add("data/plugins/languages/french/entries.xml");
|
||||
extracts.add("data/plugins/languages/german/entries.xml");
|
||||
extracts.add("data/plugins/languages/italian/entries.xml");
|
||||
extracts.add("data/plugins/languages/japanese/entries.xml");
|
||||
extracts.add("data/plugins/languages/norwegian/entries.xml");
|
||||
extracts.add("data/plugins/languages/polish/entries.xml");
|
||||
extracts.add("data/plugins/languages/portuguese/entries.xml");
|
||||
extracts.add("data/plugins/languages/russian/entries.xml");
|
||||
extracts.add("data/plugins/languages/spanish/entries.xml");
|
||||
extracts.add("data/plugins/languages/swedish/entries.xml");
|
||||
}
|
||||
|
||||
JSONObject container = new JSONObject();
|
||||
container.put("version", Integer.parseInt(fVersion.getText()));
|
||||
container.put("friendlyName", fName.getText());
|
||||
container.put("author", fAuthor.getText());
|
||||
container.put("description", fDescription.getText());
|
||||
if (!requires.isEmpty()) container.put("requires", requires);
|
||||
if (!extracts.isEmpty()) container.put("extracts", extracts);
|
||||
// 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.
|
||||
if (hasScript) {
|
||||
container.put("loaderversion", 1);
|
||||
if (isSoundtrack) {
|
||||
ArrayList<boolean[]> requiresTemp = new ArrayList<>();
|
||||
requiresTemp.add(new boolean[]{false, true, false, false});
|
||||
requiresTemp.add(new boolean[]{true, false, false, false});
|
||||
container.put("requires", requiresTemp); // Pull localization files for patching.
|
||||
}
|
||||
} else {
|
||||
container.put("loaderversion", 0);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class Ernie implements ActionListener {
|
||||
|
||||
private JFrame parent;
|
||||
|
||||
public Ernie(JFrame parent) {
|
||||
public Ernie(JFrame parent, boolean isManual) {
|
||||
this.parent = parent;
|
||||
frame.setIconImage(Main.windowIcon);
|
||||
byte[] urlraw = getFile(gitapi+"/releases?draft=false&pre-release=false");
|
||||
@@ -72,7 +72,9 @@ public class Ernie implements ActionListener {
|
||||
try {
|
||||
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"));
|
||||
if (releases.length() >= 1 && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag)) {
|
||||
if (releases.length() >= 1
|
||||
&& (!Main.isNightly && (!((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag))
|
||||
|| (Main.isNightly && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtagPrevious)))) {
|
||||
System.out.println("Updater: Your version is out of date.");
|
||||
frame.add(frameContainer);
|
||||
notnowbtn.addActionListener(this);
|
||||
@@ -97,7 +99,10 @@ public class Ernie implements ActionListener {
|
||||
}
|
||||
});
|
||||
frame.setVisible(true);
|
||||
} else { System.out.println("Updater: No updates."); }
|
||||
} else {
|
||||
System.out.println("Updater: No updates.");
|
||||
if (isManual) {JOptionPane.showMessageDialog(frame, "There are no updates at this time.", "Check for Updates", JOptionPane.INFORMATION_MESSAGE);}
|
||||
}
|
||||
} catch (IOException | JSONException ex) {
|
||||
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class Fozzie {
|
||||
frame.setIconImage(Main.windowIcon);
|
||||
frame.setVisible(true);
|
||||
|
||||
label.setText("Downloading \"" + dname + "\"");
|
||||
label.setText("Downloading " + dname);
|
||||
|
||||
try {
|
||||
URL fileURL = new URL(url);
|
||||
|
||||
@@ -25,12 +25,10 @@ import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.*;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -108,24 +106,47 @@ public class Gonzo {
|
||||
}
|
||||
|
||||
private void CompatibilityRoutine() {
|
||||
// cleanup any failed deploys to avoid scripts running when they are not supposed to be
|
||||
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
|
||||
|
||||
// create temporary working area for asset dump
|
||||
new File(System.getProperty("user.home") + "/.firestar/temp/").mkdirs();
|
||||
new File(System.getProperty("user.home") + "/.firestar/temparcs/").mkdirs();
|
||||
|
||||
// Work from bottom to top, mods on top always overwrite the ones on the bottom.
|
||||
List<Main.Mod> modsFlipped = new ArrayList<>(Main.Mods);
|
||||
Collections.reverse(modsFlipped);
|
||||
|
||||
// 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";}
|
||||
for (Main.Mod m : modsFlipped) {
|
||||
if (m.enabled) {
|
||||
System.out.println(m.friendlyName + " : " + m.requires.toString() + " : " + m.extracts.toString());
|
||||
for (String r : m.requires) if (!dumpThese.contains(r)) dumpThese.add(r);
|
||||
}
|
||||
}
|
||||
if (data0) oArcTarget = "data.psarc";
|
||||
if (data1) oArcTarget = "data1.psarc";
|
||||
if (data2) oArcTarget = "data2.psarc";
|
||||
if (dlc1) oArcTarget = "dlc1.psarc";
|
||||
if (dlc2) oArcTarget = "dlc2.psarc";
|
||||
dumpThese.remove(oArcTarget); dumpThese.add(oArcTarget); // Always dump the base game last. TODO should we allow mods to specify otherwise??
|
||||
System.out.println("List of files to dump: " + dumpThese);
|
||||
|
||||
// dump all assets to working area
|
||||
for (String s : dumpThese) {
|
||||
try {
|
||||
if (!(new File(Main.inpath + s).exists()))
|
||||
throw new IOException("A mod requested access to the archive \"" + s + "\" but it doesn't exist!");
|
||||
|
||||
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/");
|
||||
Process p;
|
||||
if (s.equals(oArcTarget)) p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||
else {
|
||||
new File(System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/").mkdirs();
|
||||
p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../../"+s}, System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/");
|
||||
}
|
||||
final Thread ioThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -159,13 +180,37 @@ public class Gonzo {
|
||||
|
||||
// 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) {
|
||||
for (Main.Mod m : modsFlipped) {
|
||||
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/");
|
||||
|
||||
if (!m.requires.isEmpty() && !m.extracts.isEmpty()) {
|
||||
for (String r : m.requires) {
|
||||
for (String e : m.extracts) {
|
||||
File f = new File(Main.inpath + "temparcs/" + r + "/" + e);
|
||||
File f2 = new File(Main.inpath + "temp/" + e);
|
||||
if (f2.exists()) {
|
||||
System.out.println("File \"" + e + "\" already exists in master PSARC. Ignoring.");
|
||||
consoleDisplay.append("File \"" + e + "\" already exists in master PSARC. Ignoring." + "\n");
|
||||
}
|
||||
else if (f.exists()) {
|
||||
Path src = Paths.get(Main.inpath + "temparcs/" + r + "/" + e);
|
||||
Path dest = Paths.get(Main.inpath + "temp/" + e);
|
||||
System.out.println("Copying extra file " + e + " from " + r);
|
||||
consoleDisplay.append("Copying extra file " + e + " from " + r + "\n");
|
||||
new File(dest.getParent().toString()).mkdirs();
|
||||
Files.copy(src, dest, StandardCopyOption.COPY_ATTRIBUTES);
|
||||
} else throw new IOException("A mod requested access to the file \"" + e + "\" from archive " + r + " but it wasn't there!");
|
||||
}
|
||||
}
|
||||
} else if (!m.extracts.isEmpty()) {
|
||||
System.out.println("WARNING: " + m.friendlyName + " by " + m.author + "tried to extract individual files without specifying a source PSARC in requires[]. Ignoring.");
|
||||
consoleDisplay.append("WARNING: " + m.friendlyName + " by " + m.author + "tried to extract individual files without specifying a source PSARC in requires[]. Ignoring." + "\n");
|
||||
}
|
||||
|
||||
File fscript = new File(Main.inpath + "temp/fscript");
|
||||
if (fscript.exists()) {
|
||||
System.out.println("Firestar is applying patches from " + m.friendlyName + " by " + m.author);
|
||||
@@ -209,7 +254,9 @@ public class Gonzo {
|
||||
} 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);
|
||||
if (e instanceof FirescriptFormatException) {JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage() + "\nOne of your mods has a broken FSCRIPT. It cannot be installed.", "Fatal Error", JOptionPane.ERROR_MESSAGE);} else {
|
||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
AllowExit();
|
||||
return;
|
||||
@@ -223,7 +270,7 @@ public class Gonzo {
|
||||
} 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);
|
||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Internal FSCRIPT Error. " + e.getMessage() + "\nThis may indicate that Firestar has been corrupted and needs reinstalling.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
AllowExit();
|
||||
return;
|
||||
@@ -267,7 +314,7 @@ public class Gonzo {
|
||||
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/");
|
||||
Process p = Main.exec(new String[]{Main.inpath + "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() {
|
||||
@@ -316,7 +363,9 @@ public class Gonzo {
|
||||
}
|
||||
try {
|
||||
File tmp = new File(System.getProperty("user.home") + "/.firestar/temp/");
|
||||
File tmp2 = new File(System.getProperty("user.home") + "/.firestar/temparcs/");
|
||||
Main.deleteDir(tmp);
|
||||
Main.deleteDir(tmp2);
|
||||
} 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());
|
||||
@@ -349,6 +398,7 @@ public class Gonzo {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
|
||||
invoker.wrapUpDeployment();
|
||||
e.getWindow().dispose();
|
||||
}
|
||||
|
||||
@@ -18,12 +18,17 @@
|
||||
|
||||
import net.lingala.zip4j.ZipFile;
|
||||
import net.lingala.zip4j.exception.ZipException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.json.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -31,11 +36,16 @@ import javax.swing.*;
|
||||
|
||||
public class Main {
|
||||
// Build Information
|
||||
public static final String vstr = "Release 1.3";
|
||||
public static String vstr = "Release 1.3.1";
|
||||
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.1"; // set to dekka-1.1 for testing
|
||||
public static final int vint = 1;
|
||||
|
||||
// Jenkins Build Information
|
||||
public static boolean isNightly = false;
|
||||
public static final String vtagPrevious = "tetsuo-1.3.1";
|
||||
public static String dateOfCompile = null;
|
||||
|
||||
// User Settings
|
||||
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
|
||||
@@ -47,6 +57,7 @@ public class Main {
|
||||
|
||||
public enum ArcTarget { // install target for 2048, type used by downloader
|
||||
BASE("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/NYEoaBGfiWymSEVZKxoyrKyBFsZNoFqxdyAIpZayZYuLLbCAArYrYXjPNhKCfXcONmhIZzZEeArycSrjiJOuNMWuWsDONUxMIQtMk.pkg"),
|
||||
FIRST("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_FURY("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/IAoJQaDpySenBmQCKiqecEPMzSdPfPcdXupxZXLTYYTuRgtsdTaHxbeejwGKRQpjJOKBdMMFzSoeEhsHYxNUasQrEzkZPeBxUEqnp.pkg");
|
||||
@@ -62,6 +73,7 @@ public class Main {
|
||||
|
||||
public enum ArcKey { // decryption keys for 2048, type used by downloader
|
||||
BASE("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||
FIRST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||
LATEST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||
ADDON_HD("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsGG5kYGIR4Ojs7ejuis9/anXfuudVNvzgdu+9z1z+asJojA9uAACgRhTl"),
|
||||
ADDON_HD_FURY("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsFG5kYGIR4Ojs7ejuis9/3fydBRm3eCJX7biz/vVTm/2jMT64AQCCYhVy");
|
||||
@@ -85,8 +97,8 @@ public class Main {
|
||||
public int loaderversion = 0; //minimum required vint or feature level from Firestar
|
||||
public String author; // if null, "Author is unknown."
|
||||
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.
|
||||
// TODO: save 'false true false false' in ost gen if necessary (patches change localization)
|
||||
public List<String> requires = new ArrayList<>();
|
||||
public List<String> extracts = new ArrayList<>();
|
||||
}
|
||||
|
||||
// Mods
|
||||
@@ -96,12 +108,26 @@ public class Main {
|
||||
public static Font fExo2;
|
||||
public static BufferedImage windowIcon;
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
// get Nightly information from Jenkins automatic builds
|
||||
if (Main.class.getResource("/jenkinsVersionString") != null) {
|
||||
System.out.println("=== This is a NIGHTLY BUILD! ===\n");
|
||||
try {
|
||||
vstr = "Nightly " + IOUtils.toString(Main.class.getResourceAsStream("/jenkinsVersionString"), StandardCharsets.UTF_8);
|
||||
dateOfCompile = IOUtils.toString(Main.class.getResourceAsStream("/jenkinsBuildDate"), StandardCharsets.UTF_8);
|
||||
System.out.println("Compiled on " + dateOfCompile);
|
||||
isNightly = true;
|
||||
} catch (Exception e) {
|
||||
System.out.println("ERROR: Something went wrong trying to get the autobuild information! defaulting to Release values\n\n");
|
||||
isNightly = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 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\n" + vstr + " (codename " + vcode + ") major " + vint + "\n" +
|
||||
"JVM host appears to be " + System.getProperty("os.name") +
|
||||
"\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) 2025 Canithesis Interactive\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" +
|
||||
"the Free Software Foundation, either version 3 of the License, or\n" +
|
||||
"(at your option) any later version.\n" +
|
||||
@@ -114,7 +140,9 @@ public class Main {
|
||||
"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");
|
||||
|
||||
//begin
|
||||
// display splash screen
|
||||
new Beaker();
|
||||
|
||||
// load global assets
|
||||
try {
|
||||
fExo2 = Font.createFont(Font.TRUETYPE_FONT, Main.class.getResourceAsStream("/exo2.ttf"));
|
||||
@@ -216,10 +244,25 @@ public class Main {
|
||||
Main.writeConf();
|
||||
}
|
||||
|
||||
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");
|
||||
public static boolean downloadDependencies () {
|
||||
boolean downloader = new Fozzie().DownloadFile("https://bonkmaykr.worlio.com/http/firestar/fire13.zip", System.getProperty("user.home") + "/.firestar/", "firesdk.zip", "Firestar dependencies");
|
||||
if (!downloader) {return false;}
|
||||
|
||||
final String expectedMD5Hash = "306807955266724172476879569959042600238"; // Prevent a malicious web server takeover from installing malware on the user's computer.
|
||||
String downloadedMD5Hash = ""; // if this number does not match for ANY reason, cancel immediately and get a programmer.
|
||||
try {downloadedMD5Hash = new BigInteger(1, MessageDigest.getInstance("MD5").digest(Files.readAllBytes(Paths.get(Main.inpath + "firesdk.zip")))).toString();}
|
||||
catch (Exception e) {
|
||||
System.out.println("ERROR: Failed to download PSARC tool due to an internal problem.\n" + e.getMessage());
|
||||
JOptionPane.showMessageDialog(null, "The file failed to download.\nPlease check your network connection and try again.\n\n" + e.getMessage(), "Download Failed", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
if (!downloadedMD5Hash.equals(expectedMD5Hash)) {
|
||||
System.out.println("ERROR: Downloaded PSARC tool is invalid. Check your network connection and ensure the file is not corrupt or infected.");
|
||||
//Object[] options = {"Abort", "Retry"};
|
||||
//int result = JOptionPane.showOptionDialog(new JFrame(), "The downloaded file failed a security check.\nPlease ensure your network connection is stable.\n\nIf this issue persists, send an email to tech support\nat bonkmaykr@screwgravity.net.", "Download Cancelled", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
|
||||
JOptionPane.showMessageDialog(null, "The downloaded file failed a security check.\nPlease ensure your network connection is stable.\n\nIf this issue persists, send an email to tech support\nat bonkmaykr@screwgravity.net.", "Download Cancelled", JOptionPane.WARNING_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
ZipFile sdk = new ZipFile(System.getProperty("user.home") + "/.firestar/firesdk.zip");
|
||||
try {
|
||||
sdk.extractAll(System.getProperty("user.home") + "/.firestar/");
|
||||
@@ -230,12 +273,9 @@ public class Main {
|
||||
}
|
||||
sdk.getFile().delete(); // cleanup
|
||||
|
||||
JOptionPane.showMessageDialog(null, "All remote dependencies satisfied.", "Download Completed", JOptionPane.INFORMATION_MESSAGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean callDownloaderStatically (String url, String folder, String name) {
|
||||
return new Fozzie().DownloadFile(url, folder, name);
|
||||
}
|
||||
|
||||
public static Process exec(String[] cmd, String cwd) throws IOException {
|
||||
Process p;
|
||||
@@ -250,4 +290,16 @@ public class Main {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
public static void printProcessLogToStdOut(Process p) {
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(p.getInputStream()));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {System.out.println(line);}
|
||||
reader.close();
|
||||
} catch (final Exception e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,11 @@ import java.math.RoundingMode;
|
||||
import java.net.URI;
|
||||
import java.nio.file.*;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lingala.zip4j.*;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -172,7 +175,7 @@ public class MissPiggy implements ActionListener {
|
||||
frame.setLayout(new GridLayout());
|
||||
frame.setLocationRelativeTo(null);
|
||||
|
||||
if (Main.checkUpdates) { StartErnie(); }
|
||||
if (Main.checkUpdates) { StartErnie(false); }
|
||||
|
||||
frame.setVisible(true);
|
||||
}
|
||||
@@ -230,6 +233,16 @@ public class MissPiggy implements ActionListener {
|
||||
if (metadata.has("loaderversion")) {m.loaderversion = Integer.parseInt(metadata.get("loaderversion").toString());}
|
||||
if (metadata.has("game")) {m.game = metadata.get("game").toString();}
|
||||
|
||||
if (m.loaderversion >= 1) {
|
||||
// Firestar 1.3 features
|
||||
if (metadata.has("requires"))
|
||||
for (Object i : (ArrayList<Object>)((Map<String, Object>)metadata.toMap()).get("requires"))
|
||||
m.requires.add(i.toString());
|
||||
if (metadata.has("extracts"))
|
||||
for (Object i : (ArrayList<Object>)((Map<String, Object>)metadata.toMap()).get("extracts"))
|
||||
m.extracts.add(i.toString());
|
||||
}
|
||||
|
||||
//send to list
|
||||
Main.Mods.add(m);
|
||||
} catch (Exception e) {
|
||||
@@ -300,11 +313,11 @@ public class MissPiggy implements ActionListener {
|
||||
createSelectionEventListener();
|
||||
}
|
||||
|
||||
private void StartErnie() {
|
||||
private void StartErnie(boolean isManual) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new Ernie(frame); // changed away from runnable in order to pass params to constructor -bonk
|
||||
new Ernie(frame, isManual); // changed away from runnable in order to pass params to constructor -bonk
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -332,7 +345,11 @@ public class MissPiggy implements ActionListener {
|
||||
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(0)) {metaEditorGUI(modList.getSelectedIndex());} else
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(1)) {generatorGUI();} else
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(2)) {new Suggs(frame);} else
|
||||
if (actionEvent.getSource() == toolsMenu.getItem(2)) {
|
||||
if (!new File(Main.inpath + "at9tool.exe").exists() || !new File(Main.inpath + "ffmpeg.exe").exists())
|
||||
JOptionPane.showMessageDialog(frame, "Your AT9 encoders are missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
else new Suggs(frame);
|
||||
} else
|
||||
|
||||
if (actionEvent.getSource() == helpMenu.getItem(0)) {
|
||||
try {
|
||||
@@ -358,7 +375,7 @@ public class MissPiggy implements ActionListener {
|
||||
JOptionPane.showMessageDialog(frame, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} else
|
||||
if (actionEvent.getSource() == helpMenu.getItem(5)) {StartErnie();} else
|
||||
if (actionEvent.getSource() == helpMenu.getItem(5)) {StartErnie(true);} else
|
||||
if (actionEvent.getSource() == helpMenu.getItem(6)) {new Rowlf(frame);}
|
||||
}
|
||||
|
||||
@@ -460,7 +477,6 @@ public class MissPiggy implements ActionListener {
|
||||
}
|
||||
|
||||
public void removeAllGUI() {
|
||||
// todo warning dialog that nukes list when Yes is clicked
|
||||
int result = JOptionPane.showConfirmDialog(frame, "Do you really want to delete all mods?", "Remove All", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
|
||||
@@ -47,15 +47,13 @@ import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
public class Rizzo {
|
||||
private final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
private Scanner scanner;
|
||||
private final int maxVer = 1;
|
||||
private int ver = 1;
|
||||
@@ -77,9 +75,9 @@ public class Rizzo {
|
||||
}
|
||||
|
||||
private boolean parseArgs(String[] args, Object context) throws FirescriptFormatException {
|
||||
System.out.println("Parsing Command: " + Arrays.toString(args));
|
||||
if (args.length > 0) {
|
||||
if (context == null) {
|
||||
System.out.println("Parsing Command: " + Arrays.toString(args));
|
||||
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");
|
||||
@@ -87,9 +85,9 @@ public class Rizzo {
|
||||
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 throw new FirescriptFormatException("fscript", "command '" + args[0] + "' is unknown or used in inappropriate context");
|
||||
} else {
|
||||
System.out.println("Using context: " + context.getClass().getName() + "@" + context.hashCode());
|
||||
System.out.println("Parsing Command: " + Arrays.toString(args) + " using context: " + context.getClass().getName() + "@" + context.hashCode());
|
||||
if (args[0].equals("{")) {
|
||||
System.out.println("New context block: " + context.getClass().getName() + "@" + context.hashCode());
|
||||
parseScript(context);
|
||||
@@ -106,7 +104,6 @@ public class Rizzo {
|
||||
}
|
||||
} 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", ""), "&", "&"), "\n", " ");
|
||||
@@ -123,15 +120,7 @@ public class Rizzo {
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, "html");
|
||||
transformer.transform(source, result);
|
||||
// Look ma, I'm breaking XML standards!
|
||||
String xmlString = result.getWriter().toString()
|
||||
.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace("	", "\t")
|
||||
.replace("", "\b")
|
||||
.replace(" ", "\n")
|
||||
.replace(" ", "\r")
|
||||
.replace("", "\f");
|
||||
String xmlString = StringEscapeUtils.unescapeHtml4(result.getWriter().toString());
|
||||
try (PrintStream ps = new PrintStream(output)) {
|
||||
ps.print(xmlString);
|
||||
}
|
||||
@@ -139,7 +128,7 @@ public class Rizzo {
|
||||
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);
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, "This usually means there's non-standard formatting from the game developer which your FSCRIPT does not account for.", ex);
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("str") || args[0].equalsIgnoreCase("xstr")) {
|
||||
try {
|
||||
@@ -206,49 +195,62 @@ public class Rizzo {
|
||||
} catch (FirescriptFormatException | PatchFailedException | IOException ex) {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} else throw new FirescriptFormatException("file", "unknown command '" + args[0] + "'");
|
||||
} else throw new FirescriptFormatException("file", "command '" + args[0] + "' is unknown or used in inappropriate context");
|
||||
} else if (args[0].equalsIgnoreCase("xml")) {
|
||||
System.out.println("fscript: XML called but file does not exist. Using placebo...");
|
||||
try {
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
parseArgs(Arrays.copyOfRange(args, 1, args.length), docBuilder.newDocument());
|
||||
} catch (ParserConfigurationException ex1) {
|
||||
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex1);
|
||||
throw new FirescriptFormatException("xml", "critical document failure");
|
||||
}
|
||||
} else System.out.println("fscript: file context not found, skipping.");
|
||||
} else if (context instanceof Document document) {
|
||||
if (args[0].equalsIgnoreCase("modify")) {
|
||||
Element elem = (Element)traverse(document, args[1]);
|
||||
parseArgs(Arrays.copyOfRange(args, 2, args.length), elem);
|
||||
} else if (args[0].equalsIgnoreCase("create")) {
|
||||
String newTag = args[1].substring(args[1].lastIndexOf(".")+1);
|
||||
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", ""), "&", "&"), "\n", " ");
|
||||
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);
|
||||
if (document.hasChildNodes()) {
|
||||
if (args[0].equalsIgnoreCase("modify")) {
|
||||
Element elem = (Element)traverse(document, args[1]);
|
||||
parseArgs(Arrays.copyOfRange(args, 2, args.length), elem);
|
||||
} else if (args[0].equalsIgnoreCase("create")) {
|
||||
String newTag = args[1].substring(args[1].lastIndexOf(".")+1);
|
||||
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 {
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
ReplacingInputStream ris = new ReplacingInputStream(new ReplacingInputStream(new ReplacingInputStream(new FileInputStream(new File(workingDir + args[1])), "\r\n", ""), "&", "&"), "\n", " ");
|
||||
Document outDoc = docBuilder.parse(ris); // throw new FirescriptFormatException("xml", "javax.xml.parsers self-destructed with error:\n" + e.getMessage() + "\nThis usually means you used a bad FSCRIPT, or there was non-standard formatting from the game developer.");
|
||||
|
||||
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);
|
||||
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, "This usually means there's non-standard formatting from the game developer which your FSCRIPT does not account for.", ex);
|
||||
}
|
||||
} 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 throw new FirescriptFormatException("xml", "command '" + args[0] + "' is unknown or used in inappropriate context");
|
||||
} else {
|
||||
System.out.println("fscript: XML document has no child nodes. Skipping...");
|
||||
parseArgs(Arrays.copyOfRange(args, 1, args.length), document);
|
||||
}
|
||||
} else if (context instanceof Element element) {
|
||||
if (args[0].equalsIgnoreCase("set")) {
|
||||
if (args[1].equalsIgnoreCase("attribute"))
|
||||
@@ -347,6 +349,7 @@ public class Rizzo {
|
||||
ns = ((Element)parent).getChildNodes();
|
||||
for (int i = 0; i < ns.getLength(); i++) {
|
||||
Node n = ns.item(i);
|
||||
if (n instanceof Comment) continue;
|
||||
if (n.getNodeName().equals("#text")) continue;
|
||||
if (((Element)n).getAttribute("name").equals(name)) {
|
||||
newParent = (Element)n;
|
||||
|
||||
@@ -58,7 +58,8 @@ public class Rowlf {
|
||||
informationText.getCaret().setVisible(false);
|
||||
informationText.setFocusable(false);
|
||||
|
||||
versionLabel.setText("Version " + Main.vstr + " (" + Main.vcode + ")");
|
||||
versionLabel.setText(Main.vstr + " (" + Main.vcode + ")");
|
||||
//if (Main.isNightly) {versionLabel.setText(versionLabel.getText() + " built " + Main.dateOfCompile);}
|
||||
environmentLabel.setText("Running on Java " + System.getProperty("java.version") + " for " + System.getProperty("os.name"));
|
||||
|
||||
// display window
|
||||
|
||||
@@ -28,10 +28,7 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
@@ -209,12 +206,14 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
}
|
||||
} else
|
||||
if (actionEvent.getSource() == spDeleteBtn) {
|
||||
dSTitle.setToolTipText(null);
|
||||
dSTitle.setText("no track");
|
||||
dSSize.setText("no size");
|
||||
sptrack = null;
|
||||
spDeleteBtn.setVisible(false);
|
||||
} else
|
||||
if (actionEvent.getSource() == mpDeleteBtn) {
|
||||
dMTitle.setToolTipText(null);
|
||||
dMTitle.setText("no track");
|
||||
dMSize.setText("no size");
|
||||
mptrack = null;
|
||||
@@ -337,7 +336,8 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
sptrack = selectedFile;
|
||||
dSTitle.setText(selectedFile.getName());
|
||||
dSTitle.setText(selectedFile.getName().substring(0, Math.min(selectedFile.getName().length(), 20)));
|
||||
if (selectedFile.getName().length() > 20) {dSTitle.setToolTipText(selectedFile.getName());}
|
||||
dSSize.setText(selectedFile.length() + " B");
|
||||
if (selectedFile.length() > 1023) {
|
||||
dSSize.setText((selectedFile.length() / 1024) + " KB");
|
||||
@@ -355,7 +355,8 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
mptrack = selectedFile;
|
||||
dMTitle.setText(selectedFile.getName());
|
||||
dMTitle.setText(selectedFile.getName().substring(0, Math.min(selectedFile.getName().length(), 20)));
|
||||
if (selectedFile.getName().length() > 20) {dMTitle.setToolTipText(selectedFile.getName());}
|
||||
dMSize.setText(selectedFile.length() + " B");
|
||||
if (selectedFile.length() > 1023) {
|
||||
dMSize.setText((selectedFile.length() / 1024) + " KB");
|
||||
@@ -433,19 +434,24 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
progressDialog.setText("Encoding track " + (i+1) + " out of " + tracklist.size() + "...");
|
||||
try {
|
||||
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
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
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");
|
||||
}
|
||||
if (normalizeVolumes) { // normalize tracks
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
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/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + "_normalized.wav");
|
||||
} else { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", at.path.getPath(), "-ar", "44100", "ffmpeg/" + at.path.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
at.path = new File(Main.inpath + "temp/ffmpeg/" + at.path.getName() + ".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/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
@@ -500,20 +506,25 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
if (sptrack.exists()) {
|
||||
try {
|
||||
System.out.println("Encoding singleplayer frontend track...");
|
||||
if (!sptrack.getName().endsWith(".wav") && !sptrack.getName().endsWith(".wave")) { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
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
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
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/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + "_normalized.wav");
|
||||
} else { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", sptrack.getPath(), "-ar", "44100", "ffmpeg/" + sptrack.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
sptrack = new File(Main.inpath + "temp/ffmpeg/" + sptrack.getName() + ".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/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
@@ -528,20 +539,25 @@ public class Suggs implements ActionListener, ListSelectionListener {
|
||||
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
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
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
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
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/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + "_normalized.wav");
|
||||
} else { // convert to WAV first if it's not readable by at9tool yet
|
||||
new File(Main.inpath + "temp/ffmpeg/").mkdirs();
|
||||
Process p = Main.exec(new String[]{Main.inpath + "ffmpeg.exe", "-y", "-i", mptrack.getPath(), "-ar", "44100", "ffmpeg/" + mptrack.getName() + ".wav"}, Main.inpath + "temp/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
mptrack = new File(Main.inpath + "temp/ffmpeg/" + mptrack.getName() + ".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/");
|
||||
final Thread ioThread = new Thread() {@Override public void run() {Main.printProcessLogToStdOut(p);}};
|
||||
ioThread.start();
|
||||
p.waitFor();
|
||||
Main.deleteDir(new File(Main.inpath + "temp/ffmpeg/"));
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
|
||||
@@ -90,7 +90,9 @@
|
||||
<grid id="b015e" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<maximum-size width="500" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<opaque value="false"/>
|
||||
@@ -99,7 +101,7 @@
|
||||
<children>
|
||||
<component id="18770" class="javax.swing.JLabel" binding="fOutpath">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<font name="Exo 2"/>
|
||||
@@ -109,7 +111,7 @@
|
||||
</component>
|
||||
<component id="fa1ee" class="javax.swing.JButton" binding="fOutpathChangebtn">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<background color="-2271221"/>
|
||||
|
||||
@@ -67,7 +67,7 @@ public class Waldorf implements ActionListener {
|
||||
dwnSDKbtn.addActionListener(this);
|
||||
fOutpathChangebtn.addActionListener(this);
|
||||
|
||||
fOutpath.setText(Main.outpath);
|
||||
updateDOutpath(Main.outpath);
|
||||
checkUpdatesToggle.setSelected(Main.checkUpdates);
|
||||
|
||||
frame.setVisible(true);
|
||||
@@ -81,6 +81,13 @@ public class Waldorf implements ActionListener {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateDOutpath(String path) {
|
||||
String s = path;
|
||||
if (s.startsWith(System.getProperty("user.home"))) {s = "~" + s.substring(System.getProperty("user.home").length());}
|
||||
if (s.length() > 50) {s = s.substring(0, Math.min(path.length(), 46)) + "...";fOutpath.setToolTipText(path);} else {fOutpath.setToolTipText(null);}
|
||||
fOutpath.setText(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
if (actionEvent.getSource() == cancelbtn) {
|
||||
@@ -126,6 +133,10 @@ public class Waldorf implements ActionListener {
|
||||
JOptionPane.showMessageDialog(frame, "PSARC files purged.", "Delete PSARCs", JOptionPane.INFORMATION_MESSAGE);
|
||||
} else
|
||||
if (actionEvent.getSource() == dwnARCbtn) {
|
||||
if (!new File(Main.inpath + "pkg2zip.exe").exists() || !new File(Main.inpath + "psvpfsparser.exe").exists()) {
|
||||
JOptionPane.showMessageDialog(frame, "Your decryption tools are missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
new Bert(invoker.frame);
|
||||
frame.dispose();
|
||||
} else
|
||||
@@ -147,7 +158,7 @@ public class Waldorf implements ActionListener {
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
if (fileChooser.getSelectedFile().isDirectory()) {
|
||||
tOutPath = fileChooser.getSelectedFile().getAbsolutePath()+"/";
|
||||
fOutpath.setText(tOutPath);
|
||||
updateDOutpath(tOutPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 851 B After Width: | Height: | Size: 5.0 KiB |
BIN
firestar/src/main/resources/splash0.png
Normal file
|
After Width: | Height: | Size: 362 KiB |
BIN
firestar/src/main/resources/splash1.png
Normal file
|
After Width: | Height: | Size: 326 KiB |
BIN
firestar/src/main/resources/splash10.png
Normal file
|
After Width: | Height: | Size: 319 KiB |
BIN
firestar/src/main/resources/splash2.png
Normal file
|
After Width: | Height: | Size: 362 KiB |
BIN
firestar/src/main/resources/splash3.png
Normal file
|
After Width: | Height: | Size: 299 KiB |
BIN
firestar/src/main/resources/splash4.png
Normal file
|
After Width: | Height: | Size: 374 KiB |
BIN
firestar/src/main/resources/splash5.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
firestar/src/main/resources/splash6.png
Normal file
|
After Width: | Height: | Size: 293 KiB |
BIN
firestar/src/main/resources/splash7.png
Normal file
|
After Width: | Height: | Size: 238 KiB |
BIN
firestar/src/main/resources/splash8.png
Normal file
|
After Width: | Height: | Size: 429 KiB |
BIN
firestar/src/main/resources/splash9.png
Normal file
|
After Width: | Height: | Size: 318 KiB |
1287
firestar/src/main/resources/unused.fscript
Normal file
@@ -1 +1 @@
|
||||
netbeans.hint.jdkPlatform=JDK_22__System_
|
||||
netbeans.hint.jdkPlatform=JDK_17__System_
|
||||
|
||||