Repository navigation
Expand file tree
/
Copy pathbuild.gradle
More file actions
287 lines (261 loc) · 10.7 KB
/
Copy pathbuild.gradle
File metadata and controls
287 lines (261 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
import org.gradle.plugins.ide.eclipse.model.SourceFolder
plugins {
id 'idea'
id 'eclipse'
id 'java-library'
id 'maven-publish'
id 'signing'
alias libs.plugins.modDevGradleLegacy
alias libs.plugins.lombok
alias libs.plugins.spotless
alias libs.plugins.kotlin.jvm
alias libs.plugins.kotlin.plugin
alias libs.plugins.kotlin.lombok
alias libs.plugins.gtopublishgradleplugin
}
version = mod_version
// Local secrets may live in the ignored .env file; process environment always wins.
def dotenv = new LinkedHashMap<String, String>()
def dotenvFile = file('.env')
if (dotenvFile.isFile()) {
dotenvFile.eachLine('UTF-8') { String rawLine ->
def line = rawLine.trim()
if (!line || line.startsWith('#')) {
return
}
if (line.startsWith('export ')) {
line = line.substring('export '.length()).trim()
}
int separator = line.indexOf('=')
if (separator <= 0) {
return
}
def key = line.substring(0, separator).trim()
if (!(key ==~ /[A-Za-z_][A-Za-z0-9_]*/)) {
return
}
def value = line.substring(separator + 1).trim()
if (value.length() >= 2 && ((value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'")))) {
value = value.substring(1, value.length() - 1)
}
dotenv.put(key, value)
}
}
def processEnv = System.getenv()
def localEnv = { String name ->
return processEnv.containsKey(name) ? processEnv.get(name) : dotenv.get(name)
}
// 模组字节码目标 21(GTCEu/gtmthings/datasynclib 等依赖要求 JVM 21+;Java 17 无法运行)。
// 开发可用 Java 25 跑 Gradle;CI 使用 Java 21 runner。
// Java 25 字节码 (major 69) 无法被当前 reobf/ART 处理。
java.toolchain.languageVersion = JavaLanguageVersion.of(21)
sourceSets.main.resources { srcDir 'src/generated/resources' }
sourceSets {
test {
compileClasspath += sourceSets.main.compileClasspath + sourceSets.main.output
runtimeClasspath += sourceSets.main.runtimeClasspath + sourceSets.main.output
}
}
apply from: "$rootDir/gradle/scripts/moddevgradle.gradle"
apply from: "$rootDir/gradle/scripts/repositories.gradle"
apply from: "$rootDir/dependencies.gradle"
// GTOLib:先打包/保护,再由 gtocore 加载(run*/jar 均依赖此流水线)
apply from: "$rootDir/gradle/scripts/gtolib-pipeline.gradle"
apply from: "$rootDir/gradle/scripts/resources.gradle"
apply from: "$rootDir/gradle/scripts/jars.gradle"
apply from: "$rootDir/gradle/scripts/spotless.gradle"
// Eclipse classpath configuration for VS Code Java Language Server
eclipse {
classpath {
// Include all compile/runtime configurations so VS Code can resolve all dependencies
plusConfigurations += [configurations.compileClasspath, configurations.runtimeClasspath]
downloadSources = true
downloadJavadoc = true
file.whenMerged { cp ->
// Add Kotlin compiled output so VS Code JDT LS can resolve Kotlin classes from Java
cp.entries += new SourceFolder(
"build/classes/kotlin/main", null
)
// Collect all jars already in the Eclipse classpath
def existingPaths = cp.entries
.findAll { it instanceof org.gradle.plugins.ide.eclipse.model.Library }
.collect { it.path }
.toSet()
// Add any resolved compileClasspath files that Eclipse missed
// (e.g. ModDevGradle artifact-transform outputs for modImplementation deps)
configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.each { art ->
def f = art.file
if (f.exists() && f.name.endsWith('.jar') && !existingPaths.contains(f.absolutePath)) {
def lib = new org.gradle.plugins.ide.eclipse.model.Library(
cp.fileReferenceFactory.fromFile(f)
)
cp.entries += lib
existingPaths.add(f.absolutePath)
}
}
}
}
}
generateModMetadata.doFirst {
mkdir('run/client')
mkdir('run/server')
mkdir('run/data')
if (file('run/client/gtocore/cache').isDirectory()) {
delete fileTree('run/client/gtocore/cache')
}
}
tasks.named('prepareClientRun') {
outputs.upToDateWhen { false }
}
def configureLegacyWriter = { String taskName, String preferredConfigName, String outFileName ->
tasks.named(taskName) {
doLast {
def cfg = configurations.findByName(preferredConfigName) ?: configurations.getByName("runtimeClasspath")
def out = file("$buildDir/moddev/${outFileName}")
out.parentFile.mkdirs()
out.text += cfg.files.collect { it.absolutePath }.findAll {
it.contains("commons-math3") || it.contains("opencc4j") ||
it.contains("heaven") || it.contains("nlp-common")
}.join(System.lineSeparator())
}
}
}
configureLegacyWriter("writeClientLegacyClasspath", "clientRuntimeClasspath", "clientLegacyClasspath.txt")
configureLegacyWriter("writeServerLegacyClasspath", "serverRuntimeClasspath", "serverLegacyClasspath.txt")
configureLegacyWriter("writeDataLegacyClasspath", "dataRuntimeClasspath", "dataLegacyClasspath.txt")
tasks.withType(JavaCompile).configureEach {
options.encoding = "UTF-8"
// 模组发行字节码固定 21(GTCEu 等依赖的属性元数据要求;勿用 25,否则 reobf 报 major 69)
options.release = 21
options.compilerArgs << "-Xlint:-deprecation" << "-Xlint:-removal"
// Mixin AP + 大体量工程:worker 默认堆过小会 OOM(与 daemon 的 org.gradle.jvmargs 无关)
options.fork = true
options.forkOptions.jvmArgs = ['-Xmx4g', '-Xms512m']
options.forkOptions.memoryMaximumSize = '4g'
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
compilerOptions.jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
}
tasks.withType(Test).configureEach {
useJUnitPlatform()
}
// Ensure Java compilation depends on Kotlin and can resolve Kotlin classes
tasks.named('compileJava', JavaCompile) {
// Mixin's annotation processors are non-incremental and always force a full
// javac run. Keeping Gradle's incremental analysis enabled only adds a costly
// post-compile class dependency scan whose result can never be reused.
options.incremental = false
dependsOn tasks.named('compileKotlin')
classpath += files(tasks.named('compileKotlin').map { it.destinationDirectory })
}
jar {
exclude "**/.cache"
exclude "**/SimplifiedToTraditional.properties"
}
java {
withSourcesJar()
}
afterEvaluate {
tasks.register("signJar") {
doLast {
def destDir = "$buildDir/libs"
def originalJar = "${buildDir}/libs/${mod_id}-forge-1.20.1-${version}.jar"
mkdir(destDir)
ant.signjar(
jar: originalJar,
destDir: destDir,
alias: "gtokey",
storetype: "jks",
keystore: "keystore.jks",
storepass: localEnv('GTO_STOREPASS'),
keypass: localEnv('GTO_KEYPASS'),
preservelastmodified: "true",
tsaurl: "http://timestamp.sectigo.com?td=sha256",
)
// Seal Runtime 独立产物一并签名(与 gtocore 并列分发)
def sealJar = file("${buildDir}/libs/gto-seal-runtime-1.0.jar")
if (!sealJar.exists()) {
def libsSeal = file("libs/gto-seal-runtime-1.0.jar")
if (libsSeal.exists()) {
copy {
from libsSeal
into destDir
rename { 'gto-seal-runtime-1.0.jar' }
}
}
}
sealJar = file("${buildDir}/libs/gto-seal-runtime-1.0.jar")
if (sealJar.exists() && sealJar.length() > 0) {
ant.signjar(
jar: sealJar.absolutePath,
destDir: destDir,
alias: "gtokey",
storetype: "jks",
keystore: "keystore.jks",
storepass: localEnv('GTO_STOREPASS'),
keypass: localEnv('GTO_KEYPASS'),
preservelastmodified: "true",
tsaurl: "http://timestamp.sectigo.com?td=sha256",
)
logger.lifecycle("GTO Seal: signed ${sealJar.name}")
} else {
logger.warn("GTO Seal: build/libs/gto-seal-runtime-1.0.jar 不存在,跳过签名")
}
}
outputs.upToDateWhen {
false
}
onlyIf {
new File("${projectDir}/keystore.jks").exists()
}
}
// 确保签名前 seal 已 stage 到 build/libs
tasks.named('signJar').configure {
if (tasks.findByName('stageSealRuntimeArtifact') != null) {
dependsOn 'stageSealRuntimeArtifact'
}
}
reobfJar.finalizedBy signJar
}
idea {
module {
downloadSources = true
downloadJavadoc = true
// 仅供 IDEA 索引/跳转
if (hasGtolibSources) {
sourceDirs += file('GTOLib/src/main/java')
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
groupId = mod_group_id
artifactId = mod_id
}
}
repositories {
maven {
name = 'gtodysseyRepository'
url = 'https://maven.gtodyssey.com/releases'
credentials {
username = findProperty('gtodysseyRepositoryUsername') ?: ''
password = findProperty('gtodysseyRepositoryPassword') ?: ''
}
}
}
}
gtoPublish {
publishMaven = true // 默认 true
publishGithub = false // 默认 false
publishCurseforge = false // 默认 false
mavenRepoName = 'gtodysseyRepository' // 默认值
mavenRepoUrl = 'releases' // 必填,可选值: 'releases' 或 'private'
minecraftVersion = '1.20.1' // 必填,Minecraft 版本号
modLoader = 'Forge' // 必填,模组加载器(NeoForge, Forge, Fabric 等)
githubRepo = 'owner/repo-name' // GitHub 仓库(启用 GitHub 发布时必填)
curseforgeProjectId = '123456' // CurseForge 项目 ID(启用 CurseForge 时必填)
curseforgeJavaVersion = 'Java 21' // 运行时最低 Java(GTCEu 等依赖要求 21+;开发机可用 Java 25)
}