20 Commits
Author SHA1 Message Date
NotCoded 9efd960153 fix not being able to download fabric from the launcher (technically) 2024-08-07 17:58:11 +02:00
NotCoded 76852b00fc actually fix size changing when moving tabs 2024-08-02 13:25:20 +02:00
NotCoded 951016e39d woahh
- change combat test 8 to archive.org link
- improve error showing to user
- make install location and button not change sizes when moving tabs
2024-08-02 13:19:42 +02:00
NotCoded e3442033df no more null!! 2024-05-25 21:09:49 +02:00
NotCoded 29209c45d9 bump version 2024-05-25 20:54:23 +02:00
NotCoded 49899f08f2 fix path not getting recognized on mac 2024-05-25 20:53:19 +02:00
NotCoded a3caa6045c update icon & .gitignore 2024-05-04 20:20:15 +02:00
NotCoded e637cf19a8 Merge branch 'main' into dev 2024-03-27 11:44:56 +01:00
NotCoded 7c7356be7e add new images 2024-03-27 11:41:46 +01:00
NotCoded 58bca1826f tweaks to http in utils 2024-03-26 22:36:52 +01:00
NotCoded b473234383 change cts 8 download link 2024-03-26 22:29:15 +01:00
NotCoded eed3cc1921 add icon to taskbar, add view cts modlist as option in fabric when done installing 2024-03-26 21:44:58 +01:00
NotCoded 3cdad232b9 errors get shown now 2024-03-07 21:14:31 +01:00
NotCoded efe491ca2d bump version + remove unnecessary stuff 2024-03-07 20:48:51 +01:00
NotCoded 9f005185bc Update README.md 2023-10-24 07:21:14 +02:00
NotCoded 45938bd323 Merge pull request #2 from nexia-cts/dev
add installing fabric support
2023-10-23 18:45:11 +02:00
NotCoded a479383fc9 fix minor bug (if you cant fix it then remove it!) 2023-10-22 16:11:04 +02:00
NotCoded b6e473111c i think its basically done now! 2023-10-22 15:03:48 +02:00
NotCoded 7dbbc87874 listen, it's scuffed but it works 👍 (fabric) 2023-10-21 21:12:40 +02:00
NotCoded ed51370c56 update wiki links 2023-09-27 18:35:18 +02:00
23 changed files with 535 additions and 91 deletions

No files matched your search

-1
View File
@@ -1 +0,0 @@
*.gif filter=lfs diff=lfs merge=lfs -text
+65 -1
View File
@@ -1,3 +1,63 @@
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
@@ -37,4 +97,8 @@ bin/
.vscode/
### Mac OS ###
.DS_Store
.DS_Store
### cache ###
cache/
+15 -4
View File
@@ -1,14 +1,25 @@
# Combat Test Installer
The combat test installer allows you to install the combat test snapshots made by jeb_, such as [Combat Test 8c](https://minecraft.fandom.com/wiki/Java_Edition_Combat_Test_8c) *(latest)*, or [1.14.3 - Combat Test](https://minecraft.fandom.com/wiki/Java_Edition_1.14.3_-_Combat_Test) *(first)*
![launcher_opened](https://raw.githubusercontent.com/nexia-cts/combat-test-installer/main/assets/launcher_opened.png)
The combat test installer allows you to install the combat test snapshots made by jeb_, such as [Combat Test 8c](https://minecraft.wiki/w/Java_Edition_Combat_Test_8c) *(latest)*, or [1.14.3 - Combat Test](https://minecraft.wiki/w/Java_Edition_1.14.3_-_Combat_Test) *(first)*
![launcher_installed_box](https://raw.githubusercontent.com/nexia-cts/combat-test-installer/main/assets/launcher_installed_box.png)
It also allows you to **install fabric** for the Combat Test Snapshots that have it.
![showcase](https://media.githubusercontent.com/media/nexia-cts/combat-test-installer/main/assets/showcase.gif)
<br>
![Launcher opened in Vanilla Tab](https://raw.githubusercontent.com/nexia-cts/combat-test-installer/main/assets/launcher_opened_vanilla.png)
![Launcher successfull installed box in Vanilla](https://raw.githubusercontent.com/nexia-cts/combat-test-installer/main/assets/launcher_installed_box_vanilla.png)
<br>
![Launcher opened in Fabric Tab](https://raw.githubusercontent.com/nexia-cts/combat-test-installer/main/assets/launcher_opened_fabric.png)
![Launcher successfull installed box in Vanilla](https://raw.githubusercontent.com/nexia-cts/combat-test-installer/main/assets/launcher_installed_box_fabric.png)
# Credits
[Fabric Installer](https://github.com/FabricMC/fabric-installer/)
# License
Licensed under the [Apache License 2.0](https://github.com/nexia-cts/combat-test-installer/blob/main/LICENSE).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
View File
Binary file not shown.
+1 -1
View File
@@ -7,7 +7,7 @@ sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
group = 'com.nexia'
version = '1.0.1'
version = '1.0.4'
repositories {
mavenCentral()
@@ -1,23 +1,30 @@
package com.nexia.installer;
import com.nexia.installer.util.InstallerHelper;
import com.nexia.installer.util.fabric.FabricInstallerHelper;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.lang.reflect.Method;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class InstallerGUI extends JFrame {
public static InstallerGUI instance;
public JPanel vanilla;
public JPanel fabric;
public JTabbedPane pane;
public InstallerGUI() {
InstallerHelper helper = new InstallerHelper();
JPanel panel = helper.setPanel(this);
this.vanilla = new InstallerHelper().setPanel(this);
this.fabric = new FabricInstallerHelper().setPanel(this);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
add(panel);
instance = this;
}
@@ -43,14 +50,38 @@ public class InstallerGUI extends JFrame {
}
InstallerGUI gui = new InstallerGUI();
gui.pane = new JTabbedPane(JTabbedPane.TOP);
gui.pane.addTab(Main.BUNDLE.getString("installer.tab.vanilla"), gui.vanilla);
gui.pane.addTab(Main.BUNDLE.getString("installer.tab.fabric"), gui.fabric);
gui.setContentPane(gui.pane);
gui.updateSize(true);
gui.setTitle(Main.BUNDLE.getString("installer.title"));
gui.setIconImage(Main.icon);
gui.setTaskBarImage(Main.icon);
gui.setLocationRelativeTo(null);
gui.setVisible(true);
}
public void updateSize(boolean updateMinimum) {
private void setTaskBarImage(Image image) {
try {
// Only supported in Java 9 +
Class<?> taskbarClass = Class.forName("java.awt.Taskbar");
Method getTaskbar = taskbarClass.getDeclaredMethod("getTaskbar");
Method setIconImage = taskbarClass.getDeclaredMethod("setIconImage", Image.class);
Object taskbar = getTaskbar.invoke(null);
setIconImage.invoke(taskbar, image);
} catch (Exception e) {
// Ignored, running on Java 8
}
}
private void updateSize(boolean updateMinimum) {
if (updateMinimum) setMinimumSize(null);
setPreferredSize(null);
pack();
+5 -7
View File
@@ -36,16 +36,14 @@ public class Main {
public static void main(String[] args) throws UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException {
if(System.getProperty("os.name").startsWith("Windows")){
os = OS.LINUX;
if (System.getProperty("os.name").contains("win")) {
os = OS.WINDOWS;
System.setProperty("javax.net.ssl.trustStoreType", "WINDOWS-ROOT");
}
if(System.getProperty("os.name").startsWith("lin"))
os = OS.LINUX;
if(System.getProperty("os.name").startsWith("mac"))
} else if (System.getProperty("os.name").contains("mac")) {
os = OS.MAC;
}
icon = Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemClassLoader().getResource("icon.png"));
InstallerGUI.load();
@@ -6,23 +6,23 @@ import java.util.List;
public class VersionHandler {
public static List<GameVersion> versions = new ArrayList<>();
public static GameVersion CombatTest8c = new GameVersion("Combat Test 8c", "1.16_combat-6", new Download("f76157734ee0611fbef7d636156f20fa67c34514", 7463, "https://www.rizecookey.net/dl/file/combat-test-patched/1_16_combat-6.zip"));
public static GameVersion CombatTest8c = new GameVersion("Combat Test 8c", "1.16_combat-6", new Download("f76157734ee0611fbef7d636156f20fa67c34514", "https://www.rizecookey.net/dl/file/combat-test-patched/1_16_combat-6.zip"));
public static GameVersion CombatTest8b = new GameVersion("Combat Test 8b", "1.16_combat-5", new Download("9b2b984d635d373564b50803807225c75d7fd447", 7044, "https://launcher.mojang.com/experiments/combat/9b2b984d635d373564b50803807225c75d7fd447/1_16_combat-5.zip"));
public static GameVersion CombatTest8b = new GameVersion("Combat Test 8b", "1.16_combat-5", new Download("9b2b984d635d373564b50803807225c75d7fd447", "https://launcher.mojang.com/experiments/combat/9b2b984d635d373564b50803807225c75d7fd447/1_16_combat-5.zip"));
public static GameVersion CombatTest8 = new GameVersion("Combat Test 8", "1.16_combat-4", new Download("b4306b421183bd084b2831bd8d33a5db05ae9f9c", 7046, "https://cdn.discordapp.com/attachments/369990015096455168/947864881028272198/1_16_combat-4.zip"));
public static GameVersion CombatTest8 = new GameVersion("Combat Test 8", "1.16_combat-4", new Download("b4306b421183bd084b2831bd8d33a5db05ae9f9c", "https://archive.org/download/1-16-combat-4_202404/1_16_combat-4.zip"));
public static GameVersion CombatTest7c = new GameVersion("Combat Test 7c", "1.16_combat-3", new Download("2557b99d95588505e988886220779087d7d6b1e9", 7049, "https://piston-data.mojang.com/experiments/combat/2557b99d95588505e988886220779087d7d6b1e9/1_16_combat-3.zip"));
public static GameVersion CombatTest7c = new GameVersion("Combat Test 7c", "1.16_combat-3", new Download("2557b99d95588505e988886220779087d7d6b1e9", "https://piston-data.mojang.com/experiments/combat/2557b99d95588505e988886220779087d7d6b1e9/1_16_combat-3.zip"));
public static GameVersion CombatTest7b = new GameVersion("Combat Test 7b", "1.16_combat-2", new Download("43266ea8f2c20601d9fb264d5aa85df8052abc9e", 7051, "https://archive.org/download/Combat_Test_7ab/1_16_combat-2.zip"));
public static GameVersion CombatTest7 = new GameVersion("Combat Test 7", "1.16_combat-1", new Download("47bb5be6cb3ba215539ee97dfae66724c73c3dd5", 7045, "https://archive.org/download/Combat_Test_7ab/1_16_combat-1.zip"));
public static GameVersion CombatTest7b = new GameVersion("Combat Test 7b", "1.16_combat-2", new Download("43266ea8f2c20601d9fb264d5aa85df8052abc9e", "https://archive.org/download/Combat_Test_7ab/1_16_combat-2.zip"));
public static GameVersion CombatTest7 = new GameVersion("Combat Test 7", "1.16_combat-1", new Download("47bb5be6cb3ba215539ee97dfae66724c73c3dd5", "https://archive.org/download/Combat_Test_7ab/1_16_combat-1.zip"));
public static GameVersion CombatTest6 = new GameVersion("Combat Test 6", "1.16_combat-0", new Download("5a8ceec8681ed96ab6ecb9607fb5d19c8a755559", 7049, "https://piston-data.mojang.com/experiments/combat/5a8ceec8681ed96ab6ecb9607fb5d19c8a755559/1_16_combat-0.zip"));
public static GameVersion CombatTest5 = new GameVersion("Combat Test 5", "1.15_combat-6", new Download("52263d42a626b40c947e523128f7a195ec5af76a", 7061, "https://piston-data.mojang.com/experiments/combat/52263d42a626b40c947e523128f7a195ec5af76a/1_15_combat-6.zip"));
public static GameVersion CombatTest4 = new GameVersion("Combat Test 4", "1.15_combat-1", new Download("ac11ea96f3bb2fa2b9b76ab1d20cacb1b1f7ef60", 7059, "https://piston-data.mojang.com/experiments/combat/ac11ea96f3bb2fa2b9b76ab1d20cacb1b1f7ef60/1_15_combat-1.zip"));
public static GameVersion CombatTest3 = new GameVersion("Combat Test 3", "1.14_combat-3", new Download("0f209c9c84b81c7d4c88b4632155b9ae550beb89", 6433, "https://piston-data.mojang.com/experiments/combat/0f209c9c84b81c7d4c88b4632155b9ae550beb89/1_14_combat-3.zip"));
public static GameVersion CombatTest2 = new GameVersion("Combat Test 2", "1.14_combat-0", new Download("d164bb6ecc5fca9ac02878c85f11befae61ac1ca", 6287, "https://piston-data.mojang.com/experiments/combat/d164bb6ecc5fca9ac02878c85f11befae61ac1ca/1_14_combat-0.zip"));
public static GameVersion CombatTest1 = new GameVersion("1.14.3 - Combat Test", "1.14_combat-212796", new Download("610f5c9874ba8926d5ae1bcce647e5f0e6e7c889",4843, "https://piston-data.mojang.com/experiments/combat/610f5c9874ba8926d5ae1bcce647e5f0e6e7c889/1_14_combat-212796.zip"));
public static GameVersion CombatTest6 = new GameVersion("Combat Test 6", "1.16_combat-0", new Download("5a8ceec8681ed96ab6ecb9607fb5d19c8a755559", "https://piston-data.mojang.com/experiments/combat/5a8ceec8681ed96ab6ecb9607fb5d19c8a755559/1_16_combat-0.zip"));
public static GameVersion CombatTest5 = new GameVersion("Combat Test 5", "1.15_combat-6", new Download("52263d42a626b40c947e523128f7a195ec5af76a", "https://piston-data.mojang.com/experiments/combat/52263d42a626b40c947e523128f7a195ec5af76a/1_15_combat-6.zip"));
public static GameVersion CombatTest4 = new GameVersion("Combat Test 4", "1.15_combat-1", new Download("ac11ea96f3bb2fa2b9b76ab1d20cacb1b1f7ef60", "https://piston-data.mojang.com/experiments/combat/ac11ea96f3bb2fa2b9b76ab1d20cacb1b1f7ef60/1_15_combat-1.zip"));
public static GameVersion CombatTest3 = new GameVersion("Combat Test 3", "1.14_combat-3", new Download("0f209c9c84b81c7d4c88b4632155b9ae550beb89", "https://piston-data.mojang.com/experiments/combat/0f209c9c84b81c7d4c88b4632155b9ae550beb89/1_14_combat-3.zip"));
public static GameVersion CombatTest2 = new GameVersion("Combat Test 2", "1.14_combat-0", new Download("d164bb6ecc5fca9ac02878c85f11befae61ac1ca", "https://piston-data.mojang.com/experiments/combat/d164bb6ecc5fca9ac02878c85f11befae61ac1ca/1_14_combat-0.zip"));
public static GameVersion CombatTest1 = new GameVersion("1.14.3 - Combat Test", "1.14_combat-212796", new Download("610f5c9874ba8926d5ae1bcce647e5f0e6e7c889", "https://piston-data.mojang.com/experiments/combat/610f5c9874ba8926d5ae1bcce647e5f0e6e7c889/1_14_combat-212796.zip"));
public static class GameVersion {
String version;
@@ -52,12 +52,10 @@ public class VersionHandler {
public static class Download {
public final String sha1;
public final long size;
public final String url;
public Download(String sha1, long size, String url) {
public Download(String sha1, String url) {
this.sha1 = sha1;
this.size = size;
this.url = url;
}
}
@@ -0,0 +1,33 @@
package com.nexia.installer.util;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpAPI {
public static String userAgent = "Mozilla/5.0 (compatible; combat-test-installer; +https://github.com/nexia-cts/combat-test-installer)";
public static String get(String url) {
try {
URL apiUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
connection.setRequestProperty("User-Agent", userAgent);
connection.setRequestMethod("GET");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
connection.disconnect();
return response.toString();
} catch (Exception ignored) { return null; }
}
}
@@ -42,6 +42,7 @@ public class InstallerHelper {
installLocation = new JTextField(20),
selectFolderButton = new JButton());
selectFolderButton.setText("...");
// It looks better when the width is set to height, so.....
selectFolderButton.setPreferredSize(new Dimension(installLocation.getPreferredSize().height, installLocation.getPreferredSize().height));
selectFolderButton.addActionListener(e -> InstallerGUI.selectInstallLocation(() -> installLocation.getText(), s -> installLocation.setText(s)));
@@ -55,9 +56,9 @@ public class InstallerHelper {
buttonInstall.addActionListener(e -> {
buttonInstall.setEnabled(false);
try {
install();
} catch (IOException ex) {
throw new RuntimeException(ex);
launch();
} catch (Exception ex) {
InstallerUtils.showError(ex);
}
});
@@ -107,9 +108,9 @@ public class InstallerHelper {
c.gridx = 0;
}
private void install() throws IOException {
public void launch() throws IOException {
String stringGameVersion = (String) gameVersionComboBox.getSelectedItem();
assert stringGameVersion != null;
VersionHandler.GameVersion gameVersion = VersionHandler.identifyGameVersion(stringGameVersion);
if(gameVersion == null) return;
@@ -1,18 +1,14 @@
package com.nexia.installer.util;
import com.nexia.installer.InstallerGUI;
import com.nexia.installer.Main;
import com.nexia.installer.game.VersionHandler;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.*;
import java.text.MessageFormat;
import java.util.List;
@@ -33,10 +29,10 @@ public class InstallerUtils {
if (Main.os.equals(Main.OS.LINUX) && !Files.exists(dir)) {
// https://github.com/flathub/com.mojang.Minecraft
final Path flatpack = homeDir.resolve(".var").resolve("app").resolve("com.mojang.Minecraft").resolve(".minecraft");
final Path flatpak = homeDir.resolve(".var").resolve("app").resolve("com.mojang.Minecraft").resolve(".minecraft");
if (Files.exists(flatpack)) {
dir = flatpack;
if (Files.exists(flatpak)) {
dir = flatpak;
}
}
}
@@ -45,6 +41,40 @@ public class InstallerUtils {
return dir.toAbsolutePath().normalize();
}
public static void downloadVanilla(Path mcDir, VersionHandler.GameVersion gameVersion) throws IOException {
String alternativeCodeName = gameVersion.getCodeName().replaceAll("\\.", "_");
System.out.println("Installing " + gameVersion.getVersion() + " (" + gameVersion.getCodeName() + ")");
Path versionsDir = mcDir.resolve("versions");
if(!Files.exists(versionsDir)) Files.createDirectories(versionsDir);
Path profileDir = versionsDir.resolve(gameVersion.getCodeName());
Path profileJson = profileDir.resolve(gameVersion.getCodeName() + ".json");
Path aProfileDir = versionsDir.resolve(alternativeCodeName);
Path aProfileJson = aProfileDir.resolve(alternativeCodeName + ".json");
if(!Files.exists(profileDir)) Files.createDirectory(profileDir);
if(!Files.exists(profileJson)) Files.createFile(profileJson);
if(!Files.exists(aProfileDir)) Files.createDirectory(aProfileDir);
if(!Files.exists(aProfileJson)) Files.createFile(aProfileJson);
File zipFile = new File(versionsDir + "/" + gameVersion.getCodeName() + ".zip");
Utils.downloadFile(URI.create(gameVersion.getDownload().url).toURL(), zipFile.toPath());
Utils.extractZip(zipFile.toPath(), versionsDir);
Files.copy(aProfileJson, profileJson, StandardCopyOption.REPLACE_EXISTING);
//System.out.println(Utils.sha1String(zipFile.toPath()).equalsIgnoreCase(gameVersion.getDownload().sha1));
aProfileJson.toFile().delete();
aProfileDir.toFile().delete();
zipFile.delete();
}
public static void install(Path mcDir, VersionHandler.GameVersion gameVersion) {
if(mcDir == null || gameVersion == null) return;
@@ -70,34 +100,7 @@ public class InstallerUtils {
}
}
String alternativeCodeName = gameVersion.getCodeName().replaceAll("\\.", "_");
System.out.println("Installing " + gameVersion.getVersion() + " (" + gameVersion.getCodeName() + ")");
Path versionsDir = mcDir.resolve("versions");
Path profileDir = versionsDir.resolve(gameVersion.getCodeName());
Path profileJson = profileDir.resolve(gameVersion.getCodeName() + ".json");
Path aProfileDir = versionsDir.resolve(alternativeCodeName);
Path aProfileJson = aProfileDir.resolve(alternativeCodeName + ".json");
if(!Files.exists(profileDir)) Files.createDirectory(profileDir);
if(!Files.exists(profileJson)) Files.createFile(profileJson);
if(!Files.exists(aProfileDir)) Files.createDirectory(aProfileDir);
if(!Files.exists(aProfileJson)) Files.createFile(aProfileJson);
File zipFile = new File(versionsDir + "/" + gameVersion.getCodeName() + ".zip");
Utils.downloadFile(URI.create(gameVersion.getDownload().url).toURL(), zipFile.toPath());
Utils.extractZip(zipFile.toPath(), versionsDir);
Files.copy(aProfileJson, profileJson, StandardCopyOption.REPLACE_EXISTING);
aProfileJson.toFile().delete();
aProfileDir.toFile().delete();
zipFile.delete();
downloadVanilla(mcDir, gameVersion);
if (InstallerHelper.createProfile.isSelected()) {
if (launcherType == null) {
@@ -108,14 +111,14 @@ public class InstallerUtils {
}
showDone(gameVersion);
} catch (Exception e) {
e.printStackTrace();
InstallerUtils.showError(e);
} finally {
InstallerHelper.buttonInstall.setEnabled(true);
}
}).start();
}
private static ProfileInstaller.LauncherType showLauncherTypeSelection() {
public static ProfileInstaller.LauncherType showLauncherTypeSelection() {
Object[] options = { Main.BUNDLE.getString("installer.prompt.launcher.type.xbox"), Main.BUNDLE.getString("installer.prompt.launcher.type.win32")};
int result = JOptionPane.showOptionDialog(null,
@@ -135,7 +138,35 @@ public class InstallerUtils {
return result == JOptionPane.YES_OPTION ? ProfileInstaller.LauncherType.MICROSOFT_STORE : ProfileInstaller.LauncherType.WIN32;
}
private static void showDone(VersionHandler.GameVersion gameVersion) throws URISyntaxException, IOException {
public static void showError(Throwable throwable) {
throwable.printStackTrace();
showError(throwable.getClass().getSimpleName() + ": " + throwable.getMessage());
}
public static void showError(String error) {
Object[] options = {"Restart Program"};
int result = JOptionPane.showOptionDialog(null,
Main.BUNDLE.getString("installer.prompt.install.error") + "\n\n" + error,
Main.BUNDLE.getString("installer.title"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
options,
options[0]
);
if(result == JOptionPane.OK_OPTION) {
try {
InstallerGUI.instance.dispose();
Main.main(new String[]{});
} catch (Exception ignored) {
System.exit(0);
}
}
}
private static void showDone(VersionHandler.GameVersion gameVersion) {
Object[] options = {"OK", "Install Fabric"};
int result = JOptionPane.showOptionDialog(null,
MessageFormat.format(Main.BUNDLE.getString("installer.prompt.install.done"), gameVersion.getVersion()),
@@ -147,6 +178,6 @@ public class InstallerUtils {
options[0]
);
if(result == JOptionPane.NO_OPTION && Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) Desktop.getDesktop().browse(new URI("https://github.com/rizecookey/fabric-installer/releases"));
if(result == JOptionPane.NO_OPTION) InstallerGUI.instance.pane.setSelectedComponent(InstallerGUI.instance.fabric);
}
}
@@ -81,13 +81,17 @@ public class ProfileInstaller {
}
public enum LauncherType {
WIN32("launcher_profiles.json"),
MICROSOFT_STORE("launcher_profiles_microsoft_store.json");
WIN32("win32", "launcher_profiles.json"),
MICROSOFT_STORE("microsoft_store", "launcher_profiles_microsoft_store.json");
public final String profileJsonName;
LauncherType(String profileJsonName) {
public final String name;
LauncherType(String name, String profileJsonName) {
this.name = name;
this.profileJsonName = profileJsonName;
}
}
}
@@ -22,10 +22,12 @@ public class Utils {
public static final DateFormat ISO_8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
public static String userAgent = "Mozilla/5.0 (compatible; combat-test-installer; +https://github.com/nexia-cts/combat-test-installer)";
public static void extractZip(Path file, Path path) throws IOException {
ZipInputStream zipIn = new ZipInputStream(Files.newInputStream(Paths.get(file.toString())));
ZipEntry entry = zipIn.getNextEntry();
String filePath = "";
String filePath;
// iterates over entries in the zip file
while (entry != null) {
filePath = path + File.separator + entry.getName();
@@ -56,7 +58,7 @@ public class Utils {
Files.write(path, string.getBytes(StandardCharsets.UTF_8));
}
public static void downloadFile(URL url, Path path) throws IOException {
public static void downloadFile(URL url, Path path) {
try (InputStream in = openUrl(url)) {
Files.createDirectories(path.getParent());
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
@@ -67,7 +69,7 @@ public class Utils {
t.addSuppressed(t2);
}
throw t;
InstallerUtils.showError(t);
}
}
@@ -76,6 +78,7 @@ public class Utils {
private static InputStream openUrl(URL url) throws IOException {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("User-Agent", userAgent);
conn.setConnectTimeout(HTTP_TIMEOUT_MS);
conn.setReadTimeout(HTTP_TIMEOUT_MS);
conn.connect();
@@ -136,9 +139,7 @@ public class Utils {
return "data:image/png;base64," + Base64.getEncoder().encodeToString(Arrays.copyOf(ret, offset));
} catch (IOException e) {
e.printStackTrace();
return "furnace"; // Fallback to default icon if we cant load the icon.
}
return "furnace"; // Fallback to furnace icon if we cant load CTS icon.
}
}
@@ -0,0 +1,226 @@
package com.nexia.installer.util.fabric;
import com.nexia.installer.InstallerGUI;
import com.nexia.installer.Main;
import com.nexia.installer.game.VersionHandler;
import com.nexia.installer.util.HttpAPI;
import com.nexia.installer.util.InstallerHelper;
import com.nexia.installer.util.InstallerUtils;
import com.nexia.installer.util.Utils;
import mjson.Json;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Objects;
public class FabricInstallerHelper extends InstallerHelper {
public static JButton buttonInstall;
public static JButton buttonFabric;
public JComboBox<String> gameVersionComboBox;
public JTextField installLocation;
public JButton selectFolderButton;
public static JCheckBox createProfile;
@Override
public JPanel setPanel(InstallerGUI gui) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(new EmptyBorder(4, 4, 4, 4));
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(6, 4, 6, 4);
c.gridx = c.gridy = 0;
addRow(panel, c, "installer.prompt.game.version",
gameVersionComboBox = new JComboBox<>(),
createSpacer()
);
for(FabricVersionHandler.GameVersion version : FabricVersionHandler.versions) {
gameVersionComboBox.addItem(version.getVersion());
}
addRow(panel, c, "installer.prompt.select.location",
installLocation = new JTextField(23),
selectFolderButton = new JButton());
selectFolderButton.setText("...");
// It looks better when the width is set to height, so.....
selectFolderButton.setPreferredSize(new Dimension(installLocation.getPreferredSize().height, installLocation.getPreferredSize().height));
selectFolderButton.addActionListener(e -> InstallerGUI.selectInstallLocation(() -> installLocation.getText(), s -> installLocation.setText(s)));
addRow(panel, c, null,
createProfile = new JCheckBox(Main.BUNDLE.getString("installer.option.create.profile"), true));
installLocation.setText(InstallerUtils.findDefaultInstallDir().toString());
addLastRow(panel, c,
buttonInstall = new JButton(Main.BUNDLE.getString("installer.button.install")));
buttonInstall.addActionListener(e -> {
buttonInstall.setEnabled(false);
try {
launch();
} catch (Exception ex) {
InstallerUtils.showError(ex);
}
});
addLastRow(panel, c,
buttonFabric = new JButton(Main.BUNDLE.getString("installer.button.fabric")));
buttonFabric.addActionListener(e -> {
try {
Process process = Runtime.getRuntime().exec("java -jar cache/" + Objects.requireNonNull(getJarFile()).getName());
while(process.isAlive()) {
buttonFabric.setEnabled(false);
}
buttonFabric.setEnabled(true);
} catch (IOException ex) {
buttonFabric.setEnabled(false);
}
});
return panel;
}
@Override
public void launch() throws IOException {
String stringGameVersion = (String) gameVersionComboBox.getSelectedItem();
assert stringGameVersion != null;
FabricVersionHandler.GameVersion gameVersion = FabricVersionHandler.identifyGameVersion(stringGameVersion);
if(gameVersion == null) return;
Path mcPath = Paths.get(installLocation.getText());
if (!Files.exists(mcPath)) {
throw new RuntimeException(Main.BUNDLE.getString("installer.exception.no.launcher.directory"));
}
VersionHandler.GameVersion vanillaGameVersion = VersionHandler.identifyGameVersion(stringGameVersion);
if(vanillaGameVersion != null) {
// Fix not being able to download fabric from the launcher
Path versionsPath = mcPath.resolve("versions").resolve(vanillaGameVersion.getCodeName());
if(!Files.exists(versionsPath)) {
try {
InstallerUtils.downloadVanilla(mcPath, vanillaGameVersion);
} catch (Exception ignored) { }
}
}
System.out.println("Installing Fabric " + gameVersion.getVersion() + " (" + gameVersion.getCodeName() + ")");
String[] cmd2 = new String[]{"java", "-jar", "cache/" + Objects.requireNonNull(getJarFile()).getName(), "client", "-dir" + "\"" + mcPath.toAbsolutePath() + "\"", "-mcversion", gameVersion.codeName};
new Thread(() -> {
try {
Process process = Runtime.getRuntime().exec(cmd2);
BufferedInputStream successBufferedInputStream = new BufferedInputStream(process.getInputStream());
BufferedInputStream errorBufferedInputStream = new BufferedInputStream(process.getErrorStream());
synchronized (process) {
process.waitFor();
}
boolean hasError = false;
if (errorBufferedInputStream.available() != 0) {
errorBufferedInputStream.close();
hasError = true;
}
if (process.exitValue() != 0) hasError = true;
if (successBufferedInputStream.available() == 0) hasError = true;
if(hasError) {
InstallerUtils.showError("The Fabric Installer has had an unknown error.");
} else {
this.showDone(gameVersion);
}
} catch (Exception e) {
InstallerUtils.showError(e);
} finally {
buttonInstall.setEnabled(true);
}
}).start();
}
private File getJarFile() throws IOException {
Path currentDir = new File("").toPath();
Path cacheDir = currentDir.resolve("cache");
String fileName = "fabric-installer-" + getFabricVersion() + ".jar";
URL url = new URL("https://github.com/rizecookey/fabric-installer/releases/latest/download/" + fileName);
if(!Files.exists(cacheDir)) {
Files.createDirectories(cacheDir);
Utils.downloadFile(url, cacheDir.resolve(fileName));
return new File(cacheDir.toFile(), fileName);
}
if(Objects.requireNonNull(cacheDir.toFile().listFiles()).length == 0) {
Files.delete(cacheDir);
return getJarFile();
}
for(File file : Objects.requireNonNull(cacheDir.toFile().listFiles())) {
if(file.getName().equals(fileName)) {
return file;
} else {
file.delete();
Utils.downloadFile(url, cacheDir.resolve(fileName));
return new File(cacheDir.toFile(), fileName);
}
}
return null;
}
private String getFabricVersion() {
String version = "1.0.0";
try {
String response = HttpAPI.get("https://api.github.com/repos/rizecookey/fabric-installer/releases/latest");
Json jsonObject = Json.read(response);
Json jsonVersion = jsonObject.at("tag_name");
if(jsonVersion == null || !jsonVersion.isString()) return version;
return jsonVersion.asString();
} catch (Exception ignored) { return version; }
}
private void showDone(FabricVersionHandler.GameVersion gameVersion) throws URISyntaxException, IOException {
Object[] options = {"OK", "View CTS Mod List"};
int result = JOptionPane.showOptionDialog(null,
MessageFormat.format(Main.BUNDLE.getString("installer.prompt.install.done.fabric"), gameVersion.getVersion()),
Main.BUNDLE.getString("installer.title"),
JOptionPane.YES_NO_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null,
options,
options[0]
);
if(result == JOptionPane.NO_OPTION) {
URI url = new URI("https://github.com/nexia-cts/cts-mod-list");
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
Desktop.getDesktop().browse(url);
} else {
throw new UnsupportedOperationException("Failed to open " + url.toURL());
}
}
}
}
@@ -0,0 +1,42 @@
package com.nexia.installer.util.fabric;
import java.util.ArrayList;
import java.util.List;
public class FabricVersionHandler {
public static List<GameVersion> versions = new ArrayList<>();
public static GameVersion CombatTest8c = new GameVersion("Combat Test 8c", "1.16_combat-6");
public static GameVersion CombatTest7c = new GameVersion("Combat Test 7c", "1.16_combat-3");
public static GameVersion CombatTest1 = new GameVersion("1.14.3 - Combat Test", "1.14_combat-212796");
public static class GameVersion {
String version;
String codeName;
public GameVersion(String version, String codeName) {
this.version = version;
this.codeName = codeName;
FabricVersionHandler.versions.add(this);
}
public String getVersion() {
return version;
}
public String getCodeName() {
return codeName;
}
}
public static GameVersion identifyGameVersion(String version) {
if(version.trim().isEmpty()) return null;
for(GameVersion gameVersion : FabricVersionHandler.versions) {
if(version.equalsIgnoreCase(gameVersion.getCodeName()) || version.equalsIgnoreCase(gameVersion.getVersion())) return gameVersion;
}
return null;
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 244 KiB

@@ -2,9 +2,17 @@ installer.prompt.game.version=Minecraft Version:
installer.prompt.select.location=Select Install Location:
installer.button.install=Install
installer.prompt.install.done={0} has been installed, if you want to install fabric then click on the "Install Fabric" button.
installer.prompt.install.done.fabric={0} has been installed, if you want mods for fabric then you should check out the CTS Mod List by clicking on the "View CTS Mod List" button.
installer.exception.no.launcher.directory=No launcher directory found!
installer.exception.no.launcher.profile=No launcher profile.json found!
installer.prompt.launcher.type.body=The Combat Test Installer has detected 2 different installations of the Minecraft Launcher, which launcher do you wish to install the Combat Tests to?\n\n- Select Microsoft Store if you are playing Minecraft through the Xbox App or the Windows Store.\n- Select Standalone if you downloaded the Minecraft launcher directly from the Minecraft.net website.\n\nIf you are unsure try the Microsoft Store option first, you can always re-run the installer.
installer.prompt.launcher.type.xbox=Microsoft Store / Xbox
installer.prompt.launcher.type.win32=Standalone (Win32)
installer.title=Combat Test Installer
installer.option.create.profile=Create profile
installer.prompt.install.error=An error has occurred, click "Restart Program" to restart the program.\nIt would be appreciated if you sent a screenshot of this error to the developers.
installer.button.fabric=Open the Fabric Installer
installer.tab.vanilla=Vanilla
installer.tab.fabric=Fabric