From 7a8427d130ba33b274fca8df543e39765cf266fd Mon Sep 17 00:00:00 2001 From: Thomas Kain Date: Sat, 5 Aug 2023 10:46:57 -0400 Subject: [PATCH 1/5] Implement support for NeoForge (#13) * Fix compilation on Java versions other than 8 * Add basic support for NeoForge This uses Forge's built-in fml.forgeGroup flag to distinguish Forge and NeoForge's package names. Consequently, this flag's value needs to be passed to most installer-related functions. * Update Javadocs with Forge group parameter * Add Forge group support for manual installs * Assume we're using NeoForge if `--fml.forgeGroup` isn't specified I was hoping not to hardcode any package names here, but this is the only way to unbreak manual installs without unintuitively asking users to add the flag themselves. --- .../forgewrapper/converter/Converter.java | 47 +++++++++++++------ converter/src/main/resources/mmc-pack.json | 2 +- ...{net.minecraftforge.json => template.json} | 6 +-- legacy/build.gradle | 5 ++ .../forgewrapper/installer/Main.java | 9 ++-- .../installer/detector/IFileDetector.java | 27 ++++++----- .../detector/MultiMCFileDetector.java | 12 +++-- 7 files changed, 71 insertions(+), 37 deletions(-) rename converter/src/main/resources/patches/{net.minecraftforge.json => template.json} (75%) diff --git a/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java b/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java index ade550f..e5771bc 100644 --- a/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java +++ b/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java @@ -28,12 +28,13 @@ public class Converter { JsonObject installProfile = getJsonFromZip(installerPath, "install_profile.json"); List arguments = getAdditionalArgs(installer); String mcVersion = arguments.get(arguments.indexOf("--fml.mcVersion") + 1); + String forgeGroup = arguments.contains("--fml.forgeGroup") ? arguments.get(arguments.indexOf("--fml.forgeGroup") + 1) : "net.neoforged"; String forgeVersion = arguments.get(arguments.indexOf("--fml.forgeVersion") + 1); String forgeFullVersion = "forge-" + mcVersion + "-" + forgeVersion; StringBuilder wrapperVersion = new StringBuilder(); - JsonObject pack = convertPackJson(mcVersion); - JsonObject patches = convertPatchesJson(installer, installProfile, mcVersion, forgeVersion, wrapperVersion); + JsonObject pack = convertPackJson(mcVersion, forgeGroup); + JsonObject patches = convertPatchesJson(installer, installProfile, mcVersion, forgeGroup, forgeVersion, wrapperVersion); Files.createDirectories(targetDir); @@ -48,14 +49,17 @@ public class Converter { Files.createDirectories(librariesPath); Files.copy(Paths.get(Converter.class.getProtectionDomain().getCodeSource().getLocation().toURI()), librariesPath.resolve(wrapperVersion.toString()), StandardCopyOption.REPLACE_EXISTING); - // Copy net.minecraftforge.json to /patches folder. + // Copy .json to /patches folder. Path patchesPath = instancePath.resolve("patches"); Files.createDirectories(patchesPath); - Files.copy(new ByteArrayInputStream(patches.toString().getBytes(StandardCharsets.UTF_8)), patchesPath.resolve("net.minecraftforge.json"), StandardCopyOption.REPLACE_EXISTING); + Files.copy(new ByteArrayInputStream(patches.toString().getBytes(StandardCharsets.UTF_8)), patchesPath.resolve(forgeGroup + ".json"), StandardCopyOption.REPLACE_EXISTING); - // Copy forge installer to MultiMC/libraries/net/minecraftforge/forge/- folder. + // Copy forge installer to MultiMC/libraries//forge/- folder. if (multimcDir != null) { - Path targetInstallerPath = multimcDir.resolve("libraries").resolve("net").resolve("minecraftforge").resolve("forge").resolve(forgeVersion); + Path targetInstallerPath = multimcDir.resolve("libraries"); + for (String dir : forgeGroup.split("\\.")) + targetInstallerPath = targetInstallerPath.resolve(dir); + targetInstallerPath = targetInstallerPath.resolve("forge").resolve(mcVersion + "-" + forgeVersion); Files.createDirectories(targetInstallerPath); Files.copy(installerPath, targetInstallerPath.resolve(forgeFullVersion + "-installer.jar"), StandardCopyOption.REPLACE_EXISTING); } @@ -83,7 +87,8 @@ public class Converter { // Convert mmc-pack.json: // - Replace Minecraft version - private static JsonObject convertPackJson(String mcVersion) { + // - Replace Forge package group + private static JsonObject convertPackJson(String mcVersion, String forgeGroup) { JsonObject pack = JsonParser.parseReader(new InputStreamReader(Converter.class.getResourceAsStream("/mmc-pack.json"))).getAsJsonObject(); for (JsonElement component : getElement(pack, "components").getAsJsonArray()) { @@ -91,26 +96,37 @@ public class Converter { JsonElement version = getElement(componentObject, "version"); if (!version.isJsonNull() && getElement(componentObject, "uid").getAsString().equals("net.minecraft")) { componentObject.addProperty("version", mcVersion); + } else if (getElement(componentObject, "uid").getAsString().equals("{FORGE_GROUP}")) { + componentObject.addProperty("uid", forgeGroup); } } return pack; } - // Convert patches/net.minecraftforge.json: + // Convert patches/.json: // - Add libraries // - Add forge-launcher url // - Replace Minecraft & Forge versions - private static JsonObject convertPatchesJson(JsonObject installer, JsonObject installProfile, String mcVersion, String forgeVersion, StringBuilder wrapperVersion) { - JsonObject patches = JsonParser.parseReader(new InputStreamReader(Converter.class.getResourceAsStream("/patches/net.minecraftforge.json"))).getAsJsonObject(); + // - Replace Forge package group + private static JsonObject convertPatchesJson(JsonObject installer, JsonObject installProfile, String mcVersion, String forgeGroup, String forgeVersion, StringBuilder wrapperVersion) { + JsonObject patches = JsonParser.parseReader(new InputStreamReader(Converter.class.getResourceAsStream("/patches/template.json"))).getAsJsonObject(); JsonArray mavenFiles = getElement(patches, "mavenFiles").getAsJsonArray(); JsonArray libraries = getElement(patches, "libraries").getAsJsonArray(); String minecraftArguments = String.join(" ", getElement(patches, "minecraftArguments").getAsString(), "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}", String.join(" ", getAdditionalArgs(installer))).trim(); patches.addProperty("minecraftArguments", minecraftArguments); + String[] forgeGroupParts = forgeGroup.split("\\."); + String[] forgeURLParts = new String[forgeGroupParts.length]; + for (int i = 0; i < forgeURLParts.length; i++) + forgeURLParts[i] = forgeGroupParts[forgeGroupParts.length - i - 1]; + String mavenURL = "https://maven." + String.join(".", forgeURLParts); + for (JsonElement mavenFile : mavenFiles) { - String name = getElement(mavenFile.getAsJsonObject(), "name").getAsString(); - mavenFile.getAsJsonObject().addProperty("name", name.replace("{VERSION}", mcVersion).replace("{FORGE_VERSION}", forgeVersion)); + JsonObject mavenJsonObj = mavenFile.getAsJsonObject(); + String name = getElement(mavenJsonObj, "name").getAsString(); + mavenJsonObj.addProperty("name", name.replace("{FORGE_GROUP}", forgeGroup).replace("{VERSION}", mcVersion).replace("{FORGE_VERSION}", forgeVersion)); + mavenJsonObj.addProperty("url", mavenURL); } for (JsonElement lib : libraries) { String name = getElement(lib.getAsJsonObject(), "name").getAsString(); @@ -119,13 +135,14 @@ public class Converter { } } Map additionalUrls = new HashMap<>(); - String path = String.format("net/minecraftforge/forge/%s-%s/forge-%s-%s", mcVersion, forgeVersion, mcVersion, forgeVersion); - additionalUrls.put(path + "-universal.jar", "https://maven.minecraftforge.net/" + path + "-universal.jar"); + String path = String.format("%s/forge/%s-%s/forge-%s-%s", String.join("/", forgeGroupParts), mcVersion, forgeVersion, mcVersion, forgeVersion); + additionalUrls.put(path + "-universal.jar", mavenURL + "/" + path + "-universal.jar"); transformLibraries(getElement(installProfile, "libraries").getAsJsonArray(), mavenFiles, additionalUrls); additionalUrls.clear(); - additionalUrls.put(path + ".jar", "https://maven.minecraftforge.net/" + path + "-launcher.jar"); + additionalUrls.put(path + ".jar", mavenURL + "/" + path + "-launcher.jar"); transformLibraries(getElement(installer, "libraries").getAsJsonArray(), libraries, additionalUrls); + patches.addProperty("uid", forgeGroup); patches.addProperty("version", forgeVersion); for (JsonElement require : getElement(patches, "requires").getAsJsonArray()) { JsonObject requireObject = require.getAsJsonObject(); diff --git a/converter/src/main/resources/mmc-pack.json b/converter/src/main/resources/mmc-pack.json index 87db08a..51ba0bf 100644 --- a/converter/src/main/resources/mmc-pack.json +++ b/converter/src/main/resources/mmc-pack.json @@ -7,7 +7,7 @@ "version": "{VERSION}" }, { - "uid": "net.minecraftforge" + "uid": "{FORGE_GROUP}" } ] } diff --git a/converter/src/main/resources/patches/net.minecraftforge.json b/converter/src/main/resources/patches/template.json similarity index 75% rename from converter/src/main/resources/patches/net.minecraftforge.json rename to converter/src/main/resources/patches/template.json index 4fac6aa..5a46916 100644 --- a/converter/src/main/resources/patches/net.minecraftforge.json +++ b/converter/src/main/resources/patches/template.json @@ -10,12 +10,12 @@ } ], "type": "release", - "uid": "net.minecraftforge", + "uid": "{FORGE_GROUP}", "version": "{FORGE_VERSION}", "mavenFiles": [ { - "name": "net.minecraftforge:forge:{VERSION}-{FORGE_VERSION}:installer", - "url": "https://maven.minecraftforge.net/" + "name": "{FORGE_GROUP}:forge:{VERSION}-{FORGE_VERSION}:installer", + "url": "{MAVEN_URL}" } ], "libraries": [ diff --git a/legacy/build.gradle b/legacy/build.gradle index 8824390..4778335 100644 --- a/legacy/build.gradle +++ b/legacy/build.gradle @@ -4,6 +4,11 @@ plugins { id "eclipse" } +sourceCompatibility = targetCompatibility = 1.8 +compileJava { + sourceCompatibility = targetCompatibility = 1.8 +} + repositories { mavenCentral() maven { diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java index 7134ba5..ab82cf2 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java @@ -17,20 +17,21 @@ public class Main { public static void main(String[] args) throws Throwable { List argsList = Stream.of(args).collect(Collectors.toList()); String mcVersion = argsList.get(argsList.indexOf("--fml.mcVersion") + 1); + String forgeGroup = argsList.contains("--fml.forgeGroup") ? argsList.get(argsList.indexOf("--fml.forgeGroup") + 1) : "net.neoforged"; String forgeVersion = argsList.get(argsList.indexOf("--fml.forgeVersion") + 1); String forgeFullVersion = mcVersion + "-" + forgeVersion; IFileDetector detector = DetectorLoader.loadDetector(); try { - Bootstrap.bootstrap(detector.getJvmArgs(forgeFullVersion), detector.getMinecraftJar(mcVersion).getFileName().toString(), detector.getLibraryDir().toAbsolutePath().toString()); + Bootstrap.bootstrap(detector.getJvmArgs(forgeGroup, forgeFullVersion), detector.getMinecraftJar(mcVersion).getFileName().toString(), detector.getLibraryDir().toAbsolutePath().toString()); } catch (Throwable ignored) { // Avoid this bunch of hacks that nuke the whole wrapper. } - if (!detector.checkExtraFiles(forgeFullVersion)) { + if (!detector.checkExtraFiles(forgeGroup, forgeFullVersion)) { System.out.println("Some extra libraries are missing! Running the installer to generate them now."); // Check installer jar. - Path installerJar = detector.getInstallerJar(forgeFullVersion); + Path installerJar = detector.getInstallerJar(forgeGroup, forgeFullVersion); if (!IFileDetector.isFile(installerJar)) { throw new RuntimeException("Unable to detect the forge installer!"); } @@ -53,7 +54,7 @@ public class Main { } } - Class mainClass = ModuleUtil.setupBootstrapLauncher(Class.forName(detector.getMainClass(forgeFullVersion))); + Class mainClass = ModuleUtil.setupBootstrapLauncher(Class.forName(detector.getMainClass(forgeGroup, forgeFullVersion))); mainClass.getMethod("main", String[].class).invoke(null, new Object[] { args }); } } diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java index 76df474..a007a77 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java @@ -61,10 +61,11 @@ public interface IFileDetector { } /** + * @param forgeGroup Forge package group (e.g. net.minecraftforge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The forge installer jar path. It can also be defined by JVM argument "-Dforgewrapper.installer=<installer-path>". */ - default Path getInstallerJar(String forgeFullVersion) { + default Path getInstallerJar(String forgeGroup, String forgeFullVersion) { String installer = System.getProperty("forgewrapper.installer"); if (installer != null) { return Paths.get(installer).toAbsolutePath(); @@ -85,11 +86,12 @@ public interface IFileDetector { } /** + * @param forgeGroup Forge package group (e.g. net.minecraftforge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The list of jvm args. */ - default List getJvmArgs(String forgeFullVersion) { - return this.getDataFromInstaller(forgeFullVersion, "version.json", e -> { + default List getJvmArgs(String forgeGroup, String forgeFullVersion) { + return this.getDataFromInstaller(forgeGroup, forgeFullVersion, "version.json", e -> { JsonElement element = getElement(e.getAsJsonObject().getAsJsonObject("arguments"), "jvm"); List args = new ArrayList<>(); if (!element.equals(JsonNull.INSTANCE)) { @@ -100,24 +102,26 @@ public interface IFileDetector { } /** + * @param forgeGroup Forge package group (e.g. net.minecraftforge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The main class. */ - default String getMainClass(String forgeFullVersion) { - return this.getDataFromInstaller(forgeFullVersion, "version.json", e -> e.getAsJsonObject().getAsJsonPrimitive("mainClass").getAsString()); + default String getMainClass(String forgeGroup, String forgeFullVersion) { + return this.getDataFromInstaller(forgeGroup, forgeFullVersion, "version.json", e -> e.getAsJsonObject().getAsJsonPrimitive("mainClass").getAsString()); } /** + * @param forgeGroup Forge package group (e.g. net.minecraftforge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The json object in the-installer-jar-->install_profile.json-->data-->xxx-->client. */ - default JsonObject getInstallProfileExtraData(String forgeFullVersion) { - return this.getDataFromInstaller(forgeFullVersion, "install_profile.json", e -> e.getAsJsonObject().getAsJsonObject("data")); + default JsonObject getInstallProfileExtraData(String forgeGroup, String forgeFullVersion) { + return this.getDataFromInstaller(forgeGroup, forgeFullVersion, "install_profile.json", e -> e.getAsJsonObject().getAsJsonObject("data")); } @SuppressWarnings("deprecation") - default R getDataFromInstaller(String forgeFullVersion, String entry, Function function) { - Path installer = this.getInstallerJar(forgeFullVersion); + default R getDataFromInstaller(String forgeGroup, String forgeFullVersion, String entry, Function function) { + Path installer = this.getInstallerJar(forgeGroup, forgeFullVersion); if (isFile(installer)) { try (ZipFile zf = new ZipFile(installer.toFile())) { ZipEntry ze = zf.getEntry(entry); @@ -140,11 +144,12 @@ public interface IFileDetector { /** * Check all cached files. + * @param forgeGroup Forge package group (e.g. net.minecraftforge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return True represents all files are ready. */ - default boolean checkExtraFiles(String forgeFullVersion) { - JsonObject jo = this.getInstallProfileExtraData(forgeFullVersion); + default boolean checkExtraFiles(String forgeGroup, String forgeFullVersion) { + JsonObject jo = this.getInstallProfileExtraData(forgeGroup, forgeFullVersion); if (jo != null) { Map libsMap = new HashMap<>(); Map hashMap = new HashMap<>(); diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java index cb87d27..7d0cf49 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java @@ -27,10 +27,16 @@ public class MultiMCFileDetector implements IFileDetector { } @Override - public Path getInstallerJar(String forgeFullVersion) { - Path path = IFileDetector.super.getInstallerJar(forgeFullVersion); + public Path getInstallerJar(String forgeGroup, String forgeFullVersion) { + Path path = IFileDetector.super.getInstallerJar(forgeGroup, forgeFullVersion); if (path == null) { - return this.installerJar != null ? this.installerJar : (this.installerJar = this.getLibraryDir().resolve("net").resolve("minecraftforge").resolve("forge").resolve(forgeFullVersion).resolve("forge-" + forgeFullVersion + "-installer.jar").toAbsolutePath()); + if (this.installerJar == null) { + Path installerBase = this.getLibraryDir(); + for (String dir : forgeGroup.split("\\.")) + installerBase = installerBase.resolve(dir); + this.installerJar = installerBase.resolve("forge").resolve(forgeFullVersion).resolve("forge-" + forgeFullVersion + "-installer.jar").toAbsolutePath(); + } + return this.installerJar; } return path; } From d7796062a4c9ff09207947d0a8a6b0a427715042 Mon Sep 17 00:00:00 2001 From: ZekerZhayard Date: Sun, 6 Aug 2023 00:42:28 +0800 Subject: [PATCH 2/5] 1.5.6 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 85a1608..e96608c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.daemon = false -fw_version = 1.5.5 +fw_version = 1.5.6 From f1b006b09569ad345e0924cc7421ca2b3bc47708 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 1 Nov 2023 13:32:07 +0100 Subject: [PATCH 3/5] Implement support for NeoForge 20.2+ (#16) Signed-off-by: Sefa Eyeoglu --- .../forgewrapper/installer/Main.java | 20 +++++++++----- .../installer/detector/IFileDetector.java | 27 +++++++++++-------- .../detector/MultiMCFileDetector.java | 6 ++--- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java index ab82cf2..5ecd971 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java @@ -15,23 +15,31 @@ import io.github.zekerzhayard.forgewrapper.installer.util.ModuleUtil; public class Main { public static void main(String[] args) throws Throwable { + // --fml.neoForgeVersion 20.2.20-beta --fml.fmlVersion 1.0.2 --fml.mcVersion 1.20.2 --fml.neoFormVersion 20231019.002635 --launchTarget forgeclient + List argsList = Stream.of(args).collect(Collectors.toList()); + // NOTE: this is only true for NeoForge versions past 20.2.x + // early versions of NeoForge (for 1.20.1) are not supposed to be covered here + boolean isNeoForge = argsList.contains("--fml.neoForgeVersion"); + String mcVersion = argsList.get(argsList.indexOf("--fml.mcVersion") + 1); String forgeGroup = argsList.contains("--fml.forgeGroup") ? argsList.get(argsList.indexOf("--fml.forgeGroup") + 1) : "net.neoforged"; - String forgeVersion = argsList.get(argsList.indexOf("--fml.forgeVersion") + 1); - String forgeFullVersion = mcVersion + "-" + forgeVersion; + String forgeArtifact = isNeoForge ? "neoforge" : "forge"; + String forgeVersionKey = isNeoForge ? "--fml.neoForgeVersion" : "--fml.forgeVersion"; + String forgeVersion = argsList.get(argsList.indexOf(forgeVersionKey) + 1); + String forgeFullVersion = isNeoForge ? forgeVersion : mcVersion + "-" + forgeVersion; IFileDetector detector = DetectorLoader.loadDetector(); try { - Bootstrap.bootstrap(detector.getJvmArgs(forgeGroup, forgeFullVersion), detector.getMinecraftJar(mcVersion).getFileName().toString(), detector.getLibraryDir().toAbsolutePath().toString()); + Bootstrap.bootstrap(detector.getJvmArgs(forgeGroup, forgeArtifact, forgeFullVersion), detector.getMinecraftJar(mcVersion).getFileName().toString(), detector.getLibraryDir().toAbsolutePath().toString()); } catch (Throwable ignored) { // Avoid this bunch of hacks that nuke the whole wrapper. } - if (!detector.checkExtraFiles(forgeGroup, forgeFullVersion)) { + if (!detector.checkExtraFiles(forgeGroup, forgeArtifact, forgeFullVersion)) { System.out.println("Some extra libraries are missing! Running the installer to generate them now."); // Check installer jar. - Path installerJar = detector.getInstallerJar(forgeGroup, forgeFullVersion); + Path installerJar = detector.getInstallerJar(forgeGroup, forgeArtifact, forgeFullVersion); if (!IFileDetector.isFile(installerJar)) { throw new RuntimeException("Unable to detect the forge installer!"); } @@ -54,7 +62,7 @@ public class Main { } } - Class mainClass = ModuleUtil.setupBootstrapLauncher(Class.forName(detector.getMainClass(forgeGroup, forgeFullVersion))); + Class mainClass = ModuleUtil.setupBootstrapLauncher(Class.forName(detector.getMainClass(forgeGroup, forgeArtifact, forgeFullVersion))); mainClass.getMethod("main", String[].class).invoke(null, new Object[] { args }); } } diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java index a007a77..b69e9b8 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java @@ -62,10 +62,11 @@ public interface IFileDetector { /** * @param forgeGroup Forge package group (e.g. net.minecraftforge). + * @param forgeArtifact Forge package artifact (e.g. forge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The forge installer jar path. It can also be defined by JVM argument "-Dforgewrapper.installer=<installer-path>". */ - default Path getInstallerJar(String forgeGroup, String forgeFullVersion) { + default Path getInstallerJar(String forgeGroup, String forgeArtifact, String forgeFullVersion) { String installer = System.getProperty("forgewrapper.installer"); if (installer != null) { return Paths.get(installer).toAbsolutePath(); @@ -87,11 +88,12 @@ public interface IFileDetector { /** * @param forgeGroup Forge package group (e.g. net.minecraftforge). + * @param forgeArtifact Forge package artifact (e.g. forge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The list of jvm args. */ - default List getJvmArgs(String forgeGroup, String forgeFullVersion) { - return this.getDataFromInstaller(forgeGroup, forgeFullVersion, "version.json", e -> { + default List getJvmArgs(String forgeGroup, String forgeArtifact, String forgeFullVersion) { + return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "version.json", e -> { JsonElement element = getElement(e.getAsJsonObject().getAsJsonObject("arguments"), "jvm"); List args = new ArrayList<>(); if (!element.equals(JsonNull.INSTANCE)) { @@ -103,25 +105,27 @@ public interface IFileDetector { /** * @param forgeGroup Forge package group (e.g. net.minecraftforge). + * @param forgeArtifact Forge package artifact (e.g. forge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The main class. */ - default String getMainClass(String forgeGroup, String forgeFullVersion) { - return this.getDataFromInstaller(forgeGroup, forgeFullVersion, "version.json", e -> e.getAsJsonObject().getAsJsonPrimitive("mainClass").getAsString()); + default String getMainClass(String forgeGroup, String forgeArtifact, String forgeFullVersion) { + return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "version.json", e -> e.getAsJsonObject().getAsJsonPrimitive("mainClass").getAsString()); } /** * @param forgeGroup Forge package group (e.g. net.minecraftforge). + * @param forgeArtifact Forge package artifact (e.g. forge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return The json object in the-installer-jar-->install_profile.json-->data-->xxx-->client. */ - default JsonObject getInstallProfileExtraData(String forgeGroup, String forgeFullVersion) { - return this.getDataFromInstaller(forgeGroup, forgeFullVersion, "install_profile.json", e -> e.getAsJsonObject().getAsJsonObject("data")); + default JsonObject getInstallProfileExtraData(String forgeGroup, String forgeArtifact, String forgeFullVersion) { + return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "install_profile.json", e -> e.getAsJsonObject().getAsJsonObject("data")); } @SuppressWarnings("deprecation") - default R getDataFromInstaller(String forgeGroup, String forgeFullVersion, String entry, Function function) { - Path installer = this.getInstallerJar(forgeGroup, forgeFullVersion); + default R getDataFromInstaller(String forgeGroup, String forgeArtifact, String forgeFullVersion, String entry, Function function) { + Path installer = this.getInstallerJar(forgeGroup, forgeArtifact, forgeFullVersion); if (isFile(installer)) { try (ZipFile zf = new ZipFile(installer.toFile())) { ZipEntry ze = zf.getEntry(entry); @@ -145,11 +149,12 @@ public interface IFileDetector { /** * Check all cached files. * @param forgeGroup Forge package group (e.g. net.minecraftforge). + * @param forgeArtifact Forge package artifact (e.g. forge). * @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0). * @return True represents all files are ready. */ - default boolean checkExtraFiles(String forgeGroup, String forgeFullVersion) { - JsonObject jo = this.getInstallProfileExtraData(forgeGroup, forgeFullVersion); + default boolean checkExtraFiles(String forgeGroup, String forgeArtifact, String forgeFullVersion) { + JsonObject jo = this.getInstallProfileExtraData(forgeGroup, forgeArtifact, forgeFullVersion); if (jo != null) { Map libsMap = new HashMap<>(); Map hashMap = new HashMap<>(); diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java index 7d0cf49..a1216f0 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/MultiMCFileDetector.java @@ -27,14 +27,14 @@ public class MultiMCFileDetector implements IFileDetector { } @Override - public Path getInstallerJar(String forgeGroup, String forgeFullVersion) { - Path path = IFileDetector.super.getInstallerJar(forgeGroup, forgeFullVersion); + public Path getInstallerJar(String forgeGroup, String forgeArtifact, String forgeFullVersion) { + Path path = IFileDetector.super.getInstallerJar(forgeGroup, forgeArtifact, forgeFullVersion); if (path == null) { if (this.installerJar == null) { Path installerBase = this.getLibraryDir(); for (String dir : forgeGroup.split("\\.")) installerBase = installerBase.resolve(dir); - this.installerJar = installerBase.resolve("forge").resolve(forgeFullVersion).resolve("forge-" + forgeFullVersion + "-installer.jar").toAbsolutePath(); + this.installerJar = installerBase.resolve(forgeArtifact).resolve(forgeFullVersion).resolve(forgeArtifact + "-" + forgeFullVersion + "-installer.jar").toAbsolutePath(); } return this.installerJar; } From fb7f889cd471900f29350df52d10a1babc06e863 Mon Sep 17 00:00:00 2001 From: ZekerZhayard Date: Wed, 1 Nov 2023 22:36:17 +0800 Subject: [PATCH 4/5] 1.5.7 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e96608c..f1db528 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.daemon = false -fw_version = 1.5.6 +fw_version = 1.5.7 From a3413eb5c46f0205b0aa7c0fd8cc326dbebcced2 Mon Sep 17 00:00:00 2001 From: ZekerZhayard Date: Wed, 20 Dec 2023 00:41:37 +0800 Subject: [PATCH 5/5] Initial support for Forge 1.20.4 (with a few minor issues). Removed the converter project. --- converter/build.gradle | 54 ------ .../forgewrapper/converter/Converter.java | 174 ------------------ .../forgewrapper/converter/Main.java | 53 ------ converter/src/main/resources/mmc-pack.json | 13 -- .../src/main/resources/patches/template.json | 28 --- gradle.properties | 2 +- .../installer/util/ModuleUtil.java | 10 + settings.gradle | 1 - .../forgewrapper/installer/Bootstrap.java | 9 + .../forgewrapper/installer/Main.java | 1 + .../installer/detector/IFileDetector.java | 29 +-- .../installer/util/ModuleUtil.java | 13 ++ 12 files changed, 51 insertions(+), 336 deletions(-) delete mode 100644 converter/build.gradle delete mode 100644 converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java delete mode 100644 converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Main.java delete mode 100644 converter/src/main/resources/mmc-pack.json delete mode 100644 converter/src/main/resources/patches/template.json diff --git a/converter/build.gradle b/converter/build.gradle deleted file mode 100644 index a3661b7..0000000 --- a/converter/build.gradle +++ /dev/null @@ -1,54 +0,0 @@ - -plugins { - id "java" - id "eclipse" -} - -version = "${rootProject.fw_version}${-> getVersionSuffix()}" -group = "io.github.zekerzhayard" -archivesBaseName = rootProject.name + "Converter" - -sourceCompatibility = targetCompatibility = 1.8 -compileJava { - sourceCompatibility = targetCompatibility = 1.8 -} - -configurations { - provided { - implementation.extendsFrom provided - } -} - -repositories { - mavenCentral() -} - -dependencies { - compileOnly "com.google.code.gson:gson:2.8.7" - provided rootProject -} - -jar { - manifest.attributes rootProject.jar.manifest.attributes - manifest.attributes([ - "Main-Class": "io.github.zekerzhayard.forgewrapper.converter.Main" - ]) - - from configurations.provided.files.collect { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - zipTree(it) - } -} - -processResources { - inputs.property "version", project.version - from(sourceSets.main.resources.srcDirs) { - duplicatesStrategy = DuplicatesStrategy.INCLUDE - include "patches/net.minecraftforge.json" - expand "version": project.version - } - from(sourceSets.main.resources.srcDirs) { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - exclude "patches/net.minecraftforge.json" - } -} diff --git a/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java b/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java deleted file mode 100644 index e5771bc..0000000 --- a/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Converter.java +++ /dev/null @@ -1,174 +0,0 @@ -package io.github.zekerzhayard.forgewrapper.converter; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -public class Converter { - public static void convert(Path installerPath, Path targetDir, Path multimcDir) throws Exception { - JsonObject installer = getJsonFromZip(installerPath, "version.json"); - JsonObject installProfile = getJsonFromZip(installerPath, "install_profile.json"); - List arguments = getAdditionalArgs(installer); - String mcVersion = arguments.get(arguments.indexOf("--fml.mcVersion") + 1); - String forgeGroup = arguments.contains("--fml.forgeGroup") ? arguments.get(arguments.indexOf("--fml.forgeGroup") + 1) : "net.neoforged"; - String forgeVersion = arguments.get(arguments.indexOf("--fml.forgeVersion") + 1); - String forgeFullVersion = "forge-" + mcVersion + "-" + forgeVersion; - StringBuilder wrapperVersion = new StringBuilder(); - - JsonObject pack = convertPackJson(mcVersion, forgeGroup); - JsonObject patches = convertPatchesJson(installer, installProfile, mcVersion, forgeGroup, forgeVersion, wrapperVersion); - - Files.createDirectories(targetDir); - - // Copy mmc-pack.json and instance.cfg to folder. - Path instancePath = targetDir.resolve(forgeFullVersion); - Files.createDirectories(instancePath); - Files.copy(new ByteArrayInputStream(pack.toString().getBytes(StandardCharsets.UTF_8)), instancePath.resolve("mmc-pack.json"), StandardCopyOption.REPLACE_EXISTING); - Files.copy(new ByteArrayInputStream(("InstanceType=OneSix\nname=" + forgeFullVersion).getBytes(StandardCharsets.UTF_8)), instancePath.resolve("instance.cfg"), StandardCopyOption.REPLACE_EXISTING); - - // Copy ForgeWrapper to /libraries folder. - Path librariesPath = instancePath.resolve("libraries"); - Files.createDirectories(librariesPath); - Files.copy(Paths.get(Converter.class.getProtectionDomain().getCodeSource().getLocation().toURI()), librariesPath.resolve(wrapperVersion.toString()), StandardCopyOption.REPLACE_EXISTING); - - // Copy .json to /patches folder. - Path patchesPath = instancePath.resolve("patches"); - Files.createDirectories(patchesPath); - Files.copy(new ByteArrayInputStream(patches.toString().getBytes(StandardCharsets.UTF_8)), patchesPath.resolve(forgeGroup + ".json"), StandardCopyOption.REPLACE_EXISTING); - - // Copy forge installer to MultiMC/libraries//forge/- folder. - if (multimcDir != null) { - Path targetInstallerPath = multimcDir.resolve("libraries"); - for (String dir : forgeGroup.split("\\.")) - targetInstallerPath = targetInstallerPath.resolve(dir); - targetInstallerPath = targetInstallerPath.resolve("forge").resolve(mcVersion + "-" + forgeVersion); - Files.createDirectories(targetInstallerPath); - Files.copy(installerPath, targetInstallerPath.resolve(forgeFullVersion + "-installer.jar"), StandardCopyOption.REPLACE_EXISTING); - } - } - - public static List getAdditionalArgs(JsonObject installer) { - List args = new ArrayList<>(); - getElement(installer.getAsJsonObject("arguments"), "game").getAsJsonArray().iterator().forEachRemaining(je -> args.add(je.getAsString())); - return args; - } - - public static JsonObject getJsonFromZip(Path path, String json) { - try { - ZipFile zf = new ZipFile(path.toFile()); - ZipEntry versionFile = zf.getEntry(json); - if (versionFile == null) { - throw new RuntimeException("The zip file is invalid!"); - } - InputStreamReader isr = new InputStreamReader(zf.getInputStream(versionFile), StandardCharsets.UTF_8); - return JsonParser.parseReader(isr).getAsJsonObject(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - // Convert mmc-pack.json: - // - Replace Minecraft version - // - Replace Forge package group - private static JsonObject convertPackJson(String mcVersion, String forgeGroup) { - JsonObject pack = JsonParser.parseReader(new InputStreamReader(Converter.class.getResourceAsStream("/mmc-pack.json"))).getAsJsonObject(); - - for (JsonElement component : getElement(pack, "components").getAsJsonArray()) { - JsonObject componentObject = component.getAsJsonObject(); - JsonElement version = getElement(componentObject, "version"); - if (!version.isJsonNull() && getElement(componentObject, "uid").getAsString().equals("net.minecraft")) { - componentObject.addProperty("version", mcVersion); - } else if (getElement(componentObject, "uid").getAsString().equals("{FORGE_GROUP}")) { - componentObject.addProperty("uid", forgeGroup); - } - } - return pack; - } - - // Convert patches/.json: - // - Add libraries - // - Add forge-launcher url - // - Replace Minecraft & Forge versions - // - Replace Forge package group - private static JsonObject convertPatchesJson(JsonObject installer, JsonObject installProfile, String mcVersion, String forgeGroup, String forgeVersion, StringBuilder wrapperVersion) { - JsonObject patches = JsonParser.parseReader(new InputStreamReader(Converter.class.getResourceAsStream("/patches/template.json"))).getAsJsonObject(); - JsonArray mavenFiles = getElement(patches, "mavenFiles").getAsJsonArray(); - JsonArray libraries = getElement(patches, "libraries").getAsJsonArray(); - - String minecraftArguments = String.join(" ", getElement(patches, "minecraftArguments").getAsString(), "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}", String.join(" ", getAdditionalArgs(installer))).trim(); - patches.addProperty("minecraftArguments", minecraftArguments); - - String[] forgeGroupParts = forgeGroup.split("\\."); - String[] forgeURLParts = new String[forgeGroupParts.length]; - for (int i = 0; i < forgeURLParts.length; i++) - forgeURLParts[i] = forgeGroupParts[forgeGroupParts.length - i - 1]; - String mavenURL = "https://maven." + String.join(".", forgeURLParts); - - for (JsonElement mavenFile : mavenFiles) { - JsonObject mavenJsonObj = mavenFile.getAsJsonObject(); - String name = getElement(mavenJsonObj, "name").getAsString(); - mavenJsonObj.addProperty("name", name.replace("{FORGE_GROUP}", forgeGroup).replace("{VERSION}", mcVersion).replace("{FORGE_VERSION}", forgeVersion)); - mavenJsonObj.addProperty("url", mavenURL); - } - for (JsonElement lib : libraries) { - String name = getElement(lib.getAsJsonObject(), "name").getAsString(); - if (name.startsWith("io.github.zekerzhayard:ForgeWrapper:")) { - wrapperVersion.append(getElement(lib.getAsJsonObject(), "MMC-filename").getAsString()); - } - } - Map additionalUrls = new HashMap<>(); - String path = String.format("%s/forge/%s-%s/forge-%s-%s", String.join("/", forgeGroupParts), mcVersion, forgeVersion, mcVersion, forgeVersion); - additionalUrls.put(path + "-universal.jar", mavenURL + "/" + path + "-universal.jar"); - transformLibraries(getElement(installProfile, "libraries").getAsJsonArray(), mavenFiles, additionalUrls); - additionalUrls.clear(); - additionalUrls.put(path + ".jar", mavenURL + "/" + path + "-launcher.jar"); - transformLibraries(getElement(installer, "libraries").getAsJsonArray(), libraries, additionalUrls); - - patches.addProperty("uid", forgeGroup); - patches.addProperty("version", forgeVersion); - for (JsonElement require : getElement(patches, "requires").getAsJsonArray()) { - JsonObject requireObject = require.getAsJsonObject(); - if (getElement(requireObject, "uid").getAsString().equals("net.minecraft")) { - requireObject.addProperty("equals", mcVersion); - } - } - return patches; - } - - private static JsonElement getElement(JsonObject object, String property) { - Optional> first = object.entrySet().stream().filter(e -> e.getKey().equals(property)).findFirst(); - if (first.isPresent()) { - return first.get().getValue(); - } - return JsonNull.INSTANCE; - } - - private static void transformLibraries(JsonArray source, JsonArray target, Map additionalUrls) { - for (JsonElement lib : source) { - JsonObject artifact = getElement(getElement(lib.getAsJsonObject(), "downloads").getAsJsonObject(), "artifact").getAsJsonObject(); - String path = getElement(artifact, "path").getAsString(); - if (additionalUrls.containsKey(path)) { - artifact.getAsJsonObject().addProperty("url", additionalUrls.get(path)); - } - target.add(lib); - } - } -} diff --git a/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Main.java b/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Main.java deleted file mode 100644 index 83ecdf9..0000000 --- a/converter/src/main/java/io/github/zekerzhayard/forgewrapper/converter/Main.java +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.zekerzhayard.forgewrapper.converter; - -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; - -public class Main { - public static void main(String[] args) { - Path installer = null, instance = Paths.get("."), multimc = null; - try { - HashMap argsMap = parseArgs(args); - installer = Paths.get(argsMap.get("--installer")); - if (argsMap.containsKey("--instance")) { - instance = Paths.get(argsMap.get("--instance")); - multimc = instance.getParent(); - } - } catch (Exception e) { - System.out.println("Invalid arguments! Use: java -jar --installer= [--instance=]"); - throw new RuntimeException(e); - } - - try { - URLClassLoader ucl = URLClassLoader.newInstance(new URL[] { - Converter.class.getProtectionDomain().getCodeSource().getLocation(), - installer.toUri().toURL() - }, null); - ucl.loadClass("io.github.zekerzhayard.forgewrapper.converter.Converter").getMethod("convert", Path.class, Path.class, Path.class).invoke(null, installer, instance, multimc); - System.out.println("Successfully install Forge for MultiMC!"); - } catch (Exception e) { - System.out.println("Failed to install Forge!"); - throw new RuntimeException(e); - } - } - - /** - * @return installer -- The path of forge installer.
- * instance -- The instance folder of MultiMC.
- * cursepack -- The version of cursepacklocator.
- */ - private static HashMap parseArgs(String[] args) { - HashMap map = new HashMap<>(); - for (String arg : args) { - String[] params = arg.split("=", 2); - map.put(params[0], params[1]); - } - if (!map.containsKey("--installer")) { - throw new IllegalArgumentException(); - } - return map; - } -} diff --git a/converter/src/main/resources/mmc-pack.json b/converter/src/main/resources/mmc-pack.json deleted file mode 100644 index 51ba0bf..0000000 --- a/converter/src/main/resources/mmc-pack.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "formatVersion": 1, - "components": [ - { - "important": true, - "uid": "net.minecraft", - "version": "{VERSION}" - }, - { - "uid": "{FORGE_GROUP}" - } - ] -} diff --git a/converter/src/main/resources/patches/template.json b/converter/src/main/resources/patches/template.json deleted file mode 100644 index 5a46916..0000000 --- a/converter/src/main/resources/patches/template.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "formatVersion": 1, - "mainClass": "io.github.zekerzhayard.forgewrapper.installer.Main", - "minecraftArguments": "", - "name": "Forge", - "requires": [ - { - "equals": "{VERSION}", - "uid": "net.minecraft" - } - ], - "type": "release", - "uid": "{FORGE_GROUP}", - "version": "{FORGE_VERSION}", - "mavenFiles": [ - { - "name": "{FORGE_GROUP}:forge:{VERSION}-{FORGE_VERSION}:installer", - "url": "{MAVEN_URL}" - } - ], - "libraries": [ - { - "name": "io.github.zekerzhayard:ForgeWrapper:${version}", - "MMC-hint": "local", - "MMC-filename": "ForgeWrapper-${version}.jar" - } - ] -} diff --git a/gradle.properties b/gradle.properties index f1db528..4fb1212 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.daemon = false -fw_version = 1.5.7 +fw_version = 1.5.8 diff --git a/jigsaw/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java b/jigsaw/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java index 9a49d7f..e15d39c 100644 --- a/jigsaw/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java +++ b/jigsaw/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java @@ -9,6 +9,7 @@ import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; import java.lang.module.ResolvedModule; import java.lang.reflect.Field; +import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; @@ -159,6 +160,15 @@ public class ModuleUtil { } } + public static void setupClassPath(Path libraryDir, List paths) throws Throwable { + Class urlClassPathClass = Class.forName("jdk.internal.loader.URLClassPath"); + Object ucp = IMPL_LOOKUP.findGetter(Class.forName("jdk.internal.loader.BuiltinClassLoader"), "ucp", urlClassPathClass).invokeWithArguments(ClassLoader.getSystemClassLoader()); + MethodHandle addURLMH = IMPL_LOOKUP.findVirtual(urlClassPathClass, "addURL", MethodType.methodType(void.class, URL.class)); + for (String path : paths) { + addURLMH.invokeWithArguments(ucp, libraryDir.resolve(path).toUri().toURL()); + } + } + // ForgeWrapper need some extra settings to invoke BootstrapLauncher. public static Class setupBootstrapLauncher(Class mainClass) throws Throwable { if (!mainClass.getModule().isOpen(mainClass.getPackageName(), ModuleUtil.class.getModule())) { diff --git a/settings.gradle b/settings.gradle index 7bda9a2..34c563d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,5 @@ rootProject.name = 'ForgeWrapper' include 'common' -include 'converter' include 'legacy' include 'jigsaw' diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Bootstrap.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Bootstrap.java index 2740b76..3604371 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Bootstrap.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Bootstrap.java @@ -15,6 +15,15 @@ public class Bootstrap { } jvmArgs = replacedJvmArgs; + // Remove NewLaunch.jar from property to prevent Forge from adding it to the module path + StringBuilder newCP = new StringBuilder(); + for (String path : System.getProperty("java.class.path").split(File.pathSeparator)) { + if (!path.endsWith("NewLaunch.jar")) { + newCP.append(path).append(File.pathSeparator); + } + } + System.setProperty("java.class.path", newCP.substring(0, newCP.length() - 1)); + String modulePath = null; List addExports = new ArrayList<>(); List addOpens = new ArrayList<>(); diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java index 5ecd971..37876a6 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/Main.java @@ -62,6 +62,7 @@ public class Main { } } + ModuleUtil.setupClassPath(detector.getLibraryDir(), detector.getExtraLibraries(forgeGroup, forgeArtifact, forgeFullVersion)); Class mainClass = ModuleUtil.setupBootstrapLauncher(Class.forName(detector.getMainClass(forgeGroup, forgeArtifact, forgeFullVersion))); mainClass.getMethod("main", String[].class).invoke(null, new Object[] { args }); } diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java index b69e9b8..67d3e1d 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java @@ -94,7 +94,7 @@ public interface IFileDetector { */ default List getJvmArgs(String forgeGroup, String forgeArtifact, String forgeFullVersion) { return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "version.json", e -> { - JsonElement element = getElement(e.getAsJsonObject().getAsJsonObject("arguments"), "jvm"); + JsonElement element = e.getAsJsonObject().get("arguments").getAsJsonObject().get("jvm"); List args = new ArrayList<>(); if (!element.equals(JsonNull.INSTANCE)) { element.getAsJsonArray().iterator().forEachRemaining(je -> args.add(je.getAsString())); @@ -103,6 +103,19 @@ public interface IFileDetector { }); } + default List getExtraLibraries(String forgeGroup, String forgeArtifact, String forgeFullVersion) { + return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "version.json", e -> { + List paths = new ArrayList<>(); + e.getAsJsonObject().getAsJsonArray("libraries").iterator().forEachRemaining(je -> { + JsonObject artifact = je.getAsJsonObject().get("downloads").getAsJsonObject().get("artifact").getAsJsonObject(); + if (artifact.get("url").getAsString().isEmpty()) { + paths.add(artifact.get("path").getAsString()); + } + }); + return paths; + }); + } + /** * @param forgeGroup Forge package group (e.g. net.minecraftforge). * @param forgeArtifact Forge package artifact (e.g. forge). @@ -162,7 +175,7 @@ public interface IFileDetector { // Get all "data//client" elements. Pattern artifactPattern = Pattern.compile("^\\[(?[^:]*):(?[^:]*):(?[^:@]*)(:(?[^@]*))?(@(?[^]]*))?]$"); for (Map.Entry entry : jo.entrySet()) { - String clientStr = getElement(entry.getValue().getAsJsonObject(), "client").getAsString(); + String clientStr = entry.getValue().getAsJsonObject().get("client").getAsString(); if (entry.getKey().endsWith("_SHA")) { Pattern p = Pattern.compile("^'(?[A-Za-z0-9]{40})'$"); Matcher m = p.matcher(clientStr); @@ -181,7 +194,7 @@ public interface IFileDetector { .resolve(groupId.replace('.', File.separatorChar)) .resolve(artifactId) .resolve(version) - .resolve(artifactId + "-" + version + (classifier.equals("") ? "" : "-") + classifier + "." + type).toAbsolutePath()); + .resolve(artifactId + "-" + version + (classifier.isEmpty() ? "" : "-") + classifier + "." + type).toAbsolutePath()); } } } @@ -208,21 +221,13 @@ public interface IFileDetector { * @return True represents the file is ready. */ static boolean checkExtraFile(Path path, String sha1) { - return sha1 == null || sha1.equals("") || (isFile(path) && sha1.toLowerCase(Locale.ENGLISH).equals(getFileSHA1(path))); + return sha1 == null || sha1.isEmpty() || (isFile(path) && sha1.toLowerCase(Locale.ENGLISH).equals(getFileSHA1(path))); } static boolean isFile(Path path) { return path != null && Files.isRegularFile(path); } - static JsonElement getElement(JsonObject object, String property) { - Optional> first = object.entrySet().stream().filter(e -> e.getKey().equals(property)).findFirst(); - if (first.isPresent()) { - return first.get().getValue(); - } - return JsonNull.INSTANCE; - } - static String getFileSHA1(Path path) { try { StringBuilder sha1 = new StringBuilder(new BigInteger(1, MessageDigest.getInstance("SHA-1").digest(Files.readAllBytes(path))).toString(16)); diff --git a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java index c89d714..9eee574 100644 --- a/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java +++ b/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java @@ -1,5 +1,10 @@ package io.github.zekerzhayard.forgewrapper.installer.util; +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; import java.util.List; public class ModuleUtil { @@ -15,6 +20,14 @@ public class ModuleUtil { // nothing to do with Java 8 } + public static void setupClassPath(Path libraryDir, List paths) throws Throwable { + Method addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); + addURLMethod.setAccessible(true); + for (String path : paths) { + addURLMethod.invoke(ClassLoader.getSystemClassLoader(), libraryDir.resolve(path).toUri().toURL()); + } + } + public static Class setupBootstrapLauncher(Class mainClass) { // nothing to do with Java 8 return mainClass;