//noinspection GroovyAssignabilityCheck //file:noinspection GroovyAssignabilityCheck import proguard.gradle.ProGuardTask buildscript { repositories { mavenCentral() } dependencies { classpath 'com.guardsquare:proguard-gradle:7.7.0' } } plugins { id 'java' id 'idea' id 'java-library' id 'maven-publish' id 'com.github.johnrengelman.shadow' version '8.1.1' id 'net.neoforged.moddev.legacyforge' version '2.0.103' } // ===================== 基础配置 ===================== def enableProguard = project.hasProperty("enableProguard") && project.enableProguard.toBoolean() tasks.named('wrapper', Wrapper).configure { distributionType = Wrapper.DistributionType.BIN } group = mod_group_id version = "${minecraft_version}-${mod_version}" java { toolchain.languageVersion = JavaLanguageVersion.of(17) } base { archivesName = mod_id } println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" // ===================== 仓库配置 ===================== repositories { mavenCentral() maven { url = "https://libraries.minecraft.net/" } maven { url = "https://neoforged.forgecdn.net/releases" } maven { url = "https://neoforged.forgecdn.net/mojang-meta" } maven { url "https://cursemaven.com" content { includeGroup "curse.maven" } } maven { name = "Progwml6" url = "https://dvs1.progwml6.com/files/maven/" } maven { name = "BlameJared" url = "https://maven.blamejared.com/" } maven { name = "ModMaven" url = "https://modmaven.dev" } maven { name = "Lucko" url = "https://repo.lucko.me/" content { includeModule 'me.lucko', 'spark-api' } } maven { name = "KosmX" url = "https://maven.kosmx.dev/" } maven { name = "Curios" url = "https://maven.theillusivec4.top/" } maven { name = "Luck perms" url = "https://repo1.maven.org/maven2/net/luckperms/api/" } maven { name = "GeckoLib" url = "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/" content { includeGroupByRegex("software\\.bernie.*") includeGroup("com.eliotlash.mclib") } } maven { name = "LTD Maven" url = "https://nexus.bot.leisuretimedock.top/repository/maven-public/" } flatDir { dir "libs" } } // ===================== Forge 配置 ===================== legacyForge { version = "${minecraft_version}-${forge_version}" accessTransformers = files("src/main/templates/META-INF/accesstransformer.cfg") parchment { minecraftVersion = minecraft_version mappingsVersion = mapping_lasting_version } runs { configureEach { systemProperty 'forge.logging.console.level', 'debug' systemProperty 'forge.logging.markers', 'REGISTRIES' logLevel = org.slf4j.event.Level.DEBUG } client { client() systemProperty 'forge.enabledGameTestNamespaces', mod_id } clientAuth { devLogin = true client() systemProperty 'forge.enabledGameTestNamespaces', mod_id } server { server() } testServer { server() // 设置服务器运行目录 gameDirectory = file('run/server') } data { data() programArguments.addAll '--mod', mod_id, '--all', '--output', file('src/generated/resources/').absolutePath, '--existing', file('src/main/resources/').absolutePath } } mods { "${mod_id}" { sourceSet sourceSets.main } } } // ===================== 源码与资源 ===================== sourceSets.main.resources { srcDir 'src/generated/resources' srcDir 'src/main/resources' } // ===================== 编译配置 ===================== tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' } // ===================== 依赖 ===================== configurations { runtimeClasspath.extendsFrom localRuntime proguardLibs { canBeResolved = true canBeConsumed = false extendsFrom modCompileOnly } } dependencies { annotationProcessor ('org.spongepowered:mixin:0.8.5:processor') modRuntimeOnly("curse.maven:debug-utils-forge-783008:5337491") modImplementation("blank:curtain-1.20.1:1.3.2") modImplementation("dev.kosmx.player-anim:player-animation-lib-forge:${player_anim_version}") modImplementation("curse.maven:bendy-lib-623373:4550371") modImplementation("curse.maven:waystones-245755:6856603") modImplementation("curse.maven:balm-531761:7087245") // modImplementation("curse.maven:kaleidoscope-doll-1233277:7201584") // modRuntimeOnly("curse.maven:luckperms-431733:4738950") modImplementation("software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}") implementation("com.eliotlash.mclib:mclib:20") modCompileOnly("top.theillusivec4.curios:curios-forge:${curios_version}:api") modCompileOnly("top.theillusivec4.curios:curios-forge:${curios_version}") modRuntimeOnly("top.theillusivec4.curios:curios-forge:${curios_version}") modCompileOnly("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}") modCompileOnly("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}") modRuntimeOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") modRuntimeOnly("curse.maven:spark-361579:4738952") compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")) modImplementation("io.github.llamalad7:mixinextras-forge:0.4.1") compileOnly("net.luckperms:api:5.4") compileOnly ('me.lucko:spark-api:0.1-SNAPSHOT') implementation 'org.ow2.asm:asm:9.6' implementation 'org.ow2.asm:asm-tree:9.6' implementation 'org.ow2.asm:asm-commons:9.6' implementation 'org.ow2.asm:asm-util:9.6' } // ===================== 修复 Javadoc 任务 ===================== tasks.named('javadoc', Javadoc).configure { group = 'documentation' description = 'Generates full Javadoc for the mod.' destinationDir = file("$buildDir/docs/javadoc") // 明确指定源与类路径 source = sourceSets.main.allJava classpath = sourceSets.main.compileClasspath options.encoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://docs.oracle.com/en/java/javase/17/docs/api/") options.memberLevel = JavadocMemberLevel.PUBLIC options.addBooleanOption('Xdoclint:none', true) options.addStringOption('doctitle', "${mod_id} ${minecraft_version} ${mod_version} Javadoc") } tasks.register('sourceJar', Jar) { from(sourceSets.main.allSource) // java archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}-sources.jar" archiveClassifier.set("sources") duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes([ 'Specification-Title' : mod_id, 'Specification-Vendor' : mod_authors, 'Specification-Version' : '1', 'Implementation-Title' : project.name, 'Implementation-Version' : archiveVersion, 'Implementation-Vendor' : mod_authors, 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), ]) } dependsOn classes } // ===================== 普通 Javadoc ===================== tasks.register('javadocJar', Jar) { archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}-javadoc.jar" archiveClassifier.set("javadoc") from tasks.javadoc dependsOn tasks.javadoc } // ===================== API Jar(class / java) ===================== tasks.register('apiJar', Jar) { archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}-api.jar" archiveClassifier.set("api") manifest { attributes 'FMLModType': 'GAMELIBRARY' } // 打包 class 和 java from(sourceSets.main.output) { // class exclude 'assets/**', 'data/**' } include "top/r3944realms/superleadrope/api/**/*" include "top/r3944realms/superleadrope/SuperLeadRopeAPI.*" dependsOn classes } tasks.register('apiSourceJar', Jar) { archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}-api-sources.jar" archiveClassifier.set("api-sources") manifest { attributes 'FMLModType': 'GAMELIBRARY' } // 打包 class 和 java from(sourceSets.main.allSource) { // java exclude 'assets/**', 'data/**' } include "top/r3944realms/superleadrope/api/**/*" include "top/r3944realms/superleadrope/SuperLeadRopeAPI.*" dependsOn classes } tasks.register('apiJavadocJar', Jar) { archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}-api-javadoc.jar" archiveClassifier.set("api-javadoc") from tasks.javadoc include "top/r3944realms/superleadrope/api/**/*" dependsOn tasks.javadoc } tasks.register('apiJavadoc', Javadoc) { group = 'documentation' description = 'Generates Javadoc for API package only.' destinationDir = file("$buildDir/docs/api-javadoc") source = sourceSets.main.allJava.matching { include "top/r3944realms/superleadrope/api/**/*" include "top/r3944realms/superleadrope/SuperLeadRopeAPI.java" } classpath = sourceSets.main.compileClasspath options.encoding = 'UTF-8' options.charSet = 'UTF-8' options.links("https://docs.oracle.com/en/java/javase/17/docs/api/") options.memberLevel = JavadocMemberLevel.PUBLIC options.addBooleanOption('Xdoclint:none', true) options.addStringOption('doctitle', "${mod_name} API ${mod_version} Javadoc") } // ===================== 主 Jar 与混淆 ===================== jar { manifest { attributes([ 'Specification-Title' : mod_id, 'Specification-Vendor' : mod_authors, 'Specification-Version' : '1', 'Implementation-Title' : project.name, 'Implementation-Version' : archiveVersion, 'Implementation-Vendor' : mod_authors, 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), ]) } archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}-origin.jar" finalizedBy 'proguard' } tasks.register('proguard', ProGuardTask) { onlyIf { enableProguard } dependsOn tasks.jar configuration 'proguard.pro' libraryjars "${System.getProperty('java.home')}/jmods" configurations.proguardLibs.resolve().each { file -> libraryjars file.absolutePath } def inputJar = tasks.jar.archiveFile.get().asFile injars inputJar outjars "${buildDir}/libs/[NOTUSE]${mod_id}-${minecraft_version}-${mod_version}-proguard.jar" doFirst { copy { from inputJar into "${buildDir}/libs" rename { "[NOTUSE]${mod_id}-${minecraft_version}-${mod_version}-origin.jar" } } } inputs.files tasks.jar.archiveFile finalizedBy 'reobfJar' } processResources { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) { var replaceProperties = [ minecraft_version : minecraft_version, minecraft_version_range : minecraft_version_range, forge_version : forge_version, forge_version_range : forge_version_range, loader_version_range : loader_version_range, mod_id : mod_id, mod_name : mod_name, mod_license : mod_license, mod_version : mod_version, mod_authors : mod_authors, mod_description : mod_description, mod_credits : mod_credits ] inputs.properties replaceProperties expand replaceProperties from "src/main/templates" into "build/generated/sources/modMetadata" } sourceSets.main.resources.srcDir generateModMetadata legacyForge.ideSyncTask generateModMetadata tasks.named('publish') { dependsOn build } afterEvaluate { tasks.named('reobfJar') { if (enableProguard) { dependsOn 'proguard' input = file("${buildDir}/libs/[NOTUSE]${mod_id}-${minecraft_version}-${mod_version}-proguard.jar") } else { dependsOn 'jar' input = tasks.jar.archiveFile.get().asFile } } } // ===================== 发布配置 ===================== publishing { publications { mavenJava(MavenPublication) { artifactId = mod_id artifact reobfJar artifact sourceJar artifact javadocJar artifact apiJar artifact apiSourceJar artifact apiJavadocJar pom { name = "${mod_id}" description = "The API for ${mod_name}" url = "https://github.com/3944Realms/SuperLeadMod" licenses { license { name = mod_license url = "https://www.gnu.org/licenses/gpl-3.0.en.html#license-text" } } developers { developer { id = "${mod_id}" name = mod_authors } } } } } repositories { maven { name = "local" url = layout.buildDirectory.dir("repo") } maven { name = 'LTDNexus' url = 'https://nexus.bot.leisuretimedock.top/repository/maven-releases/' credentials { username = System.getenv('LTDNexusUsername') ?: '' password = System.getenv('LTDNexusPassword') ?: '' } } } } // ===================== 构建任务依赖 ===================== tasks.named('build') { dependsOn sourceJar, apiSourceJar, apiJar, apiJavadocJar } tasks.named('clean') { delete fileTree(dir: "${project.projectDir}/mcmodsrepo") } // ===================== RenderDoc 运行支持 ===================== tasks.register("runWithRenderDoc", Exec) { group = "minecraft" description = "Run Minecraft with RenderDoc using runClientAuth configuration" dependsOn "classes" def renderDocCmd = file("RenderDoc_1.40_64/renderdoccmd.exe").absolutePath def captureDir = file("$buildDir/renderdoc/capture").absolutePath def runClientTask = tasks.named("runClientAuth", JavaExec).get() def javaExecPath = new File(runClientTask.getJavaLauncher().get().metadata.installationPath.asFile, "bin/java.exe").absolutePath def jdwpArgs = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" commandLine renderDocCmd, "capture", "--opt-hook-children", "--wait-for-exit", "--working-dir", "$projectDir/run", "--capture-file", "${captureDir}/minecraft_capture", javaExecPath, jdwpArgs, "@${buildDir}/moddev/clientRunVmArgs.txt", "@${buildDir}/moddev/clientRunProgramArgs.txt" environment "MOD_CLASSES", "superleadrope%%${buildDir}/classes/java/main;superleadrope%%${buildDir}/resources/main" doFirst { println "Using JVM: ${javaExecPath}" println "RenderDoc capture dir: ${captureDir}" } } // ===================== IDEA 支持 ===================== idea { module { downloadSources = true downloadJavadoc = true } } tasks.register('showTaskTree') { doLast { def showTaskDeps showTaskDeps = { task, prefix = '', isLast = true -> // 当前任务节点 def connector = isLast ? '└── ' : '├── ' println "${prefix}${connector}${task.name}" // 子任务 def dependencies = task.getTaskDependencies().getDependencies(task).toList() def newPrefix = prefix + (isLast ? ' ' : '│ ') dependencies.eachWithIndex { dep, index -> def lastChild = index == dependencies.size() - 1 showTaskDeps(dep, newPrefix, lastChild) } } def targetTask = tasks.findByName('build') if (targetTask) { println "构建任务依赖树:" showTaskDeps(targetTask, '', true) } else { println "未找到 build 任务" } } }