From fd36fb54f64b7f6c24667f591073eaca91c0a835 Mon Sep 17 00:00:00 2001 From: bestsoft100 <163331759+Bestsoft101@users.noreply.github.com> Date: Sun, 14 Jul 2024 20:00:37 +0200 Subject: [PATCH] Vanilla launcher Babric and ASMLoader support --- src/BTA Babric.json | 340 ++++++++++++++++++ src/BTA Fabric.json | 334 +++++++++++++++++ src/b100/installer/Config.java | 8 + src/b100/installer/DownloadManager.java | 6 +- src/b100/installer/Installer.java | 45 ++- src/b100/installer/ModLoader.java | 17 + src/b100/installer/Utils.java | 25 +- src/b100/installer/Version.java | 16 + src/b100/installer/VersionList.java | 36 +- .../installer/gui/BetaCraftInstallerGUI.java | 57 +-- src/b100/installer/gui/InstallerGUI.java | 2 +- .../gui/VanillaLauncherInstallerGUI.java | 150 +++++++- src/b100/installer/gui/VersionComponent.java | 55 --- src/b100/installer/gui/VersionListGUI.java | 70 +++- .../installer/gui/utils/ComboBoxData.java | 52 +++ src/b100/installer/gui/utils/GuiUtils.java | 29 ++ .../installer/gui/utils/VersionComponent.java | 72 ++++ src/versions.json | 223 ++++++++++-- 18 files changed, 1347 insertions(+), 190 deletions(-) create mode 100644 src/BTA Babric.json create mode 100644 src/BTA Fabric.json create mode 100644 src/b100/installer/ModLoader.java create mode 100644 src/b100/installer/Version.java delete mode 100644 src/b100/installer/gui/VersionComponent.java create mode 100644 src/b100/installer/gui/utils/ComboBoxData.java create mode 100644 src/b100/installer/gui/utils/GuiUtils.java create mode 100644 src/b100/installer/gui/utils/VersionComponent.java diff --git a/src/BTA Babric.json b/src/BTA Babric.json new file mode 100644 index 0000000..3717864 --- /dev/null +++ b/src/BTA Babric.json @@ -0,0 +1,340 @@ +{ + "assetIndex": { + "totalSize": 49505710, + "id": "pre-1.6", + "known": true, + "url": "https://launchermeta.mojang.com/v1/packages/3d8e55480977e32acd9844e545177e69a52f594b/pre-1.6.json", + "sha1": "3d8e55480977e32acd9844e545177e69a52f594b", + "size": 74091 + }, + "assets": "pre-1.6", + "downloads": {}, + "id": "BTA Babric", + "javaVersion": { + "component": "java-runtime-alpha", + "majorVersion": 17 + }, + "libraries": [ + { + "name": "fabric-loader:fabric-loader:0.15.6-babric.6-bta", + "downloads": { + "artifact": { + "url": "https://github.com/Turnip-Labs/fabric-loader/releases/download/0.15.6-babric.6-bta/fabric-loader-0.15.6-babric.6-bta.jar", + "sha1": "6fa9b38569bca100e8a256a9dca04184279e7606", + "size": 1239823 + } + } + }, + { + "name": "org.ow2.asm:asm:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-analysis:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-commons:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-tree:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-util:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "net.fabricmc:sponge-mixin:0.13.3+mixin.0.8.5", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.slf4j:slf4j-api:1.7.30", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.slf4j:slf4j-log4j12:1.7.30", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-core:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "log4j:log4j:1.2.17", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-1.2-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-core:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-1.2-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "com.google.guava:guava:21.0", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "net.java.jinput:jinput:2.0.5", + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar", + "sha1": "39c7796b469a600f72380316f6b1f11db6c2c7c4", + "size": 208338 + } + } + }, + { + "name": "net.java.jutils:jutils:1.0.0", + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar", + "sha1": "e12fe1fda814bd348c1579329c86943d2cd3c6a6", + "size": 7508 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl:2.9.3", + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.3/lwjgl-2.9.3.jar", + "sha1": "3df168ac74e4a8c96562cdff24ad352e255bf89c", + "size": 1053471 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.3", + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.3/lwjgl_util-2.9.3.jar", + "sha1": "751f06b62424da056954c67288fd5c494431e350", + "size": 173911 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.3", + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-linux": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.3/lwjgl-platform-2.9.3-natives-linux.jar", + "sha1": "b1eafe80093381c56415731e1d64279e6140bcd0", + "size": 578675 + }, + "natives-osx": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.3/lwjgl-platform-2.9.3-natives-osx.jar", + "sha1": "6686cf6ddaa20b4290aa6599a09bc0d17369be05", + "size": 426817 + }, + "natives-windows": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.3/lwjgl-platform-2.9.3-natives-windows.jar", + "sha1": "fbc2afb3e288578e9942578decb6291a490549a0", + "size": 613744 + } + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3", + "rules": [ + { + "action": "allow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.1-nightly-20130708-debug3/lwjgl-2.9.1-nightly-20130708-debug3.jar", + "sha1": "884511652c756fac16b37236f863f346bd1ea121", + "size": 996625 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20130708-debug3", + "rules": [ + { + "action": "allow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.1-nightly-20130708-debug3/lwjgl_util-2.9.1-nightly-20130708-debug3.jar", + "sha1": "fb693ba4e22a85432a32e8a048893dc7a92f42ac", + "size": 173338 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20130708-debug3", + "rules": [ + { + "action": "allow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-osx": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.1-nightly-20130708-debug3/lwjgl-platform-2.9.1-nightly-20130708-debug3-natives-osx.jar", + "sha1": "a9b83ad85742cad09c3574a91b0423bac3f7a0f5", + "size": 458181 + } + } + } + }, + { + "name": "net.java.jinput:jinput-platform:2.0.5", + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-linux": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar", + "sha1": "7ff832a6eb9ab6a767f1ade2b548092d0fa64795", + "size": 10362 + }, + "natives-osx": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar", + "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232", + "size": 12186 + }, + "natives-windows": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar", + "sha1": "385ee093e01f587f30ee1c8a2ee7d408fd732e16", + "size": 155179 + } + } + } + }, + { + "name": "net.java.jinput:jinput-platform:2.0.5", + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-linux": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar", + "sha1": "7ff832a6eb9ab6a767f1ade2b548092d0fa64795", + "size": 10362 + }, + "natives-osx": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar", + "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232", + "size": 12186 + }, + "natives-windows": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar", + "sha1": "385ee093e01f587f30ee1c8a2ee7d408fd732e16", + "size": 155179 + } + } + } + } + ], + "mainClass": "net.fabricmc.loader.impl.launch.knot.KnotClient", + "minecraftArguments": "${auth_player_name} ${auth_session} --gameDir ${game_directory} --assetsDir ${game_assets}", + "minimumLauncherVersion": 7, + "releaseTime": "2011-07-07T22:00:00Z", + "time": "2024-07-08T13:50:33.192Z", + "type": "modified" +} \ No newline at end of file diff --git a/src/BTA Fabric.json b/src/BTA Fabric.json new file mode 100644 index 0000000..6121145 --- /dev/null +++ b/src/BTA Fabric.json @@ -0,0 +1,334 @@ +{ + "assetIndex": { + "totalSize": 49505710, + "id": "pre-1.6", + "known": true, + "url": "https://launchermeta.mojang.com/v1/packages/3d8e55480977e32acd9844e545177e69a52f594b/pre-1.6.json", + "sha1": "3d8e55480977e32acd9844e545177e69a52f594b", + "size": 74091 + }, + "assets": "pre-1.6", + "downloads": {}, + "id": "BTA Fabric", + "javaVersion": { + "component": "java-runtime-alpha", + "majorVersion": 17 + }, + "libraries": [ + { + "name": "net.fabricmc:fabric-loader:0.15.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-analysis:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-commons:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-tree:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.ow2.asm:asm-util:9.6", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "net.fabricmc:sponge-mixin:0.13.3+mixin.0.8.5", + "url": "https://maven.fabricmc.net/" + }, + { + "name": "org.slf4j:slf4j-api:1.7.30", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.slf4j:slf4j-log4j12:1.7.30", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-core:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "log4j:log4j:1.2.17", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-1.2-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-core:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "org.apache.logging.log4j:log4j-1.2-api:2.14.1", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "com.google.guava:guava:21.0", + "url": "https://repo.maven.apache.org/maven2/" + }, + { + "name": "net.java.jinput:jinput:2.0.5", + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar", + "sha1": "39c7796b469a600f72380316f6b1f11db6c2c7c4", + "size": 208338 + } + } + }, + { + "name": "net.java.jutils:jutils:1.0.0", + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar", + "sha1": "e12fe1fda814bd348c1579329c86943d2cd3c6a6", + "size": 7508 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl:2.9.3", + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.3/lwjgl-2.9.3.jar", + "sha1": "3df168ac74e4a8c96562cdff24ad352e255bf89c", + "size": 1053471 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.3", + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.3/lwjgl_util-2.9.3.jar", + "sha1": "751f06b62424da056954c67288fd5c494431e350", + "size": 173911 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.3", + "rules": [ + { + "action": "allow" + }, + { + "action": "disallow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-linux": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.3/lwjgl-platform-2.9.3-natives-linux.jar", + "sha1": "b1eafe80093381c56415731e1d64279e6140bcd0", + "size": 578675 + }, + "natives-osx": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.3/lwjgl-platform-2.9.3-natives-osx.jar", + "sha1": "6686cf6ddaa20b4290aa6599a09bc0d17369be05", + "size": 426817 + }, + "natives-windows": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.3/lwjgl-platform-2.9.3-natives-windows.jar", + "sha1": "fbc2afb3e288578e9942578decb6291a490549a0", + "size": 613744 + } + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3", + "rules": [ + { + "action": "allow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.1-nightly-20130708-debug3/lwjgl-2.9.1-nightly-20130708-debug3.jar", + "sha1": "884511652c756fac16b37236f863f346bd1ea121", + "size": 996625 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20130708-debug3", + "rules": [ + { + "action": "allow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "downloads": { + "artifact": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.1-nightly-20130708-debug3/lwjgl_util-2.9.1-nightly-20130708-debug3.jar", + "sha1": "fb693ba4e22a85432a32e8a048893dc7a92f42ac", + "size": 173338 + } + } + }, + { + "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20130708-debug3", + "rules": [ + { + "action": "allow", + "os": { + "name": "osx", + "version": "^10\\.5\\.\\d$" + } + } + ], + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-osx": { + "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.1-nightly-20130708-debug3/lwjgl-platform-2.9.1-nightly-20130708-debug3-natives-osx.jar", + "sha1": "a9b83ad85742cad09c3574a91b0423bac3f7a0f5", + "size": 458181 + } + } + } + }, + { + "name": "net.java.jinput:jinput-platform:2.0.5", + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-linux": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar", + "sha1": "7ff832a6eb9ab6a767f1ade2b548092d0fa64795", + "size": 10362 + }, + "natives-osx": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar", + "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232", + "size": 12186 + }, + "natives-windows": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar", + "sha1": "385ee093e01f587f30ee1c8a2ee7d408fd732e16", + "size": 155179 + } + } + } + }, + { + "name": "net.java.jinput:jinput-platform:2.0.5", + "natives": { + "linux": "natives-linux", + "osx": "natives-osx", + "windows": "natives-windows" + }, + "extract": { + "exclude": [ + "META-INF/" + ] + }, + "downloads": { + "classifiers": { + "natives-linux": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar", + "sha1": "7ff832a6eb9ab6a767f1ade2b548092d0fa64795", + "size": 10362 + }, + "natives-osx": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-osx.jar", + "sha1": "53f9c919f34d2ca9de8c51fc4e1e8282029a9232", + "size": 12186 + }, + "natives-windows": { + "url": "https://libraries.minecraft.net/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-windows.jar", + "sha1": "385ee093e01f587f30ee1c8a2ee7d408fd732e16", + "size": 155179 + } + } + } + } + ], + "mainClass": "net.fabricmc.loader.impl.launch.knot.KnotClient", + "minecraftArguments": "${auth_player_name} ${auth_session} --gameDir ${game_directory} --assetsDir ${game_assets}", + "minimumLauncherVersion": 7, + "releaseTime": "2011-07-07T22:00:00Z", + "time": "2024-07-08T13:50:33.192Z", + "type": "modified" +} \ No newline at end of file diff --git a/src/b100/installer/Config.java b/src/b100/installer/Config.java index 1562f97..8943cae 100644 --- a/src/b100/installer/Config.java +++ b/src/b100/installer/Config.java @@ -17,6 +17,8 @@ public static Config getInstance() { public String lastSelectedVersion; public String lastInstallType; + public String lastMinecraftDirectory; + public String lastBetaCraftDirectory; public long lastVersionQueryTime = 0; private Config() { @@ -56,6 +58,10 @@ public void parseConfig(String key, String value) { lastInstallType = value; }else if(key.equals("lastVersionQueryTime")) { lastVersionQueryTime = Long.parseLong(value); + }else if(key.equals("lastMinecraftDirectory")) { + lastMinecraftDirectory = value; + }else if(key.equals("lastBetaCraftDirectory")) { + lastBetaCraftDirectory = value; }else { throw new RuntimeException("Invalid Key: '" + key + "'!"); } @@ -74,6 +80,8 @@ public void save() { if(lastSelectedVersion != null) str.append("lastSelectedVersion:" + lastSelectedVersion + "\n"); if(lastInstallType != null) str.append("lastInstallType:" + lastInstallType + "\n"); + if(lastMinecraftDirectory != null) str.append("lastMinecraftDirectory:" + lastMinecraftDirectory + "\n"); + if(lastBetaCraftDirectory != null) str.append("lastBetaCraftDirectory:" + lastBetaCraftDirectory + "\n"); str.append("lastVersionQueryTime:" + lastVersionQueryTime + "\n"); StringUtils.saveStringToFile(configFile, str.toString()); diff --git a/src/b100/installer/DownloadManager.java b/src/b100/installer/DownloadManager.java index 425c489..6a08d32 100644 --- a/src/b100/installer/DownloadManager.java +++ b/src/b100/installer/DownloadManager.java @@ -20,7 +20,7 @@ public class DownloadManager { } public static String getDownloadUrl(String filename) { - JsonObject downloads = VersionList.getVersions().getObject("downloads"); + JsonObject downloads = VersionList.getJson().getObject("downloads"); return downloads.getString(filename); } @@ -86,5 +86,9 @@ public static void downloadFileAndPrintProgress(String url, File file) { }catch (Exception e) {} } } + + public static File getDownloadDirectory() { + return downloadDirectory; + } } diff --git a/src/b100/installer/Installer.java b/src/b100/installer/Installer.java index 6a64590..3cedd4a 100644 --- a/src/b100/installer/Installer.java +++ b/src/b100/installer/Installer.java @@ -7,35 +7,60 @@ public class Installer { private static File installerDirectory; private static boolean portable; + private static boolean offline; static { + portable = checkFileExists("portable"); + offline = checkFileExists("offline"); + + if(portable) { + installerDirectory = new File("").getAbsoluteFile(); + }else { + installerDirectory = Utils.getAppDirectory("bta-installer"); + } + + System.out.println("Installer Directory: '" + installerDirectory.getAbsolutePath() + "'"); + System.out.println("Portable Mode: " + portable); + System.out.println("Offline Mode: " + offline); + } + + private static boolean checkFileExists(String name) { InputStream stream = null; try { - stream = Installer.class.getResourceAsStream("/portable"); - - portable = stream != null; + stream = Installer.class.getResourceAsStream("/" + name); + if(stream != null) { + return true; + } }catch (Exception e) { - portable = false; }finally { try { stream.close(); }catch (Exception e) {} } - if(portable) { - installerDirectory = new File("").getAbsoluteFile(); - }else { - installerDirectory = Utils.getAppDirectory("bta-installer"); + try { + stream = Installer.class.getResourceAsStream("/" + name + ".txt"); + if(stream != null) { + return true; + } + }catch (Exception e) { + }finally { + try { + stream.close(); + }catch (Exception e) {} } - System.out.println("Installer Directory: '" + installerDirectory.getAbsolutePath() + "'"); - System.out.println("Portable Mode: " + portable); + return false; } public static boolean isPortable() { return portable; } + public static boolean isOffline() { + return offline; + } + public static File getInstallerDirectory() { return installerDirectory; } diff --git a/src/b100/installer/ModLoader.java b/src/b100/installer/ModLoader.java new file mode 100644 index 0000000..86a8465 --- /dev/null +++ b/src/b100/installer/ModLoader.java @@ -0,0 +1,17 @@ +package b100.installer; + +public enum ModLoader { + None, Babric, Fabric, ASMLoader; + + public String getDisplayName() { + if(this == None) { + return "No Mod Loader"; + } + return name(); + } + + @Override + public String toString() { + return getDisplayName(); + } +} \ No newline at end of file diff --git a/src/b100/installer/Utils.java b/src/b100/installer/Utils.java index 4028608..afa75a1 100644 --- a/src/b100/installer/Utils.java +++ b/src/b100/installer/Utils.java @@ -21,12 +21,11 @@ import javax.imageio.ImageIO; -import b100.installer.gui.utils.ImagePanel; import b100.utils.FileUtils; import b100.utils.StreamUtils; import b100.utils.StringUtils; -public class Utils { +public abstract class Utils { public static final int OS_WINDOWS = 0; public static final int OS_MAC = 1; @@ -234,14 +233,6 @@ public static BufferedImage readImage(String path) { } } - public static ImagePanel createImagePanel(String path) { - BufferedImage image = readImage(path); - if(image == null) { - throw new NullPointerException("Image is null!"); - } - return new ImagePanel(image); - } - public static void copyFile(File from, File to) { InputStream in = null; OutputStream out = null; @@ -278,6 +269,20 @@ public static Map loadProperties(File file) { return properties; } + public static String combineStringsSeperatedWithSpaces(List list) { + if(list == null || list.size() == 0) { + return ""; + } + StringBuilder argsStr = new StringBuilder(); + for(int i=0; i < list.size(); i++) { + if(i > 0) { + argsStr.append(' '); + } + argsStr.append(list.get(i)); + } + return argsStr.toString(); + } + public static void saveProperties(File file, Map properties) { List keys = new ArrayList<>(properties.keySet()); keys.sort(String.CASE_INSENSITIVE_ORDER); diff --git a/src/b100/installer/Version.java b/src/b100/installer/Version.java new file mode 100644 index 0000000..b496daf --- /dev/null +++ b/src/b100/installer/Version.java @@ -0,0 +1,16 @@ +package b100.installer; + +public class Version { + + public String name; + + public Version(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + +} diff --git a/src/b100/installer/VersionList.java b/src/b100/installer/VersionList.java index 245def5..ccf8e38 100644 --- a/src/b100/installer/VersionList.java +++ b/src/b100/installer/VersionList.java @@ -13,46 +13,49 @@ public class VersionList { - public static boolean useInternalVersionList = false; - - public static final int VERSION = 1; + public static final int VERSION = 2; public static final String URL = "https://raw.githubusercontent.com/Bestsoft101/BTA-Installer/main/src/versions.json"; public static final long QUERYTIME = 24L * 60L * 60L * 1000L; private static File versionListFile = new File(Installer.getInstallerDirectory(), "versions.json"); - private static boolean loadedVersions = false; - private static JsonObject versions; - public static JsonObject getVersions() { - if(!loadedVersions) { + public static JsonObject getJson() { + if(versions == null) { versions = readVersions(); - loadedVersions = true; } return versions; } public static JsonObject readVersions() { - if(!useInternalVersionList) { + if(!Installer.isOffline()) { long timeSinceLastQuery = System.currentTimeMillis() - Config.getInstance().lastVersionQueryTime; if(timeSinceLastQuery > QUERYTIME || !versionListFile.exists()) { refreshVersionList(); } - JsonObject versions = null; if(versionListFile.exists()) { versions = JsonParser.instance.parseFileContent(versionListFile); - if(versions.getInt("version") > VERSION) { - JOptionPane.showMessageDialog(InstallerGUI.instance.mainFrame, "Installer is outdated, version list may be incomplete!"); + int version = versions.getInt("version"); + if(version > VERSION) { + JOptionPane.showMessageDialog(null, "Installer is outdated, version list may be incomplete!"); + System.out.println("Installer is outdated!"); versions = null; + }else if(version < VERSION) { + JOptionPane.showMessageDialog(null, "Version list on the repository is outdated, using internal version list!"); + System.out.println("Version list is outdated!"); + versions = null; + }else { + System.out.println("Using downloaded version list"); } } }else { - System.out.println("Using internal version list!"); + System.out.println("Offline mode enabled!"); } if(versions == null) { + System.out.println("Loading internal version list"); versions = JsonParser.instance.parseStream(VanillaLauncherInstallerGUI.class.getResourceAsStream("/versions.json")); if(versions == null) { throw new NullPointerException("Could not read internal version list!"); @@ -76,8 +79,7 @@ public static void refreshVersionList() { try { DownloadManager.downloadFileAndPrintProgress(URL, versionListFile); - - loadedVersions = false; + versions = null; }catch (Exception e) { JOptionPane.showMessageDialog(InstallerGUI.instance.mainFrame, "Could not get the newest version list!"); e.printStackTrace(); @@ -87,7 +89,7 @@ public static void refreshVersionList() { public static List getAllVersions() { List versionList = new ArrayList<>(); - JsonObject versions = getVersions().getObject("versions"); + JsonObject versions = getJson().getObject("versions"); for(int i=0; i < versions.entryList().size(); i++) { versionList.add(versions.entryList().get(i).name); } @@ -96,7 +98,7 @@ public static List getAllVersions() { } public static JsonObject getVersion(String name) { - return getVersions().getObject("versions").getObject(name); + return getJson().getObject("versions").getObject(name); } } diff --git a/src/b100/installer/gui/BetaCraftInstallerGUI.java b/src/b100/installer/gui/BetaCraftInstallerGUI.java index 3b8a93f..42ba61b 100644 --- a/src/b100/installer/gui/BetaCraftInstallerGUI.java +++ b/src/b100/installer/gui/BetaCraftInstallerGUI.java @@ -1,22 +1,25 @@ package b100.installer.gui; -import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.JTextField; -import javax.swing.border.TitledBorder; import b100.installer.Config; import b100.installer.DownloadManager; +import b100.installer.ModLoader; import b100.installer.Utils; import b100.installer.VersionList; import b100.installer.gui.utils.GridPanel; +import b100.installer.gui.utils.GuiUtils; +import b100.installer.gui.utils.VersionComponent; import b100.json.element.JsonObject; import b100.utils.StringUtils; @@ -39,31 +42,25 @@ public BetaCraftInstallerGUI(InstallerGUI installerGUI) { getGridBagConstraints().insets.set(inset, inset, inset, inset); betacraftDirectoryTextfield = new JTextField(); - betacraftDirectoryTextfield.setText(getBetacraftDirectory().getAbsolutePath()); + betacraftDirectoryTextfield.setText(getBetaCraftDirectory()); instanceTextfield = new JTextField(); instanceTextfield.setText("Better Than Adventure!"); - versionComponent = new VersionComponent(); + List modLoaders = new ArrayList<>(); + modLoaders.add(ModLoader.None); + versionComponent = new VersionComponent(modLoaders, (version, modLoader) -> modLoader == ModLoader.None); startButton = new JButton("Install"); startButton.addActionListener(this); - add(Utils.createImagePanel("/logo.png"), 0, 0, 1, 1); - add(createTitledPanel(betacraftDirectoryTextfield, "BetaCraft Directory"), 0, 1, 1, 0); - add(createTitledPanel(instanceTextfield, "Instance"), 0, 2, 1, 0); + add(GuiUtils.createImagePanel("/logo.png"), 0, 0, 1, 1); + add(GuiUtils.createTitledPanel(betacraftDirectoryTextfield, "BetaCraft Directory"), 0, 1, 1, 0); + add(GuiUtils.createTitledPanel(instanceTextfield, "Instance"), 0, 2, 1, 0); add(versionComponent, 0, 3, 1, 0); add(startButton, 0, 4, 1, 0); } - public GridPanel createTitledPanel(Component component, String title) { - GridPanel panel = new GridPanel(); - panel.setBorder(new TitledBorder(title)); - panel.getGridBagConstraints().insets.set(4, 4, 4, 4); - panel.add(component, 0, 0, 1, 1); - return panel; - } - @Override public void actionPerformed(ActionEvent e) { new Thread(this).start(); @@ -86,22 +83,30 @@ public void run() { } public boolean install() { - String selectedVersion = versionComponent.getVersion(); - System.out.println("Selected Version: " + selectedVersion); + String selectedVersion = versionComponent.getSelectedVersion(); + ModLoader loader = versionComponent.getSelectedLoader(); + File betacraftDirectory = new File(betacraftDirectoryTextfield.getText()); + System.out.println("Selected Version: " + selectedVersion); + System.out.println("Selected Mod Loader: " + loader); + System.out.println("BetaCraft Directory: " + betacraftDirectory.getAbsolutePath()); + + // Update config Config config = Config.getInstance(); config.lastSelectedVersion = selectedVersion; config.lastInstallType = INSTALL_TYPE; + config.lastBetaCraftDirectory = betacraftDirectory.getAbsolutePath(); config.save(); - JsonObject versionObject = VersionList.getVersion(selectedVersion); - - File betacraftDirectory = new File(betacraftDirectoryTextfield.getText()); + // Validate path if(!betacraftDirectory.exists() || !betacraftDirectory.isDirectory()) { JOptionPane.showMessageDialog(this, "Invalid BetaCraft Directory: '" + betacraftDirectory.getAbsolutePath() + "'!"); + config.lastBetaCraftDirectory = null; + config.save(); return false; } - + + JsonObject versionObject = VersionList.getVersion(selectedVersion); JsonObject betaCraftObject = versionObject.getObject("betacraft"); if(betaCraftObject == null) { JOptionPane.showMessageDialog(this, "Version '" + selectedVersion + "' is not compatible with BetaCraft!"); @@ -183,7 +188,15 @@ public boolean install() { return true; } - public static File getBetacraftDirectory() { + public String getBetaCraftDirectory() { + String last = Config.getInstance().lastBetaCraftDirectory; + if(last != null) { + return last; + } + return getDefaultBetacraftDirectory().getAbsolutePath(); + } + + public static File getDefaultBetacraftDirectory() { String folder = null; String os = System.getProperty("os.name").toLowerCase(); diff --git a/src/b100/installer/gui/InstallerGUI.java b/src/b100/installer/gui/InstallerGUI.java index e28226d..af36e1a 100644 --- a/src/b100/installer/gui/InstallerGUI.java +++ b/src/b100/installer/gui/InstallerGUI.java @@ -29,7 +29,7 @@ public InstallerGUI() { } instance = this; - mainFrame = new JFrame("BTA Installer" + (Installer.isPortable() ? " (Portable Mode)" : "")); + mainFrame = new JFrame("BTA Installer" + (Installer.isPortable() ? " (Portable Mode)" : "") + (Installer.isOffline() ? " (Offline Mode)" : "")); mainFrame.setMinimumSize(new Dimension(400, 320)); mainPanel = new GridPanel(); diff --git a/src/b100/installer/gui/VanillaLauncherInstallerGUI.java b/src/b100/installer/gui/VanillaLauncherInstallerGUI.java index 32df381..b004588 100644 --- a/src/b100/installer/gui/VanillaLauncherInstallerGUI.java +++ b/src/b100/installer/gui/VanillaLauncherInstallerGUI.java @@ -3,22 +3,30 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import javax.swing.JButton; import javax.swing.JOptionPane; +import javax.swing.JTextField; import b100.installer.Config; import b100.installer.DownloadManager; +import b100.installer.ModLoader; import b100.installer.Utils; import b100.installer.VersionList; +import b100.installer.gui.VersionListGUI.VersionFilter; import b100.installer.gui.utils.GridPanel; +import b100.installer.gui.utils.GuiUtils; +import b100.installer.gui.utils.VersionComponent; import b100.json.JsonParser; +import b100.json.element.JsonElement; import b100.json.element.JsonObject; import b100.utils.StringUtils; @SuppressWarnings("serial") -public class VanillaLauncherInstallerGUI extends GridPanel implements ActionListener, Runnable { +public class VanillaLauncherInstallerGUI extends GridPanel implements ActionListener, Runnable, VersionFilter { public static final String INSTALL_TYPE = "vanilla"; @@ -26,6 +34,7 @@ public class VanillaLauncherInstallerGUI extends GridPanel implements ActionList public VersionComponent versionComponent; public JButton installButton; + public JTextField minecraftDirectoryTextfield; public VanillaLauncherInstallerGUI(InstallerGUI installerGUI) { this.installerGUI = installerGUI; @@ -33,15 +42,22 @@ public VanillaLauncherInstallerGUI(InstallerGUI installerGUI) { int inset = 4; getGridBagConstraints().insets.set(inset, inset, inset, inset); - versionComponent = new VersionComponent(); + minecraftDirectoryTextfield = new JTextField(); + minecraftDirectoryTextfield.setText(getMinecraftDirectory()); + + List modLoaders = new ArrayList<>(); + modLoaders.add(ModLoader.None); + modLoaders.add(ModLoader.ASMLoader); + modLoaders.add(ModLoader.Babric); + versionComponent = new VersionComponent(modLoaders, this); installButton = new JButton("Install"); installButton.addActionListener(this); - add(Utils.createImagePanel("/logo.png"), 0, 0, 1, 1); - add(versionComponent, 0, 1, 1, 0); - add(installButton, 0, 2, 1, 0); - + add(GuiUtils.createImagePanel("/logo.png"), 0, 0, 1, 1); + add(GuiUtils.createTitledPanel(minecraftDirectoryTextfield, "Minecraft Directory"), 0, 1, 1, 0); + add(versionComponent, 0, 2, 1, 0); + add(installButton, 0, 3, 1, 0); } @Override @@ -50,7 +66,7 @@ public void actionPerformed(ActionEvent e) { new Thread(this).start(); } } - + @Override public void run() { installButton.setEnabled(false); @@ -68,16 +84,30 @@ public void run() { } public boolean install() { - String selectedVersion = versionComponent.getVersion(); + String selectedVersion = versionComponent.getSelectedVersion(); + ModLoader loader = versionComponent.getSelectedLoader(); + File minecraftDirectory = new File(minecraftDirectoryTextfield.getText()); + System.out.println("Selected Version: " + selectedVersion); + System.out.println("Selected Mod Loader: " + loader); + System.out.println("Minecraft Directory: " + minecraftDirectory.getAbsolutePath()); + // Update config Config config = Config.getInstance(); config.lastSelectedVersion = selectedVersion; config.lastInstallType = INSTALL_TYPE; + config.lastMinecraftDirectory = minecraftDirectory.getAbsolutePath(); config.save(); + + // Validate path + if(!minecraftDirectory.exists() || !minecraftDirectory.isDirectory()) { + JOptionPane.showMessageDialog(this, "Invalid Minecraft Directory: '" + minecraftDirectory.getAbsolutePath() + "'!"); + config.lastMinecraftDirectory = null; + config.save(); + return false; + } JsonObject versionObject = VersionList.getVersion(selectedVersion); - JsonObject vanillaObject = versionObject.getObject("vanilla"); if(vanillaObject == null) { throw new NullPointerException("No vanilla object!"); @@ -86,9 +116,29 @@ public boolean install() { String versionName = "BTA " + selectedVersion; String profileName = "Better Than Adventure!"; - File minecraftDirectory = Utils.getMinecraftDirectory(); - System.out.println("Minecraft Directory: " + minecraftDirectory.getAbsolutePath()); - + if(loader == ModLoader.Fabric || loader == ModLoader.Babric) { + versionName = versionName + " " + loader.name(); + profileName = profileName + " " + selectedVersion + " " + loader.name(); + }else if(loader != ModLoader.None) { + profileName = profileName + " " + loader.name(); + } + + String fabricVersionOverride = null; + if(loader == ModLoader.Fabric || loader == ModLoader.Babric) { + JsonObject fabricObject = versionObject.getObject("fabric"); + + if(fabricObject != null && fabricObject.has("version-name-override")) { + fabricVersionOverride = fabricObject.getString("version-name-override"); + }else { + fabricVersionOverride = selectedVersion; + } + + if(fabricVersionOverride == null) { + JOptionPane.showMessageDialog(this, "The selected version does not support Fabric!"); + return false; + } + } + File versionFolder = new File(minecraftDirectory, "versions/" + versionName); if(!versionFolder.exists()) { versionFolder.mkdirs(); @@ -110,19 +160,31 @@ public boolean install() { System.out.println("Version is installed"); } + String jsonPath; + if(loader == ModLoader.Fabric || loader == ModLoader.Babric) { + JsonElement jsonFabric = vanillaObject.get("json-" + loader.name().substring(0, 1).toLowerCase() + "abric"); + if(jsonFabric == null) { + JOptionPane.showMessageDialog(this, "The selected version does not support " + loader.name() + "!"); + return false; + } + jsonPath = "/" + jsonFabric.getAsString().value; + }else { + jsonPath = "/" + vanillaObject.getString("json"); + } + // Copy json file into instance folder and set id - JsonObject json = JsonParser.instance.parseStream(VanillaLauncherInstallerGUI.class.getResourceAsStream("/" + vanillaObject.getString("json"))); + JsonObject json = JsonParser.instance.parseStream(VanillaLauncherInstallerGUI.class.getResourceAsStream(jsonPath)); json.set("id", versionName); StringUtils.saveStringToFile(new File(versionFolder, versionName + ".json"), json.toString()); // Setup Launcher Profile - updateLauncherProfile(minecraftDirectory, profileName, versionName); + updateLauncherProfile(minecraftDirectory, profileName, versionName, loader, fabricVersionOverride); JOptionPane.showMessageDialog(this, "Done!"); return true; } - public void updateLauncherProfile(File minecraftDirectory, String profileName, String versionId) { + public void updateLauncherProfile(File minecraftDirectory, String profileName, String versionId, ModLoader loader, String fabricVersionOverride) { File launcherProfilesFile = new File(minecraftDirectory, "launcher_profiles.json"); JsonObject root = JsonParser.instance.parseFileContent(launcherProfilesFile); @@ -157,14 +219,64 @@ public void updateLauncherProfile(File minecraftDirectory, String profileName, S if(!profile.has("created")) { profile.set("created", "1970-01-01T00:00:00.000Z"); // I don't care } - if(!profile.has("lastUsed")) { - profile.set("lastUsed", "2070-01-01T00:00:00.000Z"); // All the way up - } + profile.set("lastUsed", "2070-01-01T00:00:00.000Z"); // All the way up profile.set("type", "custom"); - // TODO java args? + List javaArgs = new ArrayList<>(); + if((loader == ModLoader.Fabric || loader == ModLoader.Babric) && fabricVersionOverride != null) { + javaArgs.add("-Dfabric.gameVersion=" + fabricVersionOverride); + } + + if(loader == ModLoader.ASMLoader) { + JsonObject asmloaderObject = VersionList.getJson().getObject("asmloader"); + + String filename = asmloaderObject.getString("filename"); + + File fileInDownloadDirectory = new File(DownloadManager.getDownloadDirectory(), filename); + File fileInMinecraftDirectory = new File(minecraftDirectory, filename); + + if(!fileInDownloadDirectory.exists()) { + DownloadManager.downloadFileAndPrintProgress(asmloaderObject.getString("url"), fileInDownloadDirectory); + } + + Utils.copyFile(fileInDownloadDirectory, fileInMinecraftDirectory); + + javaArgs.add("-javaagent:" + filename); + } + profile.set("javaArgs", Utils.combineStringsSeperatedWithSpaces(javaArgs)); StringUtils.saveStringToFile(launcherProfilesFile, root.toString()); } + + public String getMinecraftDirectory() { + String last = Config.getInstance().lastMinecraftDirectory; + if(last != null) { + return last; + } + return Utils.getMinecraftDirectory().getAbsolutePath(); + } + + @Override + public boolean isCompatible(String version, ModLoader loader) { + if(loader == ModLoader.Fabric || loader == ModLoader.Babric) { + JsonObject versionObject = VersionList.getJson().getObject("versions").getObject(version); + if(loader == ModLoader.Babric) { + return versionObject.getObject("vanilla").has("json-babric"); + }else { + return versionObject.getObject("vanilla").has("json-fabric"); + } + } + if(loader == ModLoader.ASMLoader) { + JsonObject asmLoaderObject = VersionList.getJson().getObject("asmloader"); + if(asmLoaderObject == null) { + return false; + } + return asmLoaderObject.has("filename") && asmLoaderObject.has("url"); + } + if(loader == ModLoader.None) { + return true; + } + return false; + } } diff --git a/src/b100/installer/gui/VersionComponent.java b/src/b100/installer/gui/VersionComponent.java deleted file mode 100644 index b6c8904..0000000 --- a/src/b100/installer/gui/VersionComponent.java +++ /dev/null @@ -1,55 +0,0 @@ -package b100.installer.gui; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JLabel; - -import b100.installer.Config; -import b100.installer.gui.utils.GridPanel; - -@SuppressWarnings("serial") -public class VersionComponent extends GridPanel implements ActionListener { - - public JLabel selectedVersionLabel; - public JButton selectVersionButton; - - private String selectedVersion; - - public VersionComponent() { - selectedVersionLabel = new JLabel(); - selectVersionButton = new JButton("Choose Version"); - selectVersionButton.addActionListener(this); - - getGridBagConstraints().insets.set(0, 0, 0, 16); // at least 16 pixels between text and button - add(selectedVersionLabel, 0, 0, 1, 0); - getGridBagConstraints().insets.set(0, 0, 0, 0); - add(selectVersionButton, 1, 0, 0, 0); - - setVersion(Config.getInstance().getLastOrNewestVersion()); - } - - public void setVersion(String version) { - if(version == null) { - throw new NullPointerException(); - } - - this.selectedVersion = version; - this.selectedVersionLabel.setText("Selected Version: " + selectedVersion); - } - - public String getVersion() { - return selectedVersion; - } - - @Override - public void actionPerformed(ActionEvent e) { - if(e.getSource() == selectVersionButton) { - new VersionListGUI((version) -> setVersion(version), selectedVersion); - } - } - - - -} diff --git a/src/b100/installer/gui/VersionListGUI.java b/src/b100/installer/gui/VersionListGUI.java index ec594d8..a6ff8bf 100644 --- a/src/b100/installer/gui/VersionListGUI.java +++ b/src/b100/installer/gui/VersionListGUI.java @@ -7,6 +7,7 @@ import java.util.List; import javax.swing.JButton; +import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JOptionPane; @@ -17,18 +18,23 @@ import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; +import b100.installer.Installer; +import b100.installer.ModLoader; import b100.installer.Utils; import b100.installer.VersionList; +import b100.installer.gui.utils.ComboBoxData; import b100.installer.gui.utils.GridPanel; public class VersionListGUI implements ActionListener { - private List versions = new ArrayList<>(); + private List allVersions = new ArrayList<>(); + private List filteredVersions = new ArrayList<>(); private List dataListeners = new ArrayList<>(); public JFrame frame; public GridPanel mainPanel; - + + public JComboBox modLoaderSelection; public JList versionList; public Listener listener; @@ -36,24 +42,33 @@ public class VersionListGUI implements ActionListener { public JButton refreshButton; public JButton confirmButton; public JButton cancelButton; - + private String selectedVersion; + private ModLoader selectedLoader; + + public ComboBoxData modLoaderSelectionData; + public VersionFilter filter; - public VersionListGUI(Listener listener, String selectedVersion) { + public VersionListGUI(Listener listener, String selectedVersion, ModLoader selectedLoader, List modLoaders, VersionFilter filter) { this.listener = listener; this.selectedVersion = selectedVersion; + this.selectedLoader = selectedLoader; + this.filter = filter; frame = new JFrame("Select Version"); mainPanel = new GridPanel(); mainPanel.getGridBagConstraints().insets.set(4, 4, 4, 4); + + modLoaderSelectionData = new ComboBoxData<>(modLoaders); + modLoaderSelection = new JComboBox<>(modLoaderSelectionData); + modLoaderSelection.setSelectedIndex(Utils.indexOf(modLoaderSelectionData.content, selectedLoader)); + modLoaderSelection.addActionListener(this); versionList = new JList<>(new ListModelImpl()); versionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); versionList.setEnabled(false); - setupVersionList(); - JScrollPane versionListScrollPane = new JScrollPane(versionList); versionListScrollPane.setPreferredSize(new Dimension(300, 300)); @@ -63,7 +78,9 @@ public VersionListGUI(Listener listener, String selectedVersion) { GridPanel buttonPanel = new GridPanel(); buttonPanel.getGridBagConstraints().insets.set(0, 4, 4, 4); - buttonPanel.add(refreshButton, 0, 0, 0, 1); + if(!Installer.isOffline()) { + buttonPanel.add(refreshButton, 0, 0, 0, 1); + } buttonPanel.add(new JPanel(), 1, 0, 1, 1); buttonPanel.add(confirmButton, 2, 0, 0, 1); buttonPanel.add(cancelButton, 3, 0, 0, 1); @@ -72,31 +89,44 @@ public VersionListGUI(Listener listener, String selectedVersion) { confirmButton.addActionListener(this); cancelButton.addActionListener(this); - mainPanel.add(versionListScrollPane, 0, 0, 1, 1); - mainPanel.add(buttonPanel, 0, 1, 1, 0); + mainPanel.add(modLoaderSelection, 0, 0, 1.0, 0.0); + mainPanel.add(versionListScrollPane, 0, 1, 1.0, 1.0); + mainPanel.add(buttonPanel, 0, 2, 1.0, 0.0); frame.add(mainPanel); frame.pack(); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setVisible(true); + + setupVersionList(); } public static interface Listener { - public void onVersionSelected(String string); + public void onVersionSelected(String string, ModLoader loader); } - + + public static interface VersionFilter { + + public boolean isCompatible(String version, ModLoader loader); + + } + @Override public void actionPerformed(ActionEvent e) { + if(e.getSource() == modLoaderSelection) { + this.selectedLoader = modLoaderSelectionData.content.get(modLoaderSelection.getSelectedIndex()); + setupVersionList(); + } if(e.getSource() == refreshButton) { refresh(); } if(e.getSource() == confirmButton) { String selection = versionList.getSelectedValue(); if(selection != null) { - listener.onVersionSelected(selection); + listener.onVersionSelected(selection, selectedLoader); } frame.dispose(); } @@ -132,7 +162,14 @@ public void refresh() { } public void setupVersionList() { - versions = VersionList.getAllVersions(); + allVersions = VersionList.getAllVersions(); + + filteredVersions.clear(); + for(String version : allVersions) { + if(filter.isCompatible(version, selectedLoader)) { + filteredVersions.add(version); + } + } for(int i=0; i < dataListeners.size(); i++) { dataListeners.get(i).contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, 0)); @@ -141,25 +178,26 @@ public void setupVersionList() { versionList.validate(); if(selectedVersion != null) { - int i = Utils.indexOf(versions, selectedVersion); + int i = Utils.indexOf(filteredVersions, selectedVersion); if(i >= 0) { versionList.setSelectedIndex(i); } } versionList.setEnabled(true); + confirmButton.setEnabled(filteredVersions.size() > 0); } class ListModelImpl implements ListModel { @Override public int getSize() { - return versions.size(); + return filteredVersions.size(); } @Override public String getElementAt(int index) { - return versions.get(index); + return filteredVersions.get(index); } @Override diff --git a/src/b100/installer/gui/utils/ComboBoxData.java b/src/b100/installer/gui/utils/ComboBoxData.java new file mode 100644 index 0000000..8d3bfe1 --- /dev/null +++ b/src/b100/installer/gui/utils/ComboBoxData.java @@ -0,0 +1,52 @@ +package b100.installer.gui.utils; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.ComboBoxModel; +import javax.swing.event.ListDataListener; + +public class ComboBoxData implements ComboBoxModel { + + private List listDataListeners = new ArrayList<>(); + public List content = new ArrayList<>(); + private Object selectedItem; + + public ComboBoxData() { + + } + + public ComboBoxData(List content) { + this.content.addAll(content); + } + + @Override + public int getSize() { + return content.size(); + } + + @Override + public E getElementAt(int index) { + return content.get(index); + } + + @Override + public void addListDataListener(ListDataListener l) { + listDataListeners.add(l); + } + + @Override + public void removeListDataListener(ListDataListener l) { + listDataListeners.remove(l); + } + + @Override + public void setSelectedItem(Object anItem) { + selectedItem = anItem; + } + + @Override + public Object getSelectedItem() { + return selectedItem; + } +} \ No newline at end of file diff --git a/src/b100/installer/gui/utils/GuiUtils.java b/src/b100/installer/gui/utils/GuiUtils.java new file mode 100644 index 0000000..5cdb2e4 --- /dev/null +++ b/src/b100/installer/gui/utils/GuiUtils.java @@ -0,0 +1,29 @@ +package b100.installer.gui.utils; + +import java.awt.Component; +import java.awt.image.BufferedImage; + +import javax.swing.border.TitledBorder; + +import b100.installer.Utils; + +public abstract class GuiUtils { + + public static GridPanel createTitledPanel(Component component, String title) { + GridPanel panel = new GridPanel(); + panel.setBorder(new TitledBorder(title)); + panel.getGridBagConstraints().insets.set(4, 4, 4, 4); + panel.add(component, 0, 0, 1, 1); + return panel; + } + + public static ImagePanel createImagePanel(String path) { + BufferedImage image = Utils.readImage(path); + if(image == null) { + throw new NullPointerException("Image is null!"); + } + return new ImagePanel(image); + } + + +} diff --git a/src/b100/installer/gui/utils/VersionComponent.java b/src/b100/installer/gui/utils/VersionComponent.java new file mode 100644 index 0000000..1a1f3f0 --- /dev/null +++ b/src/b100/installer/gui/utils/VersionComponent.java @@ -0,0 +1,72 @@ +package b100.installer.gui.utils; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JLabel; + +import b100.installer.Config; +import b100.installer.ModLoader; +import b100.installer.gui.VersionListGUI; +import b100.installer.gui.VersionListGUI.VersionFilter; + +@SuppressWarnings("serial") +public class VersionComponent extends GridPanel implements ActionListener { + + public JLabel selectedVersionLabel; + public JButton selectVersionButton; + + private String selectedVersion; + private ModLoader selectedLoader; + + public List modLoaders; + public VersionFilter filter; + + public VersionComponent(List modLoaders, VersionFilter filter) { + this.modLoaders = modLoaders; + this.filter = filter; + + selectedVersionLabel = new JLabel(); + selectVersionButton = new JButton("Choose Version"); + selectVersionButton.addActionListener(this); + + getGridBagConstraints().insets.set(0, 0, 0, 16); // at least 16 pixels between text and button + add(selectedVersionLabel, 0, 0, 1, 0); + getGridBagConstraints().insets.set(0, 0, 0, 0); + add(selectVersionButton, 1, 0, 0, 0); + + setVersionAndLoader(Config.getInstance().getLastOrNewestVersion(), ModLoader.None); + } + + public void setVersionAndLoader(String version, ModLoader loader) { + if(version == null) { + throw new NullPointerException(); + } + + this.selectedVersion = version; + this.selectedLoader = loader; + + if(selectedLoader != ModLoader.None) { + this.selectedVersionLabel.setText(selectedVersion + " " + selectedLoader.getDisplayName()); + }else { + this.selectedVersionLabel.setText(selectedVersion); + } + } + + public String getSelectedVersion() { + return selectedVersion; + } + + public ModLoader getSelectedLoader() { + return selectedLoader; + } + + @Override + public void actionPerformed(ActionEvent e) { + if(e.getSource() == selectVersionButton) { + new VersionListGUI((version, loader) -> setVersionAndLoader(version, loader), selectedVersion, selectedLoader, modLoaders, filter); + } + } +} diff --git a/src/versions.json b/src/versions.json index cce76a2..33c837f 100644 --- a/src/versions.json +++ b/src/versions.json @@ -1,5 +1,5 @@ { - "version": 1, + "version": 2, "downloads": { "bta-21w47a.jar": "https://github.com/Better-than-Adventure/bta-download-repo/releases/download/21w47a/bta.jar", "bta-21w46a.jar": "https://github.com/Better-than-Adventure/bta-download-repo/releases/download/21w46a/bta.jar", @@ -41,31 +41,47 @@ "bta-1.7.4_01.jar": "https://github.com/Better-than-Adventure/bta-download-repo/releases/download/v1.7.4_01/bta.jar", "CustomLaunch.jar": "https://gitlab.com/bestsoft100/download/-/raw/main/CustomLaunch.jar" }, + "asmloader": { + "filename": "ASMLoader-v2-DEV-2024-06-22.jar", + "url": "https://github.com/Bestsoft101/ASMLoader/releases/download/v2-DEV-2024-06-22/ASMLoader-v2-DEV-2024-06-22.jar" + }, "versions": { "7.2 Prerelease 2": { "jar": "bta-7.2-pre2.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", "proxy": false + }, + "fabric": { + "version-name-override": "7.2-pre2" } }, "7.2 Prerelease 1": { "jar": "bta-7.2-pre1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", "proxy": false + }, + "fabric": { + "version-name-override": "7.2-pre1" } }, "7.1_01": { "jar": "bta-7.1_01.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", @@ -75,7 +91,9 @@ "7.1": { "jar": "bta-7.1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", @@ -85,47 +103,69 @@ "7.1 Prerelease 2a": { "jar": "bta-7.1-pre2a.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", "proxy": false + }, + "fabric": { + "version-name-override": "7.1-pre2a" } }, "7.1 Prerelease 2": { "jar": "bta-7.1-pre2.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", "proxy": false + }, + "fabric": { + "version-name-override": "7.1-pre2" } }, "7.1 Prerelease 1a": { "jar": "bta-7.1-pre1a.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", "proxy": false + }, + "fabric": { + "version-name-override": "7.1-pre1a" } }, "7.1 Prerelease 1": { "jar": "bta-7.1-pre1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", "proxy": false + }, + "fabric": { + "version-name-override": "7.1-pre1" } }, "1.7.7.0_02": { "jar": "bta-1.7.7.0_02.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", @@ -135,7 +175,9 @@ "1.7.7.0_01": { "jar": "bta-1.7.7.0_01.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", @@ -145,7 +187,8 @@ "1.7.7.0": { "jar": "bta-1.7.7.0.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", @@ -155,17 +198,24 @@ "1.7.7.0 Prerelease 1": { "jar": "bta-1.7.7.0-pre1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "CustomLaunch", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.7.0-pre1" } }, "1.7.6.2_02": { "jar": "bta-1.7.6.2_02.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -175,7 +225,9 @@ "1.7.6.2_01": { "jar": "bta-1.7.6.2_01.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -185,7 +237,9 @@ "1.7.6.2": { "jar": "bta-1.7.6.2.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -195,19 +249,31 @@ "1.7.6.2 Prerelease 2": { "jar": "bta-1.7.6.2-pre2.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" + }, + "fabric": { + "version-name-override": "1.7.6.2-pre2" } }, "1.7.6.2 Prerelease 1": { "jar": "bta-1.7.6.2-pre1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" + }, + "fabric": { + "version-name-override": "1.7.6.2-pre1" } }, "1.7.6.1": { "jar": "bta-1.7.6.1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -217,27 +283,39 @@ "1.7.7 Snapshot 21w47a": { "jar": "bta-21w47a.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "21w47a" } }, "1.7.7 Snapshot 21w46a": { "jar": "bta-21w46a.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "21w46a" } }, "1.7.6_01": { "jar": "bta-1.7.6_01.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -247,7 +325,9 @@ "1.7.6": { "jar": "bta-1.7.6.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -257,87 +337,129 @@ "1.7.6 Prerelease 3": { "jar": "bta-1.7.6-pre3.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.6-pre3" } }, "1.7.6 Prerelease 2c": { "jar": "bta-1.7.6-pre2c.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.6-pre2v" } }, "1.7.6 Prerelease 2b": { "jar": "bta-1.7.6-pre2b.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.6-pre2b" } }, "1.7.6 Prerelease 2": { "jar": "bta-1.7.6-pre2.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.6-pre2" } }, "1.7.6 Prerelease 1": { "jar": "bta-1.7.6-pre1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.6-pre1" } }, "1.7.6 Snapshot 21w36b": { "jar": "bta-21w36b.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "21w36b" } }, "1.7.6 Snapshot 21w36a": { "jar": "bta-21w36a.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "21w36a" } }, "1.7.6 Snapshot 21w34a": { "jar": "bta-21w34a.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "21w34a" } }, "1.7.5_01": { "jar": "bta-1.7.5_01.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -347,7 +469,9 @@ "1.7.5": { "jar": "bta-1.7.5.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -357,37 +481,54 @@ "1.7.5 Prerelease 3": { "jar": "bta-1.7.5-pre3.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.5-pre3" } }, "1.7.5 Prerelease 2": { "jar": "bta-1.7.5-pre2.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.5-pre2" } }, "1.7.5 Prerelease 1": { "jar": "bta-1.7.5-pre1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", "proxy": false + }, + "fabric": { + "version-name-override": "1.7.5-pre1" } }, "1.7.4_02": { "jar": "bta-1.7.4_02.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -397,7 +538,9 @@ "1.7.4_01_1": { "jar": "bta-1.7.4_01_1.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default", @@ -407,7 +550,9 @@ "1.7.4_01": { "jar": "bta-1.7.4_01.jar", "vanilla": { - "json": "BTA.json" + "json": "BTA.json", + "json-fabric": "BTA Fabric.json", + "json-babric": "BTA Babric.json" }, "betacraft": { "launch-method": "default",