2024-04-24 17:48:00 +00:00
import io.papermc.paperweight.PaperweightException
2023-12-06 03:35:33 +00:00
import io.papermc.paperweight.tasks.BaseTask
import io.papermc.paperweight.util.*
2021-12-31 22:28:13 +00:00
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
2023-12-06 03:35:33 +00:00
import java.io.ByteArrayOutputStream
import java.nio.file.Path
2023-12-06 04:46:41 +00:00
import java.util.regex.Pattern
2023-12-06 03:35:33 +00:00
import kotlin.io.path.*
2021-12-30 21:52:30 +00:00
2021-06-11 07:45:34 +00:00
plugins {
java
2021-08-17 22:11:04 +00:00
`maven-publish`
2024-04-26 23:19:59 +00:00
id("io.papermc.paperweight.core") version "1.6.0"
2021-06-11 07:45:34 +00:00
}
2021-08-01 07:55:02 +00:00
allprojects {
2021-06-11 07:45:34 +00:00
apply(plugin = "java")
2021-08-17 22:11:04 +00:00
apply(plugin = "maven-publish")
2021-06-11 07:45:34 +00:00
java {
toolchain {
2024-04-23 17:02:08 +00:00
languageVersion = JavaLanguageVersion.of(21)
2021-06-11 07:45:34 +00:00
}
}
2021-08-01 07:55:02 +00:00
}
2022-05-20 15:12:30 +00:00
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
2022-04-14 02:58:48 +00:00
2021-08-01 07:55:02 +00:00
subprojects {
2021-06-21 15:27:46 +00:00
tasks.withType<JavaCompile> {
options.encoding = Charsets.UTF_8.name()
2024-04-23 17:02:08 +00:00
options.release = 21
2021-06-11 07:45:34 +00:00
}
2021-06-21 15:27:46 +00:00
tasks.withType<Javadoc> {
options.encoding = Charsets.UTF_8.name()
}
tasks.withType<ProcessResources> {
filteringCharset = Charsets.UTF_8.name()
}
2021-12-30 21:52:30 +00:00
tasks.withType<Test> {
testLogging {
showStackTraces = true
exceptionFormat = TestExceptionFormat.FULL
events(TestLogEvent.STANDARD_OUT)
}
}
2021-06-11 07:45:34 +00:00
repositories {
mavenCentral()
2022-04-14 02:58:48 +00:00
maven(paperMavenPublicUrl)
2024-04-25 00:46:57 +00:00
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // TODO - Adventure snapshot
2021-06-11 07:45:34 +00:00
}
}
2022-04-07 16:36:19 +00:00
val spigotDecompiler: Configuration by configurations.creating
2021-06-11 07:45:34 +00:00
repositories {
2021-06-13 03:18:50 +00:00
mavenCentral()
2022-04-14 02:58:48 +00:00
maven(paperMavenPublicUrl) {
2022-04-07 16:36:19 +00:00
content {
onlyForConfigurations(
configurations.paperclip.name,
spigotDecompiler.name,
)
}
2021-06-11 07:45:34 +00:00
}
}
dependencies {
2024-04-23 17:02:08 +00:00
paramMappings("net.fabricmc:yarn:1.20.5+build.1:mergedv2")
2024-03-07 18:11:47 +00:00
remapper("net.fabricmc:tiny-remapper:0.10.1:fat")
2024-04-16 19:44:59 +00:00
decompiler("org.vineflower:vineflower:1.10.1")
2024-04-26 18:42:17 +00:00
spigotDecompiler("io.papermc:patched-spigot-fernflower:0.1+build.13")
2023-03-20 05:18:33 +00:00
paperclip("io.papermc:paperclip:3.0.3")
2021-06-11 07:45:34 +00:00
}
paperweight {
2023-12-06 18:48:37 +00:00
minecraftVersion = providers.gradleProperty("mcVersion")
serverProject = project(":paper-server")
2021-06-11 07:45:34 +00:00
2023-12-06 18:48:37 +00:00
paramMappingsRepo = paperMavenPublicUrl
remapRepo = paperMavenPublicUrl
2024-04-16 19:44:59 +00:00
decompileRepo = paperMavenPublicUrl
2021-11-05 00:23:06 +00:00
2022-04-07 16:36:19 +00:00
craftBukkit {
2023-12-06 18:48:37 +00:00
fernFlowerJar = layout.file(spigotDecompiler.elements.map { it.single().asFile })
2022-04-07 16:36:19 +00:00
}
2021-06-11 07:45:34 +00:00
paper {
2023-12-06 18:48:37 +00:00
spigotApiPatchDir = layout.projectDirectory.dir("patches/api")
spigotServerPatchDir = layout.projectDirectory.dir("patches/server")
2021-06-11 12:02:28 +00:00
2023-12-06 18:48:37 +00:00
mappingsPatch = layout.projectDirectory.file("build-data/mappings-patch.tiny")
reobfMappingsPatch = layout.projectDirectory.file("build-data/reobf-mappings-patch.tiny")
2021-06-11 07:45:34 +00:00
2021-06-27 03:11:45 +00:00
reobfPackagesToFix.addAll(
"co.aikar.timings",
"com.destroystokyo.paper",
"com.mojang",
"io.papermc.paper",
2021-12-02 07:21:14 +00:00
"ca.spottedleaf",
2021-06-27 03:11:45 +00:00
"net.kyori.adventure.bossbar",
"net.minecraft",
"org.bukkit.craftbukkit",
2021-12-02 07:21:14 +00:00
"org.spigotmc",
2021-06-27 03:11:45 +00:00
)
2021-06-11 07:45:34 +00:00
}
}
2021-06-18 23:38:26 +00:00
2021-08-17 22:11:04 +00:00
tasks.generateDevelopmentBundle {
2023-12-06 18:48:37 +00:00
apiCoordinates = "io.papermc.paper:paper-api"
mojangApiCoordinates = "io.papermc.paper:paper-mojangapi"
2021-11-05 00:23:06 +00:00
libraryRepositories.addAll(
"https://repo.maven.apache.org/maven2/",
2022-04-22 02:27:56 +00:00
paperMavenPublicUrl,
2024-04-25 00:46:57 +00:00
"https://s01.oss.sonatype.org/content/repositories/snapshots/", // TODO - Adventure snapshot
2021-08-17 22:11:04 +00:00
)
}
publishing {
2022-02-21 20:44:17 +00:00
if (project.providers.gradleProperty("publishDevBundle").isPresent) {
2021-08-17 22:11:04 +00:00
publications.create<MavenPublication>("devBundle") {
artifact(tasks.generateDevelopmentBundle) {
artifactId = "dev-bundle"
}
}
}
}
allprojects {
publishing {
repositories {
2022-05-20 15:12:30 +00:00
maven("https://repo.papermc.io/repository/maven-snapshots/") {
2021-08-17 22:11:04 +00:00
name = "paperSnapshots"
credentials(PasswordCredentials::class)
}
}
}
}
2021-06-18 23:38:26 +00:00
tasks.register("printMinecraftVersion") {
doLast {
2021-06-20 07:47:14 +00:00
println(providers.gradleProperty("mcVersion").get().trim())
2021-06-18 23:38:26 +00:00
}
}
2022-03-04 09:41:03 +00:00
tasks.register("printPaperVersion") {
doLast {
println(project.version)
}
}
2023-12-06 03:35:33 +00:00
// see gradle.properties
if (providers.gradleProperty("updatingMinecraft").getOrElse("false").toBoolean()) {
tasks.collectAtsFromPatches {
2023-12-06 18:48:37 +00:00
val dir = layout.projectDirectory.dir("patches/unapplied/server")
if (dir.path.isDirectory()) {
extraPatchDir = dir
}
2023-12-06 03:35:33 +00:00
}
tasks.withType<io.papermc.paperweight.tasks.RebuildGitPatches>().configureEach {
2023-12-06 18:48:37 +00:00
filterPatches = false
2023-12-06 03:35:33 +00:00
}
tasks.register("continueServerUpdate", RebasePatches::class) {
2023-12-06 04:59:31 +00:00
description = "Moves the next X patches from unapplied to applied, and applies them. X being the number of patches that apply cleanly, plus the terminal failure if any."
2023-12-06 03:35:33 +00:00
projectDir = project.projectDir
appliedPatches = file("patches/server")
unappliedPatches = file("patches/unapplied/server")
2023-12-06 18:48:37 +00:00
applyTaskName = "applyServerPatches"
2024-04-23 18:44:28 +00:00
patchedDir = "Paper-Server"
2023-12-06 03:35:33 +00:00
}
}
@UntrackedTask(because = "Does not make sense to track state")
abstract class RebasePatches : BaseTask() {
@get:Internal
abstract val projectDir: DirectoryProperty
@get:InputFiles
abstract val appliedPatches: DirectoryProperty
@get:InputFiles
abstract val unappliedPatches: DirectoryProperty
2023-12-06 18:48:37 +00:00
@get:Input
abstract val applyTaskName: Property<String>
2024-04-23 18:44:28 +00:00
@get:Input
abstract val patchedDir: Property<String>
2023-12-06 03:35:33 +00:00
private fun unapplied(): List<Path> =
unappliedPatches.path.listDirectoryEntries("*.patch").sortedBy { it.name }
2023-12-06 04:46:41 +00:00
private fun appliedLoc(patch: Path): Path = appliedPatches.path.resolve(unappliedPatches.path.relativize(patch))
companion object {
val regex = Pattern.compile("Patch failed at ([0-9]{4}) (.*)")
2024-04-23 21:26:28 +00:00
val continuationRegex = Pattern.compile("^\\s{1}.+\$")
2023-12-06 04:46:41 +00:00
const val subjectPrefix = "Subject: [PATCH] "
}
2023-12-06 03:35:33 +00:00
@TaskAction
fun run() {
2024-04-24 17:48:00 +00:00
val patchedDirPath = projectDir.path.resolve(patchedDir.get())
if (patchedDirPath.isDirectory()) {
val status = Git(patchedDirPath)("status").getText()
if (status.contains("You are in the middle of an am session.")) {
throw PaperweightException("Cannot continue update when $patchedDirPath is in the middle of an am session.")
}
}
2023-12-06 04:46:41 +00:00
val unapplied = unapplied()
for (patch in unapplied) {
patch.copyTo(appliedLoc(patch))
}
2023-12-06 03:35:33 +00:00
2023-12-06 04:46:41 +00:00
val out = ByteArrayOutputStream()
val proc = ProcessBuilder()
.directory(projectDir.path)
2023-12-06 18:48:37 +00:00
.command("./gradlew", applyTaskName.get())
2023-12-06 04:46:41 +00:00
.redirectErrorStream(true)
.start()
2023-12-06 22:32:08 +00:00
val f = redirect(proc.inputStream, out)
2023-12-06 04:46:41 +00:00
val exit = proc.waitFor()
2023-12-06 22:32:08 +00:00
f.get()
2023-12-06 04:46:41 +00:00
if (exit != 0) {
val outStr = String(out.toByteArray())
val matcher = regex.matcher(outStr)
if (!matcher.find()) error("Could not determine failure point")
val failedSubjectFragment = matcher.group(2)
val failed = unapplied.single { p ->
p.useLines { lines ->
2024-04-23 21:26:28 +00:00
val collect = mutableListOf<String>()
for (line in lines) {
if (line.startsWith(subjectPrefix)) {
collect += line
} else if (collect.size == 1) {
if (continuationRegex.matcher(line).matches()) {
collect += line
} else {
break
}
}
}
val subjectLine = collect.joinToString("").substringAfter(subjectPrefix)
2023-12-06 04:46:41 +00:00
subjectLine.startsWith(failedSubjectFragment)
}
}
// delete successful & failure point from unapplied patches dir
for (path in unapplied) {
path.deleteIfExists()
if (path == failed) {
break
}
}
2023-12-06 03:35:33 +00:00
2023-12-06 04:46:41 +00:00
// delete failed from patches dir
var started = false
for (path in unapplied) {
if (path == failed) {
started = true
continue
}
if (started) {
appliedLoc(path).deleteIfExists()
}
}
2024-04-23 18:44:28 +00:00
// Delete the build file before resetting the AM session in case it has compilation errors
2024-04-24 17:48:00 +00:00
patchedDirPath.resolve("build.gradle.kts").deleteIfExists()
2023-12-06 04:46:41 +00:00
// Apply again to reset the am session (so it ends on the failed patch, to allow us to rebuild after fixing it)
val apply2 = ProcessBuilder()
2023-12-06 03:35:33 +00:00
.directory(projectDir.path)
2023-12-06 18:48:37 +00:00
.command("./gradlew", applyTaskName.get())
2023-12-06 03:35:33 +00:00
.redirectErrorStream(true)
.start()
2023-12-06 22:32:08 +00:00
val f1 = redirect(apply2.inputStream, System.out)
2023-12-06 20:24:41 +00:00
apply2.waitFor()
2023-12-06 22:32:08 +00:00
f1.get()
2023-12-06 03:35:33 +00:00
2023-12-06 04:46:41 +00:00
logger.lifecycle(outStr)
logger.lifecycle("Patch failed at $failed; See Git output above.")
} else {
unapplied.forEach { it.deleteIfExists() }
logger.lifecycle("All patches applied!")
2023-12-06 03:35:33 +00:00
}
2023-12-06 04:46:41 +00:00
val git = Git(projectDir.path)
git("add", appliedPatches.path.toString() + "/*").runSilently()
git("add", unappliedPatches.path.toString() + "/*").runSilently()
2023-12-06 03:35:33 +00:00
}
}