diff --git a/readme.md b/readme.md index ce5c8d9..04f67cc 100644 --- a/readme.md +++ b/readme.md @@ -58,10 +58,21 @@ fusioner { addRelocate "me.hypherionmc.mcdiscordformatter", "forge.me.hypherionmc.mcdiscordformatter" } + // NeoForge Project + neoforge { + projectName = "NeoForge" // The name of the project that contains the fabric code + inputTaskName = "remapJar" // The name of the build task for the neoforge project + // OR + // inputFile = "NeoForge/build/libs/MyMod-NeoForge-1.0.jar" // Use a custom jar input + + // Packages that need to be relocated to the specific platform + addRelocate "me.hypherionmc.mcdiscordformatter", "neoforge.me.hypherionmc.mcdiscordformatter" + } + // Fabric Project fabric { projectName = "Fabric" // The name of the project that contains the fabric code - inputTaskName = "remapJar" // The name of the build task for the forge project + inputTaskName = "remapJar" // The name of the build task for the fabric project // OR // inputFile = "Fabric/build/libs/MyMod-Fabric-1.0.jar" // Use a custom jar input @@ -72,7 +83,7 @@ fusioner { // Quilt Project quilt { projectName = "Quilt" // The name of the project that contains the quilt code - inputTaskName = "remapJar" // The name of the build task for the forge project + inputTaskName = "remapJar" // The name of the build task for the quilt project // OR // inputFile = "Quilt/build/libs/MyMod-Quilt-1.0.jar" // Use a custom jar input @@ -83,7 +94,7 @@ fusioner { // For "custom", the "projectName" is a required value. custom { projectName = "sponge" // This is the name of the project. This is a required field. - inputTaskName = "jar" // The name of the build task for the forge project + inputTaskName = "jar" // The name of the build task for the project // OR // inputFile = "sponge/build/libs/MyMod-Sponge-1.0.jar" // Use a custom jar input diff --git a/src/main/java/com/hypherionmc/modfusioner/actions/JarMergeAction.java b/src/main/java/com/hypherionmc/modfusioner/actions/JarMergeAction.java index 8634a6b..60d40b5 100644 --- a/src/main/java/com/hypherionmc/modfusioner/actions/JarMergeAction.java +++ b/src/main/java/com/hypherionmc/modfusioner/actions/JarMergeAction.java @@ -47,12 +47,14 @@ public class JarMergeAction { // File Inputs @Setter private File forgeInput; + @Setter private File neoforgeInput; @Setter private File fabricInput; @Setter private File quiltInput; private final Map customInputs; // Relocations @Setter private Map forgeRelocations; + @Setter private Map neoforgeRelocations; @Setter private Map fabricRelocations; @Setter private Map quiltRelocations; @@ -93,7 +95,7 @@ public class JarMergeAction { FileTools.createOrReCreate(tempDir); // Check if the required input files exists - if (forgeInput == null && fabricInput == null && quiltInput == null && customInputs.isEmpty()) { + if (forgeInput == null && neoforgeInput == null && fabricInput == null && quiltInput == null && customInputs.isEmpty()) { throw new IllegalArgumentException("No input jars were provided."); } @@ -101,6 +103,10 @@ public class JarMergeAction { logger.warn("Forge jar does not exist! You can ignore this warning if you are not using forge"); } + if (modFusionerExtension.getNeoforgeConfiguration() != null && !FileTools.exists(neoforgeInput)) { + logger.warn("NeoForge jar does not exist! You can ignore this warning if you are not using neoforge"); + } + if (modFusionerExtension.getFabricConfiguration() != null && !FileTools.exists(fabricInput)) { logger.warn("Fabric jar does not exist! You can ignore this warning if you are not using fabric"); } @@ -121,6 +127,7 @@ public class JarMergeAction { // Create the temporary processing directories File fabricTemp = FileTools.getOrCreate(new File(tempDir, "fabric-temp")); File forgeTemp = FileTools.getOrCreate(new File(tempDir, "forge-temp")); + File neoforgeTemp = FileTools.getOrCreate(new File(tempDir, "neoforge-temp")); File quiltTemp = FileTools.getOrCreate(new File(tempDir, "quilt-temp")); customTemps = new HashMap<>(); @@ -138,6 +145,9 @@ public class JarMergeAction { if (FileTools.exists(forgeInput)) { jarManager.unpackJar(forgeInput, forgeTemp); } + if (FileTools.exists(neoforgeInput)) { + jarManager.unpackJar(neoforgeInput, neoforgeTemp); + } if (FileTools.exists(fabricInput)) { jarManager.unpackJar(fabricInput, fabricTemp); } @@ -156,9 +166,10 @@ public class JarMergeAction { })); File mergedTemp = FileTools.getOrCreate(new File(tempDir, "merged-temp")); - processManifests(mergedTemp, forgeTemp, fabricTemp, quiltTemp); + processManifests(mergedTemp, forgeTemp, neoforgeTemp, fabricTemp, quiltTemp); FileTools.moveDirectory(forgeTemp, mergedTemp); + FileTools.moveDirectory(neoforgeTemp, mergedTemp); FileTools.moveDirectory(fabricTemp, mergedTemp); FileTools.moveDirectory(quiltTemp, mergedTemp); @@ -211,6 +222,7 @@ public class JarMergeAction { logger.lifecycle("Start processing input jars"); remapJar(forgeInput, "forge", forgeRelocations); + remapJar(neoforgeInput, "neoforge", neoforgeRelocations); remapJar(fabricInput, "fabric", fabricRelocations); remapJar(quiltInput, "quilt", quiltRelocations); @@ -265,6 +277,9 @@ public class JarMergeAction { case "forge": forgeInput = remappedJar; break; + case "neoforge": + neoforgeInput = remappedJar; + break; case "fabric": fabricInput = remappedJar; break; @@ -319,13 +334,15 @@ public class JarMergeAction { /** * Process resource files from unpacked jars to remap them to their new package names * @param forgeTemps - The forge processing directory + * @param neoforgeTemps - The neoforge processing directory * @param fabricTemps - The fabric processing directory * @param quiltTemps - The quilt processing directory * @throws IOException - Thrown if an IO error occurs */ - private void remapResources(File forgeTemps, File fabricTemps, File quiltTemps) throws IOException { + private void remapResources(File forgeTemps, File neoforgeTemps, File fabricTemps, File quiltTemps) throws IOException { logger.lifecycle("Start Remapping Resources"); remapJarResources(forgeInput, "forge", forgeTemps, forgeRelocations); + remapJarResources(neoforgeInput, "neoforge", neoforgeTemps, neoforgeRelocations); remapJarResources(fabricInput, "fabric", fabricTemps, fabricRelocations); remapJarResources(quiltInput, "quilt", quiltTemps, quiltRelocations); @@ -341,7 +358,7 @@ public class JarMergeAction { } /** - * Remap resource files from jar. Used to remove duplicate code from {@link JarMergeAction#remapResources(File, File, File)} + * Remap resource files from jar. Used to remove duplicate code from {@link JarMergeAction#remapResources(File, File, File, File)} * @param jar - The jar file being processed * @param identifier - The group identifier of the packages * @param workingDir - The processing directory @@ -418,13 +435,15 @@ public class JarMergeAction { * Process the manifest files from all the input jars and combine them into one * @param mergedTemp - The processing directory * @param forgeTemp - The forge processing directory + * @param neoforgeTemp - The neoforge processing directory * @param fabricTemp - The fabric processing directory * @param quiltTemp - The quilt processing directory * @throws IOException - Thrown if an IO error occurs */ - public void processManifests(File mergedTemp, File forgeTemp, File fabricTemp, File quiltTemp) throws IOException { + public void processManifests(File mergedTemp, File forgeTemp, File neoforgeTemp, File fabricTemp, File quiltTemp) throws IOException { Manifest mergedManifest = new Manifest(); Manifest forgeManifest = new Manifest(); + Manifest neoforgeManifest = new Manifest(); Manifest fabricManifest = new Manifest(); Manifest quiltManifest = new Manifest(); List customManifests = new ArrayList<>(); @@ -432,6 +451,8 @@ public class JarMergeAction { FileInputStream fileInputStream = null; if (FileTools.exists(forgeInput)) forgeManifest.read(fileInputStream = new FileInputStream(new File(forgeTemp, "META-INF/MANIFEST.MF"))); if (fileInputStream != null) fileInputStream.close(); + if (FileTools.exists(neoforgeInput)) neoforgeManifest.read(fileInputStream = new FileInputStream(new File(neoforgeTemp, "META-INF/MANIFEST.MF"))); + if (fileInputStream != null) fileInputStream.close(); if (FileTools.exists(fabricInput)) fabricManifest.read(fileInputStream = new FileInputStream(new File(fabricTemp, "META-INF/MANIFEST.MF"))); if (fileInputStream != null) fileInputStream.close(); if (FileTools.exists(quiltInput)) quiltManifest.read(fileInputStream = new FileInputStream(new File(quiltTemp, "META-INF/MANIFEST.MF"))); @@ -449,6 +470,7 @@ public class JarMergeAction { } forgeManifest.getMainAttributes().forEach((key, value) -> mergedManifest.getMainAttributes().putValue(key.toString(), value.toString())); + neoforgeManifest.getMainAttributes().forEach((key, value) -> mergedManifest.getMainAttributes().putValue(key.toString(), value.toString())); fabricManifest.getMainAttributes().forEach((key, value) -> mergedManifest.getMainAttributes().putValue(key.toString(), value.toString())); quiltManifest.getMainAttributes().forEach((key, value) -> mergedManifest.getMainAttributes().putValue(key.toString(), value.toString())); @@ -483,7 +505,7 @@ public class JarMergeAction { if (!forgeMixins.isEmpty()) mergedManifest.getMainAttributes().putValue("MixinConfigs", String.join(",", this.forgeMixins)); } - remapResources(forgeTemp, fabricTemp, quiltTemp); + remapResources(forgeTemp, neoforgeTemp, fabricTemp, quiltTemp); if (this.forgeMixins != null && mergedManifest.getMainAttributes().getValue("MixinConfigs") == null) { logger.debug("Couldn't detect forge mixins. You can ignore this if you are not using mixins with forge.\n" + @@ -499,6 +521,7 @@ public class JarMergeAction { //mergedManifest.getMainAttributes().putValue(manifestVersionKey, version); if (FileTools.exists(forgeInput)) new File(forgeTemp, "META-INF/MANIFEST.MF").delete(); + if (FileTools.exists(neoforgeInput)) new File(neoforgeTemp, "META-INF/MANIFEST.MF").delete(); if (FileTools.exists(fabricInput)) new File(fabricTemp, "META-INF/MANIFEST.MF").delete(); if (FileTools.exists(quiltInput)) new File(quiltTemp, "META-INF/MANIFEST.MF").delete(); @@ -533,6 +556,11 @@ public class JarMergeAction { removeDuplicateRelocationResources.put("forge/" + duplicatePath, duplicatePath); } + if (FileTools.exists(neoforgeInput)) { + ignoredDuplicateRelocations.put("neoforge." + duplicate, duplicate); + removeDuplicateRelocationResources.put("neoforge/" + duplicatePath, duplicatePath); + } + if (FileTools.exists(fabricInput)) { ignoredDuplicateRelocations.put("fabric." + duplicate, duplicate); removeDuplicateRelocationResources.put("fabric/" + duplicatePath, duplicatePath); diff --git a/src/main/java/com/hypherionmc/modfusioner/plugin/FusionerExtension.java b/src/main/java/com/hypherionmc/modfusioner/plugin/FusionerExtension.java index 5a775b8..aa8c2cb 100644 --- a/src/main/java/com/hypherionmc/modfusioner/plugin/FusionerExtension.java +++ b/src/main/java/com/hypherionmc/modfusioner/plugin/FusionerExtension.java @@ -9,12 +9,13 @@ */ package com.hypherionmc.modfusioner.plugin; -import groovy.lang.Closure; import lombok.Getter; import lombok.Setter; +import org.gradle.api.Action; import java.util.*; +@SuppressWarnings("unused") public class FusionerExtension { // Group, or package names that will be used for the final jar @@ -42,6 +43,10 @@ public class FusionerExtension { @Getter @Setter FusionerExtension.ForgeConfiguration forgeConfiguration; + // Forge Project Configuration + @Getter @Setter + FusionerExtension.NeoForgeConfiguration neoforgeConfiguration; + // Fabric Project Configuration @Getter @Setter FusionerExtension.FabricConfiguration fabricConfiguration; @@ -103,36 +108,45 @@ public class FusionerExtension { /** * Set up the forge project configurations */ - public FusionerExtension.ForgeConfiguration forge(Closure closure) { + public FusionerExtension.ForgeConfiguration forge(Action action) { forgeConfiguration = new FusionerExtension.ForgeConfiguration(); - ModFusionerPlugin.rootProject.configure(forgeConfiguration, closure); + action.execute(forgeConfiguration); return forgeConfiguration; } + /** + * Set up the neoforge project configurations + */ + public FusionerExtension.NeoForgeConfiguration neoforge(Action action) { + neoforgeConfiguration = new FusionerExtension.NeoForgeConfiguration(); + action.execute(neoforgeConfiguration); + return neoforgeConfiguration; + } + /** * Set up the fabric project configurations */ - public FusionerExtension.FabricConfiguration fabric(Closure closure) { + public FusionerExtension.FabricConfiguration fabric(Action action) { fabricConfiguration = new FusionerExtension.FabricConfiguration(); - ModFusionerPlugin.rootProject.configure(fabricConfiguration, closure); + action.execute(fabricConfiguration); return fabricConfiguration; } /** * Set up the quilt project configurations */ - public FusionerExtension.QuiltConfiguration quilt(Closure closure) { + public FusionerExtension.QuiltConfiguration quilt(Action action) { quiltConfiguration = new FusionerExtension.QuiltConfiguration(); - ModFusionerPlugin.rootProject.configure(quiltConfiguration, closure); + action.execute(quiltConfiguration); return quiltConfiguration; } /** * Set up custom project configurations */ - public FusionerExtension.CustomConfiguration custom(Closure closure) { + public FusionerExtension.CustomConfiguration custom(Action action) { FusionerExtension.CustomConfiguration customConfiguration = new FusionerExtension.CustomConfiguration(); - ModFusionerPlugin.rootProject.configure(customConfiguration, closure); + action.execute(customConfiguration); if (customConfiguration.getProjectName() == null || customConfiguration.getProjectName().isEmpty()) { throw new IllegalStateException("Custom project configurations need to specify a \"projectName\""); @@ -184,6 +198,37 @@ public class FusionerExtension { } } + /** + * NeoForge Configuration Structure + */ + public static class NeoForgeConfiguration { + + // The name of the gradle module that contains the fabric code + @Getter @Setter + String projectName = "neoforge"; + + // The file that will be used as the input + @Getter @Setter + String inputFile; + + // The name of the task to run to get the input file + @Getter @Setter + String inputTaskName; + + // Packages that should be relocated, instead of duplicated + @Getter + Map relocations = new HashMap<>(); + + /** + * Add a package to relocate, instead of duplicating + * @param from - The original name of the package. For example: com.google.gson + * @param to - The new name of the package. For example: forge.com.google.gson + */ + public void addRelocate(String from, String to) { + this.relocations.put(from, to); + } + } + /** * Fabric project configuration */ diff --git a/src/main/java/com/hypherionmc/modfusioner/task/JarFuseTask.java b/src/main/java/com/hypherionmc/modfusioner/task/JarFuseTask.java index bddc6a0..54a4e8a 100644 --- a/src/main/java/com/hypherionmc/modfusioner/task/JarFuseTask.java +++ b/src/main/java/com/hypherionmc/modfusioner/task/JarFuseTask.java @@ -72,6 +72,7 @@ public class JarFuseTask extends Jar { // Get settings from extension FusionerExtension.ForgeConfiguration forgeConfiguration = modFusionerExtension.getForgeConfiguration(); + FusionerExtension.NeoForgeConfiguration neoforgeConfiguration = modFusionerExtension.getNeoforgeConfiguration(); FusionerExtension.FabricConfiguration fabricConfiguration = modFusionerExtension.getFabricConfiguration(); FusionerExtension.QuiltConfiguration quiltConfiguration = modFusionerExtension.getQuiltConfiguration(); @@ -79,6 +80,7 @@ public class JarFuseTask extends Jar { // Try to resolve the projects specific in the extension config Project forgeProject = null; + Project neoforgeProject = null; Project fabricProject = null; Project quiltProject = null; Map customProjects = new HashMap<>(); @@ -91,6 +93,13 @@ public class JarFuseTask extends Jar { } catch (NoSuchElementException ignored) { } } + if (neoforgeConfiguration != null) { + try { + neoforgeProject = rootProject.getAllprojects().stream().filter(p -> !p.getName().equals(rootProject.getName())).filter(p -> p.getName().equalsIgnoreCase(neoforgeConfiguration.getProjectName())).findFirst().get(); + validation.add(true); + } catch (NoSuchElementException ignored) { } + } + if (fabricConfiguration != null) { try { fabricProject = rootProject.getAllprojects().stream().filter(p -> !p.getName().equals(rootProject.getName())).filter(p -> p.getName().equalsIgnoreCase(fabricConfiguration.getProjectName())).findFirst().get(); @@ -124,6 +133,7 @@ public class JarFuseTask extends Jar { // Try to automatically determine the input jar from the projects File forgeJar = null; + File neoforgeJar = null; File fabricJar = null; File quiltJar = null; Map customJars = new HashMap<>(); @@ -132,6 +142,10 @@ public class JarFuseTask extends Jar { forgeJar = getInputFile(forgeConfiguration.getInputFile(), forgeConfiguration.getInputTaskName(), forgeProject); } + if (neoforgeProject != null && neoforgeConfiguration != null) { + neoforgeJar = getInputFile(neoforgeConfiguration.getInputFile(), neoforgeConfiguration.getInputTaskName(), neoforgeProject); + } + if (fabricProject != null && fabricConfiguration != null) { fabricJar = getInputFile(fabricConfiguration.getInputFile(), fabricConfiguration.getInputTaskName(), fabricProject); } @@ -164,6 +178,10 @@ public class JarFuseTask extends Jar { mergeAction.setForgeRelocations(forgeConfiguration == null ? new HashMap<>() : forgeConfiguration.getRelocations()); mergeAction.setForgeMixins(forgeConfiguration == null ? new ArrayList<>() : forgeConfiguration.getMixins()); + // NeoForge + mergeAction.setNeoforgeInput(neoforgeJar); + mergeAction.setNeoforgeRelocations(neoforgeConfiguration == null ? new HashMap<>() : neoforgeConfiguration.getRelocations()); + // Fabric mergeAction.setFabricInput(fabricJar); mergeAction.setFabricRelocations(fabricConfiguration == null ? new HashMap<>() : fabricConfiguration.getRelocations());