Update: I created a git repository on GitHub for this series. Check it out! The Repo
Many tutorials out there doesn't really tell you what the concepts in modding are. Instead, they just tell you very specific steps without explaining. I have learned a lot from the community, so now I feel it is time to give back by writing a concise and yet easy tutorial on Forge Gradle modding. If you are the type that doesn't care and just want to get things done without knowing why, then this tutorial is not for you.
Let's start from a little introduction to Gradle. It is an automatic build tool and nothing else. Instead of downloading libraries and invoking java compiler manually, Gradle does these for you. All you have to do is write a build script (the famous build.gradle file), and call “gradle” in the command line to run that script, and that's it.
Forge Gradle is nothing but a Gradle plugin. By putting the well known line:
apply plugin: 'forge'
into the build.gradle file, you tell Gradle that you are using Forge's preset stuff to build your project. Those presets are well written by the Forge team so that you don't have to know any details but still can develop a mod. Also, the plugin is “in the cloud”, which means all the files that you need will be downloaded only when you need them. Forge source distribution is only 170KB nowadays. You can now see where all those source codes went! The presets include the setupDecompWorkspace, cleanCache, runClient, build etc. That's why you see all the tutorials out there tell you to put “gradlew.bat setupDecompWorkspace” into the command line when you start to mod.
What's gradlew.bat then? The official Forge source code is distributed with a wrapper, and that's the gradlew.bat file (“w” for wrapper) and the folder "gradle". Why is this necessary? Because by using the wrapper, one doesn't need to download and setup a full Gradle environment (installing Gradle manually involves setting up environment variables like GRADLE_HOME on your system, which most people doesn't like).
After all the waste of time reading the above explanation, one will ask that why those are important. If you are smart enough, you may already guessed the answer: because in the end, you don't need to download the Forge source code to start a new mod! Why? Because the forge source is fetched by Gradle automatically, given that you setup the build.gradle script right! In order to understand how it works, in this tutorial, we are going to setup a Forge development environment without downloading anything but the Gradle distribution.
The Steps:
Step1: download Gradle from their official site: http://www.gradle.org. Choose binary only. You don't need the source code.
Step2: extract the zip file to a folder. For example: c:/gradle.
Step3: System specific, as most guys are on Windows, I'll use Windows as example. Right click on Computer → Properties → Advanced system settings → Advanced tab → Environment Variables button. In the popped up dialog of Environment Variables, click “new” under the user variable section (not the system section! Usually it is a bad idea to modify the system variables!). Enter GRADLE_HOME as the variable name, and put your gradle directory as the value. By gradle directory, I mean the directory that you extracted Gradle into, and the directory should directly contain bin, lib and media folders. For example, if you have c:/gradle/bin, then the gradle directory is c:/gradle.
Step4: Find path under the user variable section, click “edit”, add a semicolon if there is not one, and add “%GRADLE_HOME%\bin” to the end (without quotation marks). Click OK until all dialogs are gone.
Step5: now you are done setting up a Gradle environment manually. Next, create an empty folder, and create an empty file named “build.gradle”. Add the following lines to it:
minecraft {
version = "1.7.10-10.13.2.1258"
runDir = "eclipse"
}
Let's explain a little bit:
apply plugin: 'forge' tells Gradle to use forge's presets. However, Gradle doesn't know where Forge is located. Thus the block “buildscript” is put before it. Code inside buildscript tells Gradle where to look for things. The "repositories" block locates the a repository online at the URL specified. mavenCentral points to apache's central server to look for repos, and the other "maven" block tells gradle that this is a maven repo at "http://files.minecraftforge.net/maven". "dependencies" block describes the library to look for. In this case, it tells gradle to include forgeGradle into the classpath.
Also notice the block "minecraft". Forge need to know which version to use, so this is where you tell it. Ignore the runDir setting for now. You can actually put anything here, but “eclipse” is recommended if you are using eclipse as the IDE. Previously, "assetDir" was used. It is now deprecated, so use "runDir" in your project.
Step6: Hold shift while right clicking on an empty space inside the folder, and choose “open command window here” from the dropdown menu. Type the usual stuff that everybody tells you to, but replace “gradlew.bat” with “gradle”. So first, type “gradle setupDecompWorkspace”. After the long waiting, type “gradle runClient”. Tada! You never downloaded forge nor minecraft, but you started a minecraft client with forge installed!
Alright, I took you a long way to do the same thing that most people successfully did in half the time. Why does this matter? You now know much better about Gradle and Forge! You know that Forge's source distribution isn't really “source”, it is just scripts telling your computer how to download and compile the actually source. The next time you need to setup a project and upload it to github, you don't have to download Forge anymore, just type in the build script above, and you are set. Of course, please still include the Forge's credit file to show your respect.
Update:
some more explanation.
add the notice that "assetDir" is deprecated.
change "forgeFS" to "forge". They can be used interchangeably.
Also, couple of questions. You don't use them in your example, but would you be willing to provide a brief explanation of using "sourceSets{}" right after applying the plugin...
Thank you for the interest and formatted code I'm glad that I helped. The OP is replaced with your formatted text.
I was about to write a follow up tutorial about the source directory setup and the build-by-convention strategy used by gradle's java plugin, but no one replied for the past few days, so I slacked off a little bit...
Now that you asked, I'll just reply here, and probably update the OP (just probably...).
Also, couple of questions. You don't use them in your example, but would you be willing to provide a brief explanation of using "sourceSets{}" right after applying the plugin...
In short, the plugin "forge" is dependent on gradle's internal plugin "java". the "java" plugin uses a build-by-convention strategy. It means that instead of having the user to say where the source code is every time, gradle just use default folder names. Thus, without the block "sourceSets", gradle looks for java source files in "main/java" folder, and the resource files in "main/resources" folder. With the code you supplied above, gradle looks for folders named "java" instead of "main/java", and "resources" instead of "main/resources". The "$projectDir" is just an internal variable that points to the root directory where your "build.gradle" file resides.
...and the "assetsDir" inside "minecraft{}"...
minecraft {
version = "1.7.10-10.13.2.1236"
assetDir = "eclipse/assets"
}
the "assetDir" name is used to specify where to store the assets (textures, sounds, etc). Remember you can click "run" in eclipse to boot up a minecraft game? the "runDir" I talked above says where you want to put the runtime files (configs, logs, saves, etc.). However, the assets are put into different directories than the other files. If you don't put this line to specify where you want the assets to be downloaded, gradle will automatically download them into the default location (which is the ".gradle" folder in your "C:/Users/your_user_name" folder).
...as well as the following properties that can be placed at the end of the file?
group = ""
archivesBaseName = ""
version = ""
Try to run "gradle build" without putting anything in those lines. After the build finishes, go into "build/libs" directory from your project's root. You'll find a jar file there that's named something weird like ".jar". That's the packaged mod file ready for distribution. Probably you figure it out by now: the archivesBaseName field and version field determines this jar file's filename. The built jar file will be named as "archivesBaseName-version.jar". The last field, group, has no impact on the build process. It identifies your development team by a name following apache maven's tradition. It only shows its impact if you want to setup an apache maven repository so that other people could download your jar file freely. The maven repository system is something I never bother to dive into. If you are interested, there are tons of things you can read. Just type "maven" into google and have fun
With regards to the first "maven{}", I've seen the "name" property written as both "forge" and "forgeFS". Is there a difference?
Not really. When I wrote this tut the "forge" version didn't work, so I used "forgeFS". I guess they pulled it down for maintenance. When I update my github repository, it worked again. So I guess (just guessing), the forge repo is the main one, while forgeFS acts as a backup.
Many tutorials out there doesn't really tell you what the concepts in modding are. Instead, they just tell you very specific steps without explaining. I have learned a lot from the community, so now I feel it is time to give back by writing a concise and yet easy tutorial on Forge Gradle modding. If you are the type that doesn't care and just want to get things done without knowing why, then this tutorial is not for you.
Let's start from a little introduction to Gradle. It is an automatic build tool and nothing else. Instead of downloading libraries and invoking java compiler manually, Gradle does these for you. All you have to do is write a build script (the famous build.gradle file), and call “gradle” in the command line to run that script, and that's it.
Forge Gradle is nothing but a Gradle plugin. By putting the well known line:
into the build.gradle file, you tell Gradle that you are using Forge's preset stuff to build your project. Those presets are well written by the Forge team so that you don't have to know any details but still can develop a mod. Also, the plugin is “in the cloud”, which means all the files that you need will be downloaded only when you need them. Forge source distribution is only 170KB nowadays. You can now see where all those source codes went! The presets include the setupDecompWorkspace, cleanCache, runClient, build etc. That's why you see all the tutorials out there tell you to put “gradlew.bat setupDecompWorkspace” into the command line when you start to mod.
What's gradlew.bat then? The official Forge source code is distributed with a wrapper, and that's the gradlew.bat file (“w” for wrapper) and the folder "gradle". Why is this necessary? Because by using the wrapper, one doesn't need to download and setup a full Gradle environment (installing Gradle manually involves setting up environment variables like GRADLE_HOME on your system, which most people doesn't like).
After all the waste of time reading the above explanation, one will ask that why those are important. If you are smart enough, you may already guessed the answer: because in the end, you don't need to download the Forge source code to start a new mod! Why? Because the forge source is fetched by Gradle automatically, given that you setup the build.gradle script right! In order to understand how it works, in this tutorial, we are going to setup a Forge development environment without downloading anything but the Gradle distribution.
The Steps:
Step2: extract the zip file to a folder. For example: c:/gradle.
Step3: System specific, as most guys are on Windows, I'll use Windows as example. Right click on Computer → Properties → Advanced system settings → Advanced tab → Environment Variables button. In the popped up dialog of Environment Variables, click “new” under the user variable section (not the system section! Usually it is a bad idea to modify the system variables!). Enter GRADLE_HOME as the variable name, and put your gradle directory as the value. By gradle directory, I mean the directory that you extracted Gradle into, and the directory should directly contain bin, lib and media folders. For example, if you have c:/gradle/bin, then the gradle directory is c:/gradle.
Step4: Find path under the user variable section, click “edit”, add a semicolon if there is not one, and add “%GRADLE_HOME%\bin” to the end (without quotation marks). Click OK until all dialogs are gone.
Step5: now you are done setting up a Gradle environment manually. Next, create an empty folder, and create an empty file named “build.gradle”. Add the following lines to it:
Let's explain a little bit:
apply plugin: 'forge' tells Gradle to use forge's presets. However, Gradle doesn't know where Forge is located. Thus the block “buildscript” is put before it. Code inside buildscript tells Gradle where to look for things. The "repositories" block locates the a repository online at the URL specified. mavenCentral points to apache's central server to look for repos, and the other "maven" block tells gradle that this is a maven repo at "http://files.minecraftforge.net/maven". "dependencies" block describes the library to look for. In this case, it tells gradle to include forgeGradle into the classpath.
Also notice the block "minecraft". Forge need to know which version to use, so this is where you tell it. Ignore the runDir setting for now. You can actually put anything here, but “eclipse” is recommended if you are using eclipse as the IDE. Previously, "assetDir" was used. It is now deprecated, so use "runDir" in your project.
Step6: Hold shift while right clicking on an empty space inside the folder, and choose “open command window here” from the dropdown menu. Type the usual stuff that everybody tells you to, but replace “gradlew.bat” with “gradle”. So first, type “gradle setupDecompWorkspace”. After the long waiting, type “gradle runClient”. Tada! You never downloaded forge nor minecraft, but you started a minecraft client with forge installed!
Alright, I took you a long way to do the same thing that most people successfully did in half the time. Why does this matter? You now know much better about Gradle and Forge! You know that Forge's source distribution isn't really “source”, it is just scripts telling your computer how to download and compile the actually source. The next time you need to setup a project and upload it to github, you don't have to download Forge anymore, just type in the build script above, and you are set. Of course, please still include the Forge's credit file to show your respect.
Update:
add the notice that "assetDir" is deprecated.
change "forgeFS" to "forge". They can be used interchangeably.
I would like to offer the following formatted version of your gradle file for others.
To the Op: consider replacing your current gradle text with the formatted text by simply copying and pasting the text below.
Also, couple of questions. You don't use them in your example, but would you be willing to provide a brief explanation of using "sourceSets{}" right after applying the plugin...
...and the "assetsDir" inside "minecraft{}"...
...as well as the following properties that can be placed at the end of the file?
Thanks!
See that up arrow?
I was about to write a follow up tutorial about the source directory setup and the build-by-convention strategy used by gradle's java plugin, but no one replied for the past few days, so I slacked off a little bit...
Now that you asked, I'll just reply here, and probably update the OP (just probably...).
In short, the plugin "forge" is dependent on gradle's internal plugin "java". the "java" plugin uses a build-by-convention strategy. It means that instead of having the user to say where the source code is every time, gradle just use default folder names. Thus, without the block "sourceSets", gradle looks for java source files in "main/java" folder, and the resource files in "main/resources" folder. With the code you supplied above, gradle looks for folders named "java" instead of "main/java", and "resources" instead of "main/resources". The "$projectDir" is just an internal variable that points to the root directory where your "build.gradle" file resides.
the "assetDir" name is used to specify where to store the assets (textures, sounds, etc). Remember you can click "run" in eclipse to boot up a minecraft game? the "runDir" I talked above says where you want to put the runtime files (configs, logs, saves, etc.). However, the assets are put into different directories than the other files. If you don't put this line to specify where you want the assets to be downloaded, gradle will automatically download them into the default location (which is the ".gradle" folder in your "C:/Users/your_user_name" folder).
Try to run "gradle build" without putting anything in those lines. After the build finishes, go into "build/libs" directory from your project's root. You'll find a jar file there that's named something weird like ".jar". That's the packaged mod file ready for distribution. Probably you figure it out by now: the archivesBaseName field and version field determines this jar file's filename. The built jar file will be named as "archivesBaseName-version.jar". The last field, group, has no impact on the build process. It identifies your development team by a name following apache maven's tradition. It only shows its impact if you want to setup an apache maven repository so that other people could download your jar file freely. The maven repository system is something I never bother to dive into. If you are interested, there are tons of things you can read. Just type "maven" into google and have fun
See that up arrow?
Not really. When I wrote this tut the "forge" version didn't work, so I used "forgeFS". I guess they pulled it down for maintenance. When I update my github repository, it worked again. So I guess (just guessing), the forge repo is the main one, while forgeFS acts as a backup.
.