Compare commits
77 Commits
00b8d540b3
...
tetsuo-1.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| 3d91ebbbd7 | |||
| 52dbc56104 | |||
| 17bbae0d66 | |||
| 4aa017f7ac | |||
| a57e5695a5 | |||
| 009f406a4b | |||
| 2d7e0a1cb0 | |||
| b4b8b1ced5 | |||
| 7d26ed564e | |||
| 14a943edf3 | |||
| 408a52512b | |||
| 6e292212fd | |||
| a91ba62bf8 | |||
| 859ac41fde | |||
| acd1f0dfe8 | |||
| 7b7d4a206e | |||
| 1abe9519c8 | |||
| 82b351928b | |||
| 921df0cbd5 | |||
| f11dfc5378 | |||
| 68a0dcba49 | |||
| 862c5d62a4 | |||
| 47159b6efb | |||
| 07e98b12df | |||
| 93ec606440 | |||
| 869566d732 | |||
| 1d8534e39c | |||
| f46ca4c066 | |||
| 13f82e3866 | |||
| 851223fa9f | |||
| b7161a9295 | |||
| 22319167a8 | |||
| c24da0edfd | |||
| 3c6b3e84ba | |||
| 4720c3e217 | |||
| a22c77f0b8 | |||
| 6401deccc4 | |||
| a7e3815f17 | |||
| 483541e396 | |||
| b5f04cf87d | |||
| 079697fb89 | |||
| 16f729e4c2 | |||
| 422c50b610 | |||
| 49281a5248 | |||
| 028886ebe9 | |||
| b26adf95e8 | |||
| cbd9c75f81 | |||
| 55df70130c | |||
| 5fbfc33b47 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -28,6 +28,7 @@ out/
|
|||||||
### Mac OS ###
|
### Mac OS ###
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
### Binaries ###
|
||||||
/firestar.zip
|
/firestar.zip
|
||||||
/run-linux.sh
|
/run-linux.sh
|
||||||
/run-win32.bat
|
/run-win32.bat
|
||||||
@@ -37,3 +38,4 @@ out/
|
|||||||
/build/
|
/build/
|
||||||
/.gradle/
|
/.gradle/
|
||||||
/gradle/
|
/gradle/
|
||||||
|
!/gradle/wrapper/*
|
||||||
10
.idea/libraries/apache_commons_io.xml
generated
Normal file
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
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>
|
||||||
54
README.md
54
README.md
@@ -1,6 +1,6 @@
|
|||||||

|

|
||||||
|
|
||||||
**Firestar is a cross-platform Java-based mod manager for WipEout 2048**, which runs on a desktop/laptop computer and aims to allow easy installation of mods for users with very little hassle. It is compatible with both real PSVita hardware, as well as emulators.
|
**Firestar is a cross-platform Java-based mod manager for WipEout 2048**, which runs on a desktop/laptop computer and aims to allow easy installation of mods with very little hassle. It is compatible with both real PSVita hardware, as well as with emulators.
|
||||||
|
|
||||||
## Get Started: [>> CLICK HERE <<](https://git.worlio.com/bonkmaykr/firestar/wiki)
|
## Get Started: [>> CLICK HERE <<](https://git.worlio.com/bonkmaykr/firestar/wiki)
|
||||||
|
|
||||||
@@ -11,19 +11,48 @@ The latest version of Firestar will always be available from [Releases](https://
|
|||||||
If you aren't sure which file to get:
|
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://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_1.2_installer_windows.exe).
|
||||||
- **Linux:** Install one of the packages from the [Releases](https://git.worlio.com/bonkmaykr/firestar/releases) page:
|
- **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`
|
- 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`
|
- 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`
|
- 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 [Portable ZIP](https://files.worlio.com/users/bonkmaykr/tools/firestar/latest/firestar_dekka-1.2_portable.zip), extract it, and run the JAR file.
|
||||||
|
|
||||||
# System Requirements
|
# System Requirements
|
||||||
- Windows 8 or newer, Mac OS X 10.14 or older, any modern version of Linux/BSD
|
- Windows 8 or newer, Mac OS X 10.14 or older, any modern version of Linux/BSD
|
||||||
- If you have a Mac running 10.15 Catalina or newer, you should use Crossover to run the Windows version of Firestar instead.
|
- If you have a Mac running 10.15 Catalina or newer, you should use Crossover to run the Windows version of Firestar instead.
|
||||||
- Java 17 or above.
|
- Java 17 or above.
|
||||||
- **Non-Windows systems only**: WINE
|
- **Non-Windows systems only**: WINE
|
||||||
- **Version 1.3 and above only:** [Visual C++ 2012 libraries](http://www.microsoft.com/en-au/download/confirmation.aspx?id=30679)
|
- **Version 1.3 and above only:** [Visual C++ 2012 libraries](http://www.microsoft.com/en-au/download/confirmation.aspx?id=30679)
|
||||||
- Do NOT install Firestar directly to your PSVita's storage. Some of it's file operations do not play nice with FAT filesystems.
|
- Do NOT install Firestar directly to your PSVita's storage. Some of it's file operations do not play nice with FAT filesystems.
|
||||||
|
|
||||||
|
# Building
|
||||||
|
You are always free to copy the Firestar source code and compile the latest work-in-progress version for yourself.
|
||||||
|
Firestar uses the Gradle build system. We write our code and perform all our tests on Linux, but these same steps should apply to all major operating systems.
|
||||||
|
|
||||||
|
## With Intellij IDEA
|
||||||
|
1. Create a new project cloned from this Git repo
|
||||||
|
2. Open the run configurations editor by clicking "Default" in the top right corner and selecting "Edit Configurations".
|
||||||
|
3. Set the JDK to Java 17, the module to firestar.firestar.main and the main class to Firestar's Main class.
|
||||||
|
4. Go to Modify Options > Add before launch task, then add a Gradle "clean" task
|
||||||
|
5. Go there again and add a Gradle "build" task
|
||||||
|
6. Delete the default build task that has now appeared as step 1.
|
||||||
|
7. Save your options and click the Play button to compile and test.
|
||||||
|
|
||||||
|
## From the command line
|
||||||
|
1. Ensure you have both Git and Gradle installed on your system.
|
||||||
|
- Windows: Visit [git-scm.com](https://git-scm.com/downloads) and the [Gradle Installation Guide](https://gradle.org/install/).
|
||||||
|
- Linux/BSD: Install the `git` and `gradle` packages from your package manager. For example:
|
||||||
|
- Arch-based: `sudo pacman -Sy git gradle` (if this breaks your computer then run -Syu to rectify it)
|
||||||
|
- Debian-based: `sudo apt install git gradle`
|
||||||
|
- Mac: Figure it out! None of us on the dev team use Macs and we can't be assed to.
|
||||||
|
2. Open the terminal and clone the git repo. This will download the Firestar source code to a `firestar/` folder in your current working directory.
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://git.worlio.com/bonkmaykr/firestar.git
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
# FAQ
|
||||||
## Can I use this on a Vita without enso/HEN?
|
## Can I use this on a Vita without enso/HEN?
|
||||||
No. You need a modded Vita in order to use this. Hacking a Vita is super easy these days, but if you don't want to, you can always use Vita3K instead.
|
No. You need a modded Vita in order to use this. Hacking a Vita is super easy these days, but if you don't want to, you can always use Vita3K instead.
|
||||||
@@ -49,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.**
|
**If you are on Mac OS X you will need an older OS version that is still compatible with 32-bit applications.**
|
||||||
|
|
||||||
# Developer Commentary
|
# 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
|
## Third Party Code
|
||||||
Firestar is built on top of the following additional software:
|
Firestar is built on top of the following additional software:
|
||||||
- *[WINE](https://www.winehq.org/), for running the below applications across platforms.
|
- *[WINE](https://www.winehq.org/), for running the below applications across platforms.
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ configurations {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '2.11.5'
|
implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '2.11.5'
|
||||||
implementation group: 'org.json', name: 'json', version: '20240303'
|
implementation group: 'org.json', name: 'json', version: '20240303'
|
||||||
implementation "io.github.java-diff-utils:java-diff-utils:4.12"
|
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'
|
implementation 'com.jetbrains.intellij.java:java-gui-forms-rt:203.7148.30'
|
||||||
antTask 'com.jetbrains.intellij.java:java-compiler-ant-tasks:203.7148.30'
|
antTask 'com.jetbrains.intellij.java:java-compiler-ant-tasks:203.7148.30'
|
||||||
@@ -30,14 +32,15 @@ java {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
manifest {
|
||||||
attributes(
|
attributes(
|
||||||
'Main-Class': 'Main'
|
'Main-Class': 'Main'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
from {
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
from {
|
||||||
}
|
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</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="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<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"/>
|
<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,53 +120,115 @@
|
|||||||
</properties>
|
</properties>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
<children>
|
<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">
|
<component id="f3723" class="javax.swing.JCheckBox" binding="hdCheck">
|
||||||
<constraints>
|
<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="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<background color="-15128227"/>
|
<background color="-15128227"/>
|
||||||
|
<focusPainted value="false"/>
|
||||||
<font name="Exo 2"/>
|
<font name="Exo 2"/>
|
||||||
<foreground color="-1"/>
|
<foreground color="-1"/>
|
||||||
<horizontalTextPosition value="10"/>
|
<horizontalTextPosition value="10"/>
|
||||||
|
<opaque value="false"/>
|
||||||
<text value="HD Add-On Pack"/>
|
<text value="HD Add-On Pack"/>
|
||||||
|
<verticalTextPosition value="0"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="5ed0c" class="javax.swing.JCheckBox" binding="furyCheck">
|
<component id="5ed0c" class="javax.swing.JCheckBox" binding="furyCheck">
|
||||||
<constraints>
|
<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="1" 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="2" 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="0" 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>
|
||||||
|
</children>
|
||||||
|
</grid>
|
||||||
|
<component id="45b94" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="2" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<background color="-15128227"/>
|
<background color="-15128227"/>
|
||||||
<font name="Exo 2"/>
|
<font name="Exo 2"/>
|
||||||
<foreground color="-1"/>
|
<foreground color="-1"/>
|
||||||
<horizontalTextPosition value="11"/>
|
<opaque value="false"/>
|
||||||
<selected value="false"/>
|
<text value="Select DLC Packs:"/>
|
||||||
<text value="Fury Add-On Pack"/>
|
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
@@ -16,272 +16,308 @@
|
|||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class Bert implements ActionListener {
|
public class Bert implements ActionListener {
|
||||||
BufferedImage windowIcon;
|
public JFrame frame = new JFrame();
|
||||||
public JFrame frame = new JFrame();
|
private JPanel frameContainer;
|
||||||
private JPanel frameContainer;
|
private JButton cancelbtn;
|
||||||
private JButton cancelbtn;
|
private JButton downloadbtn;
|
||||||
private JButton downloadbtn;
|
private JRadioButton baseCheck;
|
||||||
private JCheckBox patchCheck;
|
private JRadioButton patchCheck1;
|
||||||
private JCheckBox baseCheck;
|
private JRadioButton patchCheck2;
|
||||||
private JCheckBox hdCheck;
|
private JCheckBox hdCheck;
|
||||||
private JCheckBox furyCheck;
|
private JCheckBox furyCheck;
|
||||||
private ButtonGroup radios = new ButtonGroup();
|
private ButtonGroup radios = new ButtonGroup();
|
||||||
|
|
||||||
private JFrame invoker;
|
private JFrame invoker;
|
||||||
|
|
||||||
private boolean wilkinsDownloadFinished = false;
|
private boolean wilkinsDownloadFinished = false;
|
||||||
|
|
||||||
public Bert(JFrame parent) {
|
public Bert(JFrame parent) {
|
||||||
parent.setEnabled(false);
|
parent.setEnabled(false);
|
||||||
this.invoker = parent;
|
this.invoker = parent;
|
||||||
|
|
||||||
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
||||||
|
|
||||||
frame.setSize(600, 300); // 1280 800
|
frame.setSize(600, 300); // 1280 800
|
||||||
frame.setTitle("Download Assets");
|
frame.setTitle("Download Assets");
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
frame.setLayout(new GridLayout());
|
frame.setLayout(new GridLayout());
|
||||||
frame.setLocationRelativeTo(parent);
|
frame.setLocationRelativeTo(parent);
|
||||||
frame.setAlwaysOnTop(true);
|
frame.setAlwaysOnTop(true);
|
||||||
|
|
||||||
cancelbtn.addActionListener(this);
|
radios.add(baseCheck);
|
||||||
downloadbtn.addActionListener(this);
|
radios.add(patchCheck1);
|
||||||
|
radios.add(patchCheck2);
|
||||||
|
|
||||||
try {
|
cancelbtn.addActionListener(this);
|
||||||
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
downloadbtn.addActionListener(this);
|
||||||
frame.setIconImage(windowIcon);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
|
||||||
}
|
|
||||||
|
|
||||||
frame.setVisible(true);
|
frame.setIconImage(Main.windowIcon);
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
|
||||||
@Override
|
|
||||||
public void windowClosing(WindowEvent e)
|
|
||||||
{
|
|
||||||
parent.setEnabled(true);
|
|
||||||
e.getWindow().dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!new File(Main.inpath + "pkg2zip.exe").exists() || !new File(Main.inpath + "psvpfsparser.exe").exists()) {
|
frame.setVisible(true);
|
||||||
JOptionPane.showMessageDialog(frame, "The decryption tool is missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
invoker.setEnabled(true);
|
@Override
|
||||||
frame.dispose();
|
public void windowClosing(WindowEvent e)
|
||||||
}
|
{
|
||||||
}
|
parent.setEnabled(true);
|
||||||
|
e.getWindow().dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
public boolean reportWhenDownloaded(WilkinsCoffee setup) {
|
if (!new File(Main.inpath + "pkg2zip.exe").exists() || !new File(Main.inpath + "psvpfsparser.exe").exists()) {
|
||||||
while (frame.isActive() || !wilkinsDownloadFinished) {}
|
JOptionPane.showMessageDialog(frame, "The decryption tool is missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
if (wilkinsDownloadFinished) { // intellij please shut the everloving FUCK up DON'T do this again or i will skin you alive
|
invoker.setEnabled(true);
|
||||||
return true;
|
frame.dispose();
|
||||||
} else {
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public boolean reportWhenDownloaded(WilkinsCoffee setup) {
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
while (frame.isActive() || !wilkinsDownloadFinished) {}
|
||||||
if (actionEvent.getSource() == cancelbtn) {
|
if (wilkinsDownloadFinished) { // intellij please shut the everloving FUCK up DON'T do this again or i will skin you alive
|
||||||
invoker.setEnabled(true);
|
return true;
|
||||||
frame.dispose();
|
} else {
|
||||||
} else if (actionEvent.getSource() == downloadbtn) {
|
return false;
|
||||||
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)");
|
|
||||||
}
|
|
||||||
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 (hdCheck.isSelected()) {
|
|
||||||
arcs.add(Main.ArcTarget.ADDON_HD);
|
|
||||||
keys.add(Main.ArcKey.ADDON_HD);
|
|
||||||
System.out.println("Begin 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)");
|
|
||||||
}
|
|
||||||
if (arcs.isEmpty()) {
|
|
||||||
JOptionPane.showMessageDialog(invoker, "Select one or more asset packs.", "Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
frame.dispose();
|
@Override
|
||||||
invoker.setVisible(false);
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
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>();
|
||||||
|
|
||||||
Thread downloaderPopupThread = new Thread(new Runnable() { // run on separate thread to prevent GUI freezing
|
// Always download predecessors to ensure no missing files
|
||||||
@Override
|
// Probably not necessary since I will be adding selective extraction to Gonzo,
|
||||||
public void run() {
|
// and throw errors when a lower PSARC doesn't exist, but there's no real reason not to.
|
||||||
for (Main.ArcTarget type : arcs) {
|
//
|
||||||
String key = "";
|
// Of course, to avoid additional download times, we should probably
|
||||||
String arcname = "";
|
// avoid adding to the download list if a file already exists, unless explicitly
|
||||||
switch (type) {
|
// selected (the exact radio button). The user can redownload one at a time
|
||||||
case BASE :
|
// but Firestar will not overwrite existing PSARCs otherwise.
|
||||||
key = Main.ArcKey.BASE.toString();
|
if (baseCheck.isSelected()) { // I have the base game
|
||||||
arcname = "Base game";
|
arcs.add(Main.ArcTarget.BASE);
|
||||||
break;
|
keys.add(Main.ArcKey.BASE);
|
||||||
case LATEST :
|
System.out.println("Begin download of data (Game version 1.0)");
|
||||||
key = Main.ArcKey.LATEST.toString();
|
}
|
||||||
arcname = "Updates";
|
if (patchCheck1.isSelected()) { // I updated it once after it came out and then didn't turn my vita on for thousands of years
|
||||||
break;
|
if (!new File(Main.inpath + "data.psarc").exists()) {
|
||||||
case ADDON_HD :
|
arcs.add(Main.ArcTarget.BASE);
|
||||||
key = Main.ArcKey.ADDON_HD.toString();
|
keys.add(Main.ArcKey.BASE);
|
||||||
arcname = "HD Add-On Pack";
|
System.out.println("Begin download of data (Game version 1.0)");
|
||||||
break;
|
}
|
||||||
case ADDON_HD_FURY :
|
arcs.add(Main.ArcTarget.FIRST);
|
||||||
key = Main.ArcKey.ADDON_HD_FURY.toString();
|
keys.add(Main.ArcKey.FIRST);
|
||||||
arcname = "Fury Add-On Pack";
|
System.out.println("Begin download of data1 (Game version 1.01)");
|
||||||
break;
|
}
|
||||||
}
|
if (patchCheck2.isSelected()) { // I'm a normal fucking person
|
||||||
if (key.isEmpty()) {
|
if (!new File(Main.inpath + "data.psarc").exists()) {
|
||||||
System.out.println("Internal Error: Bert got dementia. Get a programmer!");
|
arcs.add(Main.ArcTarget.BASE);
|
||||||
JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
keys.add(Main.ArcKey.BASE);
|
||||||
return;
|
System.out.println("Begin 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("Begin download of data1 (Game version 1.01)");
|
||||||
|
}
|
||||||
|
arcs.add(Main.ArcTarget.LATEST);
|
||||||
|
keys.add(Main.ArcKey.LATEST);
|
||||||
|
System.out.println("Begin download of data2 (Game version 1.04)");
|
||||||
|
}
|
||||||
|
|
||||||
// download file
|
// DLC are installed arbitrarily, separate of the game, and can remain as checkboxes with the old logic.
|
||||||
Fozzie downloaderHandler = new Fozzie();
|
// Likewise, the old overwrite policy applies. If the user selects these, it WILL download with no question.
|
||||||
boolean downloader = downloaderHandler.DownloadFile(type.toString(), Main.inpath, "asset.pkg", arcname);
|
if (hdCheck.isSelected()) {
|
||||||
|
arcs.add(Main.ArcTarget.ADDON_HD);
|
||||||
|
keys.add(Main.ArcKey.ADDON_HD);
|
||||||
|
System.out.println("Begin 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)");
|
||||||
|
}
|
||||||
|
if (arcs.isEmpty()) {
|
||||||
|
JOptionPane.showMessageDialog(invoker, "Select one or more asset packs.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!downloader) {
|
frame.dispose();
|
||||||
// cleanup
|
invoker.setVisible(false);
|
||||||
new File(Main.inpath + "asset.pkg").delete();
|
|
||||||
|
|
||||||
// restore controls
|
Thread downloaderPopupThread = new Thread(new Runnable() { // run on separate thread to prevent GUI freezing
|
||||||
invoker.setEnabled(true);
|
@Override
|
||||||
invoker.setVisible(true);
|
public void run() {
|
||||||
invoker.toFront();
|
for (Main.ArcTarget type : arcs) {
|
||||||
invoker.repaint();
|
String key = "";
|
||||||
return;
|
String arcname = "";
|
||||||
}
|
switch (type) {
|
||||||
|
case BASE :
|
||||||
|
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 = "Update 1.04";
|
||||||
|
break;
|
||||||
|
case ADDON_HD :
|
||||||
|
key = Main.ArcKey.ADDON_HD.toString();
|
||||||
|
arcname = "HD Add-On Pack";
|
||||||
|
break;
|
||||||
|
case ADDON_HD_FURY :
|
||||||
|
key = Main.ArcKey.ADDON_HD_FURY.toString();
|
||||||
|
arcname = "Fury Add-On Pack";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (key.isEmpty()) {
|
||||||
|
System.out.println("Internal Error: Bert got dementia. Get a programmer!");
|
||||||
|
JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// dump contents
|
// download file
|
||||||
System.out.println("Extracting " + arcname);
|
Fozzie downloaderHandler = new Fozzie();
|
||||||
Fozzie popup = new Fozzie();
|
boolean downloader = downloaderHandler.DownloadFile(type.toString(), Main.inpath, "asset.pkg", arcname);
|
||||||
popup.displayTextOnly("Extracting " + arcname + "...", "Extracting");
|
|
||||||
try {
|
|
||||||
Process p = Main.exec(new String[]{"pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath);
|
|
||||||
InputStream debugin = new BufferedInputStream(p.getInputStream());
|
|
||||||
OutputStream debugout = new BufferedOutputStream(System.out);
|
|
||||||
int c;
|
|
||||||
while ((c = debugin.read()) != -1) {
|
|
||||||
debugout.write(c);
|
|
||||||
}
|
|
||||||
debugin.close();
|
|
||||||
debugout.close();
|
|
||||||
p.waitFor();
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(e.getMessage());
|
|
||||||
JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
new File(Main.inpath + "asset.pkg").delete();
|
|
||||||
invoker.setEnabled(true);
|
|
||||||
invoker.setVisible(true);
|
|
||||||
invoker.toFront();
|
|
||||||
invoker.repaint();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decrypt
|
if (!downloader) {
|
||||||
System.out.println("Decrypting asset.pkg");
|
// cleanup
|
||||||
String extracted;
|
new File(Main.inpath + "asset.pkg").delete();
|
||||||
String name;
|
|
||||||
if (type == Main.ArcTarget.BASE) {
|
|
||||||
extracted = "app/PCSA00015";
|
|
||||||
name = "data.psarc";
|
|
||||||
} else if (type == Main.ArcTarget.LATEST) {
|
|
||||||
extracted = "patch/PCSA00015";
|
|
||||||
name = "data2.psarc";
|
|
||||||
} else if (type == Main.ArcTarget.ADDON_HD) {
|
|
||||||
extracted = "addcont/PCSA00015/DLC1W2048PACKAGE";
|
|
||||||
name = "dlc1.psarc";
|
|
||||||
} else if (type == Main.ArcTarget.ADDON_HD_FURY) { // this is not "always true" - intellij is actually very dumj
|
|
||||||
extracted = "addcont/PCSA00015/DLC2W2048PACKAGE";
|
|
||||||
name = "dlc2.psarc";
|
|
||||||
} else {
|
|
||||||
System.out.println("Internal Error: Bert got dementia. Get a programmer!");
|
|
||||||
JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
new File(Main.inpath + "asset.pkg").delete();
|
|
||||||
Main.deleteDir(new File(Main.inpath + "app/"));
|
|
||||||
Main.deleteDir(new File(Main.inpath + "patch/"));
|
|
||||||
Main.deleteDir(new File(Main.inpath + "addcont/"));
|
|
||||||
invoker.setEnabled(true);
|
|
||||||
invoker.setVisible(true);
|
|
||||||
invoker.toFront();
|
|
||||||
invoker.repaint();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
popup.setText("<html>Decrypting protected PFS:<br/>" + extracted + "</html>", "Decrypting");
|
// restore controls
|
||||||
|
invoker.setEnabled(true);
|
||||||
|
invoker.setVisible(true);
|
||||||
|
invoker.toFront();
|
||||||
|
invoker.repaint();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
// dump contents
|
||||||
Process p = Main.exec(new String[]{"psvpfsparser.exe", "-i", extracted, "-o", "./temp/", "-z", key.toString(), "-f", "cma.henkaku.xyz"}, Main.inpath);
|
System.out.println("Extracting " + arcname);
|
||||||
InputStream debugin = new BufferedInputStream(p.getInputStream());
|
Fozzie popup = new Fozzie();
|
||||||
OutputStream debugout = new BufferedOutputStream(System.out);
|
popup.displayTextOnly("Extracting " + arcname + "...", "Extracting");
|
||||||
int c;
|
try {
|
||||||
while ((c = debugin.read()) != -1) {
|
Process p = Main.exec(new String[]{Main.inpath + "pkg2zip.exe", "-x", "asset.pkg", key.toString()}, Main.inpath);
|
||||||
debugout.write(c);
|
InputStream debugin = new BufferedInputStream(p.getInputStream());
|
||||||
}
|
OutputStream debugout = new BufferedOutputStream(System.out);
|
||||||
debugin.close();
|
int c;
|
||||||
debugout.close();
|
while ((c = debugin.read()) != -1) {
|
||||||
p.waitFor();
|
debugout.write(c);
|
||||||
} catch (Exception e) {
|
}
|
||||||
System.out.println(e.getMessage());
|
debugin.close();
|
||||||
JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
debugout.close();
|
||||||
new File(Main.inpath + "asset.pkg").delete();
|
p.waitFor();
|
||||||
Main.deleteDir(new File(Main.inpath + "app/"));
|
} catch (Exception e) {
|
||||||
Main.deleteDir(new File(Main.inpath + "patch/"));
|
System.out.println(e.getMessage());
|
||||||
Main.deleteDir(new File(Main.inpath + "addcont/"));
|
JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
invoker.setEnabled(true);
|
new File(Main.inpath + "asset.pkg").delete();
|
||||||
invoker.setVisible(true);
|
invoker.setEnabled(true);
|
||||||
invoker.toFront();
|
invoker.setVisible(true);
|
||||||
invoker.repaint();
|
invoker.toFront();
|
||||||
return;
|
invoker.repaint();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
popup.setText("Deleting temporary files...", "Cleaning Up");
|
// decrypt
|
||||||
|
System.out.println("Decrypting asset.pkg");
|
||||||
|
String extracted;
|
||||||
|
String name;
|
||||||
|
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";
|
||||||
|
} else if (type == Main.ArcTarget.ADDON_HD) {
|
||||||
|
extracted = "addcont/PCSA00015/DLC1W2048PACKAGE";
|
||||||
|
name = "dlc1.psarc";
|
||||||
|
} else if (type == Main.ArcTarget.ADDON_HD_FURY) { // this is not "always true" - intellij is actually very dumj
|
||||||
|
extracted = "addcont/PCSA00015/DLC2W2048PACKAGE";
|
||||||
|
name = "dlc2.psarc";
|
||||||
|
} else {
|
||||||
|
System.out.println("Internal Error: Bert got dementia. Get a programmer!");
|
||||||
|
JOptionPane.showMessageDialog(invoker, "Internal Error: Bert got dementia. Get a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
new File(Main.inpath + "asset.pkg").delete();
|
||||||
|
Main.deleteDir(new File(Main.inpath + "app/"));
|
||||||
|
Main.deleteDir(new File(Main.inpath + "patch/"));
|
||||||
|
Main.deleteDir(new File(Main.inpath + "addcont/"));
|
||||||
|
invoker.setEnabled(true);
|
||||||
|
invoker.setVisible(true);
|
||||||
|
invoker.toFront();
|
||||||
|
invoker.repaint();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// stage & cleanup
|
popup.setText("<html>Decrypting protected PFS:<br/>" + extracted + "</html>", "Decrypting");
|
||||||
System.out.println("Cleaning up");
|
|
||||||
new File(Main.inpath + "asset.pkg").delete();
|
|
||||||
new File(Main.inpath + "temp/PSP2/" + name).renameTo(new File(Main.inpath + name));
|
|
||||||
Main.deleteDir(new File(Main.inpath + "app/"));
|
|
||||||
Main.deleteDir(new File(Main.inpath + "patch/"));
|
|
||||||
Main.deleteDir(new File(Main.inpath + "addcont/"));
|
|
||||||
Main.deleteDir(new File(Main.inpath + "temp/"));
|
|
||||||
|
|
||||||
popup.destroyDialog();
|
try {
|
||||||
}
|
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;
|
||||||
|
while ((c = debugin.read()) != -1) {
|
||||||
|
debugout.write(c);
|
||||||
|
}
|
||||||
|
debugin.close();
|
||||||
|
debugout.close();
|
||||||
|
p.waitFor();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(invoker, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
new File(Main.inpath + "asset.pkg").delete();
|
||||||
|
Main.deleteDir(new File(Main.inpath + "app/"));
|
||||||
|
Main.deleteDir(new File(Main.inpath + "patch/"));
|
||||||
|
Main.deleteDir(new File(Main.inpath + "addcont/"));
|
||||||
|
invoker.setEnabled(true);
|
||||||
|
invoker.setVisible(true);
|
||||||
|
invoker.toFront();
|
||||||
|
invoker.repaint();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// restore controls
|
popup.setText("Deleting temporary files...", "Cleaning Up");
|
||||||
JOptionPane.showMessageDialog(frame, "Assets downloaded successfully.", "Download Complete", JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
invoker.setEnabled(true);
|
// stage & cleanup
|
||||||
invoker.setVisible(true);
|
System.out.println("Cleaning up");
|
||||||
invoker.toFront();
|
new File(Main.inpath + "asset.pkg").delete();
|
||||||
invoker.repaint();
|
new File(Main.inpath + "temp/PSP2/" + name).renameTo(new File(Main.inpath + name));
|
||||||
wilkinsDownloadFinished = true;
|
Main.deleteDir(new File(Main.inpath + "app/"));
|
||||||
}
|
Main.deleteDir(new File(Main.inpath + "patch/"));
|
||||||
});
|
Main.deleteDir(new File(Main.inpath + "addcont/"));
|
||||||
downloaderPopupThread.start();
|
Main.deleteDir(new File(Main.inpath + "temp/"));
|
||||||
}
|
|
||||||
}
|
popup.destroyDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore controls
|
||||||
|
JOptionPane.showMessageDialog(frame, "Assets downloaded successfully.", "Download Complete", JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
invoker.setEnabled(true);
|
||||||
|
invoker.setVisible(true);
|
||||||
|
invoker.toFront();
|
||||||
|
invoker.repaint();
|
||||||
|
wilkinsDownloadFinished = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
downloaderPopupThread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,217 +20,253 @@ import net.lingala.zip4j.ZipFile;
|
|||||||
import net.lingala.zip4j.exception.ZipException;
|
import net.lingala.zip4j.exception.ZipException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.filechooser.FileFilter;
|
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
||||||
|
|
||||||
public class Clifford implements ActionListener {
|
public class Clifford implements ActionListener {
|
||||||
private JFrame frame = new JFrame();
|
private JFrame frame = new JFrame();
|
||||||
private JPanel frameContainer;
|
private JPanel frameContainer;
|
||||||
private JTextField fName;
|
private JTextField fName;
|
||||||
private JTextField fAuthor;
|
private JTextField fAuthor;
|
||||||
private JTextField fVersion;
|
private JTextField fVersion;
|
||||||
private JTextPane fDescription;
|
private JTextPane fDescription;
|
||||||
private JButton savebtn;
|
private JButton savebtn;
|
||||||
private JButton cancelbtn;
|
private JButton cancelbtn;
|
||||||
|
|
||||||
JFrame invoker;
|
JFrame invoker;
|
||||||
MissPiggy invokerPig;
|
MissPiggy invokerPig;
|
||||||
boolean isPig = false;
|
boolean isPig = false;
|
||||||
Main.Mod mod;
|
Main.Mod mod;
|
||||||
int index;
|
int index;
|
||||||
File directory;
|
File directory;
|
||||||
|
boolean isSoundtrack = false;
|
||||||
|
|
||||||
boolean creating;
|
boolean creating;
|
||||||
|
|
||||||
public void Action(MissPiggy inv, int modindex) {
|
public void Action(MissPiggy inv, int modindex) {
|
||||||
invokerPig = inv;
|
invokerPig = inv;
|
||||||
invoker = invokerPig.frame;
|
invoker = invokerPig.frame;
|
||||||
mod = Main.Mods.get(modindex);
|
mod = Main.Mods.get(modindex);
|
||||||
index = modindex;
|
index = modindex;
|
||||||
creating = false;
|
creating = false;
|
||||||
|
|
||||||
isPig = true;
|
isPig = true;
|
||||||
|
|
||||||
Action(invoker, modindex);
|
Action(invoker, modindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Action(MissPiggy inv, File dir) {
|
public void Action(MissPiggy inv, File dir) {
|
||||||
invokerPig = inv;
|
invokerPig = inv;
|
||||||
invoker = invokerPig.frame;
|
invoker = invokerPig.frame;
|
||||||
directory = dir;
|
directory = dir;
|
||||||
creating = true;
|
creating = true;
|
||||||
|
|
||||||
isPig = true;
|
isPig = true;
|
||||||
|
|
||||||
Action(invoker, dir);
|
Action(invoker, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Action(JFrame inv, int modindex) { // Editor
|
public void Action(JFrame inv, int modindex) { // Editor
|
||||||
invoker = inv;
|
invoker = inv;
|
||||||
mod = Main.Mods.get(modindex);
|
mod = Main.Mods.get(modindex);
|
||||||
index = modindex;
|
index = modindex;
|
||||||
creating = false;
|
creating = false;
|
||||||
|
|
||||||
frame.add(frameContainer);
|
frame.add(frameContainer);
|
||||||
try {
|
frame.setIconImage(Main.windowIcon);
|
||||||
BufferedImage windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
frame.setSize(600, 300); // 1280 800
|
||||||
frame.setIconImage(windowIcon);
|
frame.setMinimumSize(new Dimension(200,100));
|
||||||
} catch (IOException e) {
|
frame.setTitle("Options");
|
||||||
System.out.println("ERROR: Failed to find resource titleIcon.png. Window will not have an icon.");
|
frame.setResizable(false);
|
||||||
}
|
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||||
frame.setSize(600, 300); // 1280 800
|
frame.setLayout(new GridLayout());
|
||||||
frame.setMinimumSize(new Dimension(200,100));
|
frame.setLocationRelativeTo(inv);
|
||||||
frame.setTitle("Options");
|
frame.setAlwaysOnTop(true);
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
|
||||||
frame.setLayout(new GridLayout());
|
|
||||||
frame.setLocationRelativeTo(inv);
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
|
|
||||||
fName.setText(mod.friendlyName);
|
fName.setText(mod.friendlyName);
|
||||||
fAuthor.setText(mod.author);
|
fAuthor.setText(mod.author);
|
||||||
fVersion.setText(String.valueOf(mod.version));
|
fVersion.setText(String.valueOf(mod.version));
|
||||||
fDescription.setText(mod.description);
|
fDescription.setText(mod.description);
|
||||||
|
|
||||||
cancelbtn.addActionListener(this);
|
cancelbtn.addActionListener(this);
|
||||||
savebtn.addActionListener(this);
|
savebtn.addActionListener(this);
|
||||||
|
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e)
|
public void windowClosing(WindowEvent e)
|
||||||
{
|
{
|
||||||
invoker.setEnabled(true);
|
invoker.setEnabled(true);
|
||||||
e.getWindow().dispose();
|
e.getWindow().dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Action(JFrame inv, File dir) { // Generator
|
public void Action(JFrame inv, File dir) { // Generator
|
||||||
invoker = inv;
|
invoker = inv;
|
||||||
directory = dir;
|
directory = dir;
|
||||||
creating = true;
|
creating = true;
|
||||||
|
|
||||||
frame.add(frameContainer);
|
frame.add(frameContainer);
|
||||||
frame.setSize(600, 200); // 1280 800
|
frame.setSize(600, 200); // 1280 800
|
||||||
frame.setMinimumSize(new Dimension(200,100));
|
frame.setMinimumSize(new Dimension(200,100));
|
||||||
frame.setTitle("Options");
|
frame.setTitle("Options");
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||||
frame.setLayout(new GridLayout());
|
frame.setLayout(new GridLayout());
|
||||||
frame.setLocationRelativeTo(null);
|
frame.setLocationRelativeTo(null);
|
||||||
frame.setAlwaysOnTop(true);
|
frame.setAlwaysOnTop(true);
|
||||||
|
|
||||||
cancelbtn.addActionListener(this);
|
cancelbtn.addActionListener(this);
|
||||||
savebtn.addActionListener(this);
|
savebtn.addActionListener(this);
|
||||||
|
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e)
|
public void windowClosing(WindowEvent e)
|
||||||
{
|
{
|
||||||
invoker.setEnabled(true);
|
Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen
|
||||||
e.getWindow().dispose();
|
invoker.setEnabled(true);
|
||||||
}
|
e.getWindow().dispose();
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
if (actionEvent.getSource() == cancelbtn) {
|
if (actionEvent.getSource() == cancelbtn) {
|
||||||
invoker.setEnabled(true);
|
Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen
|
||||||
frame.dispose();
|
invoker.setEnabled(true);
|
||||||
} else if (actionEvent.getSource() == savebtn && !creating) {
|
frame.dispose();
|
||||||
try {
|
} else if (actionEvent.getSource() == savebtn && !creating) {
|
||||||
mod.version = Integer.parseInt(fVersion.getText());
|
try {
|
||||||
} catch (NumberFormatException e) {
|
mod.version = Integer.parseInt(fVersion.getText());
|
||||||
JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE);
|
} catch (NumberFormatException e) {
|
||||||
return;
|
JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
return;
|
||||||
mod.friendlyName = fName.getText();
|
}
|
||||||
mod.author = fAuthor.getText();
|
mod.friendlyName = fName.getText();
|
||||||
mod.description = fDescription.getText();
|
mod.author = fAuthor.getText();
|
||||||
|
mod.description = fDescription.getText();
|
||||||
|
|
||||||
JSONObject container = new JSONObject();
|
JSONObject container = new JSONObject();
|
||||||
if (mod.friendlyName.isEmpty()) {
|
if (mod.friendlyName.isEmpty()) {
|
||||||
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
container.put("version", mod.version);
|
|
||||||
container.put("friendlyName", mod.friendlyName);
|
|
||||||
container.put("author", mod.author);
|
|
||||||
container.put("description", mod.description);
|
|
||||||
container.put("loaderversion", mod.loaderversion);
|
|
||||||
container.put("game", mod.game);
|
|
||||||
|
|
||||||
try {
|
container.put("version", mod.version);
|
||||||
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + mod.path.trim()).setComment(container.toString());
|
container.put("friendlyName", mod.friendlyName);
|
||||||
} catch (ZipException e) {
|
container.put("author", mod.author);
|
||||||
System.out.println(e.getMessage());
|
container.put("description", mod.description);
|
||||||
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
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);
|
||||||
|
|
||||||
Main.Mods.set(index, mod);
|
try {
|
||||||
invoker.setEnabled(true);
|
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + mod.path.trim()).setComment(container.toString());
|
||||||
if (isPig) {invokerPig.InitializeModListInGUI();}
|
} catch (ZipException e) {
|
||||||
frame.dispose();
|
System.out.println(e.getMessage());
|
||||||
} else if (actionEvent.getSource() == savebtn && creating) {
|
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
if (fName.getText().isEmpty()) {
|
}
|
||||||
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Integer.parseInt(fVersion.getText());
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
Main.Mods.set(index, mod);
|
||||||
fileChooser.setFileFilter(new FileNameExtensionFilter("Firestar Mod Package", "fstar"));
|
invoker.setEnabled(true);
|
||||||
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
if (isPig) {invokerPig.InitializeModListInGUI();}
|
||||||
ZipFile zip = new ZipFile(fileChooser.getSelectedFile());
|
frame.dispose();
|
||||||
try {
|
} else if (actionEvent.getSource() == savebtn && creating) {
|
||||||
zip.addFolder(new File(directory.getAbsolutePath() + "/data"));
|
if (fName.getText().isEmpty()) {
|
||||||
if (new File(directory.getAbsolutePath() + "/delete.txt").exists()) {
|
JOptionPane.showMessageDialog(frame, "Mod name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
zip.addFile(new File(directory.getAbsolutePath() + "/delete.txt"));
|
return;
|
||||||
}
|
}
|
||||||
if (new File(directory.getAbsolutePath() + "/pack.png").exists()) {
|
try {
|
||||||
zip.addFile(new File(directory.getAbsolutePath() + "/pack.png"));
|
Integer.parseInt(fVersion.getText());
|
||||||
}
|
} catch (NumberFormatException e) {
|
||||||
|
JOptionPane.showMessageDialog(frame, "Mod version must be a valid integer.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject container = new JSONObject();
|
JFileChooser fileChooser = new JFileChooser();
|
||||||
container.put("version", Integer.parseInt(fVersion.getText()));
|
fileChooser.setFileFilter(new FileNameExtensionFilter("Firestar Mod Package", "fstar"));
|
||||||
container.put("friendlyName", fName.getText());
|
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
||||||
container.put("author", fAuthor.getText());
|
File modFile = fileChooser.getSelectedFile();
|
||||||
container.put("description", fDescription.getText());
|
if (!modFile.getName().endsWith(".fstar")) modFile = new File(modFile.toString() + ".fstar");
|
||||||
container.put("loaderversion", 0); // TODO for later versions: Change depending on features inside of mod folder
|
ZipFile zip = new ZipFile(modFile);
|
||||||
container.put("game", "2048");
|
boolean hasScript = false;
|
||||||
|
try {
|
||||||
|
zip.addFolder(new File(directory.getAbsolutePath() + "/data"));
|
||||||
|
if (new File(directory.getAbsolutePath() + "/delete.txt").exists()) {
|
||||||
|
zip.addFile(new File(directory.getAbsolutePath() + "/delete.txt"));
|
||||||
|
}
|
||||||
|
if (new File(directory.getAbsolutePath() + "/pack.png").exists()) {
|
||||||
|
zip.addFile(new File(directory.getAbsolutePath() + "/pack.png"));
|
||||||
|
}
|
||||||
|
if (new File(directory.getAbsolutePath() + "/fscript").exists()) {
|
||||||
|
zip.addFile(new File(directory.getAbsolutePath() + "/fscript"));
|
||||||
|
hasScript = true;
|
||||||
|
}
|
||||||
|
|
||||||
zip.setComment(container.toString());
|
ArrayList<String> requires = new ArrayList<>();
|
||||||
zip.close();
|
ArrayList<String> extracts = new ArrayList<>();
|
||||||
} catch (Exception e) {
|
if (isSoundtrack) {
|
||||||
fileChooser.getSelectedFile().delete(); //cleanup
|
requires.add("data2.psarc");
|
||||||
System.out.println(e.getMessage());
|
extracts.add("data/plugins/music/Definition.xml");
|
||||||
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
extracts.add("data/plugins/languages/american/entries.xml");
|
||||||
return;
|
extracts.add("data/plugins/languages/danish/entries.xml");
|
||||||
}
|
extracts.add("data/plugins/languages/dutch/entries.xml");
|
||||||
JOptionPane.showMessageDialog(frame, "Mod file created", "Success", JOptionPane.INFORMATION_MESSAGE);
|
extracts.add("data/plugins/languages/english/entries.xml");
|
||||||
invoker.setEnabled(true);
|
extracts.add("data/plugins/languages/finnish/entries.xml");
|
||||||
frame.dispose();
|
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);
|
||||||
|
} else {
|
||||||
|
container.put("loaderversion", 0);
|
||||||
|
}
|
||||||
|
container.put("game", "2048");
|
||||||
|
|
||||||
|
zip.setComment(container.toString());
|
||||||
|
zip.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
fileChooser.getSelectedFile().delete(); //cleanup
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JOptionPane.showMessageDialog(frame, "Mod file created", "Success", JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
Main.deleteDir(new File(Main.inpath + "temp/")); // soundtrack gen
|
||||||
|
invoker.setEnabled(true);
|
||||||
|
frame.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -33,7 +32,6 @@ import java.net.URL;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JEditorPane;
|
import javax.swing.JEditorPane;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
@@ -46,153 +44,150 @@ import org.json.JSONException;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class Ernie implements ActionListener {
|
public class Ernie implements ActionListener {
|
||||||
// Base URL for Gitea API
|
// Base URL for Gitea API
|
||||||
public static final String gitapi = "https://git.worlio.com/api/v1/repos/bonkmaykr/firestar";
|
public static final String gitapi = "https://git.worlio.com/api/v1/repos/bonkmaykr/firestar";
|
||||||
public static final String changelog = "https://bonkmaykr.worlio.com/http/firestar/changelog.htm";
|
public static final String changelog = "https://bonkmaykr.worlio.com/http/firestar/changelog.htm";
|
||||||
|
|
||||||
private HttpURLConnection httpConn;
|
private HttpURLConnection httpConn;
|
||||||
private int contentLength;
|
private int contentLength;
|
||||||
private InputStream inputStream;
|
private InputStream inputStream;
|
||||||
|
|
||||||
private JFrame frame = new JFrame();
|
private JFrame frame = new JFrame();
|
||||||
private JPanel frameContainer;
|
private JPanel frameContainer;
|
||||||
private JEditorPane changelogDisplay;
|
private JEditorPane changelogDisplay;
|
||||||
private JButton notnowbtn;
|
private JButton notnowbtn;
|
||||||
private JButton surebtn;
|
private JButton surebtn;
|
||||||
|
|
||||||
public boolean backgroundDone = false;
|
public boolean backgroundDone = false;
|
||||||
private BufferedImage windowIcon;
|
|
||||||
|
|
||||||
private JFrame parent;
|
private JFrame parent;
|
||||||
|
|
||||||
public Ernie(JFrame parent) {
|
public Ernie(JFrame parent, boolean isManual) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
try {
|
frame.setIconImage(Main.windowIcon);
|
||||||
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
byte[] urlraw = getFile(gitapi+"/releases?draft=false&pre-release=false");
|
||||||
frame.setIconImage(windowIcon);
|
if (urlraw.length <= 0) {
|
||||||
} catch (IOException e) {
|
JOptionPane.showMessageDialog(frame, "Internal Error: Couldn't check for updates.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
} else {
|
||||||
}
|
try {
|
||||||
byte[] urlraw = getFile(gitapi+"/releases?draft=false&pre-release=false");
|
JSONArray releases = new JSONArray(new String(urlraw, Charset.forName("utf-8")));
|
||||||
if (urlraw.length <= 0) {
|
System.out.println("Updater: latest release is " + ((JSONObject)releases.get(0)).get("tag_name"));
|
||||||
JOptionPane.showMessageDialog(frame, "Internal Error: Couldn't check for updates.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
if (releases.length() >= 1
|
||||||
} else {
|
&& (!Main.isNightly && (!((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag))
|
||||||
try {
|
|| (Main.isNightly && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtagPrevious)))) {
|
||||||
JSONArray releases = new JSONArray(new String(urlraw, Charset.forName("utf-8")));
|
System.out.println("Updater: Your version is out of date.");
|
||||||
System.out.println("Updater: latest release is " + ((JSONObject)releases.get(0)).get("tag_name"));
|
frame.add(frameContainer);
|
||||||
if (releases.length() >= 1 && !((JSONObject)releases.get(0)).get("tag_name").equals(Main.vtag)) {
|
notnowbtn.addActionListener(this);
|
||||||
System.out.println("Updater: Your version is out of date.");
|
surebtn.addActionListener(this);
|
||||||
frame.add(frameContainer);
|
changelogDisplay.setEditable(false);
|
||||||
notnowbtn.addActionListener(this);
|
changelogDisplay.setPage(changelog);
|
||||||
surebtn.addActionListener(this);
|
changelogDisplay.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf??
|
||||||
changelogDisplay.setEditable(false);
|
|
||||||
changelogDisplay.setPage(changelog);
|
|
||||||
changelogDisplay.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf??
|
|
||||||
|
|
||||||
frame.setTitle("An update is available!");
|
frame.setTitle("An update is available!");
|
||||||
frame.setSize(450, 400);
|
frame.setSize(450, 400);
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setLocationRelativeTo(parent);
|
frame.setLocationRelativeTo(parent);
|
||||||
frame.setAlwaysOnTop(true);
|
frame.setAlwaysOnTop(true);
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
parent.setEnabled(false);
|
parent.setEnabled(false);
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e)
|
public void windowClosing(WindowEvent e)
|
||||||
{
|
{
|
||||||
parent.setEnabled(true);
|
parent.setEnabled(true);
|
||||||
e.getWindow().dispose();
|
e.getWindow().dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
} else { System.out.println("Updater: No updates."); }
|
} else {
|
||||||
} catch (IOException ex) {
|
System.out.println("Updater: No updates.");
|
||||||
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
|
if (isManual) {JOptionPane.showMessageDialog(frame, "There are no updates at this time.", "Check for Updates", JOptionPane.INFORMATION_MESSAGE);}
|
||||||
} catch (JSONException ex) {
|
}
|
||||||
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
|
} catch (IOException | JSONException ex) {
|
||||||
}
|
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
|
||||||
if (actionEvent.getSource() == notnowbtn) {
|
|
||||||
parent.setEnabled(true);
|
|
||||||
frame.dispose();
|
|
||||||
} else
|
|
||||||
if (actionEvent.getSource() == surebtn) {
|
|
||||||
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
|
||||||
String releasepage = "https://git.worlio.com/bonkmaykr/firestar/releases";
|
|
||||||
try {
|
|
||||||
Desktop.getDesktop().browse(new URI(releasepage));
|
|
||||||
parent.setEnabled(true);
|
|
||||||
frame.dispose();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
JOptionPane.showMessageDialog(frame, "Couldn't open your web browser!\nYou can check out the latest release at the URL below:\n"+releasepage, "Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
byte[] getFile(String url) {
|
@Override
|
||||||
try {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
URL fileURL = new URL(url);
|
if (actionEvent.getSource() == notnowbtn) {
|
||||||
httpConn = (HttpURLConnection) fileURL.openConnection();
|
parent.setEnabled(true);
|
||||||
int response = httpConn.getResponseCode();
|
frame.dispose();
|
||||||
|
} else
|
||||||
|
if (actionEvent.getSource() == surebtn) {
|
||||||
|
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
||||||
|
String releasepage = "https://git.worlio.com/bonkmaykr/firestar/releases";
|
||||||
|
try {
|
||||||
|
Desktop.getDesktop().browse(new URI(releasepage));
|
||||||
|
parent.setEnabled(true);
|
||||||
|
frame.dispose();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
JOptionPane.showMessageDialog(frame, "Couldn't open your web browser!\nYou can check out the latest release at the URL below:\n"+releasepage, "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (response == HttpURLConnection.HTTP_OK) {
|
byte[] getFile(String url) {
|
||||||
contentLength = httpConn.getContentLength();
|
try {
|
||||||
inputStream = httpConn.getInputStream();
|
URL fileURL = new URL(url);
|
||||||
} else if (response == 404) {
|
httpConn = (HttpURLConnection) fileURL.openConnection();
|
||||||
throw new IOException(
|
int response = httpConn.getResponseCode();
|
||||||
"File missing from remote server.");
|
|
||||||
} else {
|
|
||||||
throw new IOException(
|
|
||||||
"Unexpected response; Server replied with " + response);
|
|
||||||
}
|
|
||||||
ErnieDownloader ed = new ErnieDownloader(this, url, httpConn.getContentLength());
|
|
||||||
ed.doInBackground();
|
|
||||||
while (!backgroundDone) {}
|
|
||||||
|
|
||||||
inputStream.close();
|
if (response == HttpURLConnection.HTTP_OK) {
|
||||||
httpConn.disconnect();
|
contentLength = httpConn.getContentLength();
|
||||||
frame.dispose();
|
inputStream = httpConn.getInputStream();
|
||||||
return ed.output;
|
} else if (response == 404) {
|
||||||
} catch (MalformedURLException e) {
|
throw new IOException(
|
||||||
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Ernie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
"File missing from remote server.");
|
||||||
frame.dispose();
|
} else {
|
||||||
return new byte[]{};
|
throw new IOException(
|
||||||
} catch (Exception e) {
|
"Unexpected response; Server replied with " + response);
|
||||||
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
}
|
||||||
frame.dispose();
|
ErnieDownloader ed = new ErnieDownloader(this, url, httpConn.getContentLength());
|
||||||
return new byte[]{};
|
ed.doInBackground();
|
||||||
}
|
while (!backgroundDone) {}
|
||||||
}
|
|
||||||
|
inputStream.close();
|
||||||
|
httpConn.disconnect();
|
||||||
|
frame.dispose();
|
||||||
|
return ed.output;
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Ernie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
frame.dispose();
|
||||||
|
return new byte[]{};
|
||||||
|
} catch (Exception e) {
|
||||||
|
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
frame.dispose();
|
||||||
|
return new byte[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ErnieDownloader extends SwingWorker<Void, Void> {
|
class ErnieDownloader extends SwingWorker<Void, Void> {
|
||||||
private static final int BUFFER_SIZE = 4096;
|
private static final int BUFFER_SIZE = 4096;
|
||||||
private String downloadURL;
|
private String downloadURL;
|
||||||
private final Ernie gui;
|
private final Ernie gui;
|
||||||
public byte[] output;
|
public byte[] output;
|
||||||
|
|
||||||
public ErnieDownloader(Ernie gui, String downloadURL, long size) {
|
public ErnieDownloader(Ernie gui, String downloadURL, long size) {
|
||||||
this.gui = gui;
|
this.gui = gui;
|
||||||
this.downloadURL = downloadURL;
|
this.downloadURL = downloadURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Exception {
|
protected Void doInBackground() throws Exception {
|
||||||
BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream());
|
BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream());
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
byte[] data = new byte[16384];
|
byte[] data = new byte[16384];
|
||||||
int x;
|
int x;
|
||||||
while ((x = in.read(data, 0, data.length)) != -1) {
|
while ((x = in.read(data, 0, data.length)) != -1) {
|
||||||
buffer.write(data, 0, x);
|
buffer.write(data, 0, x);
|
||||||
|
}
|
||||||
|
output = buffer.toByteArray();
|
||||||
|
in.close();
|
||||||
|
gui.backgroundDone = true;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
output = buffer.toByteArray();
|
|
||||||
in.close();
|
|
||||||
gui.backgroundDone = true;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
31
firestar/src/main/java/FirescriptFormatException.java
Normal file
31
firestar/src/main/java/FirescriptFormatException.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Firestar Mod Manager
|
||||||
|
* Copyright (C) 2024 bonkmaykr
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FirescriptFormatException extends Exception {
|
||||||
|
public FirescriptFormatException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FirescriptFormatException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FirescriptFormatException(String cmd, String msg) {
|
||||||
|
super(cmd + ": " + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,176 +16,159 @@
|
|||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class Fozzie {
|
public class Fozzie {
|
||||||
BufferedImage windowIcon;
|
private JFrame frame = new JFrame();
|
||||||
private JFrame frame = new JFrame();
|
public JProgressBar progressBar;
|
||||||
public JProgressBar progressBar;
|
private JPanel frameContainer;
|
||||||
private JPanel frameContainer;
|
private JLabel label;
|
||||||
private JLabel label;
|
|
||||||
|
|
||||||
private HttpURLConnection httpConn;
|
private HttpURLConnection httpConn;
|
||||||
private int contentLength;
|
private int contentLength;
|
||||||
private InputStream inputStream;
|
private InputStream inputStream;
|
||||||
|
|
||||||
public boolean backgroundDone = false;
|
public boolean backgroundDone = false;
|
||||||
|
|
||||||
boolean DownloadFile(String url, String odir, String oname) {
|
boolean DownloadFile(String url, String odir, String oname) {
|
||||||
return DownloadFile(url, odir, oname, oname);
|
return DownloadFile(url, odir, oname, oname);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean DownloadFile(String url, String odir, String oname, String dname) {
|
boolean DownloadFile(String url, String odir, String oname, String dname) {
|
||||||
frame.add(frameContainer);
|
frame.add(frameContainer);
|
||||||
frame.setSize(300, 100);
|
frame.setSize(300, 100);
|
||||||
frame.setTitle("Download in Progress");
|
frame.setTitle("Download in Progress");
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
frame.setLayout(new GridLayout());
|
frame.setLayout(new GridLayout());
|
||||||
frame.setLocationRelativeTo(null);
|
frame.setLocationRelativeTo(null);
|
||||||
frame.setAlwaysOnTop(true);
|
frame.setAlwaysOnTop(true);
|
||||||
try {
|
frame.setIconImage(Main.windowIcon);
|
||||||
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
frame.setVisible(true);
|
||||||
frame.setIconImage(windowIcon);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
|
||||||
}
|
|
||||||
frame.setVisible(true);
|
|
||||||
|
|
||||||
label.setText("Downloading \"" + dname + "\"");
|
label.setText("Downloading " + dname);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
URL fileURL = new URL(url);
|
URL fileURL = new URL(url);
|
||||||
httpConn = (HttpURLConnection) fileURL.openConnection();
|
httpConn = (HttpURLConnection) fileURL.openConnection();
|
||||||
int response = httpConn.getResponseCode();
|
int response = httpConn.getResponseCode();
|
||||||
|
|
||||||
if (response == HttpURLConnection.HTTP_OK) {
|
if (response == HttpURLConnection.HTTP_OK) {
|
||||||
String disposition = httpConn.getHeaderField("Content-Disposition");
|
String disposition = httpConn.getHeaderField("Content-Disposition");
|
||||||
String contentType = httpConn.getContentType();
|
String contentType = httpConn.getContentType();
|
||||||
contentLength = httpConn.getContentLength();
|
contentLength = httpConn.getContentLength();
|
||||||
|
|
||||||
inputStream = httpConn.getInputStream();
|
inputStream = httpConn.getInputStream();
|
||||||
} else if (response == 404) {
|
} else if (response == 404) {
|
||||||
throw new IOException(
|
throw new IOException(
|
||||||
"File missing from remote server.");
|
"File missing from remote server.");
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(
|
throw new IOException(
|
||||||
"Unexpected response; Server replied with " + response);
|
"Unexpected response; Server replied with " + response);
|
||||||
}
|
}
|
||||||
new FozzieDownloader(this, url, odir, oname, httpConn.getContentLength()).doInBackground();
|
new FozzieDownloader(this, url, odir, oname, httpConn.getContentLength()).doInBackground();
|
||||||
while (!backgroundDone) {}
|
while (!backgroundDone) {}
|
||||||
|
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
httpConn.disconnect();
|
httpConn.disconnect();
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
return true;
|
return true;
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Fozzie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Fozzie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void displayTextOnly(String text, String title) {
|
public void displayTextOnly(String text, String title) {
|
||||||
frame.add(frameContainer);
|
frame.add(frameContainer);
|
||||||
frame.setSize(300, 100);
|
frame.setSize(300, 100);
|
||||||
frame.setTitle(title);
|
frame.setTitle(title);
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
frame.setLayout(new GridLayout());
|
frame.setLayout(new GridLayout());
|
||||||
frame.setLocationRelativeTo(null);
|
frame.setLocationRelativeTo(null);
|
||||||
frame.setAlwaysOnTop(true);
|
frame.setAlwaysOnTop(true);
|
||||||
try {
|
frame.setIconImage(Main.windowIcon);
|
||||||
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
frame.setVisible(true);
|
||||||
frame.setIconImage(windowIcon);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
|
||||||
}
|
|
||||||
frame.setVisible(true);
|
|
||||||
|
|
||||||
label.setText(text);
|
label.setText(text);
|
||||||
|
|
||||||
progressBar.setVisible(false);
|
progressBar.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setText(String text, String title) {
|
public void setText(String text, String title) {
|
||||||
label.setText(text);
|
label.setText(text);
|
||||||
frame.setTitle(title);
|
frame.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroyDialog() {
|
public void destroyDialog() {
|
||||||
frame.setVisible(false);
|
frame.setVisible(false);
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect() throws IOException {
|
public void disconnect() throws IOException {
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
httpConn.disconnect();
|
httpConn.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getContentLength() {
|
public int getContentLength() {
|
||||||
return this.contentLength;
|
return this.contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
return this.inputStream;
|
return this.inputStream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FozzieDownloader extends SwingWorker<Void, Void> {
|
class FozzieDownloader extends SwingWorker<Void, Void> {
|
||||||
private static final int BUFFER_SIZE = 4096;
|
private static final int BUFFER_SIZE = 4096;
|
||||||
private String downloadURL;
|
private String downloadURL;
|
||||||
private String saveDirectory;
|
private String saveDirectory;
|
||||||
private String saveName;
|
private String saveName;
|
||||||
private final Fozzie gui;
|
private final Fozzie gui;
|
||||||
private final long completeSize;
|
private final long completeSize;
|
||||||
|
|
||||||
public FozzieDownloader(Fozzie gui, String downloadURL, String saveDirectory, String saveName, long size) {
|
public FozzieDownloader(Fozzie gui, String downloadURL, String saveDirectory, String saveName, long size) {
|
||||||
this.gui = gui;
|
this.gui = gui;
|
||||||
this.downloadURL = downloadURL;
|
this.downloadURL = downloadURL;
|
||||||
this.saveDirectory = saveDirectory;
|
this.saveDirectory = saveDirectory;
|
||||||
this.saveName = saveName;
|
this.saveName = saveName;
|
||||||
this.completeSize = size;
|
this.completeSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Exception {
|
protected Void doInBackground() throws Exception {
|
||||||
long downloadedSize = 0;
|
long downloadedSize = 0;
|
||||||
File downloadLocationDir = new File(saveDirectory);
|
File downloadLocationDir = new File(saveDirectory);
|
||||||
File downloadLocation = new File(saveDirectory + "/" + saveName);
|
File downloadLocation = new File(saveDirectory + "/" + saveName);
|
||||||
downloadLocationDir.mkdirs();
|
downloadLocationDir.mkdirs();
|
||||||
if (!downloadLocation.isFile()) {
|
if (!downloadLocation.isFile()) {
|
||||||
downloadLocation.createNewFile();
|
downloadLocation.createNewFile();
|
||||||
}
|
}
|
||||||
BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream());
|
BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream());
|
||||||
FileOutputStream fos = new FileOutputStream(saveDirectory + "/" + saveName);
|
FileOutputStream fos = new FileOutputStream(saveDirectory + "/" + saveName);
|
||||||
BufferedOutputStream out = new BufferedOutputStream(fos,1024);
|
BufferedOutputStream out = new BufferedOutputStream(fos,1024);
|
||||||
byte[] data = new byte[1024];
|
byte[] data = new byte[1024];
|
||||||
int x = 0;
|
int x = 0;
|
||||||
while ((x = in.read(data,0,1024))>=0) {
|
while ((x = in.read(data,0,1024))>=0) {
|
||||||
downloadedSize += x;
|
downloadedSize += x;
|
||||||
int progress = (int) ((((double)downloadedSize) / ((double)completeSize)) * 100d);
|
int progress = (int) ((((double)downloadedSize) / ((double)completeSize)) * 100d);
|
||||||
gui.progressBar.setValue(progress);
|
gui.progressBar.setValue(progress);
|
||||||
out.write(data, 0, x);
|
out.write(data, 0, x);
|
||||||
}
|
}
|
||||||
out.close();
|
out.close();
|
||||||
in.close();
|
in.close();
|
||||||
gui.backgroundDone = true;
|
gui.backgroundDone = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,360 +16,404 @@
|
|||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import com.github.difflib.DiffUtils;
|
|
||||||
import com.github.difflib.UnifiedDiffUtils;
|
|
||||||
import com.github.difflib.patch.Patch;
|
|
||||||
import net.lingala.zip4j.ZipFile;
|
import net.lingala.zip4j.ZipFile;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.TitledBorder;
|
import javax.swing.border.TitledBorder;
|
||||||
|
import javax.swing.text.DefaultCaret;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.DirectoryStream;
|
import java.nio.file.*;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class Gonzo {
|
public class Gonzo {
|
||||||
JFrame frame = new JFrame();
|
JFrame frame = new JFrame();
|
||||||
private JPanel frameContainer;
|
private JPanel frameContainer;
|
||||||
private JTextArea consoleDisplay;
|
private JTextArea consoleDisplay;
|
||||||
private JScrollPane scrollPane;
|
private JScrollPane scrollPane;
|
||||||
public boolean data0;
|
public boolean data0;
|
||||||
public boolean data1;
|
public boolean data1;
|
||||||
public boolean data2;
|
public boolean data2;
|
||||||
public boolean dlc1;
|
public boolean dlc1;
|
||||||
public boolean dlc2;
|
public boolean dlc2;
|
||||||
private MissPiggy invoker;
|
private MissPiggy invoker;
|
||||||
public String oArcTarget = "dlc2.psarc"; // which psarc to rebuild the assets in
|
public String oArcTarget = "dlc2.psarc"; // which psarc to rebuild the assets in
|
||||||
|
|
||||||
public void DeployMods(MissPiggy inv) {
|
// TODO 1.3: Implement requires boolean[] from Main.Mod
|
||||||
invoker = inv;
|
// Rework system to choose the last PSARC and then add more before it when called by requires[]
|
||||||
System.out.println("\n\nStarting mod deployment\n\n");
|
// Instead of the current system where it simply grabs them all and bloats the file.
|
||||||
|
//
|
||||||
|
// EDIT: requires[] is now an arraylist of booleans[], each a supported minimum combination of PSARCs.
|
||||||
|
// if any one of them is met, gonzo may continue
|
||||||
|
// for example:
|
||||||
|
// [false, true, false, false], [true, false, false, false] // user only needs either base psarc or patches PSARC, one or the other (having both is OK)
|
||||||
|
// [true, true, false, false] // user needs both base and patches
|
||||||
|
// [false, false, true, true] // user needs the HD DLC and the Fury DLC
|
||||||
|
//
|
||||||
|
// if none is found, assume "new boolean[]{false, false, false, false}" (no PSARCs required)
|
||||||
|
// (at least one of any 4 psarcs will already be checked for by MissPiggy so this is an okay way to implement it.)
|
||||||
|
|
||||||
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
public void DeployMods(MissPiggy inv) {
|
||||||
|
invoker = inv;
|
||||||
|
System.out.println("\n\nStarting mod deployment\n\n");
|
||||||
|
|
||||||
try {
|
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
||||||
BufferedImage windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
|
||||||
frame.setIconImage(windowIcon);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
|
||||||
}
|
|
||||||
frame.setSize(800, 400);
|
|
||||||
frame.setMinimumSize(new Dimension(600,400));
|
|
||||||
frame.setTitle("Mod Installation");
|
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
|
||||||
frame.setLayout(new GridLayout());
|
|
||||||
frame.setLocationRelativeTo(inv.frame);
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
frame.setVisible(true);
|
|
||||||
|
|
||||||
File psarcHandle = new File(Main.inpath + "data.psarc");
|
frame.setIconImage(Main.windowIcon);
|
||||||
data0 = psarcHandle.isFile();
|
frame.setSize(800, 400);
|
||||||
psarcHandle = new File(Main.inpath + "data1.psarc");
|
frame.setMinimumSize(new Dimension(600,400));
|
||||||
data1 = psarcHandle.isFile();
|
frame.setTitle("Mod Installation");
|
||||||
psarcHandle = new File(Main.inpath + "data2.psarc");
|
frame.setResizable(false);
|
||||||
data2 = psarcHandle.isFile();
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
psarcHandle = new File(Main.inpath + "dlc1.psarc");
|
frame.setLayout(new GridLayout());
|
||||||
dlc1 = psarcHandle.isFile();
|
frame.setLocationRelativeTo(inv.frame);
|
||||||
psarcHandle = new File(Main.inpath + "dlc2.psarc");
|
frame.setAlwaysOnTop(true);
|
||||||
dlc2 = psarcHandle.isFile();
|
frame.setVisible(true);
|
||||||
|
|
||||||
System.out.println("Source files discovered: data " + data0 + ", data1 " + data1 + ", data2 " + data2 + ", dlc1 " + dlc1 + ", dlc2 " + dlc2);
|
DefaultCaret caret = (DefaultCaret) consoleDisplay.getCaret();
|
||||||
|
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
|
||||||
|
|
||||||
final Thread managerThread = new Thread() {
|
File psarcHandle = new File(Main.inpath + "data.psarc");
|
||||||
@Override
|
data0 = psarcHandle.isFile();
|
||||||
public void run() {
|
psarcHandle = new File(Main.inpath + "data1.psarc");
|
||||||
if (/*Main.repatch*/true) { //todo implement fast mode correctly or remove
|
data1 = psarcHandle.isFile();
|
||||||
CompatibilityRoutine();
|
psarcHandle = new File(Main.inpath + "data2.psarc");
|
||||||
} else {
|
data2 = psarcHandle.isFile();
|
||||||
FastRoutine();
|
psarcHandle = new File(Main.inpath + "dlc1.psarc");
|
||||||
}
|
dlc1 = psarcHandle.isFile();
|
||||||
}
|
psarcHandle = new File(Main.inpath + "dlc2.psarc");
|
||||||
};
|
dlc2 = psarcHandle.isFile();
|
||||||
managerThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CompatibilityRoutine() {
|
System.out.println("Source files discovered: data " + data0 + ", data1 " + data1 + ", data2 " + data2 + ", dlc1 " + dlc1 + ", dlc2 " + dlc2);
|
||||||
// create temporary working area for asset dump
|
|
||||||
new File(System.getProperty("user.home") + "/.firestar/temp/").mkdirs();
|
|
||||||
|
|
||||||
// decide which files to dump
|
final Thread managerThread = new Thread() {
|
||||||
List<String> dumpThese = new ArrayList<String>();
|
@Override
|
||||||
if (data0) {dumpThese.add("data.psarc");oArcTarget = "data.psarc";}
|
public void run() {
|
||||||
if (data1) {dumpThese.add("data1.psarc");oArcTarget = "data1.psarc";}
|
if (/*Main.repatch*/true) { //todo implement fast mode correctly or remove
|
||||||
if (data2) {dumpThese.add("data2.psarc");oArcTarget = "data2.psarc";}
|
CompatibilityRoutine();
|
||||||
if (dlc1) {dumpThese.add("dlc1.psarc");oArcTarget = "dlc1.psarc";}
|
} else {
|
||||||
if (dlc2) {dumpThese.add("dlc2.psarc");oArcTarget = "dlc2.psarc";}
|
FastRoutine();
|
||||||
|
|
||||||
// dump all assets to working area
|
|
||||||
for (String s : dumpThese) {
|
|
||||||
try {
|
|
||||||
System.out.println("Firestar is extracting " + s);
|
|
||||||
consoleDisplay.append("Firestar is extracting " + s + "\n");
|
|
||||||
//Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","aplay /home/bonkyboo/kittens_loop.wav"}); // DEBUG
|
|
||||||
Process p = Main.exec(new String[]{"../psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
|
|
||||||
final Thread ioThread = new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
final BufferedReader reader = new BufferedReader(
|
|
||||||
new InputStreamReader(p.getInputStream()));
|
|
||||||
String line = null;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
System.out.println(line);
|
|
||||||
consoleDisplay.append(line + "\n");
|
|
||||||
try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
|
|
||||||
catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition. You can safely ignore this.\n" + e.getMessage());}
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ioThread.start();
|
|
||||||
p.waitFor();
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
System.out.println(e.getMessage());
|
|
||||||
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
|
||||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
|
||||||
AllowExit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// overwrite assets with custom ones from each mod and/or perform operations as specified in mod's delete list
|
|
||||||
// todo: implement RegEx functions after delete.txt
|
|
||||||
for (Main.Mod m : Main.Mods) {
|
|
||||||
if (m.enabled) {
|
|
||||||
try {
|
|
||||||
System.out.println("Firestar is extracting " + m.friendlyName + " by " + m.author);
|
|
||||||
consoleDisplay.append("Firestar is extracting " + m.friendlyName + " by " + m.author + "\n");
|
|
||||||
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + m.path).extractAll(System.getProperty("user.home") + "/.firestar/temp/");
|
|
||||||
|
|
||||||
try (Stream<Path> walkStream = Files.walk(Paths.get(System.getProperty("user.home") + "/.firestar/temp/"))) {
|
|
||||||
walkStream.filter(p -> p.toFile().isFile()).forEach(f -> {
|
|
||||||
if (f.toString().endsWith(".patch")) {
|
|
||||||
System.out.println("Patching " + f.toString() + "...");
|
|
||||||
consoleDisplay.append("Patching " + f.toString() + "...\n");
|
|
||||||
String mainFile = f.toString().substring(0, f.toString().length() - 6);
|
|
||||||
|
|
||||||
try {
|
|
||||||
List<String> original = Files.readAllLines(new File(mainFile).toPath());
|
|
||||||
List<String> patched = Files.readAllLines(f);
|
|
||||||
|
|
||||||
Patch<String> patch = UnifiedDiffUtils.parseUnifiedDiff(patched);
|
|
||||||
List<String> result = DiffUtils.patch(original, patch);
|
|
||||||
|
|
||||||
try (FileWriter fileWriter = new FileWriter(mainFile)) {
|
|
||||||
for (String str : result) {
|
|
||||||
fileWriter.write(str + "\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new File(f.toString()).delete();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.getLogger(Gonzo.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
System.out.println(ex.getMessage());
|
|
||||||
consoleDisplay.append("CRITICAL FAILURE: " + ex.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
managerThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
if (new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").isFile()) {
|
private void CompatibilityRoutine() {
|
||||||
System.out.println("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author);
|
// cleanup any failed deploys to avoid scripts running when they are not supposed to be
|
||||||
consoleDisplay.append("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author + "\n");
|
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
|
||||||
|
|
||||||
String deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/temp/delete.txt")));
|
// create temporary working area for asset dump
|
||||||
if (Main.windows) {deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "\\.firestar\\temp\\delete.txt")));} // might be unnecessary
|
new File(System.getProperty("user.home") + "/.firestar/temp/").mkdirs();
|
||||||
String[] dQarray = deleteQueue.split("\n");
|
new File(System.getProperty("user.home") + "/.firestar/temparcs/").mkdirs();
|
||||||
Arrays.sort(dQarray);
|
|
||||||
System.out.println("The deletion queue is " + dQarray.length + " files long!"); //debug
|
|
||||||
|
|
||||||
for (String file : dQarray) {
|
// Work from bottom to top, mods on top always overwrite the ones on the bottom.
|
||||||
if(file.contains("..")) { //todo: is this safe enough?
|
List<Main.Mod> modsFlipped = new ArrayList<>(Main.Mods);
|
||||||
System.out.println("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!");
|
Collections.reverse(modsFlipped);
|
||||||
consoleDisplay.append("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!\n");
|
|
||||||
} else {
|
|
||||||
if (!Main.windows) {
|
|
||||||
System.out.println("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file);
|
|
||||||
consoleDisplay.append("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file + "\n");
|
|
||||||
new File(System.getProperty("user.home") + "/.firestar/temp/data" + file).delete();}
|
|
||||||
else {
|
|
||||||
System.out.println("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\"));
|
|
||||||
consoleDisplay.append("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\") + "\n");
|
|
||||||
new File(new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\")).delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup so we don't run it again for the next mod unless needed
|
// decide which files to dump
|
||||||
// this is not necessary but good practice
|
List<String> dumpThese = new ArrayList<String>();
|
||||||
new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").delete();
|
for (Main.Mod m : modsFlipped) {
|
||||||
}
|
if (m.enabled) {
|
||||||
} catch (Exception e) {
|
System.out.println(m.friendlyName + " : " + m.requires.toString() + " : " + m.extracts.toString());
|
||||||
System.out.println(e.getMessage());
|
for (String r : m.requires) if (!dumpThese.contains(r)) dumpThese.add(r);
|
||||||
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
}
|
||||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
}
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
if (data0) oArcTarget = "data.psarc";
|
||||||
AllowExit();
|
if (data1) oArcTarget = "data1.psarc";
|
||||||
return;
|
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);
|
||||||
|
|
||||||
// create a list of the contents of data/ for psp2psarc.exe to read from
|
// dump all assets to working area
|
||||||
List<String> oFilesList = new ArrayList<String>();
|
for (String s : dumpThese) {
|
||||||
List<String> oFilesList2 = new ArrayList<String>();
|
try {
|
||||||
try {
|
if (!(new File(Main.inpath + s).exists()))
|
||||||
listAllFiles(Paths.get(System.getProperty("user.home") + "/.firestar/temp/data/"), oFilesList);
|
throw new IOException("A mod requested access to the archive \"" + s + "\" but it doesn't exist!");
|
||||||
for (String p : oFilesList) {
|
|
||||||
// We need to clean up the path here on Linux to avoid psp2psarc getting confused about where the hell "/" is.
|
|
||||||
// In WINE it should see it as Z: by default, but if it's somewhere else then I don't have an elegant way of knowing what drive letter it's on, so
|
|
||||||
// relative paths are kind of the only choice here. This can be extended to Windows too as it works there, though completely unnecessary.
|
|
||||||
if (!Main.windows) {oFilesList2.add(p.replace("\\", "/").split(new String(System.getProperty("user.home") + "/.firestar/temp/"))[1]);}
|
|
||||||
else {oFilesList2.add(p.split(new String(System.getProperty("user.home") + "\\.firestar\\temp\\").replace("\\", "\\\\"))[1]);} // path wont match regex unless adjusted for windows here
|
|
||||||
}
|
|
||||||
//oFilesList2.forEach(System.out::println); //debug
|
|
||||||
File oFilesListO = new File(System.getProperty("user.home") + "/.firestar/temp/list.txt");
|
|
||||||
if (oFilesListO.isFile()) {oFilesListO.delete();}
|
|
||||||
FileWriter oFilesListWr = new FileWriter(oFilesListO, true);
|
|
||||||
int i = 0;
|
|
||||||
for (String p : oFilesList2) {
|
|
||||||
oFilesListWr.append(p);
|
|
||||||
if (i != oFilesList2.size()) {
|
|
||||||
oFilesListWr.append("\n");
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
oFilesListWr.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(e.getMessage());
|
|
||||||
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
|
||||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
|
||||||
AllowExit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// invoke psp2psarc.exe one final time to reconstruct the assets
|
System.out.println("Firestar is extracting " + s);
|
||||||
try {
|
consoleDisplay.append("Firestar is extracting " + s + "\n");
|
||||||
System.out.println("Firestar is compiling the final build");
|
Process p;
|
||||||
consoleDisplay.append("Firestar is compiling the final build" + "\n");
|
if (s.equals(oArcTarget)) p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../"+s}, System.getProperty("user.home") + "/.firestar/temp/");
|
||||||
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/");
|
else {
|
||||||
final Thread ioThread = new Thread() {
|
new File(System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/").mkdirs();
|
||||||
@Override
|
p = Main.exec(new String[]{Main.inpath + "psp2psarc.exe", "extract", "-y", "../../"+s}, System.getProperty("user.home") + "/.firestar/temparcs/" + s + "/");
|
||||||
public void run() {
|
}
|
||||||
try {
|
final Thread ioThread = new Thread() {
|
||||||
final BufferedReader reader = new BufferedReader(
|
@Override
|
||||||
new InputStreamReader(p.getInputStream()));
|
public void run() {
|
||||||
String line = null;
|
try {
|
||||||
while ((line = reader.readLine()) != null) {
|
final BufferedReader reader = new BufferedReader(
|
||||||
System.out.println(line);
|
new InputStreamReader(p.getInputStream()));
|
||||||
consoleDisplay.append(line + "\n");
|
String line = null;
|
||||||
try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
|
while ((line = reader.readLine()) != null) {
|
||||||
catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition.\n" + e.getMessage());}
|
System.out.println(line);
|
||||||
}
|
consoleDisplay.append(line + "\n");
|
||||||
reader.close();
|
try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
|
||||||
} catch (final Exception e) {
|
catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition. You can safely ignore this.\n" + e.getMessage());}
|
||||||
e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
|
}
|
||||||
}
|
reader.close();
|
||||||
}
|
} catch (final Exception e) {
|
||||||
};
|
e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
|
||||||
ioThread.start();
|
}
|
||||||
p.waitFor();
|
}
|
||||||
} catch (IOException | InterruptedException e) {
|
};
|
||||||
System.out.println(e.getMessage());
|
ioThread.start();
|
||||||
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
p.waitFor();
|
||||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
} catch (IOException | InterruptedException e) {
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
System.out.println(e.getMessage());
|
||||||
AllowExit();
|
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
||||||
return;
|
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
|
AllowExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// cleanup
|
// overwrite assets with custom ones from each mod and/or perform operations as specified in mod's delete list
|
||||||
boolean one = new File(Main.outpath).mkdirs();
|
// todo: implement RegEx functions after delete.txt
|
||||||
boolean two;
|
for (Main.Mod m : modsFlipped) {
|
||||||
System.out.println("created export folder: " + one);
|
if (m.enabled) {
|
||||||
if (new File(Main.outpath + oArcTarget).exists()) {System.out.println("deleting existing file: " + Main.outpath + oArcTarget); new File(Main.outpath + oArcTarget).delete();} //hackjob
|
try {
|
||||||
if (!Main.windows) {two = new File(System.getProperty("user.home") + "/.firestar/temp/" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));}
|
System.out.println("Firestar is extracting " + m.friendlyName + " by " + m.author);
|
||||||
else {two = new File(System.getProperty("user.home") + "\\.firestar\\temp\\" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));}
|
consoleDisplay.append("Firestar is extracting " + m.friendlyName + " by " + m.author + "\n");
|
||||||
System.out.println("moved file to destination: " + two);
|
new ZipFile(System.getProperty("user.home") + "/.firestar/mods/" + m.path).extractAll(System.getProperty("user.home") + "/.firestar/temp/");
|
||||||
if (two) {System.out.println("file should be located at " + Main.outpath + oArcTarget);} else {
|
|
||||||
System.out.println("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!");
|
|
||||||
consoleDisplay.append("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!");
|
|
||||||
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
|
||||||
AllowExit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
File tmp = new File(System.getProperty("user.home") + "/.firestar/temp/");
|
|
||||||
Main.deleteDir(tmp);
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
|
|
||||||
consoleDisplay.append("WARNING: Temporary files may not have been properly cleared.\n" + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// done!
|
if (!m.requires.isEmpty() && !m.extracts.isEmpty()) {
|
||||||
try {
|
for (String r : m.requires) {
|
||||||
TimeUnit.SECONDS.sleep(1); // avoid race condition when logging
|
for (String e : m.extracts) {
|
||||||
} catch (InterruptedException e) {
|
File f = new File(Main.inpath + "temparcs/" + r + "/" + e);
|
||||||
//ignore
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
((TitledBorder)scrollPane.getBorder()).setTitle("DONE! Close this pop-up to continue.");
|
File fscript = new File(Main.inpath + "temp/fscript");
|
||||||
scrollPane.repaint();
|
if (fscript.exists()) {
|
||||||
|
System.out.println("Firestar is applying patches from " + m.friendlyName + " by " + m.author);
|
||||||
|
consoleDisplay.append("Firestar is applying patches from " + m.friendlyName + " by " + m.author + "\n");
|
||||||
|
new Rizzo(new FileInputStream(fscript), Main.inpath + "temp/"); // Lets rizz this mod up
|
||||||
|
fscript.delete();
|
||||||
|
}
|
||||||
|
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
if (new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").isFile()) {
|
||||||
AllowExit();
|
System.out.println("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author);
|
||||||
}
|
consoleDisplay.append("Firestar is deleting files that conflict with " + m.friendlyName + " by " + m.author + "\n");
|
||||||
|
System.out.println("WARNING: delete.txt is DEPRECATED. If using a mod with loaderversion >= 1 then this is bad practice, please use FSCRIPTs instead.");
|
||||||
|
consoleDisplay.append("WARNING: delete.txt is DEPRECATED. If using a mod with loaderversion >= 1 then this is bad practice, please use FSCRIPTs instead.");
|
||||||
|
|
||||||
private void FastRoutine() {
|
String deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/temp/delete.txt")));
|
||||||
|
if (Main.windows) {deleteQueue = new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "\\.firestar\\temp\\delete.txt")));} // might be unnecessary
|
||||||
|
String[] dQarray = deleteQueue.split("\n");
|
||||||
|
Arrays.sort(dQarray);
|
||||||
|
System.out.println("The deletion queue is " + dQarray.length + " files long!"); //debug
|
||||||
|
|
||||||
}
|
for (String file : dQarray) {
|
||||||
|
if(file.contains("..")) { //todo: is this safe enough?
|
||||||
|
System.out.println("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!");
|
||||||
|
consoleDisplay.append("WARNING: Firestar skipped a potentially dangerous delete command. Please ensure the mod you're installing is from someone you trust!\n");
|
||||||
|
} else {
|
||||||
|
if (!Main.windows) {
|
||||||
|
System.out.println("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file);
|
||||||
|
consoleDisplay.append("Deleting " + System.getProperty("user.home") + "/.firestar/temp/data/" + file + "\n");
|
||||||
|
new File(System.getProperty("user.home") + "/.firestar/temp/data" + file).delete();}
|
||||||
|
else {
|
||||||
|
System.out.println("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\"));
|
||||||
|
consoleDisplay.append("Deleting " + new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\") + "\n");
|
||||||
|
new File(new String(System.getProperty("user.home") + "\\.firestar\\temp\\data" + file).replace("/", "\\")).delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void AllowExit() {
|
// cleanup so we don't run it again for the next mod
|
||||||
System.out.println("\n\nYou may now close the pop-up window.");
|
new File(System.getProperty("user.home") + "/.firestar/temp/delete.txt").delete();
|
||||||
consoleDisplay.append("\n\n\nYou may now close the pop-up window.");
|
}
|
||||||
try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {} //ignore
|
} catch (Exception e) {
|
||||||
scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());
|
System.out.println(e.getMessage());
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
||||||
@Override
|
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 {
|
||||||
public void windowClosing(WindowEvent e)
|
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
{
|
}
|
||||||
invoker.wrapUpDeployment();
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
e.getWindow().dispose();
|
AllowExit();
|
||||||
}
|
return;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void listAllFiles(Path currentPath, List<String> allFiles)
|
// Post fscript changes
|
||||||
throws IOException
|
try (InputStream is = Main.class.getResourceAsStream("/post.fscript")) {
|
||||||
{
|
new Rizzo(is, Main.inpath + "temp/");
|
||||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(currentPath))
|
} catch (IOException | FirescriptFormatException e) {
|
||||||
{
|
System.out.println(e.getMessage());
|
||||||
for (Path entry : stream) {
|
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
||||||
if (Files.isDirectory(entry)) {
|
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Internal FSCRIPT Error. " + e.getMessage() + "\nThis may indicate that Firestar has been corrupted and needs reinstalling.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
listAllFiles(entry, allFiles);
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
} else {
|
AllowExit();
|
||||||
allFiles.add(entry.toString());
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// create a list of the contents of data/ for psp2psarc.exe to read from
|
||||||
}
|
List<String> oFilesList = new ArrayList<String>();
|
||||||
|
List<String> oFilesList2 = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
listAllFiles(Paths.get(System.getProperty("user.home") + "/.firestar/temp/data/"), oFilesList);
|
||||||
|
for (String p : oFilesList) {
|
||||||
|
// We need to clean up the path here on Linux to avoid psp2psarc getting confused about where the hell "/" is.
|
||||||
|
// In WINE it should see it as Z: by default, but if it's somewhere else then I don't have an elegant way of knowing what drive letter it's on, so
|
||||||
|
// relative paths are kind of the only choice here. This can be extended to Windows too as it works there, though completely unnecessary.
|
||||||
|
if (!Main.windows) {oFilesList2.add(p.replace("\\", "/").split(new String(System.getProperty("user.home") + "/.firestar/temp/"))[1]);}
|
||||||
|
else {oFilesList2.add(p.split(new String(System.getProperty("user.home") + "\\.firestar\\temp\\").replace("\\", "\\\\"))[1]);} // path wont match regex unless adjusted for windows here
|
||||||
|
}
|
||||||
|
//oFilesList2.forEach(System.out::println); //debug
|
||||||
|
File oFilesListO = new File(System.getProperty("user.home") + "/.firestar/temp/list.txt");
|
||||||
|
if (oFilesListO.isFile()) {oFilesListO.delete();}
|
||||||
|
FileWriter oFilesListWr = new FileWriter(oFilesListO, true);
|
||||||
|
int i = 0;
|
||||||
|
for (String p : oFilesList2) {
|
||||||
|
oFilesListWr.append(p);
|
||||||
|
if (i != oFilesList2.size()) {
|
||||||
|
oFilesListWr.append("\n");
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
oFilesListWr.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
|
AllowExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoke psp2psarc.exe one final time to reconstruct the assets
|
||||||
|
try {
|
||||||
|
System.out.println("Firestar is compiling the final build");
|
||||||
|
consoleDisplay.append("Firestar is compiling the final build" + "\n");
|
||||||
|
Process p = Main.exec(new String[]{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() {
|
||||||
|
try {
|
||||||
|
final BufferedReader reader = new BufferedReader(
|
||||||
|
new InputStreamReader(p.getInputStream()));
|
||||||
|
String line = null;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
System.out.println(line);
|
||||||
|
consoleDisplay.append(line + "\n");
|
||||||
|
try {scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());}
|
||||||
|
catch (Exception e) {System.out.println("WARNING: Swing failed to paint window due to race condition.\n" + e.getMessage());}
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
} catch (final Exception e) {
|
||||||
|
e.printStackTrace(); // will probably definitely absolutely for sure hang firestar unless we do something. Too bad!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ioThread.start();
|
||||||
|
p.waitFor();
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
consoleDisplay.append("CRITICAL FAILURE: " + e.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
|
AllowExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
boolean one = new File(Main.outpath).mkdirs();
|
||||||
|
boolean two;
|
||||||
|
System.out.println("created export folder: " + one);
|
||||||
|
if (new File(Main.outpath + oArcTarget).exists()) {System.out.println("deleting existing file: " + Main.outpath + oArcTarget); new File(Main.outpath + oArcTarget).delete();} //hackjob
|
||||||
|
if (!Main.windows) {two = new File(System.getProperty("user.home") + "/.firestar/temp/" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));}
|
||||||
|
else {two = new File(System.getProperty("user.home") + "\\.firestar\\temp\\" + oArcTarget).renameTo(new File(Main.outpath + oArcTarget));}
|
||||||
|
System.out.println("moved file to destination: " + two);
|
||||||
|
if (two) {System.out.println("file should be located at " + Main.outpath + oArcTarget);} else {
|
||||||
|
System.out.println("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!");
|
||||||
|
consoleDisplay.append("CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!");
|
||||||
|
JOptionPane.showMessageDialog(this.frame, "CRITICAL FAILURE: Please check that your output path is correct and that you have write permissions!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
|
AllowExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
File tmp = new File(System.getProperty("user.home") + "/.firestar/temp/");
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// done!
|
||||||
|
try {
|
||||||
|
TimeUnit.SECONDS.sleep(1); // avoid race condition when logging
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
((TitledBorder)scrollPane.getBorder()).setTitle("DONE! Close this pop-up to continue.");
|
||||||
|
scrollPane.repaint();
|
||||||
|
|
||||||
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
|
AllowExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FastRoutine() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AllowExit() {
|
||||||
|
System.out.println("\n\nYou may now close the pop-up window.");
|
||||||
|
consoleDisplay.append("\n\n\nYou may now close the pop-up window.");
|
||||||
|
try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {} //ignore
|
||||||
|
scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());
|
||||||
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosing(WindowEvent e)
|
||||||
|
{
|
||||||
|
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/"));
|
||||||
|
invoker.wrapUpDeployment();
|
||||||
|
e.getWindow().dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void listAllFiles(Path currentPath, List<String> allFiles) throws IOException {
|
||||||
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(currentPath)) {
|
||||||
|
for (Path entry : stream) {
|
||||||
|
if (Files.isDirectory(entry)) {
|
||||||
|
listAllFiles(entry, allFiles);
|
||||||
|
} else {
|
||||||
|
allFiles.add(entry.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,476 +0,0 @@
|
|||||||
/*
|
|
||||||
* Firestar Mod Manager
|
|
||||||
* Copyright (C) 2024 bonkmaykr
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.text.StyleConstants;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.io.*;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.*;
|
|
||||||
import java.security.*;
|
|
||||||
|
|
||||||
// handles setup window
|
|
||||||
public class Kermit implements ActionListener {
|
|
||||||
public enum Pages {
|
|
||||||
AGREEMENT(0),
|
|
||||||
EXPORT_MODE(1),
|
|
||||||
SDK_INSTALL(2),
|
|
||||||
SDK_FAILURE(3),
|
|
||||||
WHAT_OS(4),
|
|
||||||
EXPORT_LOCATION(5),
|
|
||||||
IMPORT_LOCATION(6),
|
|
||||||
DONE(7);
|
|
||||||
|
|
||||||
public final int value;
|
|
||||||
|
|
||||||
private Pages(int i) {
|
|
||||||
this.value = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JDialog frame = new JDialog();
|
|
||||||
JButton button = new JButton("Next");
|
|
||||||
JButton button2 = new JButton("Quit");
|
|
||||||
JButton button3 = new JButton("Cancel");
|
|
||||||
JButton button4 = new JButton("Back");
|
|
||||||
JTextPane dialogText = new JTextPane();
|
|
||||||
JRadioButton buttonCompat = new JRadioButton("Compatibility (for consoles)");
|
|
||||||
JRadioButton buttonFast = new JRadioButton("Fast Mode (for Vita3K emulator)");
|
|
||||||
ButtonGroup radg1 = new ButtonGroup();
|
|
||||||
JRadioButton buttonNoWine = new JRadioButton("No, I use Microsoft Windows");
|
|
||||||
JRadioButton buttonHaveWine = new JRadioButton("Yes, I have a POSIX system with WINE.");
|
|
||||||
ButtonGroup radg2 = new ButtonGroup();
|
|
||||||
JTextField pathInput = new JTextField();
|
|
||||||
JButton openconfigfolderbutton = new JButton("Open Firestar Folder");
|
|
||||||
Pages page = Pages.AGREEMENT;
|
|
||||||
javax.swing.text.StyledDocument document = dialogText.getStyledDocument();
|
|
||||||
javax.swing.text.SimpleAttributeSet align= new javax.swing.text.SimpleAttributeSet();
|
|
||||||
|
|
||||||
public void setup(File fConf) { //File variable is redundant. unused
|
|
||||||
frame.getContentPane().setBackground(Color.WHITE);
|
|
||||||
radg1.add(buttonCompat);
|
|
||||||
radg1.add(buttonFast);
|
|
||||||
radg2.add(buttonNoWine);
|
|
||||||
radg2.add(buttonHaveWine);
|
|
||||||
|
|
||||||
button.addActionListener(this);
|
|
||||||
button2.addActionListener(this);
|
|
||||||
button3.addActionListener(this);
|
|
||||||
button4.addActionListener(this);
|
|
||||||
buttonCompat.addActionListener(this);
|
|
||||||
buttonFast.addActionListener(this);
|
|
||||||
buttonNoWine.addActionListener(this);
|
|
||||||
buttonHaveWine.addActionListener(this);
|
|
||||||
openconfigfolderbutton.addActionListener(this);
|
|
||||||
|
|
||||||
changePage(Pages.AGREEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
|
||||||
if (actionEvent.getSource() == button2){
|
|
||||||
System.exit(0);
|
|
||||||
} else if (actionEvent.getSource() == button){
|
|
||||||
//frame.removeAll(); freezes??
|
|
||||||
switch (page) {
|
|
||||||
case AGREEMENT:
|
|
||||||
button.setVisible(false);frame.remove(button);
|
|
||||||
button2.setVisible(false);frame.remove(button2);
|
|
||||||
dialogText.setVisible(false);frame.remove(dialogText);
|
|
||||||
changePage(Pages.SDK_INSTALL); // EXPORT_MODE
|
|
||||||
break;
|
|
||||||
case EXPORT_MODE:
|
|
||||||
button.setVisible(false);frame.remove(button);
|
|
||||||
button3.setVisible(false);frame.remove(button3);
|
|
||||||
dialogText.setVisible(false);frame.remove(dialogText);
|
|
||||||
buttonCompat.setVisible(false);frame.remove(buttonCompat);
|
|
||||||
buttonFast.setVisible(false);frame.remove(buttonFast);
|
|
||||||
if (Main.repatch) {
|
|
||||||
changePage(Pages.SDK_INSTALL);
|
|
||||||
} else {changePage(Pages.EXPORT_LOCATION);}
|
|
||||||
break;
|
|
||||||
case SDK_INSTALL:
|
|
||||||
break;
|
|
||||||
case SDK_FAILURE:
|
|
||||||
break;
|
|
||||||
case WHAT_OS:
|
|
||||||
button.setVisible(false);frame.remove(button);
|
|
||||||
button3.setVisible(false);frame.remove(button3);
|
|
||||||
dialogText.setVisible(false);frame.remove(dialogText);
|
|
||||||
break;
|
|
||||||
case EXPORT_LOCATION:
|
|
||||||
button.setVisible(false);frame.remove(button);
|
|
||||||
button3.setVisible(false);frame.remove(button3);
|
|
||||||
dialogText.setVisible(false);frame.remove(dialogText);
|
|
||||||
buttonNoWine.setVisible(false);frame.remove(buttonNoWine);
|
|
||||||
buttonHaveWine.setVisible(false);frame.remove(buttonHaveWine);
|
|
||||||
changePage(Pages.IMPORT_LOCATION);
|
|
||||||
break;
|
|
||||||
case IMPORT_LOCATION:
|
|
||||||
Main.outpath = pathInput.getText();
|
|
||||||
pathInput.setText("");
|
|
||||||
dialogText.setVisible(false);frame.remove(dialogText);
|
|
||||||
pathInput.setVisible(false);frame.remove(pathInput);
|
|
||||||
changePage(Pages.DONE);
|
|
||||||
break;
|
|
||||||
case DONE:
|
|
||||||
if (new File(Main.inpath + "psp2psarc.exe").exists()) { // we may have been here before
|
|
||||||
new MissPiggy().Action(false);
|
|
||||||
} else {
|
|
||||||
new MissPiggy().Action(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
page = Pages.AGREEMENT; //set it here since we're disposing of the entire thing
|
|
||||||
frame.dispose();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("ERROR: Undefined behavior in Kermit's event listener. Get a programmer!");
|
|
||||||
//JOptionPane OhShit = new JOptionPane.showMessageDialog(null, "Fuck");
|
|
||||||
}
|
|
||||||
} else if (actionEvent.getSource() == button4){
|
|
||||||
//frame.removeAll(); freezes??
|
|
||||||
switch (page) { // todo remove elements when going to previous page
|
|
||||||
case EXPORT_MODE:
|
|
||||||
changePage(Pages.AGREEMENT);
|
|
||||||
break;
|
|
||||||
case SDK_INSTALL:
|
|
||||||
changePage(Pages.EXPORT_MODE);
|
|
||||||
break;
|
|
||||||
case SDK_FAILURE:
|
|
||||||
break;
|
|
||||||
case WHAT_OS:
|
|
||||||
changePage(Pages.SDK_INSTALL);
|
|
||||||
break;
|
|
||||||
case EXPORT_LOCATION:
|
|
||||||
if (Main.repatch) {changePage(Pages.WHAT_OS);} else {changePage(Pages.EXPORT_MODE);}
|
|
||||||
break;
|
|
||||||
case IMPORT_LOCATION:
|
|
||||||
changePage(Pages.EXPORT_LOCATION);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("ERROR: Undefined behavior in Kermit's event listener. Get a programmer!");
|
|
||||||
//JOptionPane OhShit = new JOptionPane.showMessageDialog(null, "Fuck");
|
|
||||||
}
|
|
||||||
} else if (actionEvent.getSource() == buttonCompat) {
|
|
||||||
Main.repatch = true;
|
|
||||||
button.setEnabled(true);
|
|
||||||
} else if (actionEvent.getSource() == buttonFast) {
|
|
||||||
Main.repatch = false;
|
|
||||||
button.setEnabled(true);
|
|
||||||
} else if (actionEvent.getSource() == buttonHaveWine) {
|
|
||||||
Main.windows = true;
|
|
||||||
button.setEnabled(true);
|
|
||||||
} else if (actionEvent.getSource() == buttonNoWine) {
|
|
||||||
Main.windows = false;
|
|
||||||
button.setEnabled(true);
|
|
||||||
}else if (actionEvent.getSource() == openconfigfolderbutton) {
|
|
||||||
try {
|
|
||||||
Desktop.getDesktop().open(new File(Main.inpath));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void changePage(Pages GoTo){
|
|
||||||
switch (GoTo) {
|
|
||||||
case AGREEMENT:
|
|
||||||
page = Pages.AGREEMENT;
|
|
||||||
|
|
||||||
button.setVisible(true);
|
|
||||||
button.setBounds(292, 343, 300, 30);
|
|
||||||
frame.add(button);
|
|
||||||
|
|
||||||
button2.setVisible(true);
|
|
||||||
button2.setBounds(0, 343, 292, 30);
|
|
||||||
frame.add(button2);
|
|
||||||
|
|
||||||
dialogText.setVisible(true);
|
|
||||||
dialogText.setHighlighter(null);
|
|
||||||
dialogText.getCaret().setVisible(false);
|
|
||||||
dialogText.setFocusable(false);
|
|
||||||
dialogText.setBounds(0, 0, 592, 343);
|
|
||||||
//dialogText.setAlignmentX(JComponent.CENTER_ALIGNMENT);
|
|
||||||
//dialogText.setAlignmentY(JComponent.CENTER_ALIGNMENT);
|
|
||||||
StyleConstants.setAlignment(align, StyleConstants.ALIGN_CENTER);
|
|
||||||
document.setParagraphAttributes(0, document.getLength(), align, false);
|
|
||||||
//dialogText.setText("Aww Fiddlesticks, what now?");
|
|
||||||
dialogText.setText("WELCOME TO FIRESTAR\n\n" +
|
|
||||||
"This initial setup guide will help you prepare your Playstation Vita, Playstation TV, or Vita3K emulator to play WipEout mods.\n\n Before continuing, please read the decryption guide at:\nhttps://git.worlio.com/bonkmaykr/firestar/wiki/Decrypting-Original-PSARC-Files\nsince you will need these files in order to use Firestar.\n\n" +
|
|
||||||
"If you encounter any issues while using Firestar you may contact the author at bonkmaykr@screwgravity.net");
|
|
||||||
frame.add(dialogText);
|
|
||||||
|
|
||||||
frame.setSize(600, 400);
|
|
||||||
frame.setTitle("Initial Setup");
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
frame.setDefaultCloseOperation(0);
|
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setLayout(null);
|
|
||||||
frame.setVisible(true);
|
|
||||||
break;
|
|
||||||
case EXPORT_MODE:
|
|
||||||
page = Pages.EXPORT_MODE;
|
|
||||||
|
|
||||||
button.setVisible(true);
|
|
||||||
button.setEnabled(false);
|
|
||||||
button.setBounds(292, 343, 300, 30);
|
|
||||||
frame.add(button);
|
|
||||||
|
|
||||||
button3.setVisible(false);
|
|
||||||
button3.setBounds(0, 343, 292, 30);
|
|
||||||
frame.add(button3);
|
|
||||||
|
|
||||||
dialogText.setVisible(true);
|
|
||||||
dialogText.setHighlighter(null);
|
|
||||||
dialogText.getCaret().setVisible(false);
|
|
||||||
dialogText.setFocusable(false);
|
|
||||||
dialogText.setBounds(0, 40, 592, 150);
|
|
||||||
StyleConstants.setAlignment(align, StyleConstants.ALIGN_CENTER);
|
|
||||||
document.setParagraphAttributes(0, document.getLength(), align, false);
|
|
||||||
dialogText.setText("Please choose how Firestar will deploy your mods.\n\n" +
|
|
||||||
"Compatibility mode requires software from the PSVita SDK, but works on real hardware.\n" +
|
|
||||||
"Fast mode is easiest, but won't work on FAT32/exFAT drives like what the Vita uses.");
|
|
||||||
frame.add(dialogText);
|
|
||||||
|
|
||||||
buttonCompat.setBounds(40, 200, 300, 25);
|
|
||||||
buttonFast.setBounds(40, 230, 300, 25);
|
|
||||||
buttonCompat.setBackground(Color.WHITE);
|
|
||||||
buttonFast.setBackground(Color.WHITE);
|
|
||||||
buttonCompat.setVisible(true);
|
|
||||||
buttonFast.setVisible(true);
|
|
||||||
frame.add(buttonCompat);
|
|
||||||
frame.add(buttonFast);
|
|
||||||
|
|
||||||
frame.setSize(600, 400);
|
|
||||||
frame.setTitle("Initial Setup");
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
frame.setDefaultCloseOperation(0);
|
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setLayout(null);
|
|
||||||
frame.setLocationRelativeTo(null);
|
|
||||||
frame.setVisible(true);
|
|
||||||
break;
|
|
||||||
case SDK_INSTALL:
|
|
||||||
page = Pages.SDK_INSTALL;
|
|
||||||
|
|
||||||
dialogText.setVisible(true);
|
|
||||||
dialogText.setHighlighter(null);
|
|
||||||
dialogText.getCaret().setVisible(false);
|
|
||||||
dialogText.setFocusable(false);
|
|
||||||
dialogText.setBounds(0, 40, 592, 300);
|
|
||||||
StyleConstants.setAlignment(align, StyleConstants.ALIGN_CENTER);
|
|
||||||
document.setParagraphAttributes(0, document.getLength(), align, false);
|
|
||||||
dialogText.setText("Firestar is downloading important dependencies. Please wait."); //some kind of race condition prevents this from displaying?
|
|
||||||
frame.add(dialogText);
|
|
||||||
|
|
||||||
frame.setSize(600, 400);
|
|
||||||
frame.setTitle("Initial Setup");
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
frame.setDefaultCloseOperation(0);
|
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setLayout(null);
|
|
||||||
frame.setVisible(true);
|
|
||||||
|
|
||||||
//md5 checksum 4ef707b2dba6944a726d46950aaddfd2
|
|
||||||
try {
|
|
||||||
File downloadLocationDir = new File(System.getProperty("user.home") + "/.firestar/");
|
|
||||||
File downloadLocation = new File(System.getProperty("user.home") + "/.firestar/psp2psarc.exe");
|
|
||||||
downloadLocationDir.mkdirs();
|
|
||||||
if (!downloadLocation.isFile()) {
|
|
||||||
downloadLocation.createNewFile();
|
|
||||||
}
|
|
||||||
BufferedInputStream in = new BufferedInputStream(new URL("http://bonkmaykr.worlio.com/http/firestar/psp2psarc.exe").openStream());
|
|
||||||
//FileOutputStream downloadOutput = new FileOutputStream(new File(System.getProperty("user.home") + "/.firestar/psp2psarc.exe"));
|
|
||||||
Files.copy(in, Paths.get(System.getProperty("user.home") + "/.firestar/psp2psarc.exe"), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
|
|
||||||
int tests = 0;
|
|
||||||
String checksum ="";
|
|
||||||
while (tests < 60 /*while(true)*/) {
|
|
||||||
byte[] hash = MessageDigest.getInstance("MD5").digest(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/psp2psarc.exe")));
|
|
||||||
checksum = new BigInteger(1, hash).toString(16);
|
|
||||||
System.out.println("Downloaded psp2psarc.exe successfully.");
|
|
||||||
if(checksum.equals("4ef707b2dba6944a726d46950aaddfd2")) {changePage(Pages.WHAT_OS);break;}
|
|
||||||
Thread.sleep(20);
|
|
||||||
tests++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(checksum.equals("4ef707b2dba6944a726d46950aaddfd2")) {changePage(Pages.WHAT_OS);} else {
|
|
||||||
System.out.println("ERROR: Failed to download PSARC tool. Check connection and ensure the file is not corrupt or infected.");
|
|
||||||
dialogText.setText("Firestar tried to download important files needed for operation, but they were either corrupted or did not finish.\n" + "\n\nYou will need to manually install psp2psarc.exe into your Firestar config folder after setup is complete! Or, you can retry the download later.");
|
|
||||||
//frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
||||||
|
|
||||||
button.setVisible(true);
|
|
||||||
button.setBounds(292, 343, 300, 30);
|
|
||||||
frame.add(button);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Failed to download PSARC tool due to an internal error:" + e.getMessage());
|
|
||||||
dialogText.setText("An error has occured.\n" + e.getMessage() + "\n\nYou will need to manually install psp2psarc.exe into your Firestar config folder after setup is complete!!!");
|
|
||||||
//frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
||||||
|
|
||||||
button.setVisible(true);
|
|
||||||
button.setBounds(292, 343, 300, 30);
|
|
||||||
frame.add(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case SDK_FAILURE:
|
|
||||||
page = Pages.SDK_FAILURE; //unused
|
|
||||||
break;
|
|
||||||
case WHAT_OS:
|
|
||||||
page = Pages.WHAT_OS;
|
|
||||||
|
|
||||||
//do window clear here since the page is never called by the event handler
|
|
||||||
button.setVisible(false);frame.remove(button);
|
|
||||||
button3.setVisible(false);frame.remove(button3);
|
|
||||||
dialogText.setVisible(false);frame.remove(dialogText);
|
|
||||||
|
|
||||||
//check if this is windows or not
|
|
||||||
if(System.getProperty("os.name").contains("Windows")) {Main.windows = true;System.out.println("Assuming we should NOT use WINE based on known system variables.");changePage(Pages.EXPORT_LOCATION);}
|
|
||||||
else {Main.windows = false;System.out.println("Assuming we should use WINE based on known system variables.");changePage(Pages.EXPORT_LOCATION);}
|
|
||||||
|
|
||||||
case EXPORT_LOCATION:
|
|
||||||
page = Pages.EXPORT_LOCATION;
|
|
||||||
|
|
||||||
button.setVisible(true);
|
|
||||||
button.setBounds(292, 343, 300, 30);
|
|
||||||
frame.add(button);
|
|
||||||
|
|
||||||
button3.setVisible(false);
|
|
||||||
button3.setBounds(0, 343, 292, 30);
|
|
||||||
frame.add(button3);
|
|
||||||
|
|
||||||
dialogText.setVisible(true);
|
|
||||||
dialogText.setHighlighter(null);
|
|
||||||
dialogText.getCaret().setVisible(false);
|
|
||||||
dialogText.setFocusable(false);
|
|
||||||
dialogText.setBounds(30, 40, 542, 150);
|
|
||||||
StyleConstants.setAlignment(align, StyleConstants.ALIGN_CENTER);
|
|
||||||
document.setParagraphAttributes(0, document.getLength(), align, false);
|
|
||||||
dialogText.setText("Now enter the location of your game's asset folder.\n" +
|
|
||||||
"This can be your install directory on your emulator, your repatch folder on your Vita memory card, or a temporary directory you'd like to copy over yourself.\n\n" +
|
|
||||||
"PLEASE DO NOT POINT THIS DIRECTLY TO WHERE THE GAME IS INSTALLED ON A REAL VITA\n" +
|
|
||||||
"(ux0:/app, ux0:/patch or ux0:/addcont)\n" +
|
|
||||||
"AS THIS WILL CORRUPT YOUR GAME AND YOU WILL NEED TO REINSTALL IT.\nDoing this on an emulator is fine.");
|
|
||||||
frame.add(dialogText);
|
|
||||||
|
|
||||||
pathInput.setVisible(true);
|
|
||||||
pathInput.setBounds(30,200,542,30);
|
|
||||||
frame.add(pathInput);
|
|
||||||
|
|
||||||
frame.setSize(600, 400);
|
|
||||||
frame.setTitle("Initial Setup");
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
frame.setDefaultCloseOperation(0);
|
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setLayout(null);
|
|
||||||
frame.setVisible(true);
|
|
||||||
break;
|
|
||||||
case IMPORT_LOCATION:
|
|
||||||
// I think for Fast Mode this step may be unnecessary? look into alternatives perhaps
|
|
||||||
|
|
||||||
page = Pages.IMPORT_LOCATION;
|
|
||||||
pathInput.setVisible(false); //GET OUT OF MY HEAD
|
|
||||||
|
|
||||||
button.setVisible(true);
|
|
||||||
button.setBounds(292, 343, 300, 30);
|
|
||||||
frame.add(button);
|
|
||||||
|
|
||||||
button3.setVisible(false);
|
|
||||||
button3.setBounds(0, 343, 292, 30);
|
|
||||||
frame.add(button3);
|
|
||||||
|
|
||||||
dialogText.setVisible(true);
|
|
||||||
dialogText.setHighlighter(null);
|
|
||||||
dialogText.getCaret().setVisible(false);
|
|
||||||
dialogText.setFocusable(false);
|
|
||||||
dialogText.setBounds(30, 40, 542, 200);
|
|
||||||
StyleConstants.setAlignment(align, StyleConstants.ALIGN_CENTER);
|
|
||||||
document.setParagraphAttributes(0, document.getLength(), align, false);
|
|
||||||
dialogText.setText("You're almost done!\n\n" +
|
|
||||||
"Please move all of your original PSARC files for WipEout (base game, patches, and HD Fury DLC) to the config folder and press Next when you are done.\n" +
|
|
||||||
"Firestar will use these to generate new PSARCs in place of the old ones.\n\n" +
|
|
||||||
"If you do not already have these files, please read:\nhttps://git.worlio.com/bonkmaykr/firestar/wiki/Decrypting-Original-PSARC-Files\nto acquire them.");
|
|
||||||
frame.add(dialogText);
|
|
||||||
|
|
||||||
//pathInput.setVisible(true);
|
|
||||||
//pathInput.setBounds(30,200,542,30);
|
|
||||||
//frame.add(pathInput);
|
|
||||||
openconfigfolderbutton.setVisible(true);
|
|
||||||
openconfigfolderbutton.setBounds(30,250,542,30);
|
|
||||||
frame.add(openconfigfolderbutton);
|
|
||||||
|
|
||||||
frame.setSize(600, 400);
|
|
||||||
frame.setTitle("Initial Setup");
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
frame.setDefaultCloseOperation(0);
|
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setLayout(null);
|
|
||||||
frame.setVisible(true);
|
|
||||||
break;
|
|
||||||
case DONE:
|
|
||||||
page = Pages.DONE;
|
|
||||||
|
|
||||||
Main.writeConf(); // save changes
|
|
||||||
|
|
||||||
//SERIOUS!!!!!!!!!!!!!! cleanup
|
|
||||||
button.setVisible(false);frame.remove(button);
|
|
||||||
button2.setVisible(false);frame.remove(button2);
|
|
||||||
button3.setVisible(false);frame.remove(button3);
|
|
||||||
button4.setVisible(false);frame.remove(button4);
|
|
||||||
openconfigfolderbutton.setVisible(false);frame.remove(openconfigfolderbutton);
|
|
||||||
pathInput.setVisible(false);frame.remove(pathInput);
|
|
||||||
buttonFast.setVisible(false);frame.remove(buttonFast);
|
|
||||||
buttonCompat.setVisible(false);frame.remove(buttonCompat);
|
|
||||||
buttonHaveWine.setVisible(false);frame.remove(buttonHaveWine);
|
|
||||||
buttonNoWine.setVisible(false);frame.remove(buttonNoWine);
|
|
||||||
|
|
||||||
//congrations, your did it (party time)
|
|
||||||
dialogText.setVisible(true);
|
|
||||||
dialogText.setHighlighter(null);
|
|
||||||
dialogText.getCaret().setVisible(false);
|
|
||||||
dialogText.setFocusable(false);
|
|
||||||
dialogText.setBounds(30, 40, 542, 200);
|
|
||||||
StyleConstants.setAlignment(align, StyleConstants.ALIGN_CENTER);
|
|
||||||
document.setParagraphAttributes(0, document.getLength(), align, false);
|
|
||||||
dialogText.setText("Firestar is ready!\n\n" +
|
|
||||||
"For technical support, see Help > Manual.");
|
|
||||||
frame.add(dialogText);
|
|
||||||
|
|
||||||
button.setVisible(true);
|
|
||||||
button.setBounds(292, 343, 300, 30);
|
|
||||||
button.setText("OK");
|
|
||||||
frame.add(button);
|
|
||||||
|
|
||||||
frame.setSize(600, 400);
|
|
||||||
frame.setTitle("Initial Setup");
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
frame.setDefaultCloseOperation(0);
|
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setLayout(null);
|
|
||||||
frame.setVisible(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("ERROR: Undefined behavior in Kermit.changePage(). Get a programmer!");
|
|
||||||
//JOptionPane OhShit = new JOptionPane.showMessageDialog(null, "Fuck");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,236 +18,285 @@
|
|||||||
|
|
||||||
import net.lingala.zip4j.ZipFile;
|
import net.lingala.zip4j.ZipFile;
|
||||||
import net.lingala.zip4j.exception.ZipException;
|
import net.lingala.zip4j.exception.ZipException;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.json.*;
|
import org.json.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
// Build Information
|
// Build Information
|
||||||
public static final String vstr = "Release 1.3";
|
public static String vstr = "Release 1.3";
|
||||||
public static final String vcode = "Tetsuo";
|
public static final String vcode = "Tetsuo";
|
||||||
public static final String vtag = "tetsuo-1.3"; // set to dekka-1.1 for testing
|
public static final String vtag = "tetsuo-1.3"; // set to dekka-1.1 for testing
|
||||||
public static final int vint = 1;
|
public static final int vint = 1;
|
||||||
|
|
||||||
// User Settings
|
// Jenkins Build Information
|
||||||
public static String outpath = System.getProperty("user.home") + "/.firestar/out/"; //game assets location
|
public static boolean isNightly = false;
|
||||||
public final static String inpath = System.getProperty("user.home") + "/.firestar/"; //firestar folder -- do not change this
|
public static final String vtagPrevious = "tetsuo-1.3";
|
||||||
public static boolean repatch; //are we in compat mode?
|
public static String dateOfCompile = null;
|
||||||
public static boolean windows; //True = windows
|
|
||||||
public static int confvint = vint;
|
|
||||||
public static boolean checkUpdates = true;
|
|
||||||
//public static String psarc; //sdk location
|
|
||||||
|
|
||||||
public enum ArcTarget { // install target for 2048, type used by downloader
|
// User Settings
|
||||||
BASE("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/NYEoaBGfiWymSEVZKxoyrKyBFsZNoFqxdyAIpZayZYuLLbCAArYrYXjPNhKCfXcONmhIZzZEeArycSrjiJOuNMWuWsDONUxMIQtMk.pkg"),
|
public static String outpath = System.getProperty("user.home") + "/.firestar/out/"; //game assets location
|
||||||
LATEST("http://gs.ww.np.dl.playstation.net/ppkg/np/PCSA00015/PCSA00015_T5/a4b7d9e35ed56e86/UP9000-PCSA00015_00-WIPEOUT2048BASE0-A0104-V0100-059564fcab8ce66d19b5a563e92677e581313205-PE.pkg"),
|
public final static String inpath = System.getProperty("user.home") + "/.firestar/"; //firestar folder -- do not change this
|
||||||
ADDON_HD("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/JYMqGNXUKqHEyNLjbOgrWcJdnQJUMzgadRFWekbWFBXAwMeGikOyiHkXKogKIfqGhtNwKgmNWwwcrJORmRUTDzylBPwjGVnVjyDfh.pkg"),
|
public static boolean repatch; //are we in compat mode?
|
||||||
ADDON_HD_FURY("http://zeus.dl.playstation.net/cdn/UP9000/PCSA00015_00/IAoJQaDpySenBmQCKiqecEPMzSdPfPcdXupxZXLTYYTuRgtsdTaHxbeejwGKRQpjJOKBdMMFzSoeEhsHYxNUasQrEzkZPeBxUEqnp.pkg");
|
public static boolean windows; //True = windows
|
||||||
|
public static int confvint = vint;
|
||||||
|
public static boolean checkUpdates = true;
|
||||||
|
//public static String psarc; //sdk location
|
||||||
|
|
||||||
private final String value;
|
public enum ArcTarget { // install target for 2048, type used by downloader
|
||||||
ArcTarget(final String value) {this.value = value;}
|
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");
|
||||||
|
|
||||||
@Override
|
private final String value;
|
||||||
public String toString() {
|
ArcTarget(final String value) {this.value = value;}
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ArcKey { // install target for 2048, type used by downloader
|
@Override
|
||||||
BASE("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
public String toString() {
|
||||||
LATEST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
return value;
|
||||||
ADDON_HD("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsGG5kYGIR4Ojs7ejuis9/anXfuudVNvzgdu+9z1z+asJojA9uAACgRhTl"),
|
}
|
||||||
ADDON_HD_FURY("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsFG5kYGIR4Ojs7ejuis9/3fydBRm3eCJX7biz/vVTm/2jMT64AQCCYhVy");
|
}
|
||||||
|
|
||||||
private final String value;
|
public enum ArcKey { // decryption keys for 2048, type used by downloader
|
||||||
ArcKey(final String value) {this.value = value;}
|
BASE("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||||
|
FIRST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||||
@Override
|
LATEST("KO5ifR1dQ+eHBlgi6TI0Bdkf7hng6h8aYmRgYuHkCLQNn/9ufV+01fmzjNSmwuVHnO4dEBuN8cENACqVFcgA"),
|
||||||
public String toString() {
|
ADDON_HD("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsGG5kYGIR4Ojs7ejuis9/anXfuudVNvzgdu+9z1z+asJojA9uAACgRhTl"),
|
||||||
return value;
|
ADDON_HD_FURY("KO5ifR1dQ+eHBlgi6TI0Bdnv4uNsFG5kYGIR4Ojs7ejuis9/3fydBRm3eCJX7biz/vVTm/2jMT64AQCCYhVy");
|
||||||
}
|
|
||||||
}
|
private final String value;
|
||||||
|
ArcKey(final String value) {this.value = value;}
|
||||||
public class Mod {
|
|
||||||
public String path; // file name
|
@Override
|
||||||
public int version = 1;
|
public String toString() {
|
||||||
public int priority = 0; //unused
|
return value;
|
||||||
public String friendlyName;
|
}
|
||||||
public String description = "";
|
}
|
||||||
public String game; //TODO for multi game support
|
|
||||||
public int loaderversion = 0; //minimum required vint or feature level from Firestar
|
public class Mod {
|
||||||
public String author; // if null, "Author is unknown."
|
public String path; // file name
|
||||||
public boolean enabled = true;
|
public int version = 1;
|
||||||
public boolean[] requires = new boolean[]{false, false, false, false}; // TODO: load optional "requires" array from mod meta if it exists. it will be base, patches, hd dlc, and fury dlc in that order.
|
public int priority = 0; //unused
|
||||||
// TODO: save 'true true false false' in ost gen if neccessary (patches change localization)
|
public String friendlyName;
|
||||||
}
|
public String description = "";
|
||||||
|
public String game; //TODO for multi game support
|
||||||
// Mods
|
public int loaderversion = 0; //minimum required vint or feature level from Firestar
|
||||||
public static List<Mod> Mods = new ArrayList<Mod>();
|
public String author; // if null, "Author is unknown."
|
||||||
|
public boolean enabled = true;
|
||||||
// UI Global Assets
|
public List<String> requires = new ArrayList<>();
|
||||||
public static Font fExo2;
|
public List<String> extracts = new ArrayList<>();
|
||||||
public static BufferedImage windowIcon;
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
// Mods
|
||||||
// license string
|
public static List<Mod> Mods = new ArrayList<Mod>();
|
||||||
System.out.printf("FIRESTAR MOD MANAGER for WipEout 2048\nversion " + vstr + " (codename " + vcode + ") major " + vint + "\n" +
|
|
||||||
"JVM host appears to be " + System.getProperty("os.name") +
|
// UI Global Assets
|
||||||
"\nRunning from " + System.getProperty("user.dir") +
|
public static Font fExo2;
|
||||||
"\nCopyright (C) 2024 bonkmaykr\n\nThis program is free software: you can redistribute it and/or modify\n" +
|
public static BufferedImage windowIcon;
|
||||||
"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" +
|
public static void main(String[] args) {
|
||||||
"(at your option) any later version.\n" +
|
// get Nightly information from Jenkins automatic builds
|
||||||
"\n" +
|
if (Main.class.getResource("/jenkinsVersionString") != null) {
|
||||||
"This program is distributed in the hope that it will be useful,\n" +
|
System.out.println("=== This is a NIGHTLY BUILD! ===\n");
|
||||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
|
try {
|
||||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
|
vstr = "Nightly " + IOUtils.toString(Main.class.getResourceAsStream("/jenkinsVersionString"), StandardCharsets.UTF_8);
|
||||||
"GNU General Public License for more details.\n" +
|
dateOfCompile = IOUtils.toString(Main.class.getResourceAsStream("/jenkinsBuildDate"), StandardCharsets.UTF_8);
|
||||||
"\n" +
|
System.out.println("Compiled on " + dateOfCompile);
|
||||||
"You should have received a copy of the GNU General Public License\n" +
|
isNightly = true;
|
||||||
"along with this program. If not, see https://www.gnu.org/licenses/.\n\n\n\n");
|
} catch (Exception e) {
|
||||||
|
System.out.println("ERROR: Something went wrong trying to get the autobuild information! defaulting to Release values\n\n");
|
||||||
//begin
|
isNightly = false;
|
||||||
// load global assets
|
}
|
||||||
try {
|
}
|
||||||
fExo2 = Font.createFont(Font.TRUETYPE_FONT, Main.class.getResourceAsStream("/exo2.ttf"));
|
|
||||||
} catch (Exception e) {
|
// license string
|
||||||
System.out.println("Font \"Exo 2\" is missing!");
|
System.out.printf("FIRESTAR MOD MANAGER for WipEout 2048\n" + vstr + " (codename " + vcode + ") major " + vint + "\n" +
|
||||||
fExo2 = new Font("Arial", Font.PLAIN, 12);
|
"JVM host appears to be " + System.getProperty("os.name") +
|
||||||
}
|
"\nRunning from " + System.getProperty("user.dir") +
|
||||||
|
"\nCopyright (C) 2025 Canithesis Interactive\n\nThis program is free software: you can redistribute it and/or modify\n" +
|
||||||
// load global window icon
|
"it under the terms of the GNU General Public License as published by\n" +
|
||||||
try {
|
"the Free Software Foundation, either version 3 of the License, or\n" +
|
||||||
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
"(at your option) any later version.\n" +
|
||||||
} catch (IOException e) {
|
"\n" +
|
||||||
System.out.println("ERROR: Failed to find titleIcon.png. Window will not have an icon.");
|
"This program is distributed in the hope that it will be useful,\n" +
|
||||||
}
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
|
||||||
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
|
||||||
// check and load configs
|
"GNU General Public License for more details.\n" +
|
||||||
File fConf = new File(System.getProperty("user.home") + "/.firestar/firestar.conf");
|
"\n" +
|
||||||
if (!fConf.isFile()) {
|
"You should have received a copy of the GNU General Public License\n" +
|
||||||
System.out.println("No configuration was found. Starting the initial setup");
|
"along with this program. If not, see https://www.gnu.org/licenses/.\n\n\n\n");
|
||||||
new WilkinsCoffee().setup();
|
|
||||||
} else {
|
// load global assets
|
||||||
new MissPiggy().Action(); // Quick! Start singing Firework by Katy Perry! (or open the main window i guess...)
|
try {
|
||||||
}
|
fExo2 = Font.createFont(Font.TRUETYPE_FONT, Main.class.getResourceAsStream("/exo2.ttf"));
|
||||||
}
|
} catch (Exception e) {
|
||||||
|
System.out.println("Font \"Exo 2\" is missing!");
|
||||||
public static void writeConf(){
|
fExo2 = new Font("Arial", Font.PLAIN, 12);
|
||||||
JSONObject container = new JSONObject();
|
}
|
||||||
container.put("version", vint);
|
|
||||||
container.put("2048path", outpath);
|
// load global window icon
|
||||||
container.put("HDpath", "TODO"); // proposed hd/fury support for ps3, will use very simplified Fast Mode due to less difficulty installing
|
try {
|
||||||
container.put("safemode", repatch);
|
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
||||||
container.put("isWin32", windows);
|
} catch (IOException e) {
|
||||||
container.put("checkUpdates", checkUpdates);
|
System.out.println("ERROR: Failed to find titleIcon.png. Window will not have an icon.");
|
||||||
container.put("currentPlaylist", "TODO"); // proposed feature: store separate mod lists in lists/ to load/save later?
|
}
|
||||||
|
|
||||||
try {
|
// check and load configs
|
||||||
Files.write(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"), container.toString().getBytes());
|
File fConf = new File(System.getProperty("user.home") + "/.firestar/firestar.conf");
|
||||||
} catch (IOException e) {
|
if (!fConf.isFile()) {
|
||||||
throw new RuntimeException(e);
|
System.out.println("No configuration was found. Starting the initial setup");
|
||||||
}
|
new WilkinsCoffee().setup();
|
||||||
}
|
} else {
|
||||||
|
new MissPiggy().Action(); // Quick! Start singing Firework by Katy Perry! (or open the main window i guess...)
|
||||||
public static void loadConf(){
|
}
|
||||||
try {
|
}
|
||||||
JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"))));
|
|
||||||
System.out.println(container.toString()); // debug
|
public static void writeConf(){
|
||||||
confvint = (int) container.get("version"); // used for converting configs between program versions later down the line
|
JSONObject container = new JSONObject();
|
||||||
outpath = container.get("2048path").toString();
|
container.put("version", vint);
|
||||||
repatch = (boolean) container.get("safemode");
|
container.put("2048path", outpath);
|
||||||
windows = (boolean) container.get("isWin32");
|
container.put("HDpath", "TODO"); // proposed hd/fury support for ps3, will use very simplified Fast Mode due to less difficulty installing
|
||||||
try {
|
container.put("safemode", repatch);
|
||||||
checkUpdates = (boolean) container.get("checkUpdates");
|
container.put("isWin32", windows);
|
||||||
} catch (JSONException e) {
|
container.put("checkUpdates", checkUpdates);
|
||||||
checkUpdates = true;
|
container.put("currentPlaylist", "TODO"); // proposed feature: store separate mod lists in lists/ to load/save later?
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
try {
|
||||||
System.out.println("ERROR: Failed to load firestar.conf");
|
Files.write(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"), container.toString().getBytes());
|
||||||
System.out.println(e.getMessage());
|
} catch (IOException e) {
|
||||||
}
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public static void loadConf(MissPiggy w){
|
|
||||||
try {
|
public static void loadConf(){
|
||||||
JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"))));
|
try {
|
||||||
System.out.println(container.toString()); // debug
|
JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"))));
|
||||||
confvint = (int) container.get("version"); // used for converting configs between program versions later down the line
|
System.out.println(container.toString()); // debug
|
||||||
outpath = container.get("2048path").toString();
|
confvint = (int) container.get("version"); // used for converting configs between program versions later down the line
|
||||||
repatch = (boolean) container.get("safemode");
|
outpath = container.get("2048path").toString();
|
||||||
windows = (boolean) container.get("isWin32");
|
repatch = (boolean) container.get("safemode");
|
||||||
try {
|
windows = (boolean) container.get("isWin32");
|
||||||
checkUpdates = (boolean) container.get("checkUpdates");
|
try {
|
||||||
} catch (JSONException e) {
|
checkUpdates = (boolean) container.get("checkUpdates");
|
||||||
checkUpdates = true;
|
} catch (JSONException e) {
|
||||||
}
|
checkUpdates = true;
|
||||||
} catch (Exception e) {
|
}
|
||||||
JOptionPane.showMessageDialog(w.frame, "Firestar couldn't load your config file. Tread lightly.\n\n" + e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE);
|
} catch (IOException e) {
|
||||||
System.out.println("ERROR: Failed to load firestar.conf");
|
System.out.println("ERROR: Failed to load firestar.conf");
|
||||||
System.out.println(e.getMessage());
|
System.out.println(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteDir(File file) { // https://stackoverflow.com/a/29175213/9259829
|
public static void loadConf(MissPiggy w){
|
||||||
File[] contents = file.listFiles();
|
try {
|
||||||
if (contents != null) {
|
JSONObject container = new JSONObject(new String(Files.readAllBytes(Paths.get(System.getProperty("user.home") + "/.firestar/firestar.conf"))));
|
||||||
for (File f : contents) {
|
System.out.println(container.toString()); // debug
|
||||||
if (! Files.isSymbolicLink(f.toPath())) {
|
confvint = (int) container.get("version"); // used for converting configs between program versions later down the line
|
||||||
deleteDir(f);
|
outpath = container.get("2048path").toString();
|
||||||
}
|
repatch = (boolean) container.get("safemode");
|
||||||
}
|
windows = (boolean) container.get("isWin32");
|
||||||
}
|
try {
|
||||||
file.delete();
|
checkUpdates = (boolean) container.get("checkUpdates");
|
||||||
}
|
} catch (JSONException e) {
|
||||||
|
checkUpdates = true;
|
||||||
public static void downloadDependenciesBeforeSetVisible(JFrame invoker) {
|
}
|
||||||
invoker.setVisible(false);
|
} catch (Exception e) {
|
||||||
Main.downloadDependencies();
|
JOptionPane.showMessageDialog(w.frame, "Firestar couldn't load your config file. Tread lightly.\n\n" + e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE);
|
||||||
invoker.setVisible(true);
|
System.out.println("ERROR: Failed to load firestar.conf");
|
||||||
confvint = vint;
|
System.out.println(e.getMessage());
|
||||||
Main.writeConf();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean downloadDependencies () { // todo: CHECKSUM!!!! THESE ARE EXECUTABLES!!!!!!!!!!! DON'T ALLOW MALWARE!!!!
|
public static void deleteDir(File file) { // https://stackoverflow.com/a/29175213/9259829
|
||||||
boolean downloader = new Fozzie().DownloadFile("https://bonkmaykr.worlio.com/http/firestar/firesdk.zip", System.getProperty("user.home") + "/.firestar/", "firesdk.zip");
|
File[] contents = file.listFiles();
|
||||||
if (!downloader) {return false;}
|
if (contents != null) {
|
||||||
|
for (File f : contents) {
|
||||||
ZipFile sdk = new ZipFile(System.getProperty("user.home") + "/.firestar/firesdk.zip");
|
if (! Files.isSymbolicLink(f.toPath())) {
|
||||||
try {
|
deleteDir(f);
|
||||||
sdk.extractAll(System.getProperty("user.home") + "/.firestar/");
|
}
|
||||||
} catch (ZipException e) {
|
}
|
||||||
JOptionPane.showMessageDialog(new JFrame(), e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE);
|
}
|
||||||
System.out.println(e.getMessage());
|
file.delete();
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
sdk.getFile().delete(); // cleanup
|
public static void downloadDependenciesBeforeSetVisible(JFrame invoker) {
|
||||||
|
invoker.setVisible(false);
|
||||||
return true;
|
Main.downloadDependencies();
|
||||||
}
|
invoker.setVisible(true);
|
||||||
|
confvint = vint;
|
||||||
public static boolean callDownloaderStatically (String url, String folder, String name) {
|
Main.writeConf();
|
||||||
return new Fozzie().DownloadFile(url, folder, name);
|
}
|
||||||
}
|
|
||||||
|
public static boolean downloadDependencies () {
|
||||||
public static Process exec(String[] cmd, String cwd) throws IOException {
|
boolean downloader = new Fozzie().DownloadFile("https://bonkmaykr.worlio.com/http/firestar/fire13.zip", System.getProperty("user.home") + "/.firestar/", "firesdk.zip", "Firestar dependencies");
|
||||||
Process p;
|
if (!downloader) {return false;}
|
||||||
String[] pcmd;
|
|
||||||
if (!Main.windows) {
|
final String expectedMD5Hash = "306807955266724172476879569959042600238"; // Prevent a malicious web server takeover from installing malware on the user's computer.
|
||||||
pcmd = new String[cmd.length + 1];
|
String downloadedMD5Hash = ""; // if this number does not match for ANY reason, cancel immediately and get a programmer.
|
||||||
pcmd[0] = "wine";
|
try {downloadedMD5Hash = new BigInteger(1, MessageDigest.getInstance("MD5").digest(Files.readAllBytes(Paths.get(Main.inpath + "firesdk.zip")))).toString();}
|
||||||
System.arraycopy(cmd, 0, pcmd, 1, cmd.length);
|
catch (Exception e) {
|
||||||
p = Runtime.getRuntime().exec(pcmd, null, new File(cwd));
|
System.out.println("ERROR: Failed to download PSARC tool due to an internal problem.\n" + e.getMessage());
|
||||||
} else {
|
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);
|
||||||
p = Runtime.getRuntime().exec(cmd, null, new File(cwd.replace("/", "\\")));
|
}
|
||||||
|
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/");
|
||||||
|
} catch (ZipException e) {
|
||||||
|
JOptionPane.showMessageDialog(new JFrame(), e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sdk.getFile().delete(); // cleanup
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(null, "All remote dependencies satisfied.", "Download Completed", JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Process exec(String[] cmd, String cwd) throws IOException {
|
||||||
|
Process p;
|
||||||
|
String[] pcmd;
|
||||||
|
if (!Main.windows) {
|
||||||
|
pcmd = new String[cmd.length + 1];
|
||||||
|
pcmd[0] = "wine";
|
||||||
|
System.arraycopy(cmd, 0, pcmd, 1, cmd.length);
|
||||||
|
p = Runtime.getRuntime().exec(pcmd, null, new File(cwd));
|
||||||
|
} else {
|
||||||
|
p = Runtime.getRuntime().exec(cmd, null, new File(cwd.replace("/", "\\")));
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
185
firestar/src/main/java/NaturalOrderComparator.java
Normal file
185
firestar/src/main/java/NaturalOrderComparator.java
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* <copyright>
|
||||||
|
*
|
||||||
|
* Copyright 1997-2007 BBNT Solutions, LLC
|
||||||
|
* under sponsorship of the Defense Advanced Research Projects
|
||||||
|
* Agency (DARPA).
|
||||||
|
*
|
||||||
|
* You can redistribute this software and/or modify it under the
|
||||||
|
* terms of the Cougaar Open Source License as published on the
|
||||||
|
* Cougaar Open Source Website (www.cougaar.org).
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* </copyright>
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
NaturalOrderComparator.java -- Perform 'natural order' comparisons of strings in Java.
|
||||||
|
Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.com>
|
||||||
|
|
||||||
|
Based on the C version by Martin Pool, of which this is more or less a straight conversion.
|
||||||
|
Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//CHANGES: KD - added case sensitive ordering capability
|
||||||
|
// Made comparison so it doesn't treat spaces as special characters
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sorting comparator to sort strings numerically,
|
||||||
|
* ie [1, 2, 10], as opposed to [1, 10, 2].
|
||||||
|
*/
|
||||||
|
public final class NaturalOrderComparator<T> implements Comparator<T> {
|
||||||
|
|
||||||
|
public static final Comparator<String> NUMERICAL_ORDER = new NaturalOrderComparator<String>(false);
|
||||||
|
public static final Comparator<String> CASEINSENSITIVE_NUMERICAL_ORDER = new NaturalOrderComparator<String>(true);
|
||||||
|
|
||||||
|
private final boolean caseInsensitive;
|
||||||
|
|
||||||
|
public NaturalOrderComparator(boolean caseInsensitive) {
|
||||||
|
this.caseInsensitive = caseInsensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareRight(String a, String b) {
|
||||||
|
int bias = 0;
|
||||||
|
int ia = 0;
|
||||||
|
int ib = 0;
|
||||||
|
|
||||||
|
// The longest run of digits wins. That aside, the greatest
|
||||||
|
// value wins, but we can't know that it will until we've scanned
|
||||||
|
// both numbers to know that they have the same magnitude, so we
|
||||||
|
// remember it in BIAS.
|
||||||
|
for (;; ia++, ib++) {
|
||||||
|
char ca = charAt(a, ia);
|
||||||
|
char cb = charAt(b, ib);
|
||||||
|
|
||||||
|
if (!Character.isDigit(ca) && !Character.isDigit(cb)) {
|
||||||
|
return bias;
|
||||||
|
} else if (!Character.isDigit(ca)) {
|
||||||
|
return -1;
|
||||||
|
} else if (!Character.isDigit(cb)) {
|
||||||
|
return +1;
|
||||||
|
} else if (ca < cb) {
|
||||||
|
if (bias == 0) {
|
||||||
|
bias = -1;
|
||||||
|
}
|
||||||
|
} else if (ca > cb) {
|
||||||
|
if (bias == 0)
|
||||||
|
bias = +1;
|
||||||
|
} else if (ca == 0 && cb == 0) {
|
||||||
|
return bias;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compare(T o1, T o2) {
|
||||||
|
String a = o1.toString();
|
||||||
|
String b = o2.toString();
|
||||||
|
|
||||||
|
int ia = 0, ib = 0;
|
||||||
|
int nza = 0, nzb = 0;
|
||||||
|
char ca, cb;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// only count the number of zeroes leading the last number compared
|
||||||
|
nza = nzb = 0;
|
||||||
|
|
||||||
|
ca = charAt(a, ia);
|
||||||
|
cb = charAt(b, ib);
|
||||||
|
|
||||||
|
// skip over leading zeros
|
||||||
|
while (ca == '0') {
|
||||||
|
if (ca == '0') {
|
||||||
|
nza++;
|
||||||
|
} else {
|
||||||
|
// only count consecutive zeroes
|
||||||
|
nza = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the next character isn't a digit, then we've had a run of only zeros
|
||||||
|
// we still need to treat this as a 0 for comparison purposes
|
||||||
|
if (!Character.isDigit(charAt(a, ia+1)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ca = charAt(a, ++ia);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cb == '0') {
|
||||||
|
if (cb == '0') {
|
||||||
|
nzb++;
|
||||||
|
} else {
|
||||||
|
// only count consecutive zeroes
|
||||||
|
nzb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the next character isn't a digit, then we've had a run of only zeros
|
||||||
|
// we still need to treat this as a 0 for comparison purposes
|
||||||
|
if (!Character.isDigit(charAt(b, ib+1)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
cb = charAt(b, ++ib);
|
||||||
|
}
|
||||||
|
|
||||||
|
// process run of digits
|
||||||
|
if (Character.isDigit(ca) && Character.isDigit(cb)) {
|
||||||
|
if ((result = compareRight(a.substring(ia), b
|
||||||
|
.substring(ib))) != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ca == 0 && cb == 0) {
|
||||||
|
// The strings compare the same. Perhaps the caller
|
||||||
|
// will want to call strcmp to break the tie.
|
||||||
|
return nza - nzb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ca < cb) {
|
||||||
|
return -1;
|
||||||
|
} else if (ca > cb) {
|
||||||
|
return +1;
|
||||||
|
}
|
||||||
|
|
||||||
|
++ia;
|
||||||
|
++ib;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private char charAt(String s, int i) {
|
||||||
|
if (i >= s.length()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return caseInsensitive ? Character.toUpperCase(s.charAt(i)) : s.charAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
136
firestar/src/main/java/ReplacingInputStream.java
Normal file
136
firestar/src/main/java/ReplacingInputStream.java
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import java.io.FilterInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Created by simon on 8/29/17.
|
||||||
|
* Copyright 2017 Simon Haoran Liang
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
|
* associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||||
|
* following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||||
|
* portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||||
|
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||||
|
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
public class ReplacingInputStream extends FilterInputStream {
|
||||||
|
|
||||||
|
private Queue<Integer> inQueue, outQueue;
|
||||||
|
private final byte[] search, replacement;
|
||||||
|
private boolean caseSensitive = true;
|
||||||
|
|
||||||
|
public ReplacingInputStream(InputStream in, String search, String replacement) {
|
||||||
|
super(in);
|
||||||
|
|
||||||
|
this.inQueue = new LinkedList<>();
|
||||||
|
this.outQueue = new LinkedList<>();
|
||||||
|
|
||||||
|
this.search = search.getBytes();
|
||||||
|
this.replacement = replacement.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReplacingInputStream(InputStream in, String search, String replacement, boolean caseSensitive) {
|
||||||
|
super(in);
|
||||||
|
|
||||||
|
this.inQueue = new LinkedList<>();
|
||||||
|
this.outQueue = new LinkedList<>();
|
||||||
|
|
||||||
|
this.search = search.getBytes();
|
||||||
|
this.replacement = replacement.getBytes();
|
||||||
|
this.caseSensitive = caseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMatchFound() {
|
||||||
|
Iterator<Integer> iterator = inQueue.iterator();
|
||||||
|
|
||||||
|
for (byte b : search) {
|
||||||
|
if (!iterator.hasNext()) return false;
|
||||||
|
Integer i = iterator.next();
|
||||||
|
if (caseSensitive && b != i) return false;
|
||||||
|
else if (Character.toLowerCase(b) != Character.toLowerCase(i.byteValue())) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readAhead() throws IOException {
|
||||||
|
// Work up some look-ahead.
|
||||||
|
while (inQueue.size() < search.length) {
|
||||||
|
int next = super.read();
|
||||||
|
inQueue.offer(next);
|
||||||
|
|
||||||
|
if (next == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
// Next byte already determined.
|
||||||
|
|
||||||
|
while (outQueue.isEmpty()) {
|
||||||
|
readAhead();
|
||||||
|
|
||||||
|
if (isMatchFound()) {
|
||||||
|
for (byte a : search) {
|
||||||
|
inQueue.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (byte b : replacement) {
|
||||||
|
outQueue.offer((int) b);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outQueue.add(inQueue.remove());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outQueue.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte b[]) throws IOException {
|
||||||
|
return read(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied straight from InputStream inplementation, just needed to to use `read()` from this class
|
||||||
|
@Override
|
||||||
|
public int read(byte b[], int off, int len) throws IOException {
|
||||||
|
if (b == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
} else if (off < 0 || len < 0 || len > b.length - off) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
} else if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int c = read();
|
||||||
|
if (c == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
b[off] = (byte)c;
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
try {
|
||||||
|
for (; i < len ; i++) {
|
||||||
|
c = read();
|
||||||
|
if (c == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
b[off + i] = (byte)c;
|
||||||
|
}
|
||||||
|
} catch (IOException ee) { }
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
459
firestar/src/main/java/Rizzo.java
Normal file
459
firestar/src/main/java/Rizzo.java
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
/*
|
||||||
|
* Firestar Mod Manager
|
||||||
|
* Copyright (C) 2024 bonkmaykr
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.github.difflib.DiffUtils;
|
||||||
|
import com.github.difflib.UnifiedDiffUtils;
|
||||||
|
import com.github.difflib.patch.Patch;
|
||||||
|
import com.github.difflib.patch.PatchFailedException;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HexFormat;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerException;
|
||||||
|
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.*;
|
||||||
|
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;
|
||||||
|
private String workingDir;
|
||||||
|
|
||||||
|
public Rizzo(InputStream infile, String workingDir) throws FileNotFoundException, FirescriptFormatException {
|
||||||
|
if (!workingDir.endsWith("/")) this.workingDir = workingDir + "/";
|
||||||
|
else this.workingDir = workingDir;
|
||||||
|
scanner = new Scanner(infile);
|
||||||
|
parseScript(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseScript(Object context) throws FirescriptFormatException {
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine().trim();
|
||||||
|
if (line.startsWith("#") || line.length() < 1) continue;
|
||||||
|
if (!parseArgs(translateCommandline(line), context)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean parseArgs(String[] args, Object context) throws FirescriptFormatException {
|
||||||
|
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");
|
||||||
|
} else if (args[0].equalsIgnoreCase("file")) {
|
||||||
|
File newCtx = new File(workingDir + args[1]);
|
||||||
|
System.out.println("Calling new parse: " + Arrays.toString(Arrays.copyOfRange(args, 2, args.length)));
|
||||||
|
parseArgs(Arrays.copyOfRange(args, 2, args.length), newCtx);
|
||||||
|
} else throw new FirescriptFormatException("fscript", "command '" + args[0] + "' is unknown or used in inappropriate context");
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
} else if (args[0].equals("}")) {
|
||||||
|
System.out.println("Ending context block: " + context.getClass().getName() + "@" + context.hashCode());
|
||||||
|
return false;
|
||||||
|
} else if (context instanceof File file) {
|
||||||
|
if (file.exists()) {
|
||||||
|
if (args[0].equalsIgnoreCase("delete")) {
|
||||||
|
System.out.println("Deleting: " + file.getPath());
|
||||||
|
if (file.getAbsolutePath().startsWith(workingDir)) {
|
||||||
|
if (file.isDirectory()) Main.deleteDir(file);
|
||||||
|
else file.delete();
|
||||||
|
}
|
||||||
|
} else if (args[0].equalsIgnoreCase("xml")) {
|
||||||
|
try {
|
||||||
|
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", " ");
|
||||||
|
Document doc = docBuilder.parse(ris);
|
||||||
|
parseArgs(Arrays.copyOfRange(args, 1, args.length), doc);
|
||||||
|
try {
|
||||||
|
FileOutputStream output = new FileOutputStream(file);
|
||||||
|
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||||
|
|
||||||
|
StreamResult result = new StreamResult(new StringWriter());
|
||||||
|
DOMSource source = new DOMSource(doc);
|
||||||
|
|
||||||
|
// WipEout 2048 will pretend to be happy with these self-closed tags but in actuality, it is screaming on the inside.
|
||||||
|
transformer.setOutputProperty(OutputKeys.METHOD, "html");
|
||||||
|
transformer.transform(source, result);
|
||||||
|
// Look ma, I'm breaking XML standards!
|
||||||
|
String xmlString = StringEscapeUtils.unescapeHtml4(result.getWriter().toString());
|
||||||
|
try (PrintStream ps = new PrintStream(output)) {
|
||||||
|
ps.print(xmlString);
|
||||||
|
}
|
||||||
|
} catch (TransformerException ex) {
|
||||||
|
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
||||||
|
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, "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 {
|
||||||
|
FileInputStream fis = new FileInputStream(file);
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(fis.readAllBytes());
|
||||||
|
fis.close();
|
||||||
|
FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
if (args[1].equalsIgnoreCase("append")) {
|
||||||
|
bais.transferTo(fos);
|
||||||
|
for (int s = 0; s < args[2].length(); s++) {
|
||||||
|
char c = args[2].charAt(s);
|
||||||
|
fos.write(c);
|
||||||
|
}
|
||||||
|
} else if (args[1].equalsIgnoreCase("replace") || args[1].equalsIgnoreCase("delete")) {
|
||||||
|
String replacement = "";
|
||||||
|
if (args[1].equalsIgnoreCase("replace")) replacement = args[3];
|
||||||
|
ReplacingInputStream ris;
|
||||||
|
if (args[0].equalsIgnoreCase("xstr")) ris = new ReplacingInputStream(bais, args[2], replacement, false);
|
||||||
|
else ris = new ReplacingInputStream(bais, args[2], replacement);
|
||||||
|
ris.transferTo(fos);
|
||||||
|
ris.close();
|
||||||
|
}
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
} else if (args[0].equalsIgnoreCase("binedit")) {
|
||||||
|
int offset = Integer.parseInt(args[1]);
|
||||||
|
String bytes = args[2];
|
||||||
|
if (bytes.length() % 2 != 0) throw new FirescriptFormatException(args[0], "invalid length of bytes");
|
||||||
|
try {
|
||||||
|
byte[] ba;
|
||||||
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
|
ba = fis.readAllBytes();
|
||||||
|
}
|
||||||
|
if (offset >= ba.length) throw new FirescriptFormatException(args[0], "offset is larger than file size");
|
||||||
|
else {
|
||||||
|
byte[] in = HexFormat.of().parseHex(bytes);
|
||||||
|
System.arraycopy(in, 0, ba, offset, in.length);
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(file)) {
|
||||||
|
fos.write(ba);
|
||||||
|
fos.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
} else if (args[0].equalsIgnoreCase("patch")) {
|
||||||
|
try {
|
||||||
|
List<String> original = Files.readAllLines(file.toPath());
|
||||||
|
File patchFile = new File(workingDir + args[1]);
|
||||||
|
if (!patchFile.exists()) throw new FirescriptFormatException(args[0], "patch file doesn't exist");
|
||||||
|
List<String> patched = Files.readAllLines(patchFile.toPath());
|
||||||
|
|
||||||
|
Patch<String> patch = UnifiedDiffUtils.parseUnifiedDiff(patched);
|
||||||
|
List<String> result = DiffUtils.patch(original, patch);
|
||||||
|
|
||||||
|
try (FileWriter fileWriter = new FileWriter(file)) {
|
||||||
|
for (String str : result) {
|
||||||
|
fileWriter.write(str + "\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (FirescriptFormatException | PatchFailedException | IOException ex) {
|
||||||
|
Logger.getLogger(Rizzo.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
} 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 (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.");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
} 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"))
|
||||||
|
// We replace newlines on XML write.
|
||||||
|
element.setAttribute(args[2], args[3].replace("\\n", " "));
|
||||||
|
else if (args[1].equalsIgnoreCase("value"))
|
||||||
|
element.setNodeValue(args[2]);
|
||||||
|
} else if (args[0].equalsIgnoreCase("create")) {
|
||||||
|
String finalTag = args[1];
|
||||||
|
String path = "";
|
||||||
|
if (finalTag.lastIndexOf(".") > 0) {
|
||||||
|
path = args[1].substring(0, finalTag.lastIndexOf("."));
|
||||||
|
finalTag = args[1].substring(finalTag.lastIndexOf(".")+1);
|
||||||
|
}
|
||||||
|
String id = "";
|
||||||
|
String name = "";
|
||||||
|
if (finalTag.contains("#")) {
|
||||||
|
id = finalTag.substring(finalTag.indexOf("#")+1);
|
||||||
|
finalTag = finalTag.substring(0, finalTag.indexOf("#"));
|
||||||
|
} else if (finalTag.contains("$")) {
|
||||||
|
name = finalTag.substring(finalTag.indexOf("$")+1);
|
||||||
|
finalTag = finalTag.substring(0, finalTag.indexOf("$"));
|
||||||
|
}
|
||||||
|
Element finalElem = element.getOwnerDocument().createElement(finalTag);
|
||||||
|
if (id != null && id.length() > 0) finalElem.setAttribute("id", id);
|
||||||
|
if (name != null && name.length() > 0) finalElem.setAttribute("name", name);
|
||||||
|
traverse(element, path).appendChild(finalElem);
|
||||||
|
parseArgs(Arrays.copyOfRange(args, 2, args.length), finalElem);
|
||||||
|
} else if (args[0].equalsIgnoreCase("create-at")) {
|
||||||
|
int index = Integer.parseInt(args[1]);
|
||||||
|
String finalTag = args[2];
|
||||||
|
String id = "";
|
||||||
|
String name = "";
|
||||||
|
if (finalTag.contains("#")) {
|
||||||
|
id = finalTag.substring(finalTag.indexOf("#")+1);
|
||||||
|
finalTag = finalTag.substring(0, finalTag.indexOf("#"));
|
||||||
|
} else if (finalTag.contains("$")) {
|
||||||
|
name = finalTag.substring(finalTag.indexOf("$")+1);
|
||||||
|
finalTag = finalTag.substring(0, finalTag.indexOf("$"));
|
||||||
|
}
|
||||||
|
Element finalElem = element.getOwnerDocument().createElement(finalTag);
|
||||||
|
if (id != null && id.length() > 0) finalElem.setAttribute("id", id);
|
||||||
|
if (name != null && name.length() > 0) finalElem.setAttribute("name", name);
|
||||||
|
element.insertBefore(finalElem, element.getChildNodes().item(index));
|
||||||
|
parseArgs(Arrays.copyOfRange(args, 3, args.length), finalElem);
|
||||||
|
} else throw new FirescriptFormatException("xml", "unknown element command '" + args[0] + "'");
|
||||||
|
} else throw new FirescriptFormatException("context is unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node traverse(Node owner, String selector) throws FirescriptFormatException {
|
||||||
|
if (selector == null || selector.length() == 0 || owner == null) {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
String[] elems = selector.split("\\.");
|
||||||
|
Node parent = owner;
|
||||||
|
for (String tag : elems) {
|
||||||
|
Node newParent = null;
|
||||||
|
int index = 0;
|
||||||
|
if (tag.contains("[")) {
|
||||||
|
index = Integer.parseInt(tag.substring(tag.indexOf("[")+1, tag.lastIndexOf("]")));
|
||||||
|
tag = tag.substring(0, tag.indexOf("["));
|
||||||
|
}
|
||||||
|
|
||||||
|
String id = "";
|
||||||
|
if (tag.contains("#")) {
|
||||||
|
id = tag.substring(tag.indexOf("#")+1);
|
||||||
|
tag = tag.substring(0, tag.indexOf("#"));
|
||||||
|
}
|
||||||
|
String name = "";
|
||||||
|
if (tag.contains("$")) {
|
||||||
|
name = tag.substring(tag.indexOf("$")+1);
|
||||||
|
tag = tag.substring(0, tag.indexOf("$"));
|
||||||
|
}
|
||||||
|
if (id.length() > 0) {
|
||||||
|
NodeList ns;
|
||||||
|
if (parent instanceof Document document)
|
||||||
|
ns = document.getElementsByTagName(tag);
|
||||||
|
else
|
||||||
|
ns = ((Element)parent).getElementsByTagName(tag);
|
||||||
|
for (int i = 0; i < ns.getLength(); i++) {
|
||||||
|
Node n = ns.item(i);
|
||||||
|
if (n.getNodeName().equals("#text")) continue;
|
||||||
|
if (((Element)n).getAttribute("id").equals(id)) {
|
||||||
|
newParent = (Element)n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (name.length() > 0) {
|
||||||
|
NodeList ns;
|
||||||
|
if (parent instanceof Document document)
|
||||||
|
ns = document.getChildNodes();
|
||||||
|
else
|
||||||
|
ns = ((Element)parent).getChildNodes();
|
||||||
|
for (int i = 0; i < ns.getLength(); i++) {
|
||||||
|
Node n = ns.item(i);
|
||||||
|
if (n instanceof Comment) continue;
|
||||||
|
if (n.getNodeName().equals("#text")) continue;
|
||||||
|
if (((Element)n).getAttribute("name").equals(name)) {
|
||||||
|
newParent = (Element)n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (parent instanceof Document document)
|
||||||
|
newParent = document.getElementsByTagName(tag).item(index);
|
||||||
|
else
|
||||||
|
newParent = ((Element)parent).getElementsByTagName(tag).item(index);
|
||||||
|
}
|
||||||
|
if (newParent == null) throw new FirescriptFormatException("xml: selector is invalid");
|
||||||
|
else parent = newParent;
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] translateCommandline(String line) throws FirescriptFormatException {
|
||||||
|
if (line == null || line.length() == 0) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
final int normal = 0;
|
||||||
|
final int inQuote = 1;
|
||||||
|
final int inDoubleQuote = 2;
|
||||||
|
int state = normal;
|
||||||
|
final ArrayList<String> result = new ArrayList<String>();
|
||||||
|
final StringBuilder current = new StringBuilder();
|
||||||
|
boolean lastTokenHasBeenQuoted = false;
|
||||||
|
boolean lastTokenWasEscaped = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < line.length(); i++) {
|
||||||
|
char nextTok = line.charAt(i);
|
||||||
|
switch (state) {
|
||||||
|
case inQuote -> {
|
||||||
|
if (nextTok == '\\') {
|
||||||
|
lastTokenWasEscaped = true;
|
||||||
|
} else if (nextTok == '\'' && !lastTokenWasEscaped) {
|
||||||
|
lastTokenHasBeenQuoted = true;
|
||||||
|
state = normal;
|
||||||
|
} else {
|
||||||
|
if (lastTokenWasEscaped) {
|
||||||
|
if (nextTok == 't') nextTok = '\t';
|
||||||
|
if (nextTok == 'b') nextTok = '\b';
|
||||||
|
if (nextTok == 'n') nextTok = '\n';
|
||||||
|
if (nextTok == 'r') nextTok = '\r';
|
||||||
|
if (nextTok == 'f') nextTok = '\f';
|
||||||
|
}
|
||||||
|
current.append(nextTok);
|
||||||
|
lastTokenWasEscaped = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case inDoubleQuote -> {
|
||||||
|
if (nextTok == '\\') {
|
||||||
|
lastTokenWasEscaped = true;
|
||||||
|
} else if (nextTok == '\"' && !lastTokenWasEscaped) {
|
||||||
|
lastTokenHasBeenQuoted = true;
|
||||||
|
state = normal;
|
||||||
|
} else {
|
||||||
|
if (lastTokenWasEscaped) {
|
||||||
|
if (nextTok == 't') nextTok = '\t';
|
||||||
|
if (nextTok == 'b') nextTok = '\b';
|
||||||
|
if (nextTok == 'n') nextTok = '\n';
|
||||||
|
if (nextTok == 'r') nextTok = '\r';
|
||||||
|
if (nextTok == 'f') nextTok = '\f';
|
||||||
|
}
|
||||||
|
current.append(nextTok);
|
||||||
|
lastTokenWasEscaped = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
switch (nextTok) {
|
||||||
|
case '\\' -> lastTokenWasEscaped = true;
|
||||||
|
case '\'' -> state = inQuote;
|
||||||
|
case '\"' -> state = inDoubleQuote;
|
||||||
|
case ' ' -> {
|
||||||
|
if (!lastTokenWasEscaped && (lastTokenHasBeenQuoted || current.length() != 0)) {
|
||||||
|
result.add(current.toString());
|
||||||
|
current.setLength(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
if (lastTokenWasEscaped) {
|
||||||
|
if (nextTok == 't') nextTok = '\t';
|
||||||
|
if (nextTok == 'b') nextTok = '\b';
|
||||||
|
if (nextTok == 'n') nextTok = '\n';
|
||||||
|
if (nextTok == 'r') nextTok = '\r';
|
||||||
|
if (nextTok == 'f') nextTok = '\f';
|
||||||
|
lastTokenWasEscaped = false;
|
||||||
|
}
|
||||||
|
current.append(nextTok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastTokenHasBeenQuoted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastTokenHasBeenQuoted || current.length() != 0) {
|
||||||
|
result.add(current.toString());
|
||||||
|
}
|
||||||
|
if (state == inQuote || state == inDoubleQuote) {
|
||||||
|
throw new FirescriptFormatException("unbalanced quotes in " + line);
|
||||||
|
}
|
||||||
|
return result.toArray(new String[result.size()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,64 +19,57 @@
|
|||||||
import javax.imageio.*;
|
import javax.imageio.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
|
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
|
||||||
|
|
||||||
public class Rowlf {
|
public class Rowlf {
|
||||||
private BufferedImage windowIcon;
|
JFrame frame = new JFrame();
|
||||||
JFrame frame = new JFrame();
|
JPanel frameContainer;
|
||||||
JPanel frameContainer;
|
Image logo;
|
||||||
Image logo;
|
JLabel picLabel;
|
||||||
JLabel picLabel;
|
private JTextField informationText;
|
||||||
private JTextField informationText;
|
private JLabel versionLabel;
|
||||||
private JLabel versionLabel;
|
private JLabel environmentLabel;
|
||||||
private JLabel environmentLabel;
|
|
||||||
|
|
||||||
public Rowlf(JFrame parent) {
|
public Rowlf(JFrame parent) {
|
||||||
try {
|
try {
|
||||||
logo = ImageIO.read(Main.class.getResourceAsStream("/logo.png")).getScaledInstance(333, 100, Image.SCALE_SMOOTH);
|
logo = ImageIO.read(Main.class.getResourceAsStream("/logo.png")).getScaledInstance(333, 100, Image.SCALE_SMOOTH);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("ERROR: Failed to open About screen because we couldn't find an image needed to display the page.");
|
System.out.println("ERROR: Failed to open About screen because we couldn't find an image needed to display the page.");
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
try {
|
frame.setIconImage(Main.windowIcon);
|
||||||
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
|
||||||
frame.setIconImage(windowIcon);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//frame.add(picLabel);
|
//frame.add(picLabel);
|
||||||
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
||||||
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
||||||
|
|
||||||
informationText.getDocument().putProperty("filterNewlines", Boolean.FALSE);
|
informationText.getDocument().putProperty("filterNewlines", Boolean.FALSE);
|
||||||
informationText.setHorizontalAlignment(JTextField.CENTER);
|
informationText.setHorizontalAlignment(JTextField.CENTER);
|
||||||
informationText.setText("Created by bonkmaykr, a.k.a. \"Downforce Agent\"\n" +
|
informationText.setText("Created by bonkmaykr & Wirlaburla\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"Special thanks to:\n" +
|
"Special thanks to:\n" +
|
||||||
"ThatOneBonk, for Thallium and for modding help\n" +
|
"ThatOneBonk, ChaCheeChoo, and the AGRF community\n" +
|
||||||
"Wirlaburla, for web hosting and code assistance\n" +
|
"Psygnosis / Studio Liverpool, SCE Europe\n" +
|
||||||
"Psygnosis, for making our favorite game ever\n" +
|
"Yifan Lu & FailOverflow, TheRadziu, NoPayStation\n" +
|
||||||
"and to all the PSVita hackers who made this possible");
|
"and to all the PSVita hackers who made this possible");
|
||||||
informationText.setHighlighter(null);
|
informationText.setHighlighter(null);
|
||||||
informationText.getCaret().setVisible(false);
|
informationText.getCaret().setVisible(false);
|
||||||
informationText.setFocusable(false);
|
informationText.setFocusable(false);
|
||||||
|
|
||||||
versionLabel.setText("Version " + Main.vstr + " (" + Main.vcode + ")");
|
versionLabel.setText(Main.vstr + " (" + Main.vcode + ")");
|
||||||
environmentLabel.setText("Running on Java " + System.getProperty("java.version") + " for " + System.getProperty("os.name"));
|
//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
|
// display window
|
||||||
frame.setSize(400, 320);
|
frame.setSize(400, 320);
|
||||||
frame.setTitle("About Firestar");
|
frame.setTitle("About Firestar");
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setAlwaysOnTop(true);
|
frame.setAlwaysOnTop(true);
|
||||||
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||||
frame.setLayout(new GridLayout());
|
frame.setLayout(new GridLayout());
|
||||||
frame.setLocationRelativeTo(parent);
|
frame.setLocationRelativeTo(parent);
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<borderPainted value="false"/>
|
<borderPainted value="false"/>
|
||||||
<foreground color="-2271221"/>
|
<foreground color="-2271221"/>
|
||||||
<indeterminate value="false"/>
|
<indeterminate value="false"/>
|
||||||
<stringPainted value="true"/>
|
<stringPainted value="false"/>
|
||||||
<value value="0"/>
|
<value value="0"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -16,64 +16,61 @@
|
|||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
public class Scooter {
|
public class Scooter {
|
||||||
private JFrame frame = new JFrame();
|
private JFrame frame = new JFrame();
|
||||||
public JProgressBar progressBar;
|
public JProgressBar progressBar;
|
||||||
private JPanel frameContainer;
|
private JPanel frameContainer;
|
||||||
private JLabel label;
|
private JLabel label;
|
||||||
|
|
||||||
public void showDialog(String title) {
|
public void showDialog(String title) {
|
||||||
frame.add(frameContainer);
|
frame.add(frameContainer);
|
||||||
frame.setSize(300, 100);
|
frame.setSize(300, 100);
|
||||||
frame.setTitle(title);
|
frame.setTitle(title);
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
frame.setLayout(new GridLayout());
|
frame.setLayout(new GridLayout());
|
||||||
frame.setLocationRelativeTo(null);
|
frame.setLocationRelativeTo(null);
|
||||||
frame.setAlwaysOnTop(true);
|
frame.setAlwaysOnTop(true);
|
||||||
frame.setIconImage(Main.windowIcon);
|
frame.setIconImage(Main.windowIcon);
|
||||||
|
|
||||||
progressBar.setStringPainted(true);
|
progressBar.setStringPainted(true);
|
||||||
|
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgressMin(int i) {
|
public void setProgressMin(int i) {
|
||||||
progressBar.setMinimum(i);
|
progressBar.setMinimum(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgressValue(int i) {
|
public void setProgressValue(int i) {
|
||||||
progressBar.setValue(i);
|
progressBar.setValue(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgressMax(int i) {
|
public void setProgressMax(int i) {
|
||||||
progressBar.setMaximum(i);
|
progressBar.setMaximum(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getProgressMin() {
|
public int getProgressMin() {
|
||||||
return progressBar.getMinimum();
|
return progressBar.getMinimum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getProgressValue() {
|
public int getProgressValue() {
|
||||||
return progressBar.getValue();
|
return progressBar.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getProgressMax() {
|
public int getProgressMax() {
|
||||||
return progressBar.getMaximum();
|
return progressBar.getMaximum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setText(String text) {
|
public void setText(String text) {
|
||||||
label.setText(text);
|
label.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroyDialog() {
|
public void destroyDialog() {
|
||||||
frame.setVisible(false);
|
frame.setVisible(false);
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<grid id="27dc6" binding="frameContainer" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27dc6" binding="frameContainer" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="10" left="10" bottom="10" right="10"/>
|
<margin top="10" left="10" bottom="10" right="10"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<xy x="20" y="20" width="756" height="460"/>
|
<xy x="20" y="20" width="771" height="460"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<background color="-15128227"/>
|
<background color="-15128227"/>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</scrollpane>
|
</scrollpane>
|
||||||
<grid id="eb54e" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="eb54e" 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"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="4" column="1" row-span="1" col-span="1" 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="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<children>
|
<children>
|
||||||
<component id="adce7" class="javax.swing.JButton" binding="cancelBtn">
|
<component id="adce7" class="javax.swing.JButton" binding="cancelBtn">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<background color="-2271221"/>
|
<background color="-2271221"/>
|
||||||
@@ -67,25 +67,27 @@
|
|||||||
</component>
|
</component>
|
||||||
<hspacer id="8ecbf">
|
<hspacer id="8ecbf">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="0" row-span="2" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="0" row-span="3" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</hspacer>
|
</hspacer>
|
||||||
<component id="b6c2f" class="javax.swing.JCheckBox" binding="checkAdditive">
|
<component id="b6c2f" class="javax.swing.JCheckBox" binding="checkAdditive">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<enabled value="false"/>
|
<enabled value="false"/>
|
||||||
|
<focusPainted value="false"/>
|
||||||
<font name="Exo 2"/>
|
<font name="Exo 2"/>
|
||||||
<foreground color="-1"/>
|
<foreground color="-1"/>
|
||||||
<opaque value="false"/>
|
<opaque value="false"/>
|
||||||
<text value="Append to default playlist"/>
|
<text value="Append to default playlist"/>
|
||||||
|
<toolTipText value="Check this box to add your playlist to the existing in-game one instead of overwriting it."/>
|
||||||
<visible value="false"/>
|
<visible value="false"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="a7b02" class="javax.swing.JButton" binding="saveBtn">
|
<component id="a7b02" class="javax.swing.JButton" binding="saveBtn">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="2" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<background color="-2271221"/>
|
<background color="-2271221"/>
|
||||||
@@ -96,6 +98,21 @@
|
|||||||
<text value="Save"/>
|
<text value="Save"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
|
<component id="2252b" class="javax.swing.JCheckBox" binding="checkNormalize">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="10" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<enabled value="true"/>
|
||||||
|
<focusPainted value="false"/>
|
||||||
|
<font name="Exo 2"/>
|
||||||
|
<foreground color="-1"/>
|
||||||
|
<opaque value="false"/>
|
||||||
|
<text value="Normalize Volumes"/>
|
||||||
|
<toolTipText value="Prevents sound effects from drowning out the music, but may reduce sound quality. This process is SKIPPED for ATRAC9 files since they are never transcoded!"/>
|
||||||
|
<visible value="true"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
<grid id="cc2" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="cc2" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
@@ -125,7 +142,9 @@
|
|||||||
<preferred-size width="150" height="-1"/>
|
<preferred-size width="150" height="-1"/>
|
||||||
</grid>
|
</grid>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties/>
|
<properties>
|
||||||
|
<disabledTextColor color="-10124141"/>
|
||||||
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="f7802" class="javax.swing.JLabel">
|
<component id="f7802" class="javax.swing.JLabel">
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -143,7 +162,9 @@
|
|||||||
<preferred-size width="150" height="-1"/>
|
<preferred-size width="150" height="-1"/>
|
||||||
</grid>
|
</grid>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties/>
|
<properties>
|
||||||
|
<disabledTextColor color="-10124141"/>
|
||||||
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<grid id="27515" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27515" 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"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
@@ -183,7 +204,9 @@
|
|||||||
<grid id="568f5" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="568f5" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||||
|
<maximum-size width="600" height="-1"/>
|
||||||
|
</grid>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<opaque value="false"/>
|
<opaque value="false"/>
|
||||||
@@ -287,7 +310,7 @@
|
|||||||
<color color="-1"/>
|
<color color="-1"/>
|
||||||
</border>
|
</border>
|
||||||
<children>
|
<children>
|
||||||
<grid id="6168c" layout-manager="GridLayoutManager" row-count="7" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="6168c" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<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"/>
|
<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"/>
|
||||||
@@ -309,7 +332,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component id="74c7a" class="javax.swing.JLabel">
|
<component id="74c7a" class="javax.swing.JLabel">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<font name="Exo 2"/>
|
<font name="Exo 2"/>
|
||||||
@@ -319,7 +342,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component id="1fda4" class="javax.swing.JLabel" binding="dSTitle">
|
<component id="1fda4" class="javax.swing.JLabel" binding="dSTitle">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<font name="Exo 2" style="2"/>
|
<font name="Exo 2" style="2"/>
|
||||||
@@ -329,7 +352,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component id="99b42" class="javax.swing.JLabel" binding="dMTitle">
|
<component id="99b42" class="javax.swing.JLabel" binding="dMTitle">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="5" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<font name="Exo 2" style="2"/>
|
<font name="Exo 2" style="2"/>
|
||||||
@@ -337,9 +360,9 @@
|
|||||||
<text value="no track"/>
|
<text value="no track"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="c11e8" class="javax.swing.JLabel" binding="dSSize">
|
<component id="c11e8" class="javax.swing.JLabel" binding="dSSize">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<font name="Exo 2" style="2"/>
|
<font name="Exo 2" style="2"/>
|
||||||
@@ -347,9 +370,9 @@
|
|||||||
<text value="no size"/>
|
<text value="no size"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="8480f" class="javax.swing.JLabel" binding="dMSize">
|
<component id="8480f" class="javax.swing.JLabel" binding="dMSize">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="6" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<font name="Exo 2" style="2"/>
|
<font name="Exo 2" style="2"/>
|
||||||
@@ -359,9 +382,35 @@
|
|||||||
</component>
|
</component>
|
||||||
<vspacer id="73ce0">
|
<vspacer id="73ce0">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
<grid row="3" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="1" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</vspacer>
|
</vspacer>
|
||||||
|
<component id="6ab1b" class="javax.swing.JButton" binding="spDeleteBtn">
|
||||||
|
<constraints>
|
||||||
|
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="1" hsize-policy="1" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<background color="-2271221"/>
|
||||||
|
<borderPainted value="false"/>
|
||||||
|
<focusPainted value="false"/>
|
||||||
|
<foreground color="-1"/>
|
||||||
|
<text value="Remove"/>
|
||||||
|
<visible value="false"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="9d8a0" class="javax.swing.JButton" binding="mpDeleteBtn">
|
||||||
|
<constraints>
|
||||||
|
<grid row="4" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="1" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<background color="-2271221"/>
|
||||||
|
<borderPainted value="false"/>
|
||||||
|
<focusPainted value="false"/>
|
||||||
|
<foreground color="-1"/>
|
||||||
|
<text value="Remove"/>
|
||||||
|
<visible value="false"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -26,9 +28,7 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
@@ -48,348 +48,588 @@ import javax.xml.transform.dom.DOMSource;
|
|||||||
import javax.xml.transform.stream.StreamResult;
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
|
||||||
public class Suggs implements ActionListener, ListSelectionListener {
|
public class Suggs implements ActionListener, ListSelectionListener {
|
||||||
public JFrame frame = new JFrame();
|
public JFrame frame = new JFrame();
|
||||||
private JPanel frameContainer;
|
private JPanel frameContainer;
|
||||||
private JList dSongList;
|
private JList dSongList;
|
||||||
private JButton moveDownBtn;
|
private JButton moveDownBtn;
|
||||||
private JButton saveBtn;
|
private JButton saveBtn;
|
||||||
private JButton cancelBtn;
|
private JButton cancelBtn;
|
||||||
private JTextField fTitle;
|
private JTextField fTitle;
|
||||||
private JTextField fArtist;
|
private JTextField fArtist;
|
||||||
private JLabel dTrackNo;
|
private JLabel dTrackNo;
|
||||||
private JLabel dFileSize;
|
private JLabel dFileSize;
|
||||||
private JButton frontendDemoChooseBtn;
|
private JButton frontendDemoChooseBtn;
|
||||||
private JButton frontendMainChooseBtn;
|
private JButton frontendMainChooseBtn;
|
||||||
private JButton deleteSongBtn;
|
private JButton deleteSongBtn;
|
||||||
private JButton addSongBtn;
|
private JButton addSongBtn;
|
||||||
private JButton moveUpBtn;
|
private JButton moveUpBtn;
|
||||||
private JLabel dSTitle;
|
private JLabel dSTitle;
|
||||||
private JLabel dMTitle;
|
private JLabel dMTitle;
|
||||||
private JLabel dSSize;
|
private JLabel dSSize;
|
||||||
private JLabel dMSize;
|
private JLabel dMSize;
|
||||||
private JCheckBox checkAdditive;
|
private JCheckBox checkAdditive;
|
||||||
private Scooter progressDialog;
|
private JButton spDeleteBtn;
|
||||||
|
private JButton mpDeleteBtn;
|
||||||
|
private JCheckBox checkNormalize;
|
||||||
|
private Scooter progressDialog;
|
||||||
|
|
||||||
JFrame parent;
|
JFrame parent;
|
||||||
int curIndex = -1;
|
int curIndex = -1;
|
||||||
|
boolean normalizeVolumes = false;
|
||||||
|
|
||||||
public class AudioTrack {
|
public class AudioTrack {
|
||||||
public File path; // file name
|
public File path; // file name
|
||||||
public String title; // audio title
|
public String title; // audio title
|
||||||
public String artist; // audio artist
|
public String artist; // audio artist
|
||||||
public long size; // file size in bytes
|
public long size; // file size in bytes
|
||||||
public boolean noConvert;
|
public boolean noConvert;
|
||||||
}
|
|
||||||
private static List<AudioTrack> tracklist = new ArrayList<AudioTrack>();
|
|
||||||
private File sptrack;
|
|
||||||
private File mptrack;
|
|
||||||
|
|
||||||
public Suggs(JFrame parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
parent.setEnabled(false);
|
|
||||||
|
|
||||||
frame.setIconImage(Main.windowIcon);
|
|
||||||
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
|
||||||
|
|
||||||
frame.setSize(700, 400);
|
|
||||||
frame.setMinimumSize(new Dimension(650,280));
|
|
||||||
frame.setTitle("Soundtrack Mod Generator");
|
|
||||||
frame.setResizable(true);
|
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
|
||||||
frame.setLayout(new GridLayout());
|
|
||||||
frame.setLocationRelativeTo(parent);
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
|
|
||||||
cancelBtn.addActionListener(this); // TODO: put warning dialog "Are you sure? All unsaved changes will be lost."
|
|
||||||
saveBtn.addActionListener(this);
|
|
||||||
addSongBtn.addActionListener(this); // file picker
|
|
||||||
deleteSongBtn.addActionListener(this); // delete from list
|
|
||||||
moveUpBtn.addActionListener(this);
|
|
||||||
moveDownBtn.addActionListener(this);
|
|
||||||
fTitle.addActionListener(this); // automatically change selected item when changed &
|
|
||||||
fArtist.addActionListener(this); // also update field when new item selected
|
|
||||||
frontendMainChooseBtn.addActionListener(this); // file picker for singleplayer campaign grid music
|
|
||||||
frontendDemoChooseBtn.addActionListener(this); // file picker for multiplayer lobby music
|
|
||||||
dSongList.addListSelectionListener(this);
|
|
||||||
|
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
|
||||||
@Override
|
|
||||||
public void windowClosing(WindowEvent e)
|
|
||||||
{// TODO: put warning dialog "Are you sure? All unsaved changes will be lost."
|
|
||||||
parent.setEnabled(true);
|
|
||||||
e.getWindow().dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
frame.setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void haveSeggs() { // kill yourself
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
|
||||||
if (actionEvent.getSource() == cancelBtn) {
|
|
||||||
parent.setEnabled(true);
|
|
||||||
frame.dispose();
|
|
||||||
} else
|
|
||||||
if (actionEvent.getSource() == fTitle || actionEvent.getSource() == fArtist) {
|
|
||||||
tracklist.get(curIndex).title = fTitle.getText();
|
|
||||||
tracklist.get(curIndex).artist = fArtist.getText();
|
|
||||||
InitializeSongListInGUI();
|
|
||||||
dSongList.setSelectedIndex(curIndex);
|
|
||||||
} else
|
|
||||||
if (actionEvent.getSource() == addSongBtn) {addSong();} else
|
|
||||||
if (actionEvent.getSource() == deleteSongBtn) {remove(curIndex);} else
|
|
||||||
if (actionEvent.getSource() == moveUpBtn) {moveUp(curIndex);} else
|
|
||||||
if (actionEvent.getSource() == moveDownBtn) {moveDown(curIndex);} else
|
|
||||||
if (actionEvent.getSource() == frontendMainChooseBtn) {setSPMusic();} else
|
|
||||||
if (actionEvent.getSource() == frontendDemoChooseBtn) {setMPMusic();} else
|
|
||||||
if (actionEvent.getSource() == saveBtn) {save();}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void valueChanged(ListSelectionEvent listSelectionEvent) {
|
|
||||||
curIndex = dSongList.getSelectedIndex();
|
|
||||||
if (curIndex >= 0) {
|
|
||||||
AudioTrack at = tracklist.get(curIndex);
|
|
||||||
fTitle.setText(at.title);
|
|
||||||
fArtist.setText(at.artist);
|
|
||||||
dTrackNo.setText(String.format("MT_%02d", curIndex));
|
|
||||||
dFileSize.setText((at.size / 1000) + "kb");
|
|
||||||
} else {
|
|
||||||
fTitle.setText("");
|
|
||||||
fArtist.setText("");
|
|
||||||
dTrackNo.setText("--");
|
|
||||||
dFileSize.setText("-kb");
|
|
||||||
}
|
}
|
||||||
}
|
private List<AudioTrack> tracklist = new ArrayList<AudioTrack>();
|
||||||
|
private File sptrack;
|
||||||
|
private File mptrack;
|
||||||
|
|
||||||
private void remove(int index) {
|
DocumentListener id3TagEditorHandler = new DocumentListener() {
|
||||||
if (index >= 0) {
|
@Override
|
||||||
tracklist.remove(index);
|
public void insertUpdate(DocumentEvent documentEvent) {
|
||||||
InitializeSongListInGUI();
|
updateSelectionToMatchTextFields();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moveUp(int index) {
|
|
||||||
if (index > 0) {
|
|
||||||
Collections.swap(tracklist, index, index - 1);
|
|
||||||
InitializeSongListInGUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moveDown(int index) {
|
|
||||||
if (index < (tracklist.size() - 1)) {
|
|
||||||
Collections.swap(tracklist, index, index + 1);
|
|
||||||
InitializeSongListInGUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeSongListInGUI() {
|
|
||||||
dSongList.clearSelection();
|
|
||||||
dSongList.removeAll();
|
|
||||||
dSongList.setVisibleRowCount(tracklist.size());
|
|
||||||
dSongList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
||||||
|
|
||||||
// add text entry for each
|
|
||||||
int i = 0;
|
|
||||||
String[] contents = new String[tracklist.size()];
|
|
||||||
while (i < tracklist.size()) {
|
|
||||||
if (tracklist.get(i).title == null || tracklist.get(i).title.isEmpty())
|
|
||||||
{tracklist.get(i).title = tracklist.get(i).path.getName();}
|
|
||||||
if (tracklist.get(i).artist == null || tracklist.get(i).artist.isEmpty())
|
|
||||||
{tracklist.get(i).artist = "???";}
|
|
||||||
contents[i] = tracklist.get(i).artist + " - " + tracklist.get(i).title;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
dSongList.setListData(contents);
|
|
||||||
dSongList.setSelectedIndex(curIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSPMusic() {
|
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
|
||||||
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
|
|
||||||
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("WAVE", "wav"));
|
|
||||||
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("ATRAC9", "at9"));
|
|
||||||
|
|
||||||
int result = fileChooser.showOpenDialog(frame);
|
|
||||||
if (result == JFileChooser.APPROVE_OPTION) {
|
|
||||||
File selectedFile = fileChooser.getSelectedFile();
|
|
||||||
sptrack = selectedFile;
|
|
||||||
dSTitle.setText(selectedFile.getName());
|
|
||||||
dSSize.setText((selectedFile.length() / 1000) + "kb");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setMPMusic() {
|
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
|
||||||
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
|
|
||||||
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("WAVE", "wav"));
|
|
||||||
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("ATRAC9", "at9"));
|
|
||||||
|
|
||||||
int result = fileChooser.showOpenDialog(frame);
|
|
||||||
if (result == JFileChooser.APPROVE_OPTION) {
|
|
||||||
File selectedFile = fileChooser.getSelectedFile();
|
|
||||||
mptrack = selectedFile;
|
|
||||||
dMTitle.setText(selectedFile.getName());
|
|
||||||
dMSize.setText((selectedFile.length() / 1000) + "kb");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addSong() {
|
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
|
||||||
fileChooser.setMultiSelectionEnabled(true);
|
|
||||||
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
|
|
||||||
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("WAVE", "wav"));
|
|
||||||
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("ATRAC9", "at9"));
|
|
||||||
|
|
||||||
int result = fileChooser.showOpenDialog(frame);
|
|
||||||
if (result == JFileChooser.APPROVE_OPTION) {
|
|
||||||
File[] selectedFiles = fileChooser.getSelectedFiles();
|
|
||||||
for (File f : selectedFiles) {
|
|
||||||
if (f.exists()) {
|
|
||||||
System.out.println("Importing audio file \"" + f.getName() + "\"");
|
|
||||||
AudioTrack track = new AudioTrack();
|
|
||||||
track.path = f;
|
|
||||||
String fname = f.getName();
|
|
||||||
if (fname.contains(" - ")) {
|
|
||||||
track.title = fname.substring(fname.indexOf(" - ")+3, fname.lastIndexOf("."));
|
|
||||||
track.artist = fname.substring(0, fname.indexOf(" - "));
|
|
||||||
} else track.title = fname;
|
|
||||||
track.size = f.length();
|
|
||||||
tracklist.add(track);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
InitializeSongListInGUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void save() {
|
@Override
|
||||||
frame.setEnabled(false);
|
public void removeUpdate(DocumentEvent documentEvent) {
|
||||||
frame.setAlwaysOnTop(false);
|
updateSelectionToMatchTextFields();
|
||||||
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/")); // starts with clean temp
|
}
|
||||||
new Thread(() -> {
|
|
||||||
int progressSize = tracklist.size()+(sptrack != null?1:0)+(mptrack != null?1:0)+3; // Accounting for processes
|
|
||||||
|
|
||||||
progressDialog = new Scooter();
|
@Override
|
||||||
progressDialog.showDialog("Soundtrack Mod Generator");
|
public void changedUpdate(DocumentEvent documentEvent) {
|
||||||
progressDialog.setText("Generating audio files...");
|
updateSelectionToMatchTextFields();
|
||||||
progressDialog.setProgressMax(progressSize);
|
}
|
||||||
progressDialog.setProgressValue(0);
|
};
|
||||||
|
|
||||||
new File(Main.inpath + "temp/data/audio/music").mkdirs();
|
public Suggs(JFrame parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
parent.setEnabled(false);
|
||||||
|
|
||||||
for (int i = 0; i < tracklist.size(); i++) {
|
frame.setIconImage(Main.windowIcon);
|
||||||
AudioTrack at = tracklist.get(i);
|
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
||||||
String trackno = String.format("%02d", i);
|
|
||||||
new File(Main.inpath + "temp/data/audio/music/" + trackno).mkdirs();
|
frame.setSize(700, 400);
|
||||||
if (at.path.getName().endsWith(".at9")) {
|
frame.setMinimumSize(new Dimension(700,400));
|
||||||
progressDialog.setText("Copying track " + (i+1) + " out of " + tracklist.size() + "...");
|
frame.setTitle("Soundtrack Mod Generator");
|
||||||
try {
|
frame.setResizable(true);
|
||||||
// Assume whoever made the AT9s knows what they're doing
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
System.out.println("Copying track #" + (i+1) + " \"" + at.title + " - " + at.artist + "\"...");
|
frame.setLayout(new GridLayout());
|
||||||
Files.copy(at.path.toPath(), Paths.get(Main.inpath + "tmp/data/audio/music/" + trackno + "/music_stereo.at9"), StandardCopyOption.REPLACE_EXISTING);
|
frame.setLocationRelativeTo(parent);
|
||||||
} catch (IOException ex) {
|
frame.setAlwaysOnTop(true);
|
||||||
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
cancelBtn.addActionListener(this);
|
||||||
|
saveBtn.addActionListener(this);
|
||||||
|
addSongBtn.addActionListener(this); // file picker
|
||||||
|
deleteSongBtn.addActionListener(this); // delete from list
|
||||||
|
moveUpBtn.addActionListener(this);
|
||||||
|
moveDownBtn.addActionListener(this);
|
||||||
|
fTitle.addActionListener(this); // automatically change selected item when changed &
|
||||||
|
fArtist.addActionListener(this); // also update field when new item selected
|
||||||
|
frontendMainChooseBtn.addActionListener(this); // file picker for singleplayer campaign grid music
|
||||||
|
frontendDemoChooseBtn.addActionListener(this); // file picker for multiplayer lobby music
|
||||||
|
spDeleteBtn.addActionListener(this);
|
||||||
|
mpDeleteBtn.addActionListener(this);
|
||||||
|
dSongList.addListSelectionListener(this);
|
||||||
|
|
||||||
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosing(WindowEvent e)
|
||||||
|
{
|
||||||
|
if (!tracklist.isEmpty() || sptrack != null || mptrack != null) {
|
||||||
|
int result = JOptionPane.showConfirmDialog(frame, "Are you sure?\nAll unsaved changes will be lost.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||||
|
if (result == JOptionPane.NO_OPTION) {return;}
|
||||||
|
}
|
||||||
|
parent.setEnabled(true);
|
||||||
|
e.getWindow().dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fTitle.setText("");
|
||||||
|
fArtist.setText("");
|
||||||
|
dTrackNo.setText("\u200E");
|
||||||
|
dFileSize.setText("\u200E");
|
||||||
|
fTitle.setEnabled(false);
|
||||||
|
fArtist.setEnabled(false);
|
||||||
|
|
||||||
|
fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
|
||||||
|
fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
|
||||||
|
|
||||||
|
frame.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void haveSeggs() { // kill yourself
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
if (actionEvent.getSource() == cancelBtn) {
|
||||||
|
if (!tracklist.isEmpty() || sptrack != null || mptrack != null) {
|
||||||
|
int result = JOptionPane.showConfirmDialog(frame, "Are you sure?\nAll unsaved changes will be lost.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||||
|
if (result == JOptionPane.NO_OPTION) {return;}
|
||||||
|
}
|
||||||
|
parent.setEnabled(true);
|
||||||
|
frame.dispose();
|
||||||
|
} else
|
||||||
|
if (actionEvent.getSource() == addSongBtn) {addSong();} else
|
||||||
|
if (actionEvent.getSource() == deleteSongBtn) {remove(curIndex);} else
|
||||||
|
if (actionEvent.getSource() == moveUpBtn) {moveUp(curIndex);} else
|
||||||
|
if (actionEvent.getSource() == moveDownBtn) {moveDown(curIndex);} else
|
||||||
|
if (actionEvent.getSource() == frontendMainChooseBtn) {setSPMusic();} else
|
||||||
|
if (actionEvent.getSource() == frontendDemoChooseBtn) {setMPMusic();} else
|
||||||
|
if (actionEvent.getSource() == saveBtn) {
|
||||||
|
if (tracklist.isEmpty() && sptrack == null && mptrack == null) {
|
||||||
|
JOptionPane.showMessageDialog(frame, "Please add at least one song to the playlist.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
String deets;
|
||||||
|
if (tracklist.isEmpty()) {
|
||||||
|
deets = "no songs";
|
||||||
|
} else {
|
||||||
|
deets = tracklist.size() + " songs";
|
||||||
|
}
|
||||||
|
if (sptrack != null && mptrack == null) {
|
||||||
|
deets = deets + " and a custom campaign menu track";
|
||||||
|
} else if (mptrack != null && sptrack == null) {
|
||||||
|
deets = deets + " and a custom lobby menu track";
|
||||||
|
} else if (mptrack != null && sptrack != null) {
|
||||||
|
deets = deets + ", a custom campaign menu track, and a custom lobby menu track";
|
||||||
|
}
|
||||||
|
int result = JOptionPane.showConfirmDialog(frame, "Your custom playlist with " + deets + " will be generated.\nPress YES to continue, or NO to continue editing.", "Soundtrack Mod Generator", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||||
|
if (result == JOptionPane.YES_OPTION) {
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
mpDeleteBtn.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent listSelectionEvent) {
|
||||||
|
fTitle.getDocument().removeDocumentListener(id3TagEditorHandler);
|
||||||
|
fArtist.getDocument().removeDocumentListener(id3TagEditorHandler);
|
||||||
|
curIndex = dSongList.getSelectedIndex();
|
||||||
|
if (curIndex >= 0) {
|
||||||
|
fTitle.setEnabled(true);
|
||||||
|
fArtist.setEnabled(true);
|
||||||
|
AudioTrack at = tracklist.get(curIndex);
|
||||||
|
fTitle.setText(at.title);
|
||||||
|
fArtist.setText(at.artist);
|
||||||
|
dTrackNo.setText(String.format("MT_%02d", curIndex+1));
|
||||||
|
dFileSize.setText(at.size + " B");
|
||||||
|
if (at.size > 1023) {
|
||||||
|
dFileSize.setText((at.size / 1024) + " KB");
|
||||||
|
}
|
||||||
|
if (at.size > 1048575) {
|
||||||
|
dFileSize.setText((at.size / 1048576) + " MB");
|
||||||
|
}
|
||||||
|
fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
|
||||||
|
fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
|
||||||
} else {
|
} else {
|
||||||
progressDialog.setText("Encoding track " + (i+1) + " out of " + tracklist.size() + "...");
|
fTitle.setEnabled(false);
|
||||||
try {
|
fArtist.setEnabled(false);
|
||||||
System.out.println("Encoding track #" + (i+1) + " \"" + at.title + " - " + at.artist + "\"...");
|
fTitle.setText("");
|
||||||
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/");
|
fArtist.setText("");
|
||||||
p.waitFor();
|
dTrackNo.setText("\u200E");
|
||||||
} catch (IOException | InterruptedException ex) {
|
dFileSize.setText("\u200E");
|
||||||
|
fTitle.getDocument().addDocumentListener(id3TagEditorHandler);
|
||||||
|
fArtist.getDocument().addDocumentListener(id3TagEditorHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSelectionToMatchTextFields() {
|
||||||
|
tracklist.get(curIndex).title = fTitle.getText();
|
||||||
|
tracklist.get(curIndex).artist = fArtist.getText();
|
||||||
|
InitializeSongListInGUI();
|
||||||
|
dSongList.setSelectedIndex(curIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void remove(int index) {
|
||||||
|
if (index >= 0) {
|
||||||
|
tracklist.remove(index);
|
||||||
|
InitializeSongListInGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveUp(int index) {
|
||||||
|
if (index > 0) {
|
||||||
|
Collections.swap(tracklist, index, index - 1);
|
||||||
|
curIndex--;
|
||||||
|
InitializeSongListInGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveDown(int index) {
|
||||||
|
if (index < (tracklist.size() - 1)) {
|
||||||
|
Collections.swap(tracklist, index, index + 1);
|
||||||
|
curIndex++;
|
||||||
|
InitializeSongListInGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeSongListInGUI() {
|
||||||
|
dSongList.removeListSelectionListener(this); // prevent weird bullshit
|
||||||
|
dSongList.clearSelection();
|
||||||
|
dSongList.removeAll();
|
||||||
|
dSongList.setVisibleRowCount(tracklist.size());
|
||||||
|
dSongList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
|
// add text entry for each
|
||||||
|
int i = 0;
|
||||||
|
String[] contents = new String[tracklist.size()];
|
||||||
|
while (i < tracklist.size()) {
|
||||||
|
String dTitleInList; // avoid editing the actual list
|
||||||
|
String dArtistInList; // otherwise we cause weird JTextField behavior
|
||||||
|
if (tracklist.get(i).title == null || tracklist.get(i).title.isEmpty())
|
||||||
|
dTitleInList = tracklist.get(i).path.getName();
|
||||||
|
else
|
||||||
|
dTitleInList = tracklist.get(i).title;
|
||||||
|
if (tracklist.get(i).artist == null || tracklist.get(i).artist.isEmpty())
|
||||||
|
dArtistInList = "Unknown Artist";
|
||||||
|
else
|
||||||
|
dArtistInList = tracklist.get(i).artist;
|
||||||
|
contents[i] = dArtistInList + " - " + dTitleInList;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
dSongList.setListData(contents);
|
||||||
|
dSongList.setSelectedIndex(curIndex);
|
||||||
|
dSongList.addListSelectionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFileChooser commonSoundFilePicker(boolean multiselect) {
|
||||||
|
JFileChooser fileChooser = new JFileChooser();
|
||||||
|
fileChooser.setMultiSelectionEnabled(multiselect);
|
||||||
|
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
|
||||||
|
fileChooser.setFileFilter(new FileNameExtensionFilter("All Compatible Files", "mp3", "ogg", "oga", "opus", "m4a", "3gp", "wav", "wave", "aif", "aiff", "aifc", "flac", "at3", "at9"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("MPEG Audio Layer 3", "mp3"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Ogg Audio", "ogg", "oga", "opus"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("AAC or MPEG-4 Audio", "m4a", "3gp"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("IBM/Microsoft WAVE", "wav", "wave"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Apple AIFF", "aif", "aiff", "aifc"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Free Lossless Audio Codec", "flac"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Sony ATRAC3", "at3"));
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Sony ATRAC9", "at9"));
|
||||||
|
return fileChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSPMusic() {
|
||||||
|
JFileChooser fileChooser = commonSoundFilePicker(false);
|
||||||
|
int result = fileChooser.showOpenDialog(frame);
|
||||||
|
if (result == JFileChooser.APPROVE_OPTION) {
|
||||||
|
File selectedFile = fileChooser.getSelectedFile();
|
||||||
|
sptrack = selectedFile;
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
if (selectedFile.length() > 1048575) {
|
||||||
|
dSSize.setText((selectedFile.length() / 1048576) + " MB");
|
||||||
|
}
|
||||||
|
spDeleteBtn.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMPMusic() {
|
||||||
|
JFileChooser fileChooser = commonSoundFilePicker(false);
|
||||||
|
int result = fileChooser.showOpenDialog(frame);
|
||||||
|
if (result == JFileChooser.APPROVE_OPTION) {
|
||||||
|
File selectedFile = fileChooser.getSelectedFile();
|
||||||
|
mptrack = selectedFile;
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
if (selectedFile.length() > 1048575) {
|
||||||
|
dMSize.setText((selectedFile.length() / 1048576) + " MB");
|
||||||
|
}
|
||||||
|
mpDeleteBtn.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSong() {
|
||||||
|
JFileChooser fileChooser = commonSoundFilePicker(true);
|
||||||
|
|
||||||
|
int result = fileChooser.showOpenDialog(frame);
|
||||||
|
if (result == JFileChooser.APPROVE_OPTION) {
|
||||||
|
File[] selectedFiles = fileChooser.getSelectedFiles();
|
||||||
|
for (File f : selectedFiles) {
|
||||||
|
if (f.exists()) {
|
||||||
|
System.out.println("Importing audio file \"" + f.getName() + "\"");
|
||||||
|
AudioTrack track = new AudioTrack();
|
||||||
|
track.path = f;
|
||||||
|
String fname = f.getName();
|
||||||
|
if (fname.contains(" - ")) {
|
||||||
|
track.title = fname.substring(fname.indexOf(" - ")+3, fname.lastIndexOf("."));
|
||||||
|
track.artist = fname.substring(0, fname.indexOf(" - "));
|
||||||
|
} else track.title = fname;
|
||||||
|
track.size = f.length();
|
||||||
|
tracklist.add(track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InitializeSongListInGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void save() {
|
||||||
|
frame.setEnabled(false);
|
||||||
|
frame.setAlwaysOnTop(false);
|
||||||
|
normalizeVolumes = checkNormalize.isSelected();
|
||||||
|
Main.deleteDir(new File(System.getProperty("user.home") + "/.firestar/temp/")); // starts with clean temp
|
||||||
|
new Thread(() -> {
|
||||||
|
int progressSize = tracklist.size()+(sptrack != null?1:0)+(mptrack != null?1:0)+1; // Accounting for processes
|
||||||
|
|
||||||
|
progressDialog = new Scooter();
|
||||||
|
progressDialog.showDialog("Soundtrack Mod Generator");
|
||||||
|
progressDialog.setText("Generating audio files...");
|
||||||
|
progressDialog.setProgressMax(progressSize);
|
||||||
|
progressDialog.setProgressValue(0);
|
||||||
|
progressDialog.progressBar.setStringPainted(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new File(Main.inpath + "temp/data/audio/music").mkdirs();
|
||||||
|
FileOutputStream fos = new FileOutputStream(new File(Main.inpath + "temp/fscript"));
|
||||||
|
PrintStream ps = new PrintStream(fos);
|
||||||
|
ps.println("fscript 1");
|
||||||
|
ps.println("# AUTOGENERATED BY FIRESTAR");
|
||||||
|
for (int i = 0; i < tracklist.size(); i++) {
|
||||||
|
AudioTrack at = tracklist.get(i);
|
||||||
|
String trackno = String.format("%02d", i+1);
|
||||||
|
String oTitle;
|
||||||
|
if (at.title == null) {oTitle = "";} else {oTitle = at.title;}
|
||||||
|
String oArtist;
|
||||||
|
if (at.artist == null) {oArtist = "";} else {oArtist = at.artist;}
|
||||||
|
new File(Main.inpath + "temp/data/audio/music/" + trackno).mkdirs();
|
||||||
|
if (at.path.getName().endsWith(".at9")) {
|
||||||
|
progressDialog.setText("Copying track " + (i+1) + " out of " + tracklist.size() + "...");
|
||||||
|
try {
|
||||||
|
// Assume whoever made the AT9s knows what they're doing
|
||||||
|
System.out.println("Copying track #" + (i+1) + " \"" + at.artist + " - " + at.title + "\"...");
|
||||||
|
Files.copy(at.path.toPath(), Paths.get(Main.inpath + "temp/data/audio/music/" + trackno + "/music_stereo.at9"), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
progressDialog.setText("Encoding track " + (i+1) + " out of " + tracklist.size() + "...");
|
||||||
|
try {
|
||||||
|
System.out.println("Encoding track #" + (i+1) + " \"" + oArtist + " - " + oTitle + "\"...");
|
||||||
|
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) {
|
||||||
|
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String ocmd = "modify";
|
||||||
|
if (i >= 12) ocmd = "create";
|
||||||
|
String oArtistLine;
|
||||||
|
if (!oArtist.isEmpty()) {
|
||||||
|
oArtistLine = oArtist.replace("\"", "\\\"")+"\\n";
|
||||||
|
} else {
|
||||||
|
oArtistLine = "";
|
||||||
|
}
|
||||||
|
int i2 = 0;
|
||||||
|
while (i2 < 15 /*17 languages*/) {
|
||||||
|
String language = "INTERNAL_ERROR";
|
||||||
|
switch (i2) {
|
||||||
|
case 0 -> language = "american";
|
||||||
|
case 1 -> language = "danish";
|
||||||
|
case 2 -> language = "dutch";
|
||||||
|
case 3 -> language = "english";
|
||||||
|
case 4 -> language = "finnish";
|
||||||
|
case 5 -> language = "french";
|
||||||
|
case 6 -> language = "german";
|
||||||
|
case 7 -> language = "italian";
|
||||||
|
case 8 -> language = "japanese";
|
||||||
|
case 9 -> language = "norwegian";
|
||||||
|
case 10 -> language = "polish";
|
||||||
|
case 11 -> language = "portuguese";
|
||||||
|
case 12 -> language = "russian";
|
||||||
|
case 13 -> language = "spanish";
|
||||||
|
case 14 -> language = "swedish";
|
||||||
|
default -> {
|
||||||
|
int result = JOptionPane.showConfirmDialog(frame, "Firestar encountered an internal error.\nString 'language' exported to FSCRIPT was blank.", "Fatal Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
|
||||||
|
if (result == JOptionPane.OK_OPTION) {System.exit(1);} //user safety
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//case 9: language = "korean"; break;
|
||||||
|
//case 16: language = "traditionalchinese"; break;
|
||||||
|
ps.println("file \"data/plugins/languages/"+language+"/entries.xml\" xml "+ocmd+" StringTable.entry#MT_"+trackno+" set attribute \"string\" \""+oArtistLine+oTitle.replace("\"", "\\\"")+"\"");
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
ps.println("file \"data/audio/music/"+trackno+"/music_stereo.fft\" delete");
|
||||||
|
progressDialog.setProgressValue(i+1);
|
||||||
|
}
|
||||||
|
for (int s = tracklist.size(); s < 12; s++) {
|
||||||
|
ps.println("file \"data/audio/music/"+String.format("%02d", s+1)+"/music_stereo.fft\" delete");
|
||||||
|
}
|
||||||
|
if (sptrack != null) {
|
||||||
|
progressDialog.setText("Encoding singleplayer frontend track...");
|
||||||
|
if (sptrack.exists()) {
|
||||||
|
try {
|
||||||
|
System.out.println("Encoding singleplayer frontend track...");
|
||||||
|
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) {
|
||||||
|
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ps.println("file \"data/audio/music/FEMusic/frontend_stereo.fft\" delete");
|
||||||
|
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
||||||
|
}
|
||||||
|
if (mptrack != null) {
|
||||||
|
progressDialog.setText("Encoding multiplayer frontend track...");
|
||||||
|
try {
|
||||||
|
assert(mptrack.exists());
|
||||||
|
System.out.println("Encoding multiplayer frontend track...");
|
||||||
|
if (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) {
|
||||||
|
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
ps.println("file \"data/audio/music/FEDemoMusic/frontend_stereo.fft\" delete");
|
||||||
|
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
||||||
|
}
|
||||||
|
System.out.println("Finished encoding.");
|
||||||
|
|
||||||
|
progressDialog.setText("Generating Music Definitions...");
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||||
|
|
||||||
|
Document defDoc = docBuilder.newDocument();
|
||||||
|
Element docScreen = defDoc.createElement("Screen");
|
||||||
|
docScreen.setAttribute("name", "Top");
|
||||||
|
for (int i = 0; i < tracklist.size(); i++) { // TODO: support for additive
|
||||||
|
AudioTrack at = tracklist.get(i);
|
||||||
|
String trackno = String.format("%02d", i+1);
|
||||||
|
|
||||||
|
Element trackElem = defDoc.createElement("PI_Music");
|
||||||
|
trackElem.setAttribute("name", trackno);
|
||||||
|
|
||||||
|
Element pathElem = defDoc.createElement("Values");
|
||||||
|
pathElem.setAttribute("location", "data\\audio\\music\\"+trackno);
|
||||||
|
trackElem.appendChild(pathElem);
|
||||||
|
|
||||||
|
Element artistElem = defDoc.createElement("Entry");
|
||||||
|
artistElem.setAttribute("Artist", at.artist);
|
||||||
|
trackElem.appendChild(artistElem);
|
||||||
|
|
||||||
|
Element titleElem = defDoc.createElement("Entry");
|
||||||
|
titleElem.setAttribute("Label", at.title);
|
||||||
|
trackElem.appendChild(titleElem);
|
||||||
|
|
||||||
|
docScreen.appendChild(trackElem);
|
||||||
|
System.out.println("Adding \"" + trackno + ". " + at.artist + " - " + at.title + "\" to Definition.xml");
|
||||||
|
}
|
||||||
|
defDoc.appendChild(docScreen);
|
||||||
|
|
||||||
|
new File(Main.inpath + "temp/data/plugins/music/").mkdirs();
|
||||||
|
FileOutputStream output = new FileOutputStream(Main.inpath + "temp/data/plugins/music/Definition.xml");
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
Transformer transformer = transformerFactory.newTransformer();
|
||||||
|
DOMSource source = new DOMSource(defDoc);
|
||||||
|
StreamResult result = new StreamResult(output);
|
||||||
|
|
||||||
|
transformer.transform(source, result);
|
||||||
|
} catch (IOException | ParserConfigurationException | TransformerException ex) {
|
||||||
|
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
||||||
|
|
||||||
|
progressDialog.setText("Finalizing script...");
|
||||||
|
System.out.println("Finalizing Fscript...");
|
||||||
|
ps.println("# END FIRESTAR AUTOGENERATION");
|
||||||
|
ps.close();
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
progressDialog.setProgressValue(i+1);
|
|
||||||
}
|
|
||||||
if (sptrack != null) {
|
|
||||||
progressDialog.setText("Encoding singleplayer frontend track...");
|
|
||||||
if (sptrack.exists()) {
|
|
||||||
try {
|
|
||||||
System.out.println("Encoding singleplayer frontend track...");
|
|
||||||
new File(Main.inpath + "temp/data/audio/music/FEMusic").mkdirs();
|
|
||||||
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", sptrack.getPath(), "data/audio/music/FEMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/");
|
|
||||||
p.waitFor();
|
|
||||||
} catch (IOException | InterruptedException ex) {
|
|
||||||
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
|
||||||
}
|
|
||||||
if (mptrack != null) {
|
|
||||||
progressDialog.setText("Encoding multiplayer frontend track...");
|
|
||||||
try {
|
|
||||||
assert(mptrack.exists());
|
|
||||||
System.out.println("Encoding multiplayer frontend track...");
|
|
||||||
new File(Main.inpath + "temp/data/audio/music/FEDemoMusic").mkdirs();
|
|
||||||
Process p = Main.exec(new String[]{Main.inpath + "at9tool.exe", "-e", "-br", "144", mptrack.getPath(), "data/audio/music/FEDemoMusic/frontend_stereo.at9"}, System.getProperty("user.home") + "/.firestar/temp/");
|
|
||||||
p.waitFor();
|
|
||||||
} catch (IOException | InterruptedException ex) {
|
|
||||||
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
|
||||||
}
|
|
||||||
System.out.println("Finished encoding.");
|
|
||||||
|
|
||||||
progressDialog.setText("Generating Music Definitions...");
|
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
||||||
try {
|
|
||||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
|
||||||
|
|
||||||
Document defDoc = docBuilder.newDocument();
|
progressDialog.destroyDialog();
|
||||||
Element docScreen = defDoc.createElement("Screen");
|
frame.dispose();
|
||||||
docScreen.setAttribute("name", "Top");
|
Clifford saveDialog = new Clifford();
|
||||||
for (int i = 0; i < tracklist.size(); i++) { // TODO: support for additive
|
saveDialog.isSoundtrack = true;
|
||||||
AudioTrack at = tracklist.get(i);
|
saveDialog.Action(frame, new File(Main.inpath + "temp/"));
|
||||||
String trackno = String.format("%02d", i);
|
parent.setEnabled(true);
|
||||||
|
}).start();
|
||||||
Element trackElem = defDoc.createElement("PI_Music");
|
}
|
||||||
trackElem.setAttribute("name", trackno);
|
|
||||||
|
|
||||||
Element pathElem = defDoc.createElement("Values");
|
|
||||||
pathElem.setAttribute("location", "data\\audio\\music\\"+trackno);
|
|
||||||
trackElem.appendChild(pathElem);
|
|
||||||
|
|
||||||
Element artistElem = defDoc.createElement("Entry");
|
|
||||||
artistElem.setAttribute("Artist", at.artist);
|
|
||||||
trackElem.appendChild(artistElem);
|
|
||||||
|
|
||||||
Element titleElem = defDoc.createElement("Entry");
|
|
||||||
titleElem.setAttribute("Label", at.title);
|
|
||||||
trackElem.appendChild(titleElem);
|
|
||||||
|
|
||||||
docScreen.appendChild(trackElem);
|
|
||||||
System.out.println("Adding \"" + trackno + ". " + at.artist + " - " + at.title + "\" to Definition.xml");
|
|
||||||
}
|
|
||||||
defDoc.appendChild(docScreen);
|
|
||||||
|
|
||||||
new File(Main.inpath + "temp/data/plugins/music/").mkdirs();
|
|
||||||
FileOutputStream output = new FileOutputStream(Main.inpath + "temp/data/plugins/music/Definition.xml");
|
|
||||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
|
||||||
Transformer transformer = transformerFactory.newTransformer();
|
|
||||||
DOMSource source = new DOMSource(defDoc);
|
|
||||||
StreamResult result = new StreamResult(output);
|
|
||||||
|
|
||||||
transformer.transform(source, result);
|
|
||||||
} catch (IOException | ParserConfigurationException | TransformerException ex) {
|
|
||||||
Logger.getLogger(Suggs.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
|
||||||
|
|
||||||
progressDialog.setText("Localizing...");
|
|
||||||
System.out.println("Creating localization edits for music tracks...");
|
|
||||||
// TODO: Actually do what the above print-out says
|
|
||||||
progressDialog.setProgressValue(progressDialog.getProgressValue()+1);
|
|
||||||
|
|
||||||
progressDialog.destroyDialog();
|
|
||||||
frame.dispose();
|
|
||||||
new Clifford().Action(frame, new File(Main.inpath + "temp/"));
|
|
||||||
parent.setEnabled(true);
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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">
|
<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"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<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>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<opaque value="false"/>
|
<opaque value="false"/>
|
||||||
@@ -99,7 +101,7 @@
|
|||||||
<children>
|
<children>
|
||||||
<component id="18770" class="javax.swing.JLabel" binding="fOutpath">
|
<component id="18770" class="javax.swing.JLabel" binding="fOutpath">
|
||||||
<constraints>
|
<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>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<font name="Exo 2"/>
|
<font name="Exo 2"/>
|
||||||
@@ -109,7 +111,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component id="fa1ee" class="javax.swing.JButton" binding="fOutpathChangebtn">
|
<component id="fa1ee" class="javax.swing.JButton" binding="fOutpathChangebtn">
|
||||||
<constraints>
|
<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>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<background color="-2271221"/>
|
<background color="-2271221"/>
|
||||||
|
|||||||
@@ -16,153 +16,151 @@
|
|||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
||||||
|
|
||||||
public class Waldorf implements ActionListener {
|
public class Waldorf implements ActionListener {
|
||||||
private JFrame frame = new JFrame();
|
private JFrame frame = new JFrame();
|
||||||
private JPanel frameContainer;
|
private JPanel frameContainer;
|
||||||
private JButton okbtn;
|
private JButton okbtn;
|
||||||
private JButton cancelbtn;
|
private JButton cancelbtn;
|
||||||
private JLabel fOutpath;
|
private JLabel fOutpath;
|
||||||
private JButton resetbtn;
|
private JButton resetbtn;
|
||||||
private JButton bOpenFolder;
|
private JButton bOpenFolder;
|
||||||
private JButton dwnSDKbtn;
|
private JButton dwnSDKbtn;
|
||||||
private JButton dwnARCbtn;
|
private JButton dwnARCbtn;
|
||||||
private JButton fOutpathChangebtn;
|
private JButton fOutpathChangebtn;
|
||||||
private JCheckBox checkUpdatesToggle;
|
private JCheckBox checkUpdatesToggle;
|
||||||
private JButton bDelArcs;
|
private JButton bDelArcs;
|
||||||
|
|
||||||
MissPiggy invoker;
|
MissPiggy invoker;
|
||||||
private String tOutPath = Main.outpath;
|
private String tOutPath = Main.outpath;
|
||||||
|
|
||||||
public void Action(MissPiggy inv) {
|
public void Action(MissPiggy inv) {
|
||||||
invoker = inv;
|
invoker = inv;
|
||||||
|
|
||||||
frame.add(frameContainer);
|
frame.add(frameContainer);
|
||||||
try {
|
frame.setIconImage(Main.windowIcon);
|
||||||
BufferedImage windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
frame.setSize(600, 300); // 1280 800
|
||||||
frame.setIconImage(windowIcon);
|
frame.setMinimumSize(new Dimension(200,100));
|
||||||
} catch (IOException e) {
|
frame.setTitle("Options");
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
frame.setResizable(false);
|
||||||
}
|
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||||
frame.setSize(600, 300); // 1280 800
|
frame.setLayout(new GridLayout());
|
||||||
frame.setMinimumSize(new Dimension(200,100));
|
frame.setLocationRelativeTo(inv.frame);
|
||||||
frame.setTitle("Options");
|
frame.setAlwaysOnTop(true);
|
||||||
frame.setResizable(false);
|
|
||||||
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
|
||||||
frame.setLayout(new GridLayout());
|
|
||||||
frame.setLocationRelativeTo(inv.frame);
|
|
||||||
frame.setAlwaysOnTop(true);
|
|
||||||
|
|
||||||
cancelbtn.addActionListener(this);
|
cancelbtn.addActionListener(this);
|
||||||
okbtn.addActionListener(this);
|
okbtn.addActionListener(this);
|
||||||
resetbtn.addActionListener(this);
|
resetbtn.addActionListener(this);
|
||||||
bOpenFolder.addActionListener(this);
|
bOpenFolder.addActionListener(this);
|
||||||
bDelArcs.addActionListener(this);
|
bDelArcs.addActionListener(this);
|
||||||
dwnARCbtn.addActionListener(this);
|
dwnARCbtn.addActionListener(this);
|
||||||
dwnSDKbtn.addActionListener(this);
|
dwnSDKbtn.addActionListener(this);
|
||||||
fOutpathChangebtn.addActionListener(this);
|
fOutpathChangebtn.addActionListener(this);
|
||||||
|
|
||||||
fOutpath.setText(Main.outpath);
|
updateDOutpath(Main.outpath);
|
||||||
checkUpdatesToggle.setSelected(Main.checkUpdates);
|
checkUpdatesToggle.setSelected(Main.checkUpdates);
|
||||||
|
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e)
|
public void windowClosing(WindowEvent e)
|
||||||
{
|
{
|
||||||
invoker.frame.setEnabled(true);
|
invoker.frame.setEnabled(true);
|
||||||
e.getWindow().dispose();
|
e.getWindow().dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void updateDOutpath(String path) {
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
String s = path;
|
||||||
if (actionEvent.getSource() == cancelbtn) {
|
if (s.startsWith(System.getProperty("user.home"))) {s = "~" + s.substring(System.getProperty("user.home").length());}
|
||||||
invoker.frame.setEnabled(true);
|
if (s.length() > 50) {s = s.substring(0, Math.min(path.length(), 46)) + "...";fOutpath.setToolTipText(path);} else {fOutpath.setToolTipText(null);}
|
||||||
frame.dispose();
|
fOutpath.setText(s);
|
||||||
} else
|
}
|
||||||
if (actionEvent.getSource() == okbtn) {
|
|
||||||
Main.outpath = tOutPath;
|
|
||||||
Main.checkUpdates = checkUpdatesToggle.isSelected();
|
|
||||||
Main.writeConf();
|
|
||||||
Main.loadConf();
|
|
||||||
|
|
||||||
invoker.frame.setEnabled(true);
|
@Override
|
||||||
frame.dispose();
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
} else
|
if (actionEvent.getSource() == cancelbtn) {
|
||||||
if (actionEvent.getSource() == resetbtn) {
|
invoker.frame.setEnabled(true);
|
||||||
int result = JOptionPane.showConfirmDialog(frame,"Are you sure you want to redo the initial setup?", "Restore Default Settings", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
frame.dispose();
|
||||||
if (result == JOptionPane.YES_OPTION) {
|
} else
|
||||||
System.out.println("Restoring default settings");
|
if (actionEvent.getSource() == okbtn) {
|
||||||
new File(System.getProperty("user.home") + "/.firestar/firestar.conf").delete();
|
Main.outpath = tOutPath;
|
||||||
System.out.println("Deleting existing PSARCs");
|
Main.checkUpdates = checkUpdatesToggle.isSelected();
|
||||||
new File(Main.inpath + "data.psarc").delete();
|
Main.writeConf();
|
||||||
new File(Main.inpath + "data1.psarc").delete();
|
Main.loadConf();
|
||||||
new File(Main.inpath + "data2.psarc").delete();
|
|
||||||
new File(Main.inpath + "dlc1.psarc").delete();
|
invoker.frame.setEnabled(true);
|
||||||
new File(Main.inpath + "dlc2.psarc").delete();
|
frame.dispose();
|
||||||
int result2 = JOptionPane.showConfirmDialog(frame,"Firestar will now close.", "Restore Default Settings", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
|
} else
|
||||||
if (result2 == JOptionPane.OK_OPTION) {
|
if (actionEvent.getSource() == resetbtn) {
|
||||||
System.exit(0);
|
int result = JOptionPane.showConfirmDialog(frame,"Are you sure you want to redo the initial setup?", "Restore Default Settings", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||||
}
|
if (result == JOptionPane.YES_OPTION) {
|
||||||
}
|
System.out.println("Restoring default settings");
|
||||||
} else
|
new File(System.getProperty("user.home") + "/.firestar/firestar.conf").delete();
|
||||||
if (actionEvent.getSource() == bOpenFolder) {
|
int result2 = JOptionPane.showConfirmDialog(frame,"Firestar will now close.", "Restore Default Settings", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
|
||||||
try {
|
if (result2 == JOptionPane.OK_OPTION) {
|
||||||
Desktop.getDesktop().open(new File(Main.inpath));
|
System.exit(0);
|
||||||
} catch (IOException e) {
|
}
|
||||||
throw new RuntimeException(e);
|
}
|
||||||
}
|
} else
|
||||||
} else
|
if (actionEvent.getSource() == bOpenFolder) {
|
||||||
if (actionEvent.getSource() == bDelArcs) {
|
try {
|
||||||
int result = JOptionPane.showConfirmDialog(frame, "All existing PSARC dumps will be deleted.\nDo you want to continue?", "Delete PSARCs", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
Desktop.getDesktop().open(new File(Main.inpath));
|
||||||
if (result == JOptionPane.NO_OPTION) {return;}
|
} catch (IOException e) {
|
||||||
System.out.println("User requested arc wipe, deleting existing PSARCs");
|
throw new RuntimeException(e);
|
||||||
new File(Main.inpath + "data.psarc").delete();
|
}
|
||||||
new File(Main.inpath + "data1.psarc").delete();
|
} else
|
||||||
new File(Main.inpath + "data2.psarc").delete();
|
if (actionEvent.getSource() == bDelArcs) {
|
||||||
new File(Main.inpath + "dlc1.psarc").delete();
|
int result = JOptionPane.showConfirmDialog(frame, "All existing PSARC dumps will be deleted.\nDo you want to continue?", "Delete PSARCs", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||||
new File(Main.inpath + "dlc2.psarc").delete();
|
if (result == JOptionPane.NO_OPTION) {return;}
|
||||||
JOptionPane.showMessageDialog(frame, "PSARC files purged.", "Delete PSARCs", JOptionPane.INFORMATION_MESSAGE);
|
System.out.println("User requested arc wipe, deleting existing PSARCs");
|
||||||
} else
|
new File(Main.inpath + "data.psarc").delete();
|
||||||
if (actionEvent.getSource() == dwnARCbtn) {
|
new File(Main.inpath + "data1.psarc").delete();
|
||||||
new Bert(invoker.frame);
|
new File(Main.inpath + "data2.psarc").delete();
|
||||||
frame.dispose();
|
new File(Main.inpath + "dlc1.psarc").delete();
|
||||||
} else
|
new File(Main.inpath + "dlc2.psarc").delete();
|
||||||
if (actionEvent.getSource() == dwnSDKbtn) {
|
JOptionPane.showMessageDialog(frame, "PSARC files purged.", "Delete PSARCs", JOptionPane.INFORMATION_MESSAGE);
|
||||||
Thread downloaderPopupThread = new Thread(new Runnable() {
|
} else
|
||||||
@Override
|
if (actionEvent.getSource() == dwnARCbtn) {
|
||||||
public void run() {
|
if (!new File(Main.inpath + "pkg2zip.exe").exists() || !new File(Main.inpath + "psvpfsparser.exe").exists()) {
|
||||||
Main.downloadDependenciesBeforeSetVisible(invoker.frame);
|
JOptionPane.showMessageDialog(frame, "Your decryption tools are missing.\nPlease select \"Get Dependencies\" in the Options menu.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
invoker.frame.setEnabled(true);
|
return;
|
||||||
}
|
}
|
||||||
});
|
new Bert(invoker.frame);
|
||||||
downloaderPopupThread.start();
|
frame.dispose();
|
||||||
frame.dispose();
|
} else
|
||||||
} else
|
if (actionEvent.getSource() == dwnSDKbtn) {
|
||||||
if (actionEvent.getSource() == fOutpathChangebtn) {
|
Thread downloaderPopupThread = new Thread(new Runnable() {
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
@Override
|
||||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
public void run() {
|
||||||
int result = fileChooser.showOpenDialog(frame);
|
Main.downloadDependenciesBeforeSetVisible(invoker.frame);
|
||||||
if (result == JFileChooser.APPROVE_OPTION) {
|
invoker.frame.setEnabled(true);
|
||||||
if (fileChooser.getSelectedFile().isDirectory()) {
|
}
|
||||||
tOutPath = fileChooser.getSelectedFile().getAbsolutePath();
|
});
|
||||||
fOutpath.setText(tOutPath);
|
downloaderPopupThread.start();
|
||||||
}
|
frame.dispose();
|
||||||
}
|
} else
|
||||||
}
|
if (actionEvent.getSource() == fOutpathChangebtn) {
|
||||||
}
|
JFileChooser fileChooser = new JFileChooser();
|
||||||
|
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
|
int result = fileChooser.showOpenDialog(frame);
|
||||||
|
if (result == JFileChooser.APPROVE_OPTION) {
|
||||||
|
if (fileChooser.getSelectedFile().isDirectory()) {
|
||||||
|
tOutPath = fileChooser.getSelectedFile().getAbsolutePath()+"/";
|
||||||
|
updateDOutpath(tOutPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import javax.swing.text.html.HTMLDocument;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -32,182 +31,176 @@ import java.nio.file.Files;
|
|||||||
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
||||||
|
|
||||||
public class WilkinsCoffee implements ActionListener {
|
public class WilkinsCoffee implements ActionListener {
|
||||||
BufferedImage windowIcon;
|
Image logo;
|
||||||
Image logo;
|
public Pages page;
|
||||||
public Pages page;
|
public JFrame frame = new JFrame();
|
||||||
public JFrame frame = new JFrame();
|
private JPanel frameContainer;
|
||||||
private JPanel frameContainer;
|
private JLabel picLabel;
|
||||||
private JLabel picLabel;
|
private JEditorPane instructions;
|
||||||
private JEditorPane instructions;
|
private JButton contBtn;
|
||||||
private JButton contBtn;
|
private JPanel inputContainer;
|
||||||
private JPanel inputContainer;
|
private JButton PSARC_downBtn;
|
||||||
private JButton PSARC_downBtn;
|
private JButton PSARC_impBtn;
|
||||||
private JButton PSARC_impBtn;
|
private JPanel inputContainer2;
|
||||||
private JPanel inputContainer2;
|
private JButton EXPORT_openFolderBtn;
|
||||||
private JButton EXPORT_openFolderBtn;
|
private JLabel pathDisplay;
|
||||||
private JLabel pathDisplay;
|
private JPanel checklistContainer;
|
||||||
private JPanel checklistContainer;
|
private JLabel checklistFury;
|
||||||
private JLabel checklistFury;
|
private JLabel checklistHD;
|
||||||
private JLabel checklistHD;
|
private JLabel checklistPatch2;
|
||||||
private JLabel checklistPatch2;
|
private JLabel checklistPatch1;
|
||||||
private JLabel checklistPatch1;
|
private JLabel checklistBase;
|
||||||
private JLabel checklistBase;
|
|
||||||
|
|
||||||
public enum Pages {
|
public enum Pages {
|
||||||
INTRO(0),
|
INTRO(0),
|
||||||
PSARC(1),
|
PSARC(1),
|
||||||
EXPORT_LOCATION(2),
|
EXPORT_LOCATION(2),
|
||||||
DONE(3);
|
DONE(3);
|
||||||
|
|
||||||
public final int value;
|
public final int value;
|
||||||
|
|
||||||
private Pages(int i) {
|
private Pages(int i) {
|
||||||
this.value = i;
|
this.value = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String outPathTemp = System.getProperty("user.home") + "/Documents";
|
private String outPathTemp = System.getProperty("user.home") + "/Documents/";
|
||||||
private boolean sdkInstalled = false;
|
private boolean sdkInstalled = false;
|
||||||
|
|
||||||
public void setup() {
|
public void setup() {
|
||||||
page = Pages.INTRO;
|
page = Pages.INTRO;
|
||||||
inputContainer.setVisible(false);
|
inputContainer.setVisible(false);
|
||||||
checklistContainer.setVisible(false);
|
checklistContainer.setVisible(false);
|
||||||
inputContainer2.setVisible(false);
|
inputContainer2.setVisible(false);
|
||||||
|
|
||||||
// check if this is windows or not
|
// check if this is windows or not
|
||||||
if(System.getProperty("os.name").contains("Windows")) {Main.windows = true;System.out.println("Assuming we should NOT use WINE based on known system variables.");}
|
if(System.getProperty("os.name").contains("Windows")) {Main.windows = true;System.out.println("Assuming we should NOT use WINE based on known system variables.");}
|
||||||
else {Main.windows = false;System.out.println("Assuming we should use WINE based on known system variables.");}
|
else {Main.windows = false;System.out.println("Assuming we should use WINE based on known system variables.");}
|
||||||
|
|
||||||
// reformat path slightly for windows
|
// reformat path slightly for windows
|
||||||
if (Main.windows) {outPathTemp.replace("/", "\\");}
|
if (Main.windows) {outPathTemp.replace("/", "\\");}
|
||||||
|
|
||||||
try {
|
frame.setIconImage(Main.windowIcon);
|
||||||
windowIcon = ImageIO.read(Main.class.getResourceAsStream("/titleIcon.png"));
|
try {
|
||||||
frame.setIconImage(windowIcon);
|
logo = ImageIO.read(Main.class.getResourceAsStream("/programIcon.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
||||||
} catch (IOException e) {
|
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
||||||
System.out.println("ERROR: Failed to find /resources/titleIcon.png. Window will not have an icon.");
|
} catch (IOException e) {
|
||||||
}
|
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
||||||
try {
|
picLabel.setText("");
|
||||||
logo = ImageIO.read(Main.class.getResourceAsStream("/programIcon.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
}
|
||||||
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
|
||||||
picLabel.setText("");
|
|
||||||
}
|
|
||||||
|
|
||||||
String bodyRule = "html, body {margin:0px;} p#first-p {margin-top:-13px;} p {margin-left:-20px;}";
|
String bodyRule = "html, body {margin:0px;} p#first-p {margin-top:-13px;} p {margin-left:-20px;}";
|
||||||
((HTMLDocument)instructions.getDocument()).getStyleSheet().addRule(bodyRule);
|
((HTMLDocument)instructions.getDocument()).getStyleSheet().addRule(bodyRule);
|
||||||
instructions.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf??
|
instructions.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); // makes text smaller than joe biden's windmill if font set manually. wtf??
|
||||||
contBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
contBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
||||||
PSARC_downBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
PSARC_downBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
||||||
PSARC_impBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
PSARC_impBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
||||||
EXPORT_openFolderBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
EXPORT_openFolderBtn.setFont(Main.fExo2.deriveFont(Font.BOLD).deriveFont(12f));
|
||||||
|
|
||||||
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
frame.add(frameContainer); // initialize window contents -- will be handled by IntelliJ IDEA
|
||||||
|
|
||||||
contBtn.addActionListener(this);
|
contBtn.addActionListener(this);
|
||||||
PSARC_downBtn.addActionListener(this);
|
PSARC_downBtn.addActionListener(this);
|
||||||
PSARC_impBtn.addActionListener(this);
|
PSARC_impBtn.addActionListener(this);
|
||||||
EXPORT_openFolderBtn.addActionListener(this);
|
EXPORT_openFolderBtn.addActionListener(this);
|
||||||
|
|
||||||
frame.setSize(400, 400);
|
frame.setSize(400, 400);
|
||||||
frame.setTitle("Firestar Setup");
|
frame.setTitle("Firestar Setup");
|
||||||
frame.setResizable(false);
|
frame.setResizable(false);
|
||||||
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||||
frame.setLayout(new GridLayout());
|
frame.setLayout(new GridLayout());
|
||||||
frame.setLocationRelativeTo(null);
|
frame.setLocationRelativeTo(null);
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
WilkinsCoffee threadParent = this;
|
WilkinsCoffee threadParent = this;
|
||||||
if (actionEvent.getSource() == PSARC_downBtn) {
|
if (actionEvent.getSource() == PSARC_downBtn) {
|
||||||
Thread waiterThread = new Thread(new Runnable() {@Override
|
Thread waiterThread = new Thread(new Runnable() {@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (new Bert(frame).reportWhenDownloaded(threadParent)) {
|
if (new Bert(frame).reportWhenDownloaded(threadParent)) {
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
|
|
||||||
refreshChecklist();
|
refreshChecklist();
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
waiterThread.start();
|
waiterThread.start();
|
||||||
} else
|
} else
|
||||||
if (actionEvent.getSource() == PSARC_impBtn) {
|
if (actionEvent.getSource() == PSARC_impBtn) {
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
JFileChooser fileChooser = new JFileChooser();
|
||||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||||
FileFilter fileChooserFilter = new FileNameExtensionFilter("Sony Playstation Archive File", "psarc");
|
FileFilter fileChooserFilter = new FileNameExtensionFilter("Sony Playstation Archive File", "psarc");
|
||||||
fileChooser.setFileFilter(fileChooserFilter);
|
fileChooser.setFileFilter(fileChooserFilter);
|
||||||
int result = fileChooser.showOpenDialog(frame);
|
int result = fileChooser.showOpenDialog(frame);
|
||||||
if (result == JFileChooser.APPROVE_OPTION) {
|
if (result == JFileChooser.APPROVE_OPTION) {
|
||||||
try {
|
try {
|
||||||
Files.copy(fileChooser.getSelectedFile().toPath(), new File(Main.inpath + fileChooser.getSelectedFile().getName()).toPath());
|
Files.copy(fileChooser.getSelectedFile().toPath(), new File(Main.inpath + fileChooser.getSelectedFile().getName()).toPath());
|
||||||
refreshChecklist();
|
refreshChecklist();
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println(e.getMessage());
|
System.out.println(e.getMessage());
|
||||||
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(frame, "An error has occured.\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (actionEvent.getSource() == EXPORT_openFolderBtn) {
|
if (actionEvent.getSource() == EXPORT_openFolderBtn) {
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
JFileChooser fileChooser = new JFileChooser();
|
||||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
int result = fileChooser.showOpenDialog(frame);
|
int result = fileChooser.showOpenDialog(frame);
|
||||||
if (result == JFileChooser.APPROVE_OPTION) {
|
if (result == JFileChooser.APPROVE_OPTION) {
|
||||||
if (fileChooser.getSelectedFile().isDirectory()) {
|
if (fileChooser.getSelectedFile().isDirectory()) {
|
||||||
outPathTemp = fileChooser.getSelectedFile().getAbsolutePath();
|
outPathTemp = fileChooser.getSelectedFile().getAbsolutePath()+"/";
|
||||||
pathDisplay.setText("Export path: " + outPathTemp);
|
pathDisplay.setText("Export path: " + outPathTemp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (actionEvent.getSource() == contBtn) {
|
if (actionEvent.getSource() == contBtn) {
|
||||||
switch (page) {
|
switch (page) {
|
||||||
case INTRO:
|
case INTRO:
|
||||||
if (!new File(Main.inpath + "psp2psarc.exe").exists()) { // we may have been here before // nag
|
if (!new File(Main.inpath + "psp2psarc.exe").exists()) { // we may have been here before // nag
|
||||||
frame.setEnabled(false);
|
frame.setEnabled(false);
|
||||||
int result = JOptionPane.showConfirmDialog(frame, "Firestar needs to download additional software to function. Setup is automatic and will only take a few minutes.\nIf you select NO, you will have to download additional dependencies later on.\n\nContinue?", "Firestar Setup", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
int result = JOptionPane.showConfirmDialog(frame, "Firestar needs to download additional software to function. Setup is automatic and will only take a few minutes.\nIf you select NO, you will have to download additional dependencies later on.\n\nContinue?", "Firestar Setup", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||||
if (result == JOptionPane.YES_OPTION) {
|
if (result == JOptionPane.YES_OPTION) {
|
||||||
sdkInstalled = true;
|
sdkInstalled = true;
|
||||||
Thread downloaderPopupThread = new Thread(new Runnable() {
|
Thread downloaderPopupThread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Main.downloadDependenciesBeforeSetVisible(frame);
|
Main.downloadDependenciesBeforeSetVisible(frame);
|
||||||
frame.setEnabled(true);
|
frame.setEnabled(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
downloaderPopupThread.start();
|
downloaderPopupThread.start();
|
||||||
} else {
|
} else {
|
||||||
frame.setEnabled(true);
|
frame.setEnabled(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sdkInstalled = true;
|
sdkInstalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
page = Pages.PSARC;
|
page = Pages.PSARC;
|
||||||
try {
|
try {
|
||||||
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconPSARC.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconPSARC.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
||||||
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
||||||
picLabel.setText("");
|
picLabel.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
contBtn.setEnabled(false);
|
contBtn.setEnabled(false);
|
||||||
contBtn.setBackground(new Color(102, 74, 58)); //brown
|
contBtn.setBackground(new Color(102, 74, 58)); //brown
|
||||||
refreshChecklist();
|
refreshChecklist();
|
||||||
inputContainer.setVisible(true);
|
inputContainer.setVisible(true);
|
||||||
checklistContainer.setVisible(true);
|
checklistContainer.setVisible(true);
|
||||||
if (!sdkInstalled) {
|
if (!sdkInstalled) {
|
||||||
PSARC_downBtn.setEnabled(false);
|
PSARC_downBtn.setEnabled(false);
|
||||||
PSARC_downBtn.setBackground(new Color(102, 74, 58)); //brown
|
PSARC_downBtn.setBackground(new Color(102, 74, 58)); //brown
|
||||||
}
|
}
|
||||||
|
|
||||||
instructions.setText("<html>\n" +
|
instructions.setText("<html>\n" +
|
||||||
" <head>\n" +
|
" <head>\n" +
|
||||||
" \n" +
|
" \n" +
|
||||||
" </head>\n" +
|
" </head>\n" +
|
||||||
" <body>\n" +
|
" <body>\n" +
|
||||||
@@ -220,24 +213,24 @@ public class WilkinsCoffee implements ActionListener {
|
|||||||
" </body>\n" +
|
" </body>\n" +
|
||||||
"</html>\n");
|
"</html>\n");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PSARC:
|
case PSARC:
|
||||||
page = Pages.EXPORT_LOCATION;
|
page = Pages.EXPORT_LOCATION;
|
||||||
try {
|
try {
|
||||||
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconEXPORT.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconEXPORT.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
||||||
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
||||||
picLabel.setText("");
|
picLabel.setText("");
|
||||||
}
|
}
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
inputContainer.setVisible(false);
|
inputContainer.setVisible(false);
|
||||||
checklistContainer.setVisible(false);
|
checklistContainer.setVisible(false);
|
||||||
inputContainer2.setVisible(true);
|
inputContainer2.setVisible(true);
|
||||||
|
|
||||||
instructions.setText("<html>\n" +
|
instructions.setText("<html>\n" +
|
||||||
" <head>\n" +
|
" <head>\n" +
|
||||||
" \n" +
|
" \n" +
|
||||||
" </head>\n" +
|
" </head>\n" +
|
||||||
" <body>\n" +
|
" <body>\n" +
|
||||||
@@ -250,25 +243,25 @@ public class WilkinsCoffee implements ActionListener {
|
|||||||
" </body>\n" +
|
" </body>\n" +
|
||||||
"</html>\n");
|
"</html>\n");
|
||||||
|
|
||||||
pathDisplay.setText("Export path: " + outPathTemp);
|
pathDisplay.setText("Export path: " + outPathTemp);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case EXPORT_LOCATION:
|
case EXPORT_LOCATION:
|
||||||
page = Pages.DONE;
|
page = Pages.DONE;
|
||||||
try {
|
try {
|
||||||
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconDONE.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
logo = ImageIO.read(Main.class.getResourceAsStream("/setupIconDONE.png")).getScaledInstance(96, 96, Image.SCALE_SMOOTH);
|
||||||
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
picLabel.setIcon(new ImageIcon(logo));picLabel.setText("");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
System.out.println("ERROR: Missing resource in Wilkins. Page will be without images.");
|
||||||
picLabel.setText("");
|
picLabel.setText("");
|
||||||
}
|
}
|
||||||
inputContainer2.setVisible(false);
|
inputContainer2.setVisible(false);
|
||||||
Main.outpath = outPathTemp + "/";
|
Main.outpath = outPathTemp;
|
||||||
Main.repatch = true;
|
Main.repatch = true;
|
||||||
Main.writeConf();
|
Main.writeConf();
|
||||||
|
|
||||||
instructions.setText("<html>\n" +
|
instructions.setText("<html>\n" +
|
||||||
" <head>\n" +
|
" <head>\n" +
|
||||||
" \n" +
|
" \n" +
|
||||||
" </head>\n" +
|
" </head>\n" +
|
||||||
" <body>\n" +
|
" <body>\n" +
|
||||||
@@ -278,48 +271,48 @@ public class WilkinsCoffee implements ActionListener {
|
|||||||
" </body>\n" +
|
" </body>\n" +
|
||||||
"</html>\n");
|
"</html>\n");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DONE:
|
case DONE:
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
new MissPiggy().Action();
|
new MissPiggy().Action();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("ERROR: Setup page-flip event listener didn't drink any Wilkins Coffee. Get a programmer!");
|
throw new UnsupportedOperationException("ERROR: Setup page-flip event listener didn't drink any Wilkins Coffee. Get a programmer!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshChecklist() {
|
private void refreshChecklist() {
|
||||||
ImageIcon positive = new ImageIcon(Main.class.getResource("/lightPositive.png"));
|
ImageIcon positive = new ImageIcon(Main.class.getResource("/lightPositive.png"));
|
||||||
ImageIcon negative = new ImageIcon(Main.class.getResource("/lightNegative.png"));
|
ImageIcon negative = new ImageIcon(Main.class.getResource("/lightNegative.png"));
|
||||||
|
|
||||||
// enabling the continue button here leaves the previous one redundant,
|
// enabling the continue button here leaves the previous one redundant,
|
||||||
// but it's needed to ensure we don't force a redownload if the setup is interrupted
|
// but it's needed to ensure we don't force a redownload if the setup is interrupted
|
||||||
|
|
||||||
if(new File(Main.inpath + "data.psarc").exists()) {
|
if(new File(Main.inpath + "data.psarc").exists()) {
|
||||||
checklistBase.setIcon(positive);
|
checklistBase.setIcon(positive);
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
} else {checklistBase.setIcon(negative);}
|
} else {checklistBase.setIcon(negative);}
|
||||||
if(new File(Main.inpath + "data1.psarc").exists()) {
|
if(new File(Main.inpath + "data1.psarc").exists()) {
|
||||||
checklistPatch1.setIcon(positive);
|
checklistPatch1.setIcon(positive);
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
} else {checklistPatch1.setIcon(negative);}
|
} else {checklistPatch1.setIcon(negative);}
|
||||||
if(new File(Main.inpath + "data2.psarc").exists()) {
|
if(new File(Main.inpath + "data2.psarc").exists()) {
|
||||||
checklistPatch2.setIcon(positive);
|
checklistPatch2.setIcon(positive);
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
} else {checklistPatch2.setIcon(negative);}
|
} else {checklistPatch2.setIcon(negative);}
|
||||||
if(new File(Main.inpath + "dlc1.psarc").exists()) {
|
if(new File(Main.inpath + "dlc1.psarc").exists()) {
|
||||||
checklistHD.setIcon(positive);
|
checklistHD.setIcon(positive);
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
} else {checklistHD.setIcon(negative);}
|
} else {checklistHD.setIcon(negative);}
|
||||||
if(new File(Main.inpath + "dlc2.psarc").exists()) {
|
if(new File(Main.inpath + "dlc2.psarc").exists()) {
|
||||||
checklistFury.setIcon(positive);
|
checklistFury.setIcon(positive);
|
||||||
contBtn.setEnabled(true);
|
contBtn.setEnabled(true);
|
||||||
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
contBtn.setBackground(new Color(221, 88, 11)); //orange
|
||||||
} else {checklistFury.setIcon(negative);}
|
} else {checklistFury.setIcon(negative);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8222
firestar/src/main/resources/post.fscript
Normal file
8222
firestar/src/main/resources/post.fscript
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
|||||||
netbeans.hint.jdkPlatform=JDK_22__System_
|
netbeans.hint.jdkPlatform=JDK_17__System_
|
||||||
|
|||||||
Reference in New Issue
Block a user