diff --git a/README.md b/README.md index 88de773..0a2caf4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MultiLoader Template -This project provides a Gradle project template that can compile mods for multiple modloaders using a common sourceset. This project does not require any third party libraries or dependencies. If you have any questions or want to discuss the project join our [Discord](https://discord.myceliummod.network). +This project provides a Gradle project template that can compile Minecraft mods for multiple modloaders using a common project for the sources. This project does not require any third party libraries or dependencies. If you have any questions or want to discuss the project, please join our [Discord](https://discord.myceliummod.network). ## Getting Started @@ -8,23 +8,27 @@ This project provides a Gradle project template that can compile mods for multip This guide will show how to import the MultiLoader Template into IntelliJ IDEA. The setup process is roughly equivalent to setting up the modloaders independently and should be very familiar to anyone who has worked with their MDKs. 1. Clone or download this repository to your computer. -2. Configure the project by editing the `group`, `mod_name`, `mod_author`, and `mod_id` properties in the `gradle.properties` file. You will also need to change the `rootProject.name` property in `settings.gradle`, this should match the folder name of your project, or else IDEA may complain. -3. Open the template's root folder as a new project in IDEA. This is the folder that contains this README file and the gradlew executable. +2. Configure the project by setting the properties in the `gradle.properties` file. You will also need to change the `rootProject.name` property in `settings.gradle`, this should match the folder name of your project, or else IDEA may complain. +3. Open the template's root folder as a new project in IDEA. This is the folder that contains this README.md file and the gradlew executable. 4. If your default JVM/JDK is not Java 21 you will encounter an error when opening the project. This error is fixed by going to `File > Settings > Build, Execution, Deployment > Build Tools > Gradle > Gradle JVM` and changing the value to a valid Java 21 JVM. You will also need to set the Project SDK to Java 21. This can be done by going to `File > Project Structure > Project SDK`. Once both have been set open the Gradle tab in IDEA and click the refresh button to reload the project. -5. Open the Gradle tab in IDEA if it has not already been opened. Navigate to `Your Project > Common > Tasks > vanilla gradle > decompile`. Run this task to decompile Minecraft. -6. Open your Run/Debug Configurations. Under the Application category there should now be options to run NeoForge and Fabric projects. Select one of the client options and try to run it. -7. Assuming you were able to run the game in step 7 your workspace should now be set up. +5. Open your Run/Debug Configurations. Under the `Application` category there should now be options to run Fabric and NeoForge projects. Select one of the client options and try to run it. +6. Assuming you were able to run the game in step 6 your workspace should now be set up. ### Eclipse While it is possible to use this template in Eclipse it is not recommended. During the development of this template multiple critical bugs and quirks related to Eclipse were found at nearly every level of the required build tools. While we continue to work with these tools to report and resolve issues support for projects like these are not there yet. For now Eclipse is considered unsupported by this project. The development cycle for build tools is notoriously slow so there are no ETAs available. ## Development Guide -When using this template the majority of your mod is developed in the Common project. The Common project is compiled against the vanilla game and is used to hold code that is shared between the different loader-specific versions of your mod. The Common project has no knowledge or access to ModLoader specific code, apis, or concepts. Code that requires something from a specific loader must be done through the project that is specific to that loader, such as the NeoForge or Fabric project. +When using this template the majority of your mod should be developed in the `common` project. The `common` project is compiled against the vanilla game and is used to hold code that is shared between the different loader-specific versions of your mod. The `common` project has no knowledge or access to ModLoader specific code, apis, or concepts. Code that requires something from a specific loader must be done through the project that is specific to that loader, such as the `fabric` or `neoforge` projects. -Loader specific projects such as the NeoForge and Fabric project are used to load the Common project into the game. These projects also define code that is specific to that loader. Loader specific projects can access all of the code in the Common project. It is important to remember that the Common project can not access code from loader specific projects. +Loader specific projects such as the `fabric` and `neoforge` project are used to load the `common` project into the game. These projects also define code that is specific to that loader. Loader specific projects can access all the code in the `common` project. It is important to remember that the `common` project can not access code from loader specific projects. ## Removing Platforms and Loaders -While the MultiLoader Template includes support for many platforms and loaders you can easily remove support for the ones you don't need. This can be done by deleting the subproject folder and then removing it from the `settings.gradle` file. For example if you wanted to remove support for Forge you would follow the following steps. +While the MultiLoader-Template includes support for many platforms and loaders you can easily remove support for the ones you don't need. This can be done by deleting the subproject folder and then removing it from the `settings.gradle` file. For example if you wanted to remove support for Forge you would follow the following steps. +## Removing Platforms and Loaders +While this template has support for many modloaders, new loaders may appear in the future, and existing loaders may become less relevant. + +Removing loader specific projects is as easy as deleting the folder, and removing the `include("projectname")` line from the `settings.gradle` file. +For example if you wanted to remove support for `forge` you would follow the following steps: 1. Delete the subproject folder. For example, delete `MultiLoader-Template/forge`. 2. Remove the project from `settings.gradle`. For example, remove `include("forge")`. diff --git a/build.gradle b/build.gradle index 0f12253..5b7a2c5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,6 @@ plugins { - // Required for NeoGradle - id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" + // see https://fabricmc.net/develop/ for new versions + id 'fabric-loom' version '1.7-SNAPSHOT' apply false + // see https://projects.neoforged.net/neoforged/moddevgradle for new versions + id 'net.neoforged.moddev' version '0.1.110' apply false } \ No newline at end of file diff --git a/buildSrc/src/main/groovy/multiloader-common.gradle b/buildSrc/src/main/groovy/multiloader-common.gradle index 9d57a16..f594d45 100644 --- a/buildSrc/src/main/groovy/multiloader-common.gradle +++ b/buildSrc/src/main/groovy/multiloader-common.gradle @@ -23,7 +23,16 @@ repositories { url = 'https://repo.spongepowered.org/repository/maven-public' } } - filter { includeGroupAndSubgroups("org.spongepowered") } + filter { includeGroupAndSubgroups('org.spongepowered') } + } + exclusiveContent { + forRepository { + maven { + name = 'ParchmentMC' + url = 'https://maven.parchmentmc.org/' + } + } + filter { includeGroup('org.parchmentmc.data') } } maven { name = 'BlameJared' @@ -45,13 +54,13 @@ repositories { } sourcesJar { - from(rootProject.file("LICENSE")) { + from(rootProject.file('LICENSE')) { rename { "${it}_${mod_name}" } } } jar { - from(rootProject.file("LICENSE")) { + from(rootProject.file('LICENSE')) { rename { "${it}_${mod_name}" } } @@ -70,21 +79,21 @@ jar { processResources { def expandProps = [ - "version": version, - "group": project.group, //Else we target the task's group. - "minecraft_version": minecraft_version, - "minecraft_version_range": minecraft_version_range, - "fabric_version": fabric_version, - "fabric_loader_version": fabric_loader_version, - "mod_name": mod_name, - "mod_author": mod_author, - "mod_id": mod_id, - "license": license, - "description": project.description, - "neoforge_version": neoforge_version, - "neoforge_loader_version_range": neoforge_loader_version_range, - "credits": credits, - "java_version": java_version + 'version': version, + 'group': project.group, //Else we target the task's group. + 'minecraft_version': minecraft_version, + 'minecraft_version_range': minecraft_version_range, + 'fabric_version': fabric_version, + 'fabric_loader_version': fabric_loader_version, + 'mod_name': mod_name, + 'mod_author': mod_author, + 'mod_id': mod_id, + 'license': license, + 'description': project.description, + 'neoforge_version': neoforge_version, + 'neoforge_loader_version_range': neoforge_loader_version_range, + 'credits': credits, + 'java_version': java_version ] filesMatching(['pack.mcmeta', 'fabric.mod.json', 'META-INF/mods.toml', 'META-INF/neoforge.mods.toml', '*.mixins.json']) { @@ -102,7 +111,7 @@ publishing { } repositories { maven { - url System.getenv("local_maven_url") + url System.getenv('local_maven_url') } } } diff --git a/buildSrc/src/main/groovy/multiloader-loader.gradle b/buildSrc/src/main/groovy/multiloader-loader.gradle index 8ebec22..92e2325 100644 --- a/buildSrc/src/main/groovy/multiloader-loader.gradle +++ b/buildSrc/src/main/groovy/multiloader-loader.gradle @@ -36,7 +36,7 @@ tasks.named('javadoc', Javadoc).configure { source(configurations.commonJava) } -tasks.named("sourcesJar", Jar) { +tasks.named('sourcesJar', Jar) { dependsOn(configurations.commonJava) from(configurations.commonJava) dependsOn(configurations.commonResources) diff --git a/common/build.gradle b/common/build.gradle index d213886..faa1824 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,18 +1,30 @@ plugins { id 'multiloader-common' - id 'org.spongepowered.gradle.vanilla' version '0.2.1-SNAPSHOT' + id 'net.neoforged.moddev' } -minecraft { - version(minecraft_version) - def aw = file("src/main/resources/${mod_id}.accesswidener") - if(aw.exists()){ - accessWideners(aw) +neoForge { + neoFormVersion = neo_form_version + // Automatically enable AccessTransformers if the file exists + // While this location can be changed, it is recommended for + // common and neoforge to share an accesstransformer file + // and this location is hardcoded in FML + // https://github.com/neoforged/FancyModLoader/blob/a952595eaaddd571fbc53f43847680b00894e0c1/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/ModFile.java#L118 + def at = file('src/main/resources/META-INF/accesstransformer.cfg') + if (at.exists()) { + accessTransformers.add(at.absolutePath) + } + parchment { + minecraftVersion = parchment_minecraft + mappingsVersion = parchment_version } } dependencies { - compileOnly group:'org.spongepowered', name:'mixin', version:'0.8.5' + compileOnly group: 'org.spongepowered', name: 'mixin', version: '0.8.5' + // fabric and neoforge both bundle mixinextras, so it is safe to use it in common + compileOnly group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.3.5' + annotationProcessor group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.3.5' } configurations { diff --git a/fabric/build.gradle b/fabric/build.gradle index 82e5281..f82b365 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,16 +1,19 @@ plugins { id 'multiloader-loader' - id 'fabric-loom' version '1.7-SNAPSHOT' + id 'fabric-loom' } dependencies { minecraft "com.mojang:minecraft:${minecraft_version}" - mappings loom.officialMojangMappings() + mappings loom.layered { + officialMojangMappings() + parchment("org.parchmentmc.data:parchment-${parchment_minecraft}:${parchment_version}@zip") + } modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}" } loom { - def aw = project(":common").file("src/main/resources/${mod_id}.accesswidener") + def aw = project(':common').file("src/main/resources/${mod_id}.accesswidener") if (aw.exists()) { accessWidenerPath.set(aw) } @@ -20,15 +23,15 @@ loom { runs { client { client() - setConfigName("Fabric Client") + setConfigName('Fabric Client') ideConfigGenerated(true) - runDir("runs/client") + runDir('runs/client') } server { server() - setConfigName("Fabric Server") + setConfigName('Fabric Server') ideConfigGenerated(true) - runDir("runs/server") + runDir('runs/server') } } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index baa459a..defa86b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,13 +15,19 @@ license=CC0-1.0 credits= description=The description of your mod. \\nAccepts multilines (but they must be double-escaped). minecraft_version_range=[1.21, 1.22) +## This is the version of minecraft that the 'common' project uses, you can find a list of all versions here +## https://projects.neoforged.net/neoforged/neoform +neo_form_version=1.21-20240613.152323 +# The version of ParchmentMC that is used, see https://parchmentmc.org/docs/getting-started#choose-a-version for new versions +parchment_minecraft=1.21 +parchment_version=2024.06.23 # Fabric fabric_version=0.100.1+1.21 fabric_loader_version=0.15.11 # NeoForge -neoforge_version=21.0.20-beta +neoforge_version=21.0.37-beta neoforge_loader_version_range=[4,) # Gradle diff --git a/neoforge/build.gradle b/neoforge/build.gradle index ffae280..c756533 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -1,38 +1,41 @@ plugins { id 'multiloader-loader' - id 'net.neoforged.gradle.userdev' version '7.0.145' + id 'net.neoforged.moddev' } -// Automatically enable neoforge AccessTransformers if the file exists -// This location is hardcoded in FML and can not be changed. -// https://github.com/neoforged/FancyModLoader/blob/a952595eaaddd571fbc53f43847680b00894e0c1/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/ModFile.java#L118 -def at = file('src/main/resources/META-INF/accesstransformer.cfg') -if (at.exists()) { - minecraft.accessTransformers.file at -} -runs { - configureEach { - modSource project.sourceSets.main +neoForge { + version = neoforge_version + // Automatically enable neoforge AccessTransformers if the file exists + // This location is hardcoded in FML and can not be changed. + // https://github.com/neoforged/FancyModLoader/blob/a952595eaaddd571fbc53f43847680b00894e0c1/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/ModFile.java#L118 + def at = project(':common').file('src/main/resources/META-INF/accesstransformer.cfg') + if (at.exists()) { + accessTransformers.add(at.absolutePath) } - client { - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + parchment { + minecraftVersion = parchment_minecraft + mappingsVersion = parchment_version } - server { - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id - programArgument '--nogui' + runs { + configureEach { + systemProperty('neoforge.enabledGameTestNamespaces', mod_id) + ideName = "NeoForge ${it.name.capitalize()} (${project.path})" // Unify the run config names with fabric + } + client { + client() + } + data { + data() + } + server { + server() + } } - - gameTestServer { - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id - } - - data { - programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() + mods { + "${mod_id}" { + sourceSet sourceSets.main + } } } -sourceSets.main.resources { srcDir 'src/generated/resources' } - -dependencies { - implementation "net.neoforged:neoforge:${neoforge_version}" -} \ No newline at end of file +sourceSets.main.resources { srcDir 'src/generated/resources' } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 774b87b..8d8d7b8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,36 +6,35 @@ pluginManagement { forRepository { maven { name = 'Fabric' - url = uri("https://maven.fabricmc.net") + url = uri('https://maven.fabricmc.net') } } filter { - includeGroup("net.fabricmc") - includeGroup("fabric-loom") + includeGroup('net.fabricmc') + includeGroup('fabric-loom') } } exclusiveContent { forRepository { maven { name = 'NeoForge' - url = uri("https://maven.neoforged.net/releases") + url = uri('https://maven.neoforged.net/releases') } } filter { - includeGroupAndSubgroups("net.neoforged") - includeGroup("codechicken") + includeGroupAndSubgroups('net.neoforged') } } exclusiveContent { forRepository { maven { name = 'Sponge Snapshots' - url = uri("https://repo.spongepowered.org/repository/maven-public") + url = uri('https://repo.spongepowered.org/repository/maven-public') } } filter { - includeGroupAndSubgroups("org.spongepowered") - includeGroup("net.minecraftforge") + includeGroupAndSubgroups('org.spongepowered') + includeGroup('net.minecraftforge') } } } @@ -47,6 +46,6 @@ plugins { // This should match the folder name of the project, or else IDEA may complain (see https://youtrack.jetbrains.com/issue/IDEA-317606) rootProject.name = 'MultiLoader-Template' -include("common") -include("fabric") -include("neoforge") +include('common') +include('fabric') +include('neoforge')