//file:noinspection GroovyAssignabilityCheck 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' } java { toolchain.languageVersion = JavaLanguageVersion.of(17) } tasks.named('wrapper', Wrapper).configure { distributionType = Wrapper.DistributionType.BIN } version = "${minecraft_version}-${mod_version}" group = mod_group_id repositories { mavenLocal() maven { url = "https://libraries.minecraft.net/" } maven { url = "https://neoforged.forgecdn.net/releases" } maven { url = "https://neoforged.forgecdn.net/mojang-meta" } maven { url = "https://maven.neoforged.net/releases" } maven { name = "LTD Maven" url = "https://nexus.bot.leisuretimedock.top/repository/maven-public/" } flatDir { dir "libs" } } base { archivesName = mod_id } // Mojang ships Java 17 to end users in 1.20.1, so mods should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(17) legacyForge { // Specify the version of MinecraftForge to use. version = project.minecraft_version + '-' + project.forge_version parchment { mappingsVersion = project.parchment_mappings_version minecraftVersion = project.parchment_minecraft_version } // Default run configurations. runs { client { client() systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } clientAuth{ devLogin = true client() systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } server { server() programArgument '--nogui' systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } gameTestServer { type = "gameTestServer" systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } data { data() programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() } configureEach { systemProperty 'forge.logging.markers', 'REGISTRIES' logLevel = org.slf4j.event.Level.DEBUG } } mods { "${mod_id}" { sourceSet(sourceSets.main) } } } // Include resources generated by data generators. sourceSets.main.resources { srcDir 'src/generated/resources' } configurations { runtimeClasspath.extendsFrom localRuntime } obfuscation { createRemappingConfiguration(configurations.localRuntime) } dependencies { // 依赖项可以在这里添加 } // This block of code expands all declared replace properties in the specified resource targets. 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 ] duplicatesStrategy = DuplicatesStrategy.EXCLUDE inputs.properties replaceProperties expand replaceProperties from "src/main/templates" into "build/generated/sources/modMetadata" } sourceSets.main.resources.srcDir generateModMetadata legacyForge.ideSyncTask generateModMetadata // ==================== Javadoc 配置 ==================== javadoc { options { encoding = 'UTF-8' charSet = 'UTF-8' author = true version = true windowTitle = "Lib39 ${project.mod_version} API" docTitle = "Lib39 ${project.mod_version} API" memberLevel = JavadocMemberLevel.PROTECTED links = [ 'https://docs.oracle.com/javase/8/docs/api/' ] addBooleanOption('Xdoclint:none', true) addBooleanOption('html5', true) } source = sourceSets.main.allJava classpath = configurations.compileClasspath exclude '**/test/**' exclude '**/internal/**' } tasks.register('javadocJar', Jar) { archiveClassifier.set('javadoc') from tasks.javadoc dependsOn tasks.javadoc } // ===================== 主包完整 Jar(class + java) ===================== tasks.register('deobfJar', Jar) { archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}.jar" from(sourceSets.main.output) // === 避免重复打包资源(即使混入其他 jar 时也不会重复) === duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes( 'Specification-Title': mod_id, 'Specification-Vendor': mod_authors, '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 } // ==================== 发布配置 ==================== publishing { publications { mavenJava(MavenPublication) { artifactId = mod_id artifact deobfJar artifact javadocJar pom { name = 'Lib39' description = 'Lib39 is a general-purpose dependency library for Minecraft mods.' url = 'https://github.com/3944Realms/lib39' properties = [ 'minecraft.version': project.minecraft_version, 'mod.version': project.mod_version, 'forge.version': project.forge_version, 'java.version': '17' ] licenses { license { name = 'MIT' url = 'https://raw.githubusercontent.com/3944Realms/lib39/refs/heads/main/LICENSE' distribution = 'repo' } } developers { developer { id = 'R3944Realms' name = "${mod_authors}" email = 'f256198830@hotmail.com' } } scm { connection = 'scm:git:https://github.com/3944Realms/lib39.git' developerConnection = 'scm:git:ssh://git@github.com:3944Realms/lib39.git' url = 'https://github.com/3944Realms/lib39' tag = 'main' } issueManagement { system = 'GitHub' url = 'https://github.com/3944Realms/lib39/issues' } } } } repositories { // 本地仓库 maven { name = 'local' url = layout.buildDirectory.dir("repo") } // Nexus 远程仓库 maven { name = 'LTDNexus' url = 'https://nexus.bot.leisuretimedock.top/repository/maven-releases/' credentials { username = System.getenv('LTDNexusUsername') ?: '' password = System.getenv('LTDNexusPassword') ?: '' } } } } // ==================== 任务配置 ==================== tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.compilerArgs += ['-Xlint:unchecked', '-Xlint:deprecation'] } // 配置 Javadoc JAR - 使用标准 javadoc 任务输出 tasks.named('javadocJar') { from javadoc.destinationDir } // ==================== 验证任务 ==================== tasks.register('verifyNexusCredentials') { doLast { def username = System.getenv('LTDNexusUsername') def password = System.getenv('LTDNexusPassword') // 安全地显示用户名和密码(只显示最后两位) def displayUsername = username ? "***${username.length() > 2 ? username.substring(username.length() - 2) : '**'}" : 'NOT SET' def displayPassword = password ? "***${password.length() > 2 ? password.substring(password.length() - 2) : '**'}" : 'NOT SET' println "Nexus Username: ${displayUsername}" println "Nexus Password: ${displayPassword}" if (!username || !password) { throw new GradleException('LTDNexusUsername or LTDNexusPassword environment variables are not set') } } } tasks.register('checkPublicationContents') { doLast { def publication = publishing.publications.mavenJava println "=== Publication Details ===" println "Group: ${publication.groupId}" println "Artifact: ${publication.artifactId}" println "Version: ${publication.version}" println "Artifacts:" publication.artifacts.each { artifact -> def file = artifact.file def exists = file.exists() println " - ${file.name} (${artifact.classifier ?: 'main'}) - Exists: ${exists}" if (!exists) { throw new GradleException("Publication artifact missing: ${file.absolutePath}") } } } } // ==================== 任务依赖 ==================== tasks.named('publishMavenJavaPublicationToLTDNexusRepository') { dependsOn verifyNexusCredentials dependsOn checkPublicationContents } tasks.withType(PublishToMavenRepository) { dependsOn assemble dependsOn javadocJar } // ==================== 便捷任务 ==================== tasks.register('publishToNexus') { group = 'publishing' description = 'Publishes all publications to LTD Nexus' dependsOn 'publishMavenJavaPublicationToLTDNexusRepository' } tasks.register('publishLocal') { group = 'publishing' description = 'Publishes all publications to the local Maven repository' dependsOn 'publishToMavenLocal' } tasks.register('cleanRepo', Delete) { delete layout.buildDirectory.dir("repo") } tasks.named('clean') { dependsOn cleanRepo } // ==================== IDEA 配置 ==================== idea { module { downloadSources = true downloadJavadoc = true } } // 禁用模块元数据生成 tasks.withType(GenerateModuleMetadata) { enabled = false } afterEvaluate { tasks.named('deobfJar') { doLast { def jar = file(layout.buildDirectory.dir("repo") + "${mod_id}-${minecraft_version}-${mod_version}.jar") if (jar.exists()) ant.delete(jar) } } }