Merge overhaul branch to be upstream (#24)
* Debug mode for publishing artifacts * Jabel * Generation of mod meta, pack meta and mixin jsons * Fixed runObfServer using 1.7's main class rather than 1.12's - Allows changing of source without it being regenerated in dev * ExampleMod + fixing tag collection * Template expanding for mcmod.info + pack.mcmeta + remove redundant tasks - Now supports arbitrary script blocks to retrieve value `${{ }}` from directly in gradle.properties * Deployment via tasks/actions + changelog support + script folder * Fixed mixin json generating condition * Fix ATs not being applied * Allow mixinbooter & configanytime to be prioritized in obf runs * Remove redundant coremod arg addition as manifest is read at runtime * Allow processResources to work correctly * refactor: make parser changelog as method instead of job * fix: ensure correct header parser for changelog (2to2 and 3to3) * fix: no env available due to Github don't automatic inject env value to GHA * refactor: standardize mod version with SemVer, remove unnecessary changelog block in `build.gradle` * refactor: mixin config template and generator, resource filter * Updated Gradle to 8.7 + RetroFuturaGradle to 1.3.35 * Update MixinBooter to 9.1 + provide wiki link Co-authored-by: Oganesson897 <101081378+Darknight123MC@users.noreply.github.com> Co-authored-by: Li <nhatlinh.l195@gmail.com> Co-authored-by: Li <li.hvktqs@gmail.com>
This commit is contained in:
parent
7db468db1e
commit
c82fcee8aa
16 changed files with 730 additions and 133 deletions
61
.github/workflows/deploy.yml
vendored
Normal file
61
.github/workflows/deploy.yml
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
# A deployment template that works out of the box
|
||||
# It supports these objectives:
|
||||
# - Deploy to Maven (Build Job) [Secrets: MAVEN_USER, MAVEN_PASS]
|
||||
# - Deploy to CurseForge (Upload Job) [Secrets: CURSEFORGE_TOKEN]
|
||||
# - Deploy to Modrinth (Upload Job) [Secrets: MODRINTH_TOKEN]
|
||||
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Grant Execute Permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Read gradle.properties
|
||||
uses: BrycensRanch/read-properties-action@v1
|
||||
id: properties
|
||||
with:
|
||||
file: gradle.properties
|
||||
all: true
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
|
||||
- name: Publish to Maven
|
||||
if: steps.properties.outputs.publish_to_maven == 'true' && steps.properties.outputs.publish_to_local_maven == 'true'
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: |
|
||||
publish
|
||||
-P${{ steps.properties.outputs.maven_name }}Username=${{ secrets.MAVEN_USER }}
|
||||
-P${{ steps.properties.outputs.maven_name }}Password=${{ secrets.MAVEN_PASS }}
|
||||
|
||||
- name: Publish to CurseForge
|
||||
if: steps.properties.outputs.publish_to_curseforge == 'true'
|
||||
uses: gradle/gradle-build-action@v2
|
||||
env:
|
||||
CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }}
|
||||
with:
|
||||
arguments: curseforge
|
||||
|
||||
- name: Publish to Modrinth
|
||||
if: steps.properties.outputs.publish_to_modrinth == 'true'
|
||||
uses: gradle/gradle-build-action@v2
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
with:
|
||||
arguments: modrinth
|
6
CHANGELOG.md
Normal file
6
CHANGELOG.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Changelog
|
||||
|
||||
## [1.0.0] - 2023-09-15
|
||||
|
||||
### Added
|
||||
- This is a default template changelog that follows the [KeepAChangelog Convention](https://keepachangelog.com/en/1.1.0/)
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Template workspace for modding Minecraft 1.12.2. Licensed under MIT, it is made for public use.
|
||||
|
||||
This template currently utilizies **Gradle 8.1.1** + **[RetroFuturaGradle](https://github.com/GTNewHorizons/RetroFuturaGradle) 1.3.27** + **Forge 14.23.5.2847**.
|
||||
This template currently utilizies **Gradle 8.7** + **[RetroFuturaGradle](https://github.com/GTNewHorizons/RetroFuturaGradle) 1.3.35** + **Forge 14.23.5.2847**.
|
||||
|
||||
With **coremod and mixin support** that is easy to configure.
|
||||
|
||||
|
|
315
build.gradle
315
build.gradle
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* It is advised that you do not edit anything in the build.gradle; unless you are sure of what you are doing
|
||||
*/
|
||||
import com.gtnewhorizons.retrofuturagradle.mcp.InjectTagsTask
|
||||
import org.jetbrains.changelog.Changelog
|
||||
import org.jetbrains.gradle.ext.Gradle
|
||||
|
||||
plugins {
|
||||
|
@ -5,29 +10,58 @@ plugins {
|
|||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.7'
|
||||
id 'eclipse'
|
||||
id 'com.gtnewhorizons.retrofuturagradle' version '1.3.27'
|
||||
id 'com.matthewprenger.cursegradle' version '1.4.0'
|
||||
id 'com.gtnewhorizons.retrofuturagradle' version '1.3.35'
|
||||
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
|
||||
id 'com.modrinth.minotaur' version '2.+' apply false
|
||||
id 'org.jetbrains.changelog' version '2.2.0'
|
||||
}
|
||||
|
||||
version = project.mod_version
|
||||
group = project.maven_group
|
||||
archivesBaseName = project.archives_base_name
|
||||
apply from: 'gradle/scripts/helpers.gradle'
|
||||
|
||||
// Early Assertions
|
||||
assertProperty 'mod_version'
|
||||
assertProperty 'root_package'
|
||||
assertProperty 'mod_id'
|
||||
assertProperty 'mod_name'
|
||||
|
||||
assertSubProperties 'use_tags', 'tag_class_name'
|
||||
assertSubProperties 'use_access_transformer', 'access_transformer_locations'
|
||||
assertSubProperties 'use_mixins', 'mixin_booter_version', 'mixin_refmap'
|
||||
assertSubProperties 'is_coremod', 'coremod_includes_mod', 'coremod_plugin_class_name'
|
||||
assertSubProperties 'use_asset_mover', 'asset_mover_version'
|
||||
|
||||
setDefaultProperty 'use_modern_java_syntax', false, false
|
||||
setDefaultProperty 'generate_sources_jar', true, false
|
||||
setDefaultProperty 'generate_javadocs_jar', true, false
|
||||
setDefaultProperty 'mapping_channel', true, 'stable'
|
||||
setDefaultProperty 'mapping_version', true, '39'
|
||||
setDefaultProperty 'use_dependency_at_files', true, true
|
||||
setDefaultProperty 'minecraft_username', true, 'Developer'
|
||||
setDefaultProperty 'extra_jvm_args', false, ''
|
||||
setDefaultProperty 'extra_tweak_classes', false, ''
|
||||
setDefaultProperty 'change_minecraft_sources', false, false
|
||||
|
||||
version = propertyString('mod_version')
|
||||
group = propertyString('root_package')
|
||||
|
||||
base {
|
||||
archivesName.set(propertyString('mod_id'))
|
||||
}
|
||||
|
||||
tasks.decompressDecompiledSources.enabled !propertyBool('change_minecraft_sources')
|
||||
|
||||
// Set the toolchain version to decouple the Java we run Gradle with from the Java used to compile and run the mod
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(8))
|
||||
languageVersion.set(JavaLanguageVersion.of(propertyBool('use_modern_java_syntax') ? 16 : 8))
|
||||
// Azul covers the most platforms for Java 8 toolchains, crucially including MacOS arm64
|
||||
vendor.set(org.gradle.jvm.toolchain.JvmVendorSpec.AZUL)
|
||||
vendor.set(JvmVendorSpec.AZUL)
|
||||
}
|
||||
if (propertyBool('generate_sources_jar')) {
|
||||
withSourcesJar()
|
||||
}
|
||||
if (propertyBool('generate_javadocs_jar')) {
|
||||
withJavadocJar()
|
||||
}
|
||||
// Generate sources and javadocs jars when building and publishing
|
||||
withSourcesJar()
|
||||
// withJavadocJar()
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
configurations {
|
||||
|
@ -36,44 +70,36 @@ configurations {
|
|||
}
|
||||
|
||||
minecraft {
|
||||
mcVersion = '1.12.2'
|
||||
mcVersion.set('1.12.2')
|
||||
|
||||
// MCP Mappings
|
||||
mcpMappingChannel = 'stable'
|
||||
mcpMappingVersion = '39'
|
||||
|
||||
// Set username here, the UUID will be looked up automatically
|
||||
username = 'Developer'
|
||||
mcpMappingChannel.set(propertyString('mapping_channel'))
|
||||
mcpMappingVersion.set(propertyString('mapping_version'))
|
||||
|
||||
useDependencyAccessTransformers.set(propertyBool('use_dependency_at_files'))
|
||||
|
||||
username.set(propertyString('minecraft_username'))
|
||||
|
||||
// Add any additional tweaker classes here
|
||||
// extraTweakClasses.add('org.spongepowered.asm.launch.MixinTweaker')
|
||||
|
||||
extraTweakClasses.addAll(propertyStringList('extra_tweak_classes'))
|
||||
|
||||
// Add various JVM arguments here for runtime
|
||||
def args = ["-ea:${project.group}"]
|
||||
if (project.use_coremod.toBoolean()) {
|
||||
args << '-Dfml.coreMods.load=' + coremod_plugin_class_name
|
||||
}
|
||||
if (project.use_mixins.toBoolean()) {
|
||||
def args = ['-ea:' + group]
|
||||
if (propertyBool('use_mixins')) {
|
||||
args << '-Dmixin.hotSwap=true'
|
||||
args << '-Dmixin.checks.interfaces=true'
|
||||
args << '-Dmixin.debug.export=true'
|
||||
}
|
||||
extraRunJvmArguments.addAll(args)
|
||||
extraRunJvmArguments.addAll(propertyStringList('extra_jvm_args'))
|
||||
|
||||
// Include and use dependencies' Access Transformer files
|
||||
useDependencyAccessTransformers = true
|
||||
|
||||
// Add any properties you want to swap out for a dynamic value at build time here
|
||||
// Any properties here will be added to a class at build time, the name can be configured below
|
||||
// Example:
|
||||
// injectedTags.put('VERSION', project.version)
|
||||
// injectedTags.put('MOD_ID', project.archives_base_name)
|
||||
}
|
||||
|
||||
// Generate a group.archives_base_name.Tags class
|
||||
tasks.injectTags.configure {
|
||||
// Change Tags class' name here:
|
||||
outputClassName.set("${project.group}.${project.archives_base_name}.Tags")
|
||||
if (propertyBool('use_tags')) {
|
||||
if (file('tags.properties').exists()) {
|
||||
Properties props = new Properties().tap { it.load(file('tags.properties').newInputStream()); it }
|
||||
if (!props.isEmpty()) {
|
||||
injectedTags.set(props.collectEntries { k, v -> [(k): interpolate(v)] })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -81,34 +107,29 @@ repositories {
|
|||
name 'CleanroomMC Maven'
|
||||
url 'https://maven.cleanroommc.com'
|
||||
}
|
||||
maven {
|
||||
name 'SpongePowered Maven'
|
||||
url 'https://repo.spongepowered.org/maven'
|
||||
}
|
||||
maven {
|
||||
name 'CurseMaven'
|
||||
url 'https://cursemaven.com'
|
||||
content {
|
||||
includeGroup 'curse.maven'
|
||||
}
|
||||
}
|
||||
mavenLocal() // Must be last for caching to work
|
||||
}
|
||||
|
||||
dependencies {
|
||||
if (project.use_assetmover.toBoolean()) {
|
||||
implementation 'com.cleanroommc:assetmover:2.5'
|
||||
if (propertyBool('use_modern_java_syntax')) {
|
||||
annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0'
|
||||
// Workaround for https://github.com/bsideup/jabel/issues/174
|
||||
annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0'
|
||||
compileOnly ('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') {
|
||||
transitive = false
|
||||
}
|
||||
// Allow jdk.unsupported classes like sun.misc.Unsafe, workaround for JDK-8206937 and fixes crashes in tests
|
||||
patchedMinecraft 'me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0'
|
||||
// Include for tests
|
||||
testAnnotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0'
|
||||
testCompileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') {
|
||||
transitive = false // We only care about the 1 annotation class
|
||||
}
|
||||
}
|
||||
if (project.use_mixins.toBoolean()) {
|
||||
implementation 'zone.rong:mixinbooter:7.1'
|
||||
if (propertyBool('use_asset_mover')) {
|
||||
implementation "com.cleanroommc:assetmover:${propertyString('asset_mover_version')}"
|
||||
}
|
||||
|
||||
// Example of deobfuscating a dependency
|
||||
// implementation rfg.deobf('curse.maven:had-enough-items-557549:4543375')
|
||||
|
||||
if (project.use_mixins.toBoolean()) {
|
||||
// Change your mixin refmap name here:
|
||||
String mixin = modUtils.enableMixins('org.spongepowered:mixin:0.8.3', "mixins.${project.archives_base_name}.refmap.json")
|
||||
if (propertyBool('use_mixins')) {
|
||||
String mixin = modUtils.enableMixins("zone.rong:mixinbooter:${propertyString('mixin_booter_version')}", propertyString('mixin_refmap'))
|
||||
api (mixin) {
|
||||
transitive = false
|
||||
}
|
||||
|
@ -119,50 +140,65 @@ dependencies {
|
|||
transitive = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
apply from: 'gradle/scripts/dependencies.gradle'
|
||||
|
||||
// Adds Access Transformer files to tasks
|
||||
if (project.use_access_transformer.toBoolean()) {
|
||||
for (File at : sourceSets.getByName("main").resources.files) {
|
||||
if (at.name.toLowerCase().endsWith("_at.cfg")) {
|
||||
tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at)
|
||||
tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at)
|
||||
if (propertyBool('use_access_transformer')) {
|
||||
for (def location : propertyStringList('access_transformer_locations')) {
|
||||
def fileLocation = file("${projectDir}/src/main/resources/${location}")
|
||||
if (fileLocation.exists()) {
|
||||
tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(fileLocation)
|
||||
tasks.srgifyBinpatchedJar.accessTransformerFiles.from(fileLocation)
|
||||
} else {
|
||||
throw new GradleException("Access Transformer file [$fileLocation] does not exist!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
// This will ensure that this task is redone when the versions change
|
||||
inputs.property 'version', project.version
|
||||
inputs.property 'mcversion', project.minecraft.version
|
||||
|
||||
// Replace various properties in mcmod.info and pack.mcmeta if applicable
|
||||
filesMatching(['mcmod.info', 'pack.mcmeta']) { fcd ->
|
||||
// Replace version and mcversion
|
||||
fcd.expand (
|
||||
'version': project.version,
|
||||
'mcversion': project.minecraft.version
|
||||
|
||||
def filterList = ['mcmod.info', 'pack.mcmeta']
|
||||
filterList.addAll(propertyStringList('mixin_configs').collect(config -> "mixins.${config}.json" as String))
|
||||
|
||||
filesMatching(filterList) { fcd ->
|
||||
fcd.expand(
|
||||
'mod_id': propertyString('mod_id'),
|
||||
'mod_name': propertyString('mod_name'),
|
||||
'mod_version': propertyString('mod_version'),
|
||||
'mod_description': propertyString('mod_description'),
|
||||
'mod_authors': "[${propertyStringList('mod_authors', ',').join(', ')}]",
|
||||
'mod_credits': propertyString('mod_credits'),
|
||||
'mod_url': propertyString('mod_url'),
|
||||
'mod_update_json': propertyString('mod_update_json'),
|
||||
'mod_logo_path': propertyString('mod_logo_path'),
|
||||
'mixin_refmap': propertyString('mixin_refmap'),
|
||||
'mixin_package': propertyString('mixin_package')
|
||||
)
|
||||
}
|
||||
|
||||
if (project.use_access_transformer.toBoolean()) {
|
||||
rename '(.+_at.cfg)', 'META-INF/$1' // Make sure Access Transformer files are in META-INF folder
|
||||
if (propertyBool('use_access_transformer')) {
|
||||
rename '(.+_at.cfg)', 'META-INF/$1'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
def attribute_map = [:]
|
||||
if (project.use_coremod.toBoolean()) {
|
||||
attribute_map['FMLCorePlugin'] = project.coremod_plugin_class_name
|
||||
if (project.include_mod.toBoolean()) {
|
||||
if (propertyBool('is_coremod')) {
|
||||
attribute_map['FMLCorePlugin'] = propertyString('coremod_plugin_class_name')
|
||||
if (propertyBool('coremod_includes_mod')) {
|
||||
attribute_map['FMLCorePluginContainsFMLMod'] = true
|
||||
attribute_map['ForceLoadAsMod'] = project.gradle.startParameter.taskNames[0] == "build"
|
||||
def currentTasks = gradle.startParameter.taskNames
|
||||
if (currentTasks[0] == 'build' || currentTasks[0] == 'prepareObfModsFolder' || currentTasks[0] == 'runObfClient') {
|
||||
attribute_map['ForceLoadAsMod'] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (project.use_access_transformer.toBoolean()) {
|
||||
attribute_map['FMLAT'] = project.archives_base_name + '_at.cfg'
|
||||
if (propertyBool('use_access_transformer')) {
|
||||
attribute_map['FMLAT'] = propertyString('access_transformer_locations')
|
||||
}
|
||||
attributes(attribute_map)
|
||||
}
|
||||
|
@ -202,6 +238,99 @@ idea {
|
|||
}
|
||||
}
|
||||
|
||||
tasks.named("processIdeaSettings").configure {
|
||||
dependsOn("injectTags")
|
||||
compileTestJava {
|
||||
sourceCompatibility = targetCompatibility = 8
|
||||
}
|
||||
|
||||
test {
|
||||
javaLauncher.set(javaToolchains.launcherFor {
|
||||
languageVersion = JavaLanguageVersion.of(8)
|
||||
})
|
||||
}
|
||||
|
||||
String parserChangelog() {
|
||||
if (!file('CHANGELOG.md').exists()) {
|
||||
throw new GradleException('publish_with_changelog is true, but CHANGELOG.md does not exist in the workspace!')
|
||||
}
|
||||
String parsedChangelog = changelog.renderItem(
|
||||
changelog.get(propertyString('mod_version')).withHeader(false).withEmptySections(false),
|
||||
Changelog.OutputType.MARKDOWN)
|
||||
if (parsedChangelog.isEmpty()) {
|
||||
throw new GradleException('publish_with_changelog is true, but the changelog for the latest version is empty!')
|
||||
}
|
||||
return parsedChangelog
|
||||
}
|
||||
|
||||
tasks.register('generateMixinJson') {
|
||||
group 'cleanroom helpers'
|
||||
def missingConfig = propertyStringList('mixin_configs').findAll(config -> !file("src/main/resources/mixins.${config}.json").exists())
|
||||
onlyIf {
|
||||
if (propertyBool('use_mixins') && propertyBool('generate_mixins_json')) {
|
||||
return !missingConfig.empty
|
||||
}
|
||||
return false
|
||||
}
|
||||
doLast {
|
||||
for (String mixinConfig : missingConfig) {
|
||||
def file = file("src/main/resources/mixins.${mixinConfig}.json")
|
||||
file << """{\n\t"package": "",\n\t"required": true,\n\t"refmap": "${mixin_refmap}",\n\t"target": "@env(DEFAULT)",\n\t"minVersion": "0.8.5",\n\t"compatibilityLevel": "JAVA_8",\n\t"mixins": [],\n\t"server": [],\n\t"client": []\n}"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8'
|
||||
if (propertyBool('use_modern_java_syntax')) {
|
||||
if (it.name in ['compileMcLauncherJava', 'compilePatchedMcJava']) {
|
||||
return
|
||||
}
|
||||
sourceCompatibility = 17
|
||||
options.release.set(8)
|
||||
javaCompiler.set(javaToolchains.compilerFor {
|
||||
languageVersion.set(JavaLanguageVersion.of(16))
|
||||
vendor.set(JvmVendorSpec.AZUL)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('cleanroomAfterSync') {
|
||||
group 'cleanroom helpers'
|
||||
dependsOn 'injectTags', 'generateMixinJson'
|
||||
}
|
||||
|
||||
if (propertyBool('use_modern_java_syntax')) {
|
||||
tasks.withType(Javadoc).configureEach {
|
||||
sourceCompatibility = 17
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('injectTags', InjectTagsTask).configure {
|
||||
onlyIf {
|
||||
return propertyBool('use_tags') && !it.getTags().get().isEmpty()
|
||||
}
|
||||
it.outputClassName.set(propertyString('tag_class_name'))
|
||||
}
|
||||
|
||||
tasks.named('prepareObfModsFolder').configure {
|
||||
finalizedBy 'prioritizeCoremods'
|
||||
}
|
||||
|
||||
tasks.register('prioritizeCoremods') {
|
||||
dependsOn 'prepareObfModsFolder'
|
||||
doLast {
|
||||
fileTree('run/obfuscated').forEach {
|
||||
if (it.isFile() && it.name =~ '(mixinbooter|configanytime)(-)([0-9])+\\.+([0-9])+(.jar)') {
|
||||
it.renameTo(new File(it.parentFile, "!${it.name}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idea.project.settings {
|
||||
taskTriggers {
|
||||
afterSync 'cleanroomAfterSync'
|
||||
}
|
||||
}
|
||||
|
||||
apply from: 'gradle/scripts/publishing.gradle'
|
||||
apply from: 'gradle/scripts/extra.gradle'
|
||||
|
|
|
@ -1,22 +1,122 @@
|
|||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
# Gradle Properties
|
||||
org.gradle.jvmargs = -Xmx3G
|
||||
|
||||
# Source Options
|
||||
# Use Modern Java(9+) Syntax (Courtesy of Jabel)
|
||||
use_modern_java_syntax = false
|
||||
|
||||
# Compilation Options
|
||||
generate_sources_jar = true
|
||||
generate_javadocs_jar = false
|
||||
|
||||
# Mod Information
|
||||
mod_version = 1.0
|
||||
maven_group = com.cleanroommc
|
||||
archives_base_name = modid
|
||||
# HIGHLY RECOMMEND complying with SemVer for mod_version: https://semver.org/
|
||||
mod_version = 1.0.0
|
||||
root_package = com.example
|
||||
mod_id = modid
|
||||
mod_name = Mod Name
|
||||
|
||||
# If any properties changes below this line, run `gradlew setupDecompWorkspace` and refresh gradle again to ensure everything is working correctly.
|
||||
# Mod Metadata (Optional)
|
||||
mod_description =
|
||||
mod_url =
|
||||
mod_update_json =
|
||||
# Delimit authors with commas
|
||||
mod_authors =
|
||||
mod_credits =
|
||||
mod_logo_path =
|
||||
|
||||
# Boilerplate Options
|
||||
use_mixins = false
|
||||
use_coremod = false
|
||||
use_assetmover = false
|
||||
# Mapping Properties
|
||||
mapping_channel = stable
|
||||
mapping_version = 39
|
||||
use_dependency_at_files = true
|
||||
|
||||
# Access Transformer files should be in the root of `resources` folder and with the filename formatted as: `{archives_base_name}_at.cfg`
|
||||
# Run Configurations
|
||||
# If multiple arguments/tweak classes are stated, use spaces as the delimiter
|
||||
minecraft_username = Developer
|
||||
extra_jvm_args =
|
||||
extra_tweak_classes =
|
||||
|
||||
# Maven Publishing (Provide secret: MAVEN_USER, MAVEN_PASS)
|
||||
publish_to_maven = false
|
||||
# Good for debugging artifacts before uploading to remote maven
|
||||
# GitHub actions won't run if this is true, test this by running the task `publishToMavenLocal`
|
||||
publish_to_local_maven = false
|
||||
maven_name = ${mod_name}
|
||||
maven_url =
|
||||
|
||||
# Publishing
|
||||
# release_type can only be: release, beta or alpha (applies to CurseForge / Modrinth)
|
||||
release_type = release
|
||||
publish_with_changelog = ${{ it.file('CHANGELOG.md').exists() }}
|
||||
|
||||
# Publishing to CurseForge (Provide secret: CURSEFORGE_TOKEN)
|
||||
# To configure dependencies, head to publishing.gradle's curseforge block
|
||||
publish_to_curseforge = false
|
||||
# CurseForge project ID must be the numerical ID and not the slug
|
||||
curseforge_project_id =
|
||||
curseforge_debug = false
|
||||
|
||||
# Publishing to Modrinth (Provide secret: MODRINTH_TOKEN), the token must have the `CREATE_VERSION` and `PROJECT_WRITE` permissions
|
||||
# To configure dependencies, head to publishing.gradle's modrinth block
|
||||
publish_to_modrinth = false
|
||||
modrinth_project_id =
|
||||
# Allows gradle to publish updated READMEs to the project body (via the modrinthSyncBody task)
|
||||
modrinth_sync_readme = false
|
||||
modrinth_debug = false
|
||||
|
||||
# If any properties changes below this line, refresh gradle again to ensure everything is working correctly.
|
||||
|
||||
# Modify Minecraft Sources
|
||||
# RetroFuturaGradle allows Minecraft sources to be edited, and have the changes reflected upon running it
|
||||
# Good for previews when coremodding, or generally seeing how behaviours can change with certain code applied/unapplied
|
||||
# Turning this on allows Minecraft sources to persist and not regenerate
|
||||
change_minecraft_sources = false
|
||||
|
||||
# Tags
|
||||
# A RetroFuturaGradle concept akin to Ant ReplaceTokens
|
||||
# A class is generated at build-time for compilation, to describe properties that have values that could change at build time such as versioning
|
||||
# Class name is configurable with the `tag_class_name` property
|
||||
# Tag properties can be stated in the `tags.properties` file, references are allowed
|
||||
use_tags = true
|
||||
tag_class_name = ${root_package}.${mod_id}.Tags
|
||||
|
||||
# Access Transformers
|
||||
# A way to change visibility of Minecraft's classes, methods and fields
|
||||
# An example access transformer file is given in the path: `src/main/resources/example_at.cfg`
|
||||
# AT files should be in the root of src/main/resources with the filename formatted as: `mod_id_at.cfg`
|
||||
# Use the property `access_transformer_locations` to state custom AT files if you aren't using the default `mod_id_at.cfg` location
|
||||
# If multiple locations are stated, use spaces as the delimiter
|
||||
use_access_transformer = false
|
||||
access_transformer_locations = ${mod_id}_at.cfg
|
||||
|
||||
# Coremod Arguments
|
||||
include_mod = true
|
||||
coremod_plugin_class_name =
|
||||
# Mixins
|
||||
# Powerful tool to do runtime description changes of classes
|
||||
# Wiki: https://github.com/SpongePowered/Mixin/wiki + https://github.com/CleanroomMC/MixinBooter/ + https://cleanroommc.com/wiki/forge-mod-development/mixin/preface
|
||||
# Only use mixins once you understand the underlying structure
|
||||
use_mixins = false
|
||||
mixin_booter_version = 9.1
|
||||
# A configuration defines a mixin set, and you may have as many mixin sets as you require for your application.
|
||||
# Each config can only have one and only one package root.
|
||||
# Generate missing configs, obtain from mixin_configs and generate file base on name convention: "mixins.config_name.json"
|
||||
# You should change package root once they are generated
|
||||
generate_mixins_json = true
|
||||
# Delimit configs with spaces. Should only put configs name instead of full file name
|
||||
mixin_configs = ${mod_id}
|
||||
# A refmap is a json that denotes mapping conversions, this json is generated automatically, with the name `mixins.mod_id.refmap.json`
|
||||
# Use the property `mixin_refmap` if you want it to use a different name, only one name is accepted
|
||||
mixin_refmap = mixins.${mod_id}.refmap.json
|
||||
|
||||
# Coremods
|
||||
# The most powerful way to change java classes at runtime, it is however very primitive with little documentation.
|
||||
# Only make a coremod if you are absolutely sure of what you are doing
|
||||
# Change the property `coremod_includes_mod` to false if your coremod doesn't have a @Mod annotation
|
||||
# You MUST state a class name for `coremod_plugin_class_name` if you are making a coremod, the class should implement `IFMLLoadingPlugin`
|
||||
is_coremod = false
|
||||
coremod_includes_mod = true
|
||||
coremod_plugin_class_name =
|
||||
|
||||
# AssetMover
|
||||
# Convenient way to allow downloading of assets from official vanilla Minecraft servers, CurseForge, or any direct links
|
||||
# Documentation: https://github.com/CleanroomMC/AssetMover
|
||||
use_asset_mover = false
|
||||
asset_mover_version = 2.5
|
62
gradle/scripts/dependencies.gradle
Normal file
62
gradle/scripts/dependencies.gradle
Normal file
|
@ -0,0 +1,62 @@
|
|||
apply from: 'gradle/scripts/helpers.gradle'
|
||||
|
||||
repositories {
|
||||
// Other repositories described by default:
|
||||
// CleanroomMC: https://maven.cleanroommc.com
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven {
|
||||
name 'CurseMaven'
|
||||
url 'https://cursemaven.com'
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup 'curse.maven'
|
||||
}
|
||||
}
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven {
|
||||
name 'Modrinth'
|
||||
url 'https://api.modrinth.com/maven'
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup 'maven.modrinth'
|
||||
}
|
||||
}
|
||||
mavenLocal() // Must be last for caching to work
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Example - Dependency descriptor:
|
||||
// 'com.google.code.gson:gson:2.8.6' << group: com.google.code.gson, name:gson, version:2.8.6
|
||||
// 'group:name:version:classifier' where classifier is optional
|
||||
|
||||
// Example - Deobfuscating dependencies:
|
||||
// rfg.deobf('curse.maven:had-enough-items-557549:4543375')
|
||||
// By wrapping a dependency descriptor in rfg.deobf() method call, the dependency is queued for deobfuscation
|
||||
// When deobfuscating, RFG respects the mapping_channel + mapping_version stated in gradle.properties
|
||||
|
||||
// Example - CurseMaven dependencies:
|
||||
// 'curse.maven:had-enough-items-557549:4543375' << had-enough-items = project slug, 557549 = project id, 4543375 = file id
|
||||
// Full documentation: https://cursemaven.com/
|
||||
|
||||
// Example - Modrinth dependencies:
|
||||
// 'maven.modrinth:jei:4.16.1.1000' << jei = project name, 4.16.1.1000 = file version
|
||||
// Full documentation: https://docs.modrinth.com/docs/tutorials/maven/
|
||||
|
||||
// Common dependency types (configuration):
|
||||
// implementation = dependency available at both compile time and runtime
|
||||
// runtimeOnly = runtime dependency
|
||||
// compileOnly = compile time dependency
|
||||
// annotationProcessor = annotation processing dependencies
|
||||
|
||||
// Transitive dependencies:
|
||||
// (Dependencies that your dependency depends on)
|
||||
// If you wish to exclude transitive dependencies in the described dependencies
|
||||
// Use a closure as such:
|
||||
// implementation ('com.google.code.gson:gson:2.8.6') {
|
||||
// transitive = false
|
||||
// }
|
||||
}
|
5
gradle/scripts/extra.gradle
Normal file
5
gradle/scripts/extra.gradle
Normal file
|
@ -0,0 +1,5 @@
|
|||
// You may write any gradle buildscript component in this file
|
||||
// This file is automatically applied after build.gradle + dependencies.gradle is ran
|
||||
|
||||
// If you wish to use the default helper methods, uncomment the line below
|
||||
// apply from: 'gradle/scripts/helpers.gradle'
|
96
gradle/scripts/helpers.gradle
Normal file
96
gradle/scripts/helpers.gradle
Normal file
|
@ -0,0 +1,96 @@
|
|||
import groovy.text.SimpleTemplateEngine
|
||||
import org.codehaus.groovy.runtime.MethodClosure
|
||||
|
||||
ext.propertyString = this.&propertyString as MethodClosure
|
||||
ext.propertyBool = this.&propertyBool as MethodClosure
|
||||
ext.propertyStringList = this.&propertyStringList as MethodClosure
|
||||
ext.interpolate = this.&interpolate as MethodClosure
|
||||
ext.assertProperty = this.&assertProperty as MethodClosure
|
||||
ext.assertSubProperties = this.&assertSubProperties as MethodClosure
|
||||
ext.setDefaultProperty = this.&setDefaultProperty as MethodClosure
|
||||
ext.assertEnvironmentVariable = this.&assertEnvironmentVariable as MethodClosure
|
||||
|
||||
String propertyString(String key) {
|
||||
return $property(key).toString()
|
||||
}
|
||||
|
||||
boolean propertyBool(String key) {
|
||||
return propertyString(key).toBoolean()
|
||||
}
|
||||
|
||||
Collection<String> propertyStringList(String key) {
|
||||
return propertyStringList(key, ' ')
|
||||
}
|
||||
|
||||
Collection<String> propertyStringList(String key, String delimit) {
|
||||
return propertyString(key).split(delimit).findAll { !it.isEmpty() }
|
||||
}
|
||||
|
||||
private Object $property(String key) {
|
||||
def value = project.findProperty(key)
|
||||
if (value instanceof String) {
|
||||
return interpolate(value)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
String interpolate(String value) {
|
||||
if (value.startsWith('${{') && value.endsWith('}}')) {
|
||||
value = value.substring(3, value.length() - 2)
|
||||
Binding newBinding = new Binding(this.binding.getVariables())
|
||||
newBinding.setProperty('it', this)
|
||||
return new GroovyShell(this.getClass().getClassLoader(), newBinding).evaluate(value)
|
||||
}
|
||||
if (value.contains('${')) {
|
||||
return new SimpleTemplateEngine().createTemplate(value).make(project.properties).toString()
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
void assertProperty(String propertyName) {
|
||||
def property = property(propertyName)
|
||||
if (property == null) {
|
||||
throw new GradleException("Property ${propertyName} is not defined!")
|
||||
}
|
||||
if (property.isEmpty()) {
|
||||
throw new GradleException("Property ${propertyName} is empty!")
|
||||
}
|
||||
}
|
||||
|
||||
void assertSubProperties(String propertyName, String... subPropertyNames) {
|
||||
assertProperty(propertyName)
|
||||
if (propertyBool(propertyName)) {
|
||||
for (String subPropertyName : subPropertyNames) {
|
||||
assertProperty(subPropertyName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setDefaultProperty(String propertyName, boolean warn, defaultValue) {
|
||||
def property = property(propertyName)
|
||||
def exists = true
|
||||
if (property == null) {
|
||||
exists = false
|
||||
if (warn) {
|
||||
project.logger.log(LogLevel.WARN, "Property ${propertyName} is not defined!")
|
||||
}
|
||||
} else if (property.isEmpty()) {
|
||||
exists = false
|
||||
if (warn) {
|
||||
project.logger.log(LogLevel.WARN, "Property ${propertyName} is empty!")
|
||||
}
|
||||
}
|
||||
if (!exists) {
|
||||
project.setProperty(propertyName, defaultValue.toString())
|
||||
}
|
||||
}
|
||||
|
||||
void assertEnvironmentVariable(String propertyName) {
|
||||
def property = System.getenv(propertyName)
|
||||
if (property == null) {
|
||||
throw new GradleException("System Environment Variable $propertyName is not defined!")
|
||||
}
|
||||
if (property.isEmpty()) {
|
||||
throw new GradleException("Property $propertyName is empty!")
|
||||
}
|
||||
}
|
107
gradle/scripts/publishing.gradle
Normal file
107
gradle/scripts/publishing.gradle
Normal file
|
@ -0,0 +1,107 @@
|
|||
apply from: 'gradle/scripts/helpers.gradle'
|
||||
|
||||
setDefaultProperty('publish_to_maven', true, false)
|
||||
setDefaultProperty('publish_to_curseforge', true, false)
|
||||
setDefaultProperty('publish_to_modrinth', true, false)
|
||||
|
||||
if (propertyBool('publish_to_maven')) {
|
||||
assertProperty('maven_name')
|
||||
assertProperty('maven_url')
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name propertyString('maven_name').replaceAll("\\s", "")
|
||||
url propertyString('maven_url')
|
||||
credentials(PasswordCredentials)
|
||||
}
|
||||
}
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
from components.java // Publish with standard artifacts
|
||||
setGroupId(propertyString('root_package'))// Publish with root package as maven group
|
||||
setArtifactId(propertyString('mod_id')) // Publish artifacts with mod id as the artifact id
|
||||
|
||||
// Custom artifact:
|
||||
// If you want to publish a different artifact to the one outputted when building normally
|
||||
// Create a different gradle task (Jar task), in extra.gradle
|
||||
// Remove the 'from components.java' line above
|
||||
// Add this line (change the task name):
|
||||
// artifacts task_name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Documentation here: https://github.com/matthewprenger/CurseGradle/wiki/
|
||||
if (propertyBool('publish_to_curseforge')) {
|
||||
apply plugin: 'com.matthewprenger.cursegradle'
|
||||
assertProperty('curseforge_project_id')
|
||||
assertProperty('release_type')
|
||||
setDefaultProperty('curseforge_debug', false, false)
|
||||
curseforge {
|
||||
apiKey = System.getenv('CURSEFORGE_TOKEN') == null ? "" : System.getenv('CURSEFORGE_TOKEN')
|
||||
// noinspection GroovyAssignabilityCheck
|
||||
project {
|
||||
id = propertyString('curseforge_project_id')
|
||||
addGameVersion 'Java 8'
|
||||
addGameVersion 'Forge'
|
||||
addGameVersion '1.12.2'
|
||||
releaseType = propertyString('release_type')
|
||||
if (!propertyBool('publish_with_changelog')) {
|
||||
changelog = parserChangelog()
|
||||
changelogType = 'markdown'
|
||||
}
|
||||
mainArtifact tasks.reobfJar, {
|
||||
displayName = "${propertyString('mod_name')} ${propertyString('mod_version')}"
|
||||
if (propertyBool('use_mixins')) {
|
||||
relations {
|
||||
requiredDependency 'mixin-booter'
|
||||
}
|
||||
}
|
||||
if (propertyBool('use_asset_mover')) {
|
||||
relations {
|
||||
requiredDependency 'assetmover'
|
||||
}
|
||||
}
|
||||
}
|
||||
options {
|
||||
debug = propertyBool('curseforge_debug')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Documentation here: https://github.com/modrinth/minotaur
|
||||
if (propertyBool('publish_to_modrinth')) {
|
||||
apply plugin: 'com.modrinth.minotaur'
|
||||
assertProperty('modrinth_project_id')
|
||||
assertProperty('release_type')
|
||||
setDefaultProperty('modrinth_debug', false, false)
|
||||
modrinth {
|
||||
token = System.getenv('MODRINTH_TOKEN') ? "" : System.getenv('MODRINTH_TOKEN')
|
||||
projectId = propertyString('modrinth_project_id')
|
||||
versionNumber = propertyString('mod_version')
|
||||
versionType = propertyString('release_type')
|
||||
uploadFile = tasks.reobfJar
|
||||
gameVersions = ['1.12.2']
|
||||
loaders = ['forge']
|
||||
debugMode = propertyBool('modrinth_debug')
|
||||
if (propertyBool('use_mixins') || propertyBool('use_asset_mover')) {
|
||||
dependencies {
|
||||
if (propertyBool('use_mixins')) {
|
||||
required.project 'mixinbooter'
|
||||
}
|
||||
if (propertyBool('use_asset_mover')) {
|
||||
required.project 'assetmover'
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!propertyBool('publish_with_changelog')) {
|
||||
changelog = parserChangelog()
|
||||
}
|
||||
if (propertyBool('modrinth_sync_readme')) {
|
||||
syncBodyFrom = file('README.md').text
|
||||
tasks.modrinth.dependsOn(tasks.modrinthSyncBody)
|
||||
}
|
||||
}
|
||||
}
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
- Here lies the root of the `io.github.cleanroommc` package, add another level with your mod id and use that as the root for your mod classes.
|
||||
|
24
src/main/java/com/example/modid/ExampleMod.java
Normal file
24
src/main/java/com/example/modid/ExampleMod.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
package com.example.modid;
|
||||
|
||||
import com.example.modid.Tags;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = Tags.MOD_ID, name = Tags.MOD_NAME, version = Tags.VERSION)
|
||||
public class ExampleMod {
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger(Tags.MOD_NAME);
|
||||
|
||||
/**
|
||||
* <a href="https://wiki.cleanroommc.com/mod-development/event/overview/">
|
||||
* Take a look at how many FMLStateEvents you can listen to via the @Mod.EventHandler annotation here
|
||||
* </a>
|
||||
*/
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
LOGGER.info("Hello From {}!", Tags.MOD_NAME);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +1,12 @@
|
|||
[
|
||||
{
|
||||
"modid": "examplemod",
|
||||
"name": "Example Mod",
|
||||
"description": "Example placeholder mod.",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"url": "",
|
||||
"updateUrl": "",
|
||||
"authorList": ["CleanroomMC"],
|
||||
"credits": "Authors of this project",
|
||||
"logoFile": "",
|
||||
"screenshots": [],
|
||||
"dependencies": []
|
||||
}
|
||||
]
|
||||
[{
|
||||
"modid": "${mod_id}",
|
||||
"name": "${mod_name}",
|
||||
"version": "${mod_version}",
|
||||
"mcversion": "1.12.2",
|
||||
"description": "${mod_description}",
|
||||
"authorList": ${mod_authors},
|
||||
"credits": "${mod_credits}",
|
||||
"url": "${mod_url}",
|
||||
"updateJSON": "${mod_update_json}",
|
||||
"logoFile": "${mod_logo_path}"
|
||||
}]
|
11
src/main/resources/mixins.modid.json
Normal file
11
src/main/resources/mixins.modid.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"package": "",
|
||||
"required": true,
|
||||
"refmap": "${mixin_refmap}",
|
||||
"target": "@env(DEFAULT)",
|
||||
"minVersion": "0.8.5",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [],
|
||||
"server": [],
|
||||
"client": []
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"pack": {
|
||||
"description": "examplemod resources",
|
||||
"pack_format": 3,
|
||||
"_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)."
|
||||
}
|
||||
}
|
||||
"pack": {
|
||||
"description": "${mod_name} Resources",
|
||||
"pack_format": 3
|
||||
}
|
||||
}
|
3
tags.properties
Normal file
3
tags.properties
Normal file
|
@ -0,0 +1,3 @@
|
|||
VERSION = ${mod_version}
|
||||
MOD_ID = ${mod_id}
|
||||
MOD_NAME = ${mod_name}
|
Loading…
Reference in a new issue