import io.papermc.fill.model.BuildChannel import io.papermc.paperweight.attribute.DevBundleOutput import io.papermc.paperweight.util.* import java.time.Instant plugins { `java-library` `maven-publish` idea id("io.papermc.paperweight.core") id("io.papermc.fill.gradle") version "1.0.14" } val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" dependencies { mache("io.papermc:mache:26.3+build.1") paperclip("io.papermc:paperclip:3.0.4") } paperweight { minecraftVersion = providers.gradleProperty("mcVersion") gitFilePatches = false // Infstar:在 Paper 的服务端源码上应用自有补丁。 val infstar = forks.register("infstar") { upstream.patchDir("paperServer") { upstreamPath = "paper-server" excludes = setOf("src/minecraft", "patches", "build.gradle.kts") patchesDir = rootDirectory.dir("infstar-server/paper-patches") outputDir = rootDirectory.dir("paper-server") } } activeFork = infstar updatingMinecraft { //oldPaperCommit = "e5fe71723e2ffde7cc9fafc085ac3bb73e63175e" } } tasks.generateDevelopmentBundle { libraryRepositories.addAll( "https://repo.maven.apache.org/maven2/", paperMavenPublicUrl, ) } abstract class Services { @get:Inject abstract val archiveOperations: ArchiveOperations } val services = objects.newInstance() if (project.providers.gradleProperty("publishDevBundle").isPresent) { val devBundleComponent = publishing.softwareComponentFactory.adhoc("devBundle") components.add(devBundleComponent) val devBundle = configurations.consumable("devBundle") { attributes.attribute(DevBundleOutput.ATTRIBUTE, objects.named(DevBundleOutput.ZIP)) outgoing.artifact(tasks.generateDevelopmentBundle.flatMap { it.devBundleFile }) } devBundleComponent.addVariantsFromConfiguration(devBundle) {} val runtime = configurations.consumable("serverRuntimeClasspath") { attributes.attribute(DevBundleOutput.ATTRIBUTE, objects.named(DevBundleOutput.SERVER_DEPENDENCIES)) attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) extendsFrom(configurations.runtimeClasspath.get()) } devBundleComponent.addVariantsFromConfiguration(runtime) { mapToMavenScope("runtime") } val compile = configurations.consumable("serverCompileClasspath") { attributes.attribute(DevBundleOutput.ATTRIBUTE, objects.named(DevBundleOutput.SERVER_DEPENDENCIES)) attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_API)) extendsFrom(configurations.compileClasspath.get()) } devBundleComponent.addVariantsFromConfiguration(compile) { mapToMavenScope("compile") } tasks.withType(GenerateMavenPom::class).configureEach { doLast { val text = destination.readText() // Remove dependencies from pom, dev bundle is designed for gradle module metadata consumers destination.writeText( text.substringBefore("") + text.substringAfter("") ) } } publishing { publications.create("devBundle") { artifactId = "dev-bundle" from(devBundleComponent) } } } // Infstar:编译生成后的 Paper 源码,而不是空的模块目录。 sourceSets { main { java { srcDir("../paper-server/src/main/java") srcDir("../paper-server/src/generated/java") } resources { srcDir("../paper-server/src/main/resources") } } test { java { srcDir("../paper-server/src/test/java") } resources { srcDir("../paper-server/src/test/resources") } } } val log4jPlugins = sourceSets.create("log4jPlugins") { java { srcDir("../paper-server/src/log4jPlugins/java") } } configurations.named(log4jPlugins.compileClasspathConfigurationName) { extendsFrom(configurations.compileClasspath.get()) } val alsoShade: Configuration = configurations.create("alsoShade") configurations.consumable("runtimeConfiguration") { attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) extendsFrom(configurations.getByName(sourceSets.main.get().runtimeElementsConfigurationName)) } // Configure mockito agent that is needed in newer java versions val mockitoAgent = configurations.register("mockitoAgent") abstract class MockitoAgentProvider : CommandLineArgumentProvider { @get:CompileClasspath abstract val fileCollection: ConfigurableFileCollection override fun asArguments(): Iterable { return listOf("-javaagent:" + fileCollection.files.single().absolutePath) } } dependencies { implementation(project(":infstar-api")) implementation(platform("ca.spottedleaf.leafpile:bom:1.2.4")) implementation("ca.spottedleaf.leafpile:common") implementation("ca.spottedleaf.leafpile:concurrentutil") implementation("ca.spottedleaf.leafpile:converter") implementation("org.jline:jline-terminal-ffm:4.4.6") implementation("net.minecrell:terminalconsoleappender:1.3.0") implementation("net.kyori:adventure-text-serializer-ansi") /* Required to add the missing Log4j2Plugins.dat file from log4j-core which has been removed by Mojang. Without it, log4j has to classload all its classes to check if they are plugins. Scanning takes about 1-2 seconds so adding this speeds up the server start. */ implementation("org.apache.logging.log4j:log4j-core:2.26.0") log4jPlugins.annotationProcessorConfigurationName("org.apache.logging.log4j:log4j-core:2.26.0") // Needed to generate meta for our Log4j plugins runtimeOnly(log4jPlugins.output) alsoShade(log4jPlugins.output) implementation("com.velocitypowered:velocity-native:4.1.0") { isTransitive = false } implementation("io.netty:netty-codec-haproxy:4.2.16.Final") // Add support for proxy protocol implementation("org.apache.logging.log4j:log4j-iostreams:2.26.0") implementation("org.ow2.asm:asm-commons:9.9.1") implementation("org.spongepowered:configurate-yaml:4.2.0") // Deps that were previously in the API but have now been moved here for backwards compat, eventually to be removed runtimeOnly("commons-lang:commons-lang:2.6") runtimeOnly("org.xerial:sqlite-jdbc:3.49.1.0") runtimeOnly("com.mysql:mysql-connector-j:9.2.0") runtimeOnly("com.lmax:disruptor:3.4.4") implementation("com.googlecode.json-simple:json-simple:1.1.1") { // change to runtimeOnly once Timings is removed isTransitive = false // includes junit } testImplementation("io.github.classgraph:classgraph:4.8.184") // For mob goal test testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.0.3") testImplementation("org.junit.jupiter:junit-jupiter:6.0.3") testImplementation("org.junit.platform:junit-platform-suite-engine:6.0.3") testImplementation("org.hamcrest:hamcrest:2.2") testImplementation("org.mockito:mockito-core:5.22.0") mockitoAgent("org.mockito:mockito-core:5.22.0") { isTransitive = false } // Configure mockito agent that is needed in newer java versions testImplementation("org.ow2.asm:asm-tree:9.9.1") testImplementation("org.junit-pioneer:junit-pioneer:2.3.0") // CartesianTest // Spark implementation("me.lucko:spark-api:0.1-20240720.200737-2") implementation("me.lucko:spark-paper:1.10.191") } tasks.jar { manifest { val git = Git(rootProject.layout.projectDirectory.path) val mcVersion = rootProject.providers.gradleProperty("mcVersion").get() val buildTime = providers.environmentVariable("BUILD_STARTED_AT").map(Instant::parse).orElse(Instant.EPOCH).get() val buildVersion = project.version.toString() val gitHash = buildVersion.substringAfterLast('-') val gitBranch = runCatching { git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim() }.getOrDefault("unknown") attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "Infstar", "Implementation-Version" to buildVersion, "Implementation-Vendor" to "Infstar", "Specification-Title" to "Infstar", "Specification-Version" to project.version, "Specification-Vendor" to "Infstar", "Brand-Id" to "infstarmc:infstar", "Brand-Name" to "Infstar", "Build-Number" to "", "Build-Time" to buildTime.toString(), "Git-Branch" to gitBranch, "Git-Commit" to gitHash, ) for (tld in setOf("net", "com", "org")) { attributes("$tld/bukkit", "Sealed" to true) } } } // Compile tests with -parameters for better junit parameterized test names tasks.compileTestJava { options.compilerArgs.add("-parameters") } tasks.named(log4jPlugins.compileJavaTaskName) { options.compilerArgs.addAll( listOf( "-Alog4j.graalvm.groupId=${project.group}", "-Alog4j.graalvm.artifactId=${project.name}" ) ) } // Bump compile tasks to 1GB memory to avoid OOMs tasks.withType().configureEach { options.forkOptions.memoryMaximumSize = "1G" } val scanJarForBadCalls = tasks.register("scanJarForBadCalls") { badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;") jarToScan.set(tasks.jar.flatMap { it.archiveFile }) classpath.from(configurations.compileClasspath) } tasks.check { dependsOn(scanJarForBadCalls) } // Use TCA for console improvements tasks.jar { val archiveOperations = services.archiveOperations from(alsoShade.elements.map { it.map { f -> if (f.asFile.isFile) { archiveOperations.zipTree(f.asFile) } else { f.asFile } } }) } tasks.test { include("**/**TestSuite.class") workingDir = temporaryDir useJUnitPlatform { forkEvery = 1 excludeTags("Slow") } // Configure mockito agent that is needed in newer java versions val provider = objects.newInstance() provider.fileCollection.from(mockitoAgent) jvmArgumentProviders.add(provider) // Hides repeated jline/joml warnings due to forking jvmArgs("--enable-native-access=ALL-UNNAMED") systemProperty("joml.nounsafe", true) } tasks.withType().configureEach { extraManifestMainAttributes = mapOf( "Enable-Native-Access" to "ALL-UNNAMED", ) } val generatedDir: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath() idea { module { generatedSourceDirs.add(generatedDir.toFile()) } } sourceSets { main { java { srcDir(generatedDir) } } } fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { group = "runs" mainClass.set("org.bukkit.craftbukkit.Main") standardInput = System.`in` workingDir = rootProject.layout.projectDirectory .dir(providers.gradleProperty("paper.runWorkDir").getOrElse("run")) .asFile javaLauncher.set(project.javaToolchains.launcherFor { languageVersion.set(JavaLanguageVersion.of(25)) // TODO - JB runtime 25 has issues with spark rn // vendor.set(JvmVendorSpec.JETBRAINS) }) jvmArgs(/*"-XX:+AllowEnhancedClassRedefinition", */"--enable-native-access=ALL-UNNAMED") if (rootProject.childProjects["test-plugin"] != null) { val testPluginJar = rootProject.project(":test-plugin").tasks.jar.flatMap { it.archiveFile } inputs.file(testPluginJar) args("-add-plugin=${testPluginJar.get().asFile.absolutePath}") } args("--nogui") systemProperty("net.kyori.adventure.text.warnWhenLegacyFormattingDetected", true) if (providers.gradleProperty("paper.runDisableWatchdog").getOrElse("false") == "true") { systemProperty("disable.watchdog", true) } systemProperty("io.papermc.paper.suppress.sout.nags", true) systemProperty("paper.alwaysPrintWarningState", true) systemProperty("paper.maxChatCommandInputSize", 32767) systemProperty("paper.disableMigrationDelay", true) systemProperty("joml.nounsafe", true) systemProperty("paper.updatingMinecraft", providers.gradleProperty("updatingMinecraft").getOrElse("false").toBoolean()) val memoryGb = providers.gradleProperty("paper.runMemoryGb").getOrElse("2") minHeapSize = "${memoryGb}G" maxHeapSize = "${memoryGb}G" doFirst { workingDir.mkdirs() } block(this) } tasks.registerRunTask("runServer") { description = "Spin up a test server from the Mojang mapped server jar" classpath(tasks.jar) classpath(configurations.runtimeClasspath) } tasks.registerRunTask("runDevServer") { description = "Spin up a test server without assembling a jar" classpath(sourceSets.main.map { it.runtimeClasspath }) } tasks.registerRunTask("runBundler") { description = "Spin up a test server from the Mojang mapped bundler jar" classpath(tasks.createBundlerJar.flatMap { it.outputZip }) mainClass.set(null as String?) } tasks.registerRunTask("runPaperclip") { description = "Spin up a test server from the Mojang mapped Paperclip jar" classpath(tasks.createPaperclipJar.flatMap { it.outputZip }) mainClass.set(null as String?) } fill { project("paper") versionFamily(paperweight.minecraftVersion.map { it.split(".", "-").takeWhile { part -> part.toIntOrNull() != null }.take(2).joinToString(".") }) version(paperweight.minecraftVersion) build { channel = providers.gradleProperty("channel").map { BuildChannel.valueOf(it.uppercase()) } downloads { register("server:default") { file = tasks.createPaperclipJar.flatMap { it.outputZip } nameResolver.set { project, _, version, build -> "$project-$version-$build.jar" } } } } }