diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 0000000000..4076969c7f --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,31 @@ +plugins { + `kotlin-dsl` +} + +repositories { + gradlePluginPortal() + maven { + name = "EngineHub Repository" + url = uri("https://maven.enginehub.org/repo/") + } +} + +dependencies { + implementation(gradleApi()) + implementation(libs.grgit) + implementation(libs.shadow) + implementation(libs.paperweight) + + constraints { + val asmVersion = "[${libs.versions.minimumAsm.get()},)" + implementation("org.ow2.asm:asm:$asmVersion") { + because("Need Java 21 support in shadow") + } + implementation("org.ow2.asm:asm-commons:$asmVersion") { + because("Need Java 21 support in shadow") + } + implementation("org.vafer:jdependency:[${libs.versions.minimumJdependency.get()},)") { + because("Need Java 21 support in shadow") + } + } +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000000..aa5e146f1c --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,9 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" diff --git a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts new file mode 100644 index 0000000000..4fe0aa6b45 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts @@ -0,0 +1,61 @@ +import buildlogic.getVersion +import buildlogic.stringyLibs + +plugins { + `java-library` + id("buildlogic.common") + id("buildlogic.common-java") + id("io.papermc.paperweight.userdev") +} + +paperweight { + injectPaperRepository = false + reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTION +} + +repositories { + maven { + name = "PaperMC" + url = uri("https://repo.papermc.io/repository/maven-public/") + content { + excludeModule("io.papermc.paper", "dev-bundle") + } + } + maven { + name = "EngineHub Repository" + url = uri("https://maven.enginehub.org/repo/") + content { + excludeModule("io.papermc.paper", "dev-bundle") + } + } + maven { + name = "IntellectualSites" + url = uri("https://repo.intellectualsites.dev/repository/paper-dev-bundles/") + content { + includeModule("io.papermc.paper", "dev-bundle") + } + } + mavenCentral() + afterEvaluate { + killNonEngineHubRepositories() + } +} + +dependencies { + implementation(project(":worldedit-bukkit")) + constraints { + //Reduces the amount of libraries Gradle and IntelliJ need to resolve + implementation("net.kyori:adventure-bom") { + version { strictly(stringyLibs.getVersion("adventure").strictVersion) } + because("Ensure a consistent version of adventure is used.") + } + } +} + +tasks.named("assemble") { + dependsOn("reobfJar") +} + +tasks.named("javadoc") { + enabled = false +} diff --git a/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts b/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts new file mode 100644 index 0000000000..1d92782248 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts @@ -0,0 +1,71 @@ +import buildlogic.stringyLibs +import buildlogic.getLibrary + +plugins { + id("eclipse") + id("idea") + id("buildlogic.common") +} + +tasks + .withType() + .matching { it.name == "compileJava" || it.name == "compileTestJava" } + .configureEach { + // TODO: re-enable this-escape when ANTLR suppresses it properly + val disabledLint = listOf( + "processing", "path", "fallthrough", "serial", "overloads", "this-escape", + ) + options.release.set(21) + options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) + options.isDeprecation = true + options.encoding = "UTF-8" + options.compilerArgs.add("-parameters") + options.compilerArgs.add("--add-modules=jdk.incubator.vector") + } + +tasks.withType().configureEach { + useJUnitPlatform { + includeEngines("junit-jupiter", "jqwik") + } +} + +dependencies { + "compileOnly"(stringyLibs.getLibrary("jsr305")) + "testImplementation"(platform(stringyLibs.getLibrary("junit-bom"))) + "testImplementation"(stringyLibs.getLibrary("junit-jupiter-api")) + "testImplementation"(stringyLibs.getLibrary("junit-jupiter-params")) + "testImplementation"(stringyLibs.getLibrary("jqwik")) + "testImplementation"(platform(stringyLibs.getLibrary("mockito-bom"))) + "testImplementation"(stringyLibs.getLibrary("mockito-core")) + "testImplementation"(stringyLibs.getLibrary("mockito-junit-jupiter")) + "testRuntimeOnly"(stringyLibs.getLibrary("junit-jupiter-engine")) + "testRuntimeOnly"(stringyLibs.getLibrary("junit-platform-launcher")) +} + +// Java 8 turns on doclint which we fail +tasks.withType().configureEach { + options.encoding = "UTF-8" + (options as StandardJavadocDocletOptions).apply { + addStringOption("Xdoclint:none", "-quiet") + addStringOption("-add-modules", "jdk.incubator.vector") + addBooleanOption("Xdoclint:-missing", true) + tags( + "apiNote:a:API Note:", + "implSpec:a:Implementation Requirements:", + "implNote:a:Implementation Note:" + ) + links( + "https://jd.advntr.dev/api/latest/", + "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", + "https://www.antlr.org/api/Java/", + "https://jd.papermc.io/paper/1.21.10/", + "https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/" + ) + docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}" + } +} + +configure { + withJavadocJar() + withSourcesJar() +} diff --git a/build-logic/src/main/kotlin/buildlogic.common.gradle.kts b/build-logic/src/main/kotlin/buildlogic.common.gradle.kts new file mode 100644 index 0000000000..227ec60d08 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.common.gradle.kts @@ -0,0 +1,54 @@ +import buildlogic.getLibrary +import buildlogic.stringyLibs +import org.gradle.plugins.ide.idea.model.IdeaModel + +group = rootProject.group +version = rootProject.version + +configurations.all { + resolutionStrategy { + cacheChangingModulesFor(1, TimeUnit.DAYS) + } +} + +plugins.withId("java") { + the().toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +dependencies { + for (conf in listOf("implementation", "api")) { + if (!configurations.names.contains(conf)) { + continue + } + add(conf, platform(stringyLibs.getLibrary("log4j-bom")).map { + val dep = create(it) + dep.because("Mojang provides Log4j") + dep + }) + constraints { + add(conf, stringyLibs.getLibrary("guava")) { + version { require("33.3.1-jre") } + because("Mojang provides Guava") + } + add(conf, stringyLibs.getLibrary("gson")) { + version { require("2.11.0") } + because("Mojang provides Gson") + } + add(conf, stringyLibs.getLibrary("fastutil")) { + version { require("8.5.15") } + because("Mojang provides FastUtil") + } + } + } +} + +plugins.withId("idea") { + configure { + module { + isDownloadSources = true + isDownloadJavadoc = true + } + } +} diff --git a/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts b/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts new file mode 100644 index 0000000000..fcc6e691c2 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts @@ -0,0 +1,87 @@ +plugins { + id("java") + id("maven-publish") + id("buildlogic.common-java") + id("signing") +} + +ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}" + +val publishingExtension = the() + +configure { + if (!version.toString().endsWith("-SNAPSHOT")) { + val signingKey: String? by project + val signingPassword: String? by project + useInMemoryPgpKeys(signingKey, signingPassword) + isRequired + sign(publishingExtension.publications) + } +} + +publishing { + publications { + register("maven") { + afterEvaluate { + versionMapping { + usage("java-api") { + fromResolutionOf("runtimeClasspath") + } + usage("java-runtime") { + fromResolutionResult() + } + } + group = "com.fastasyncworldedit" + artifactId = "${rootProject.name}-${project.description}" + version = "$version" + pom { + name.set("${rootProject.name}-${project.description}" + " " + project.version) + description.set("Blazingly fast Minecraft world manipulation for artists, builders and everyone else.") + url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") + + licenses { + license { + name.set("GNU General Public License, Version 3.0") + url.set("https://www.gnu.org/licenses/gpl-3.0.html") + distribution.set("repo") + } + } + + developers { + developer { + id.set("NotMyFault") + name.set("Alexander Brandes") + email.set("contact(at)notmyfault.dev") + organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") + } + developer { + id.set("SirYwell") + name.set("Hannes Greule") + organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") + } + developer { + id.set("dordsor21") + name.set("dordsor21") + organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") + } + } + + scm { + url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") + connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") + developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") + tag.set("${project.version}") + } + + issueManagement { + system.set("GitHub") + url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit/issues") + } + } + } + } + } +} diff --git a/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts b/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts new file mode 100644 index 0000000000..620ef44be7 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts @@ -0,0 +1,280 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.tasks.bundling.Jar +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.provideDelegate +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.the +import org.gradle.plugins.signing.SigningExtension + +plugins { + id("java-base") + id("maven-publish") + id("com.gradleup.shadow") + id("buildlogic.common") + id("signing") +} + +// A horrible hack because `softwareComponentFactory` has to be gotten via plugin +// gradle why +internal open class LibsConfigPluginHack @Inject constructor( + private val softwareComponentFactory: SoftwareComponentFactory +) : Plugin { + override fun apply(project: Project) { + val libsComponents = softwareComponentFactory.adhoc("libs") + project.components.add(libsComponents) + } +} + +configurations { + create("shade") +} + +group = "${rootProject.group}.worldedit-libs" + +val relocations = mapOf( + "net.kyori.text" to "com.sk89q.worldedit.util.formatting.text", + "net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori", +) + +tasks.register("jar") { + configurations = listOf(project.configurations["shade"]) + archiveClassifier.set("") + + // Yeet module-info's + exclude("module-info.class") + + dependencies { + exclude(dependency("com.google.guava:guava")) + exclude(dependency("com.google.code.gson:gson")) + exclude(dependency("com.google.errorprone:error_prone_annotations")) + exclude(dependency("com.google.guava:failureaccess")) + exclude(dependency("org.checkerframework:checker-qual")) + exclude(dependency("org.jetbrains:annotations")) + exclude(dependency("org.apache.logging.log4j:log4j-api")) + exclude(dependency("com.google.code.findbugs:jsr305")) + exclude { + it.moduleGroup == "org.jetbrains.kotlin" + } + } + + relocations.forEach { (from, to) -> + relocate(from, to) + } +} +val altConfigFiles = { artifactType: String -> + val deps = configurations["shade"].incoming.dependencies + .filterIsInstance() + .map { it.copy() } + .map { dependency -> + val category = dependency.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE)?.name + if (category == Category.REGULAR_PLATFORM || category == Category.ENFORCED_PLATFORM) { + return@map dependency + } + try { + dependency.artifact { + name = dependency.name + type = artifactType + extension = "jar" + classifier = artifactType + } + } catch (e: Exception) { + throw RuntimeException("Failed to add artifact to dependency: $dependency", e) + } + dependency + } + + files(configurations.detachedConfiguration(*deps.toTypedArray()) + .resolvedConfiguration.lenientConfiguration.artifacts + .filter { it.classifier == artifactType } + .map { zipTree(it.file) }) +} +tasks.register("sourcesJar") { + from({ + altConfigFiles("sources") + }) + + // Yeet module-info's + exclude("module-info.java") + + relocations.forEach { (from, to) -> + val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)") + val textPattern = Regex.fromLiteral(from) + eachFile { + filter { + it.replaceFirst(textPattern, to) + } + path = path.replaceFirst(filePattern, "$1${to.replace('.', '/')}$2") + } + } + archiveClassifier.set("sources") +} + +// This a dummy jar to comply with the requirements of the OSSRH, +// libs are not API and therefore no "proper" javadoc jar is necessary +tasks.register("javadocJar") { + archiveClassifier.set("javadoc") +} + +tasks.named("assemble").configure { + dependsOn(tasks.named("jar")) + dependsOn(tasks.named("sourcesJar")) + dependsOn(tasks.named("javadocJar")) +} + +project.apply() + +val libsComponent = project.components["libs"] as AdhocComponentWithVariants + +val apiElements = project.configurations.register("apiElements") { + isVisible = false + description = "API elements for libs" + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) + attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) + attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) + } + outgoing.artifact(tasks.named("jar")) +} + +val runtimeElements = project.configurations.register("runtimeElements") { + isVisible = false + description = "Runtime elements for libs" + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME)) + attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) + attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) + attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) + } + outgoing.artifact(tasks.named("jar")) +} + +val sourcesElements = project.configurations.register("sourcesElements") { + isVisible = false + description = "Source elements for libs" + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME)) + attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION)) + attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) + attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES)) + } + outgoing.artifact(tasks.named("sourcesJar")) +} + +val javadocElements = project.configurations.register("javadocElements") { + isVisible = false + description = "Javadoc elements for libs" + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME)) + attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION)) + attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) + attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.JAVADOC)) + } + outgoing.artifact(tasks.named("javadocJar")) +} + +libsComponent.addVariantsFromConfiguration(apiElements.get()) { + mapToMavenScope("compile") +} + +libsComponent.addVariantsFromConfiguration(runtimeElements.get()) { + mapToMavenScope("runtime") +} + +libsComponent.addVariantsFromConfiguration(sourcesElements.get()) { + mapToMavenScope("runtime") +} + +libsComponent.addVariantsFromConfiguration(javadocElements.get()) { + mapToMavenScope("runtime") +} + +val publishingExtension = the() + +configure { + if (!version.toString().endsWith("-SNAPSHOT")) { + val signingKey: String? by project + val signingPassword: String? by project + useInMemoryPgpKeys(signingKey, signingPassword) + isRequired + sign(publishingExtension.publications) + } +} + +configure { + publications { + register("maven") { + from(libsComponent) + + group = "com.fastasyncworldedit" + artifactId = "FastAsyncWorldEdit-Libs-${project.name.replaceFirstChar(Char::titlecase)}" + version = "$version" + + pom { + name.set("${rootProject.name}-Libs" + " " + project.version) + description.set("Blazingly fast Minecraft world manipulation for artists, builders and everyone else.") + url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") + + licenses { + license { + name.set("GNU General Public License, Version 3.0") + url.set("https://www.gnu.org/licenses/gpl-3.0.html") + distribution.set("repo") + } + } + + developers { + developer { + id.set("NotMyFault") + name.set("Alexander Brandes") + email.set("contact(at)notmyfault.dev") + organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") + } + developer { + id.set("SirYwell") + name.set("Hannes Greule") + organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") + } + developer { + id.set("dordsor21") + name.set("dordsor21") + organization.set("IntellectualSites") + organizationUrl.set("https://github.com/IntellectualSites") + } + } + + scm { + url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") + connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") + developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") + tag.set("${project.version}") + } + + issueManagement { + system.set("GitHub") + url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit/issues") + } + } + + } + } +} + +if (project != project(":worldedit-libs:core")) { + evaluationDependsOn(":worldedit-libs:core") + configurations["shade"].shouldResolveConsistentlyWith(project(":worldedit-libs:core").configurations["shade"]) +} diff --git a/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts b/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts new file mode 100644 index 0000000000..0856762ef5 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts @@ -0,0 +1,62 @@ +import buildlogic.getLibrary +import buildlogic.stringyLibs +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + id("com.gradleup.shadow") + id("buildlogic.core-and-platform") +} + +val platform = extensions.create("platform") +platform.includeClasspath.convention(false) +platform.extraAttributes.convention(mapOf()) + +tasks.named("shadowJar") { + archiveClassifier.set("dist") + relocate("com.sk89q.jchronic", "com.sk89q.worldedit.jchronic") + val jchronic = stringyLibs.getLibrary("jchronic").get() + dependencies { + include(project(":worldedit-libs:core")) + include(project(":worldedit-libs:${project.name.replace("worldedit-", "")}")) + include(project(":worldedit-core")) + include(dependency(jchronic)) + exclude(dependency("com.google.code.findbugs:jsr305")) + } + exclude("GradleStart**") + exclude(".cache") + exclude("LICENSE*") + exclude("META-INF/maven/**") + minimize { + // jchronic + lz4-java uses reflection to load things, so we need to exclude it from minimizing + exclude(dependency(jchronic)) + exclude(dependency(stringyLibs.getLibrary("lz4Java").get())) + } +} +val javaComponent = components["java"] as AdhocComponentWithVariants +// I don't think we want this published (it's the shadow jar) +javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) { + skip() +} + +tasks.named("jar") { + val kind = platform.kind.get() + val includeClasspath = platform.includeClasspath.get() + val extraAttributes = platform.extraAttributes.get() + + val version = project(":worldedit-core").version + inputs.property("version", version) + val attributes = mutableMapOf( + "Implementation-Version" to version, + "WorldEdit-Version" to version, + "WorldEdit-Kind" to kind.name, + "Main-Class" to kind.mainClass + ) + if (includeClasspath) { + attributes["Class-Path"] = listOf("truezip", "truevfs", "js") + .map { "$it.jar" } + .flatMap { listOf(it, "WorldEdit/$it", "../$it", "../WorldEdit/$it") } + .joinToString(separator = " ") + } + attributes.putAll(extraAttributes) + manifest.attributes(attributes) +} diff --git a/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt b/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt new file mode 100644 index 0000000000..77b0059dbc --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt @@ -0,0 +1,30 @@ +package buildlogic + +import org.gradle.api.Project +import org.gradle.api.artifacts.MinimalExternalModuleDependency +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.artifacts.VersionConstraint +import org.gradle.api.plugins.ExtraPropertiesExtension +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.the + +val Project.ext: ExtraPropertiesExtension + get() = extensions.getByType() + +val Project.sourceSets: SourceSetContainer + get() = the().sourceSets + +val Project.stringyLibs: VersionCatalog + get() = extensions.getByType().named("libs") + +fun VersionCatalog.getLibrary(name: String): Provider = findLibrary(name).orElseThrow { + error("Library $name not found in version catalog") +} + +fun VersionCatalog.getVersion(name: String): VersionConstraint = findVersion(name).orElseThrow { + error("Version $name not found in version catalog") +} diff --git a/build-logic/src/main/kotlin/buildlogic/PlatformExtension.kt b/build-logic/src/main/kotlin/buildlogic/PlatformExtension.kt new file mode 100644 index 0000000000..d27a3e4955 --- /dev/null +++ b/build-logic/src/main/kotlin/buildlogic/PlatformExtension.kt @@ -0,0 +1,19 @@ +package buildlogic + +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property + +interface PlatformExtension { + val kind: Property + val includeClasspath: Property + val extraAttributes: MapProperty +} + +sealed class WorldEditKind( + val name: String, + val mainClass: String = "com.sk89q.worldedit.internal.util.InfoEntryPoint" +) { + class Standalone(mainClass: String) : WorldEditKind("STANDALONE", mainClass) + object Mod : WorldEditKind("MOD") + object Plugin : WorldEditKind("PLUGIN") +} diff --git a/build-logic/src/main/kotlin/repositoriesHelper.kt b/build-logic/src/main/kotlin/repositoriesHelper.kt new file mode 100644 index 0000000000..11d5c008c2 --- /dev/null +++ b/build-logic/src/main/kotlin/repositoriesHelper.kt @@ -0,0 +1,38 @@ +import org.gradle.api.artifacts.dsl.RepositoryHandler +import org.gradle.api.artifacts.repositories.MavenArtifactRepository +import org.gradle.api.logging.Logging + +// The primary point of this is repository up-time. We replace most other repositories with EngineHub's repository. +// This is because we have stronger up-time guarantees for our repository. However, Maven Central and Sonatype are +// clearly even better, so we allow those as well. We also allow Gradle's plugin repository. +private val ALLOWED_PREFIXES = listOf( + "https://repo.intellectualsites.dev", + "https://maven.enginehub.org", + "https://repo.maven.apache.org/maven2/", + "https://s01.oss.sonatype.org/content/repositories/snapshots/", + "https://plugins.gradle.org", + "file:" +) +private val LOGGER = Logging.getLogger("repositoriesHelper") + +fun RepositoryHandler.killNonEngineHubRepositories() { + val toRemove = mutableListOf() + for (repo in this) { + if (repo is MavenArtifactRepository && !ALLOWED_PREFIXES.any { repo.url.toString().startsWith(it) }) { + LOGGER.info("Removing non-EngineHub repository: {}", repo.url) + toRemove.add(repo) + } + } + toRemove.forEach { remove(it) } +} + +fun RepositoryHandler.verifyEngineHubRepositories() { + for (repo in this) { + if (repo is MavenArtifactRepository) { + val urlString = repo.url.toString() + check(ALLOWED_PREFIXES.any { urlString.startsWith(it) }) { + "Only EngineHub/Central repositories are allowed: ${repo.url} found" + } + } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 1a69f66f94..6c2612425a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,40 +1,18 @@ import org.ajoberstar.grgit.Grgit import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED -import java.net.URI import java.time.format.DateTimeFormatter import xyz.jpenilla.runpaper.task.RunServer plugins { - id("io.github.gradle-nexus.publish-plugin") version "2.0.0" - id("xyz.jpenilla.run-paper") version "2.3.1" + alias(libs.plugins.codecov) + jacoco + id("buildlogic.common") + id("com.gradleup.nmcp.aggregation") version "1.2.0" + id("xyz.jpenilla.run-paper") version "3.0.2" } -if (!File("$rootDir/.git").exists()) { - logger.lifecycle(""" - ************************************************************************************** - You need to fork and clone this repository! Don't download a .zip file. - If you need assistance, consult the GitHub docs: https://docs.github.com/get-started/quickstart/fork-a-repo - ************************************************************************************** - """.trimIndent() - ).also { kotlin.system.exitProcess(1) } -} - -logger.lifecycle(""" -******************************************* - You are building FastAsyncWorldEdit! - - If you encounter trouble: - 1) Read COMPILING.adoc if you haven't yet - 2) Try running 'build' in a separate Gradle run - 3) Use gradlew and not gradle - 4) If you still need help, ask on Discord! https://discord.gg/intellectualsites - - Output files will be in [subproject]/build/libs -******************************************* -""") - -var rootVersion by extra("2.13.0") +var rootVersion by extra("2.14.1") var snapshot by extra("SNAPSHOT") var revision: String by extra("") var buildNumber by extra("") @@ -52,7 +30,7 @@ ext { } } -version = String.format("%s", rootVersion) +version = String.format("%s-%s", rootVersion, buildNumber) if (!project.hasProperty("gitCommitHash")) { apply(plugin = "org.ajoberstar.grgit") @@ -65,12 +43,47 @@ if (!project.hasProperty("gitCommitHash")) { } } +val totalReport = tasks.register("jacocoTotalReport") { + for (proj in subprojects) { + proj.apply(plugin = "jacoco") + proj.plugins.withId("java") { + executionData( + fileTree(proj.layout.buildDirectory).include("**/jacoco/*.exec") + ) + sourceSets(proj.the().sourceSets["main"]) + reports { + xml.required.set(true) + xml.outputLocation.set(rootProject.layout.buildDirectory.file("reports/jacoco/report.xml")) + html.required.set(true) + } + dependsOn(proj.tasks.named("test")) + } + } +} +afterEvaluate { + totalReport.configure { + classDirectories.setFrom(classDirectories.files.map { + fileTree(it).apply { + exclude("**/*AutoValue_*") + exclude("**/*Registration.*") + } + }) + } +} + +codecov { + reportTask.set(totalReport) +} + allprojects { gradle.projectsEvaluated { - tasks.withType(JavaCompile::class) { + tasks.withType().configureEach { + options.compilerArgs.addAll(listOf("--add-modules", "jdk.incubator.vector")) options.compilerArgs.addAll(arrayOf("-Xmaxerrs", "1000")) } - tasks.withType(Test::class) { + tasks.withType().configureEach { + jvmArgs("--add-modules", "jdk.incubator.vector") + maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1 testLogging { events(FAILED) exceptionFormat = FULL @@ -79,11 +92,13 @@ allprojects { showStackTraces = true } } + tasks.withType().configureEach { + jvmArgs("--add-modules", "jdk.incubator.vector") + } } } -applyCommonConfiguration() -val supportedVersions = listOf("1.20.4", "1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.3", "1.21.4") +val supportedVersions: List = listOf("1.20.4", "1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.3", "1.21.4") tasks { supportedVersions.forEach { @@ -96,19 +111,21 @@ tasks { runDirectory.set(file("run-$it")) } } - runServer { - minecraftVersion("1.21.3") + runServer { + minecraftVersion(supportedVersions.last()) pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) + jvmArgs("-Dcom.mojang.eula.agree=true") } } -nexusPublishing { - this.repositories { - sonatype { - nexusUrl.set(URI.create("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - } +nmcpAggregation { + centralPortal { + publishingType = "AUTOMATIC" + username = providers.gradleProperty("mavenCentralUsername") + password = providers.gradleProperty("mavenCentralPassword") } + + publishAllProjectsProbablyBreakingProjectIsolation() } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index 02aa1e66f1..0000000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,46 +0,0 @@ -import java.util.Properties - -plugins { - `kotlin-dsl` - kotlin("jvm") version embeddedKotlinVersion -} - -repositories { - mavenCentral() - gradlePluginPortal() - maven { - name = "EngineHub" - url = uri("https://maven.enginehub.org/repo/") - } -} - -val properties = Properties().also { props -> - project.projectDir.resolveSibling("gradle.properties").bufferedReader().use { - props.load(it) - } -} - -dependencies { - implementation(gradleApi()) - implementation("org.ajoberstar.grgit:grgit-gradle:5.3.0") - implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.6") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.7") - constraints { - val asmVersion = "[9.7,)" - implementation("org.ow2.asm:asm:$asmVersion") { - because("Need Java 21 support in shadow") - } - implementation("org.ow2.asm:asm-commons:$asmVersion") { - because("Need Java 21 support in shadow") - } - implementation("org.vafer:jdependency:[2.10,)") { - because("Need Java 21 support in shadow") - } - } -} - -kotlin { - jvmToolchain { - (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(21)) - } -} diff --git a/buildSrc/src/main/kotlin/AdapterConfig.kt b/buildSrc/src/main/kotlin/AdapterConfig.kt deleted file mode 100644 index 1d141621bb..0000000000 --- a/buildSrc/src/main/kotlin/AdapterConfig.kt +++ /dev/null @@ -1,27 +0,0 @@ -import org.gradle.api.Project -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.dependencies - -// For specific version pinning, see -// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ -fun Project.applyPaperweightAdapterConfiguration() { - applyCommonConfiguration() - apply(plugin = "java-library") - applyCommonJavaConfiguration( - sourcesJar = true, - banSlf4j = false, - ) - apply(plugin = "io.papermc.paperweight.userdev") - - dependencies { - "implementation"(project(":worldedit-bukkit")) - } - - tasks.named("assemble") { - dependsOn("reobfJar") - } - - tasks.named("javadoc") { - enabled = false - } -} diff --git a/buildSrc/src/main/kotlin/CommonConfig.kt b/buildSrc/src/main/kotlin/CommonConfig.kt deleted file mode 100644 index e8fd3db87e..0000000000 --- a/buildSrc/src/main/kotlin/CommonConfig.kt +++ /dev/null @@ -1,62 +0,0 @@ -import org.gradle.api.Project -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.jvm.toolchain.JavaLanguageVersion -import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.repositories -import org.gradle.kotlin.dsl.the - -fun Project.applyCommonConfiguration() { - group = rootProject.group - version = rootProject.version - - repositories { - mavenCentral() - maven { - name = "EngineHub" - url = uri("https://maven.enginehub.org/repo/") - } - maven { - name = "OSS Sonatype Snapshots" - url = uri("https://oss.sonatype.org/content/repositories/snapshots/") - } - maven { - name = "Athion" - url = uri("https://ci.athion.net/plugin/repository/tools/") - } - } - - configurations.all { - resolutionStrategy { - cacheChangingModulesFor(5, "MINUTES") - } - } - - plugins.withId("java") { - the().toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) - } - } - - dependencies { - constraints { - for (conf in configurations) { - if (conf.isCanBeConsumed || conf.isCanBeResolved) { - // dependencies don't get declared in these - continue - } - add(conf.name, "com.google.guava:guava") { - version { require("31.1-jre") } - because("Mojang provides Guava") - } - add(conf.name, "com.google.code.gson:gson") { - version { require("2.10") } - because("Mojang provides Gson") - } - add(conf.name, "it.unimi.dsi:fastutil") { - version { require("8.5.9") } - because("Mojang provides FastUtil") - } - } - } - } -} diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt deleted file mode 100644 index 0b90d1e063..0000000000 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ /dev/null @@ -1,91 +0,0 @@ -import org.gradle.api.Project -import org.gradle.api.attributes.java.TargetJvmVersion -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.api.tasks.testing.Test -import org.gradle.external.javadoc.StandardJavadocDocletOptions -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.withType - -fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean = true) { - applyCommonConfiguration() - apply(plugin = "eclipse") - apply(plugin = "idea") - - tasks - .withType() - .matching { it.name == "compileJava" || it.name == "compileTestJava" } - .configureEach { - val disabledLint = listOf( - "processing", "path", "fallthrough", "serial", "overloads", "this-escape", - ) - options.release.set(21) - options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" }) - options.isDeprecation = true - options.encoding = "UTF-8" - options.compilerArgs.add("-parameters") - options.compilerArgs.add("--add-modules=jdk.incubator.vector") - } - - configurations.all { - attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) - } - - tasks.withType().configureEach { - useJUnitPlatform() - } - - dependencies { - "compileOnly"("com.google.code.findbugs:jsr305:3.0.2") - "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.11.1") - "testImplementation"("org.junit.jupiter:junit-jupiter-params:5.11.1") - "testImplementation"("org.mockito:mockito-core:5.14.0") - "testImplementation"("org.mockito:mockito-junit-jupiter:5.14.0") - "testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.11.1") - } - - // Java 8 turns on doclint which we fail - tasks.withType().configureEach { - (options as StandardJavadocDocletOptions).apply { - addStringOption("Xdoclint:none", "-quiet") - addStringOption("-add-modules", "jdk.incubator.vector") - tags( - "apiNote:a:API Note:", - "implSpec:a:Implementation Requirements:", - "implNote:a:Implementation Note:" - ) - options.encoding = "UTF-8" - - links( - "https://jd.advntr.dev/api/latest/", - "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", - "https://www.antlr.org/api/Java/", - "https://jd.papermc.io/paper/1.21.1/", - "https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/" - ) - docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}" - } - } - - configure { - disableAutoTargetJvm() - withJavadocJar() - if (sourcesJar) { - withSourcesJar() - } - } - - if (banSlf4j) { - configurations["compileClasspath"].apply { - resolutionStrategy.componentSelection { - withModule("org.slf4j:slf4j-api") { - reject("No SLF4J allowed on compile classpath") - } - } - } - } -} diff --git a/buildSrc/src/main/kotlin/GradleExtras.kt b/buildSrc/src/main/kotlin/GradleExtras.kt deleted file mode 100644 index beedf16078..0000000000 --- a/buildSrc/src/main/kotlin/GradleExtras.kt +++ /dev/null @@ -1,12 +0,0 @@ -import org.gradle.api.Project -import org.gradle.api.plugins.ExtraPropertiesExtension -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.tasks.SourceSetContainer -import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.the - -val Project.ext: ExtraPropertiesExtension - get() = extensions.getByType() - -val Project.sourceSets: SourceSetContainer - get() = the().sourceSets diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt deleted file mode 100644 index 0599a8567a..0000000000 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ /dev/null @@ -1,298 +0,0 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.artifacts.ExternalModuleDependency -import org.gradle.api.artifacts.ModuleDependency -import org.gradle.api.attributes.Bundling -import org.gradle.api.attributes.Category -import org.gradle.api.attributes.DocsType -import org.gradle.api.attributes.LibraryElements -import org.gradle.api.attributes.Usage -import org.gradle.api.attributes.java.TargetJvmVersion -import org.gradle.api.component.AdhocComponentWithVariants -import org.gradle.api.component.SoftwareComponentFactory -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.tasks.bundling.Jar -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.invoke -import org.gradle.kotlin.dsl.named -import org.gradle.kotlin.dsl.provideDelegate -import org.gradle.kotlin.dsl.register -import org.gradle.kotlin.dsl.the -import org.gradle.plugins.signing.SigningExtension -import javax.inject.Inject - -fun Project.applyLibrariesConfiguration() { - applyCommonConfiguration() - apply(plugin = "java-base") - apply(plugin = "maven-publish") - apply(plugin = "com.gradleup.shadow") - apply(plugin = "signing") - - configurations { - create("shade") - } - - group = "${rootProject.group}.worldedit-libs" - - val relocations = mapOf( - "net.kyori.text" to "com.sk89q.worldedit.util.formatting.text", - "net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori" - - ) - - tasks.register("jar") { - configurations = listOf(project.configurations["shade"]) - archiveClassifier.set("") - - dependencies { - exclude(dependency("com.google.guava:guava")) - exclude(dependency("com.google.code.gson:gson")) - exclude(dependency("com.google.errorprone:error_prone_annotations")) - exclude(dependency("com.google.guava:failureaccess")) - exclude(dependency("org.checkerframework:checker-qual")) - exclude(dependency("org.jetbrains:annotations")) - exclude(dependency("org.apache.logging.log4j:log4j-api")) - exclude(dependency("com.google.code.findbugs:jsr305")) - exclude { - it.moduleGroup == "org.jetbrains.kotlin" - } - } - - relocations.forEach { (from, to) -> - relocate(from, to) - } - } - val altConfigFiles = { artifactType: String -> - val deps = configurations["shade"].incoming.dependencies - .filterIsInstance() - .map { it.copy() } - .map { dependency -> - val category = dependency.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE)?.name - if (category == Category.REGULAR_PLATFORM || category == Category.ENFORCED_PLATFORM) { - return@map dependency - } - try { - dependency.artifact { - name = dependency.name - type = artifactType - extension = "jar" - classifier = artifactType - } - } catch (e: Exception) { - throw RuntimeException("Failed to add artifact to dependency: $dependency", e) - } - dependency - } - - files(configurations.detachedConfiguration(*deps.toTypedArray()) - .resolvedConfiguration.lenientConfiguration.artifacts - .filter { it.classifier == artifactType } - .map { zipTree(it.file) }) - } - tasks.register("sourcesJar") { - from({ - altConfigFiles("sources") - }) - - // Yeet module-info's - exclude("module-info.java") - - relocations.forEach { (from, to) -> - val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)") - val textPattern = Regex.fromLiteral(from) - eachFile { - filter { - it.replaceFirst(textPattern, to) - } - path = path.replaceFirst(filePattern, "$1${to.replace('.', '/')}$2") - } - } - archiveClassifier.set("sources") - } - - // This a dummy jar to comply with the requirements of the OSSRH, - // libs are not API and therefore no "proper" javadoc jar is necessary - tasks.register("javadocJar") { - archiveClassifier.set("javadoc") - } - - tasks.named("assemble").configure { - dependsOn("jar", "sourcesJar", "javadocJar") - } - - project.apply() - - val libsComponent = project.components["libs"] as AdhocComponentWithVariants - - val apiElements = project.configurations.register("apiElements") { - isVisible = false - description = "API elements for libs" - isCanBeResolved = false - isCanBeConsumed = true - attributes { - attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) - attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) - attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) - } - outgoing.artifact(tasks.named("jar")) - } - - val runtimeElements = project.configurations.register("runtimeElements") { - isVisible = false - description = "Runtime elements for libs" - isCanBeResolved = false - isCanBeConsumed = true - attributes { - attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME)) - attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) - attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) - } - outgoing.artifact(tasks.named("jar")) - } - - val sourcesElements = project.configurations.register("sourcesElements") { - isVisible = false - description = "Source elements for libs" - isCanBeResolved = false - isCanBeConsumed = true - attributes { - attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME)) - attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION)) - attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) - attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES)) - } - outgoing.artifact(tasks.named("sourcesJar")) - } - - val javadocElements = project.configurations.register("javadocElements") { - isVisible = false - description = "Javadoc elements for libs" - isCanBeResolved = false - isCanBeConsumed = true - attributes { - attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME)) - attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION)) - attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED)) - attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.JAVADOC)) - } - outgoing.artifact(tasks.named("javadocJar")) - } - - libsComponent.addVariantsFromConfiguration(apiElements.get()) { - mapToMavenScope("compile") - } - - libsComponent.addVariantsFromConfiguration(runtimeElements.get()) { - mapToMavenScope("runtime") - } - - libsComponent.addVariantsFromConfiguration(sourcesElements.get()) { - mapToMavenScope("runtime") - } - - libsComponent.addVariantsFromConfiguration(javadocElements.get()) { - mapToMavenScope("runtime") - } - - val publishingExtension = the() - - configure { - if (!version.toString().endsWith("-SNAPSHOT")) { - val signingKey: String? by project - val signingPassword: String? by project - useInMemoryPgpKeys(signingKey, signingPassword) - isRequired - sign(publishingExtension.publications) - } - } - - configure { - publications { - register("maven") { - from(libsComponent) - - group = "com.fastasyncworldedit" - artifactId = "FastAsyncWorldEdit-Libs-${project.name.replaceFirstChar(Char::titlecase)}" - version = version - - pom { - name.set("${rootProject.name}-Libs" + " " + project.version) - description.set("Blazingly fast Minecraft world manipulation for artists, builders and everyone else.") - url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - - licenses { - license { - name.set("GNU General Public License, Version 3.0") - url.set("https://www.gnu.org/licenses/gpl-3.0.html") - distribution.set("repo") - } - } - - developers { - developer { - id.set("NotMyFault") - name.set("Alexander Brandes") - email.set("contact(at)notmyfault.dev") - organization.set("IntellectualSites") - } - developer { - id.set("SirYwell") - name.set("Hannes Greule") - organization.set("IntellectualSites") - } - developer { - id.set("dordsor21") - name.set("dordsor21") - organization.set("IntellectualSites") - } - } - - scm { - url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") - developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") - tag.set("${project.version}") - } - - issueManagement { - system.set("GitHub") - url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit/issues") - } - } - } - } - } - -} - -// A horrible hack because `softwareComponentFactory` has to be gotten via plugin -// gradle why -internal open class LibsConfigPluginHack @Inject constructor( - private val softwareComponentFactory: SoftwareComponentFactory -) : Plugin { - override fun apply(project: Project) { - val libsComponents = softwareComponentFactory.adhoc("libs") - project.components.add(libsComponents) - } -} - -fun Project.constrainDependenciesToLibsCore() { - evaluationDependsOn(":worldedit-libs:core") - val coreDeps = project(":worldedit-libs:core").configurations["shade"].dependencies - .filterIsInstance() - dependencies.constraints { - for (coreDep in coreDeps) { - add("shade", "${coreDep.group}:${coreDep.name}:${coreDep.version}") { - because("libs should align with libs:core") - } - } - } -} diff --git a/buildSrc/src/main/kotlin/PlatformConfig.kt b/buildSrc/src/main/kotlin/PlatformConfig.kt deleted file mode 100644 index 1b89a362e4..0000000000 --- a/buildSrc/src/main/kotlin/PlatformConfig.kt +++ /dev/null @@ -1,182 +0,0 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import org.gradle.api.Project -import org.gradle.api.component.AdhocComponentWithVariants -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.tasks.bundling.Jar -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.named -import org.gradle.kotlin.dsl.provideDelegate -import org.gradle.kotlin.dsl.register -import org.gradle.kotlin.dsl.the -import org.gradle.kotlin.dsl.withType -import org.gradle.plugins.signing.SigningExtension - -fun Project.applyPlatformAndCoreConfiguration() { - applyCommonConfiguration() - apply(plugin = "java") - apply(plugin = "eclipse") - apply(plugin = "idea") - apply(plugin = "maven-publish") - apply(plugin = "com.gradleup.shadow") - apply(plugin = "signing") - - applyCommonJavaConfiguration( - sourcesJar = name in setOf("worldedit-core", "worldedit-bukkit"), - ) - - if (project.hasProperty("buildnumber")) { - ext["internalVersion"] = "$version;${rootProject.ext["gitCommitHash"]}" - } else { - ext["internalVersion"] = "$version" - } - - configure { - disableAutoTargetJvm() - withJavadocJar() - } - - if (name in setOf("worldedit-core", "worldedit-bukkit", "worldedit-cli")) { - the().withSourcesJar() - } - - val javaComponent = components["java"] as AdhocComponentWithVariants - javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) { - skip() - } - - val publishingExtension = the() - - configure { - if (!version.toString().endsWith("-SNAPSHOT")) { - val signingKey: String? by project - val signingPassword: String? by project - useInMemoryPgpKeys(signingKey, signingPassword) - isRequired - sign(publishingExtension.publications) - } - } - - configure { - publications { - register("maven") { - from(javaComponent) - - group = "com.fastasyncworldedit" - artifactId = "${rootProject.name}-${project.description}" - version = version - - pom { - name.set("${rootProject.name}-${project.description}" + " " + project.version) - description.set("Blazingly fast Minecraft world manipulation for artists, builders and everyone else.") - url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - - licenses { - license { - name.set("GNU General Public License, Version 3.0") - url.set("https://www.gnu.org/licenses/gpl-3.0.html") - distribution.set("repo") - } - } - - developers { - developer { - id.set("NotMyFault") - name.set("Alexander Brandes") - email.set("contact(at)notmyfault.dev") - organization.set("IntellectualSites") - organizationUrl.set("https://github.com/IntellectualSites") - } - developer { - id.set("SirYwell") - name.set("Hannes Greule") - organization.set("IntellectualSites") - organizationUrl.set("https://github.com/IntellectualSites") - } - developer { - id.set("dordsor21") - name.set("dordsor21") - organization.set("IntellectualSites") - organizationUrl.set("https://github.com/IntellectualSites") - } - } - - scm { - url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit") - connection.set("scm:git:https://github.com/IntellectualSites/FastAsyncWorldEdit.git") - developerConnection.set("scm:git:git@github.com:IntellectualSites/FastAsyncWorldEdit.git") - tag.set("${project.version}") - } - - issueManagement{ - system.set("GitHub") - url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit/issues") - } - } - } - } - } - - if (name != "worldedit-fabric") { - configurations["compileClasspath"].apply { - resolutionStrategy.componentSelection { - withModule("org.slf4j:slf4j-api") { - reject("No SLF4J allowed on compile classpath") - } - } - } - } - -} - -fun Project.applyShadowConfiguration() { - tasks.withType().configureEach { - relocate("com.sk89q.jchronic", "com.sk89q.worldedit.jchronic") - dependencies { - include(project(":worldedit-libs:core")) - include(project(":worldedit-libs:${project.name.replace("worldedit-", "")}")) - include(project(":worldedit-core")) - exclude("com.google.code.findbugs:jsr305") - } - exclude("GradleStart**") - exclude(".cache") - exclude("LICENSE*") - exclude("META-INF/maven/**") - minimize() - } -} - -val CLASSPATH = listOf("truezip", "truevfs", "js") - .map { "$it.jar" } - .flatMap { listOf(it, "FastAsyncWorldEdit/$it") } - .joinToString(separator = " ") - -sealed class WorldEditKind( - val name: String, - val mainClass: String = "com.sk89q.worldedit.internal.util.InfoEntryPoint" -) { - class Standalone(mainClass: String) : WorldEditKind("STANDALONE", mainClass) - object Mod : WorldEditKind("MOD") - object Plugin : WorldEditKind("PLUGIN") -} - -fun Project.addJarManifest(kind: WorldEditKind, includeClasspath: Boolean = false, extraAttributes: Map = mapOf()) { - tasks.named("jar") { - val version = project(":worldedit-core").version - inputs.property("version", version) - val attributes = mutableMapOf( - "Implementation-Version" to version, - "WorldEdit-Version" to version, - "WorldEdit-Kind" to kind.name, - "Main-Class" to kind.mainClass - ) - if (includeClasspath) { - attributes["Class-Path"] = CLASSPATH - } - attributes.putAll(extraAttributes) - manifest.attributes(attributes) - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e723ed68d4..202f34fb98 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,32 +1,31 @@ [versions] # Minecraft expectations -paper = "1.21-R0.1-SNAPSHOT" -fastutil = "8.5.9" -guava = "31.1-jre" -log4j = "2.19.0" -gson = "2.10" -snakeyaml = "2.0" +paperApi = "1.21-R0.1-SNAPSHOT" +fastutil = "8.5.15" +guava = "33.3.1-jre" +log4j = "2.24.1" +gson = "2.11.0" +snakeyaml = "2.2" # Plugins dummypermscompat = "1.10" -worldguard-bukkit = "7.0.13" -mapmanager = "1.8.0-SNAPSHOT" -griefprevention = "17.0.0" +worldguard-bukkit = "7.0.14" +griefprevention = "18.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.101.1.4" -plotsquared = "7.4.2" +towny = "0.101.2.5" +plotsquared = "7.5.8" # Third party bstats = "3.1.0" sparsebitset = "1.3" parallelgzip = "1.0.5" -adventure = "4.19.0" -adventure-bukkit = "4.3.4" -checkerqual = "3.49.0" +adventure = "4.25.0" +adventure-bukkit = "4.4.1" +checkerqual = "3.51.1" truezip = "6.8.4" auto-value = "1.11.0" -findbugs = "3.0.2" +jsr305 = "3.0.2" rhino-runtime = "1.7.15" zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs antlr4 = "4.13.2" @@ -35,30 +34,50 @@ jlibnoise = "1.0.0" jchronic = "0.2.4a" lz4-java = "1.8.0" lz4-stream = "1.0.0" -commons-cli = "1.9.0" -paperlib = "1.0.8" -paster = "1.1.6" +commons-cli = "1.10.0" +paperLib = "1.0.8" +paster = "1.1.7" vault = "1.7.1" -serverlib = "2.3.6" +serverlib = "2.3.7" linbus = "0.2.0" +autoService = "1.1.1" ## Internal text-adapter = "3.0.6" text = "3.0.4" piston = "0.5.10" # Tests -mockito = "5.15.2" +mockito = "5.20.0" +junit = "6.0.0" # Gradle plugins pluginyml = "0.6.0" -mod-publish-plugin = "0.8.4" +mod-publish-plugin = "1.0.0" +grgit = "5.3.3" +shadow = "9.0.2" +paperweight = "2.0.0-SNAPSHOT" +codecov = "0.2.0" + + +jqwik = "1.9.3" + +# Minimum versions we apply to make dependencies support newer Java +minimumAsm = "9.7" +minimumJdependency = "2.10" +#minimumTinyRemapper = "0.8.11" + [libraries] +# Gradle plugins +grgit = { group = "org.ajoberstar.grgit", name = "grgit-gradle", version.ref = "grgit" } +shadow = { group = "com.gradleup.shadow", name = "shadow-gradle-plugin", version.ref = "shadow" } +paperweight = { group = "io.papermc.paperweight.userdev", name = "io.papermc.paperweight.userdev.gradle.plugin", version.ref = "paperweight" } + # Minecraft expectations -paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" } +paperApi = { group = "io.papermc.paper", name = "paper-api", version.ref = "paperApi" } fastutil = { group = "it.unimi.dsi", name = "fastutil", version.ref = "fastutil" } -log4jBom = { group = "org.apache.logging.log4j", name = "log4j-bom", version.ref = "log4j" } -log4jApi = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } +log4j-bom = { group = "org.apache.logging.log4j", name = "log4j-bom", version.ref = "log4j" } +log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeyaml" } @@ -66,34 +85,33 @@ snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeyaml" # Plugins dummypermscompat = { group = "com.sk89q", name = "dummypermscompat", version.ref = "dummypermscompat" } worldguard = { group = "com.sk89q.worldguard", name = "worldguard-bukkit", version.ref = "worldguard-bukkit" } -mapmanager = { group = "com.github.InventivetalentDev", name = "MapManager", version.ref = "mapmanager" } griefprevention = { group = "com.github.TechFortress", name = "GriefPrevention", version.ref = "griefprevention" } griefdefender = { group = "com.griefdefender", name = "api", version.ref = "griefdefender" } residence = { group = "com.bekvon.bukkit.residence", name = "Residence", version.ref = "residence" } towny = { group = "com.palmergames.bukkit.towny", name = "towny", version.ref = "towny" } -plotSquaredCore = { group = "com.intellectualsites.plotsquared", name = "plotsquared-core", version.ref = "plotsquared" } -plotSquaredBukkit = { group = "com.intellectualsites.plotsquared", name = "plotsquared-bukkit", version.ref = "plotsquared" } +plotsquared-core = { group = "com.intellectualsites.plotsquared", name = "plotsquared-core", version.ref = "plotsquared" } +plotsquared-bukkit = { group = "com.intellectualsites.plotsquared", name = "plotsquared-bukkit", version.ref = "plotsquared" } # Third Party -bstatsBase = { group = "org.bstats", name = "bstats-base", version.ref = "bstats" } -bstatsBukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" } +bstats-base = { group = "org.bstats", name = "bstats-base", version.ref = "bstats" } +bstats-bukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" } sparsebitset = { group = "com.zaxxer", name = "SparseBitSet", version.ref = "sparsebitset" } parallelgzip = { group = "org.anarres", name = "parallelgzip", version.ref = "parallelgzip" } -truezip = { group = "de.schlichtherle", name = "truezip", version.ref = "truezip" } -autoValueAnnotations = { group = "com.google.auto.value", name = "auto-value-annotations", version.ref = "auto-value" } +trueZip = { group = "de.schlichtherle", name = "truezip", version.ref = "truezip" } autoValue = { group = "com.google.auto.value", name = "auto-value", version.ref = "auto-value" } -findbugs = { group = "com.google.code.findbugs", name = "jsr305", version.ref = "findbugs" } +autoValue-annotations = { group = "com.google.auto.value", name = "auto-value-annotations", version.ref = "auto-value" } +jsr305 = { group = "com.google.code.findbugs", name = "jsr305", version.ref = "jsr305" } rhino = { group = "org.mozilla", name = "rhino-runtime", version.ref = "rhino-runtime" } zstd = { group = "com.github.luben", name = "zstd-jni", version.ref = "zstd-jni" } antlr4 = { group = "org.antlr", name = "antlr4", version.ref = "antlr4" } -antlr4Runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr4" } -jsonSimple = { group = "com.googlecode.json-simple", name = "json-simple", version.ref = "json-simple" } +antlr4-runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr4" } +json-simple = { group = "com.googlecode.json-simple", name = "json-simple", version.ref = "json-simple" } jlibnoise = { group = "com.sk89q.lib", name = "jlibnoise", version.ref = "jlibnoise" } jchronic = { group = "com.sk89q", name = "jchronic", version.ref = "jchronic" } lz4Java = { group = "org.lz4", name = "lz4-java", version.ref = "lz4-java" } lz4JavaStream = { group = "net.jpountz", name = "lz4-java-stream", version.ref = "lz4-stream" } commonsCli = { group = "commons-cli", name = "commons-cli", version.ref = "commons-cli" } -paperlib = { group = "io.papermc", name = "paperlib", version.ref = "paperlib" } +paperLib = { group = "io.papermc", name = "paperlib", version.ref = "paperLib" } adventureApi = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" } adventureMiniMessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" } adventureBukkit = { group = "net.kyori", name = "adventure-platform-bukkit", version.ref = "adventure-bukkit" } @@ -101,6 +119,9 @@ paster = { group = "com.intellectualsites.paster", name = "Paster", version.ref vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" } serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" } checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" } + +autoService = { group = "com.google.auto.service", name = "auto-service", version.ref = "autoService" } + linBus-bom = { group = "org.enginehub.lin-bus", name = "lin-bus-bom", version.ref = "linbus" } linBus-common = { group = "org.enginehub.lin-bus", name = "lin-bus-common" } linBus-stream = { group = "org.enginehub.lin-bus", name = "lin-bus-stream" } @@ -109,22 +130,49 @@ linBus-format-snbt = { group = "org.enginehub.lin-bus.format", name = "lin-bus-f # Internal ## Text -adventureTextAdapterBukkit = { group = "net.kyori", name = "text-adapter-bukkit", version.ref = "text-adapter" } -adventureTextApi = { group = "net.kyori", name = "text-api", version.ref = "text" } -adventureTextSerializerGson = { group = "net.kyori", name = "text-serializer-gson", version.ref = "text" } -adventureTextSerializerLegacy = { group = "net.kyori", name = "text-serializer-legacy", version.ref = "text" } -adventureTextSerializerPlain = { group = "net.kyori", name = "text-serializer-plain", version.ref = "text" } +kyoriText-adapter-bukkit = { group = "net.kyori", name = "text-adapter-bukkit", version.ref = "text-adapter" } +kyoriText-api = { group = "net.kyori", name = "text-api", version.ref = "text" } +kyoriText-serializer-gson = { group = "net.kyori", name = "text-serializer-gson", version.ref = "text" } +kyoriText-serializer-legacy = { group = "net.kyori", name = "text-serializer-legacy", version.ref = "text" } +kyoriText-serializer-plain = { group = "net.kyori", name = "text-serializer-plain", version.ref = "text" } + +junit-bom = { group = "org.junit", name = "junit-bom", version.ref = "junit" } +junit-jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api" } +junit-jupiter-params = { group = "org.junit.jupiter", name = "junit-jupiter-params" } +junit-jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine" } +junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher" } + +jqwik = { group = "net.jqwik", name = "jqwik", version.ref = "jqwik" } + +mockito-bom = { group = "org.mockito", name = "mockito-bom", version.ref = "mockito" } +mockito-core = { group = "org.mockito", name = "mockito-core" } +mockito-junit-jupiter = { group = "org.mockito", name = "mockito-core" } + +log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } + ## Piston -piston = { group = "org.enginehub.piston", name = "core", version.ref = "piston" } -pistonImpl = { group = "org.enginehub.piston", name = "default-impl", version.ref = "piston" } -pistonAnnotations = { group = "org.enginehub.piston.core-ap", name = "annotations", version.ref = "piston" } -pistonProcessor = { group = "org.enginehub.piston.core-ap", name = "processor", version.ref = "piston" } -pistonRuntime = { group = "org.enginehub.piston.core-ap", name = "runtime", version.ref = "piston" } +[libraries.piston-core] +module = "org.enginehub.piston:core" +version.ref = "piston" + +[libraries.piston-defaultImpl] +module = "org.enginehub.piston:default-impl" +version.ref = "piston" + +[libraries.piston-coreAp-annotations] +module = "org.enginehub.piston.core-ap:annotations" +version.ref = "piston" + +[libraries.piston-coreAp-processor] +module = "org.enginehub.piston.core-ap:processor" +version.ref = "piston" + +[libraries.piston-coreAp-runtime] +module = "org.enginehub.piston.core-ap:runtime" +version.ref = "piston" -# Tests -mockito = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" } -log4jCore = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } [plugins] pluginyml = { id = "net.minecrell.plugin-yml.bukkit", version.ref = "pluginyml" } mod-publish-plugin = { id = "me.modmuss50.mod-publish-plugin", version.ref = "mod-publish-plugin" } +codecov = { id = "org.enginehub.codecov", version.ref = "codecov" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530..8bdaf60c75 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e18bc253b8..a35649f5fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f3b75f3b0d..ef07e0162b 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -205,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9b42019c79..5eed7ee845 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle.kts b/settings.gradle.kts index dd8d68515d..8d18df47e9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,58 @@ +import kotlin.system.exitProcess + +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = "EngineHub Repository" + url = uri("https://maven.enginehub.org/repo/") + } + } +} +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} +dependencyResolutionManagement { + repositories { + maven { + name = "EngineHub Repository" + url = uri("https://maven.enginehub.org/repo/") + content { + excludeGroup("net.kyori") + } + } + mavenCentral() + } +} + +if (!File("$rootDir/.git").exists()) { + logger.lifecycle(""" + ************************************************************************************** + You need to fork and clone this repository! Don't download a .zip file. + If you need assistance, consult the GitHub docs: https://docs.github.com/get-started/quickstart/fork-a-repo + ************************************************************************************** + """.trimIndent() + ).also { exitProcess(1) } +} + +logger.lifecycle(""" +******************************************* + You are building FastAsyncWorldEdit! + + If you encounter trouble: + 1) Read COMPILING.adoc if you haven't yet + 2) Try running 'build' in a separate Gradle run + 3) Use gradlew and not gradle + 4) If you still need help, ask on Discord! https://discord.gg/intellectualsites + + Output files will be in [subproject]/build/libs +******************************************* +""") + rootProject.name = "FastAsyncWorldEdit" +includeBuild("build-logic") + include("worldedit-libs") listOf("1_20_2", "1_20_4", "1_20_5", "1_21", "1_21_3", "1_21_4").forEach { @@ -12,14 +65,5 @@ listOf("bukkit", "core", "cli").forEach { } include("worldedit-libs:core:ap") -dependencyResolutionManagement { - repositories { - mavenCentral() - maven { - name = "EngineHub" - url = uri("https://maven.enginehub.org/repo/") - } - } -} enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts index 9954460597..d5f822a5e6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_2/build.gradle.kts @@ -1,17 +1,11 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - java -} - -applyPaperweightAdapterConfiguration() - -repositories { - gradlePluginPortal() + id("buildlogic.adapter") } dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.2-R0.1-SNAPSHOT the().paperDevBundle("1.20.2-R0.1-20231203.034718-121") - compileOnly(libs.paperlib) + compileOnly(libs.paperLib) } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts index be348efdb5..983766a4c2 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_4/build.gradle.kts @@ -1,17 +1,11 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - java -} - -applyPaperweightAdapterConfiguration() - -repositories { - gradlePluginPortal() + id("buildlogic.adapter") } dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT the().paperDevBundle("1.20.4-R0.1-20241030.192207-176") - compileOnly(libs.paperlib) + compileOnly(libs.paperLib) } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts index ffe10e3ff4..2287124ff2 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts @@ -1,17 +1,11 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - java -} - -applyPaperweightAdapterConfiguration() - -repositories { - gradlePluginPortal() + id("buildlogic.adapter") } dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/ the().paperDevBundle("1.20.6-R0.1-20241030.191541-126") - compileOnly(libs.paperlib) + compileOnly(libs.paperLib) } diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index 4164c6262f..92fb1dc97c 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -1,17 +1,12 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - java -} - -applyPaperweightAdapterConfiguration() + id("buildlogic.adapter") -repositories { - gradlePluginPortal() } dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20241121.101634-127") - compileOnly(libs.paperlib) + the().paperDevBundle("1.21.1-R0.1-20250328.161643-128") + compileOnly(libs.paperLib) } diff --git a/worldedit-bukkit/adapters/adapter-1_21_3/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_3/build.gradle.kts index c1276ad527..18c389f940 100644 --- a/worldedit-bukkit/adapters/adapter-1_21_3/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_3/build.gradle.kts @@ -1,17 +1,12 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - java -} - -applyPaperweightAdapterConfiguration() + id("buildlogic.adapter") -repositories { - gradlePluginPortal() } dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.3-R0.1-SNAPSHOT/ the().paperDevBundle("1.21.3-R0.1-20241223.191244-86") - compileOnly(libs.paperlib) + compileOnly(libs.paperLib) } diff --git a/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts index 7f098bd05c..8e2d3c2036 100644 --- a/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21_4/build.gradle.kts @@ -1,17 +1,12 @@ import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension plugins { - java -} - -applyPaperweightAdapterConfiguration() + id("buildlogic.adapter") -repositories { - gradlePluginPortal() } dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.4-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.4-R0.1-20241215.095037-18") - compileOnly(libs.paperlib) + the().paperDevBundle("1.21.4-R0.1-20250609.101859-227") + compileOnly(libs.paperLib) } diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 250c5f23c1..c60a861440 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -1,16 +1,24 @@ +import buildlogic.getLibrary +import buildlogic.sourceSets +import buildlogic.stringyLibs import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar import io.papermc.paperweight.userdev.attribute.Obfuscation import me.modmuss50.mpp.ReleaseType +import kotlin.getOrElse plugins { `java-library` + id("buildlogic.platform") alias(libs.plugins.mod.publish.plugin) } project.description = "Bukkit" -applyPlatformAndCoreConfiguration() -applyShadowConfiguration() +platform { + kind = buildlogic.WorldEditKind.Plugin + includeClasspath = true +} repositories { maven { @@ -18,9 +26,10 @@ repositories { url = uri("https://repo.papermc.io/repository/maven-public/") } maven { - name = "EngineHub" + name = "EngineHub Repository" url = uri("https://maven.enginehub.org/repo/") } + mavenCentral() maven { name = "JitPack" url = uri("https://jitpack.io") @@ -38,6 +47,14 @@ repositories { url = uri("https://repo.glaremasters.me/repository/towny/") } maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // TODO Remove when 4.17.0 is released + maven { + name = "Athion" + url = uri("https://ci.athion.net/plugin/repository/tools/") + } + maven { + name = "inventive-repo" + url = uri("https://repo.inventivetalent.org/content/groups/public/") + } flatDir { dir(File("src/main/resources")) } } @@ -46,6 +63,8 @@ val localImplementation = configurations.create("localImplementation") { isCanBeConsumed = false isCanBeResolved = false } +configurations["compileOnly"].extendsFrom(localImplementation) +configurations["testImplementation"].extendsFrom(localImplementation) val adapters = configurations.create("adapters") { description = "Adapters to include in the JAR (Mojmap)" @@ -69,52 +88,45 @@ val adaptersReobf = configurations.create("adaptersReobf") { } dependencies { - // Modules - api(projects.worldeditCore) - api(projects.worldeditLibs.bukkit) - - project.project(":worldedit-bukkit:adapters").subprojects.forEach { - "adapters"(project(it.path)) - } + api(project(":worldedit-core")) + api(project(":worldedit-libs:bukkit")) - // Minecraft expectations - implementation(libs.fastutil) - - // Platform expectations - compileOnly(libs.paper) { + localImplementation(libs.paperApi) { exclude("junit", "junit") exclude(group = "org.slf4j", module = "slf4j-api") } - - // Logging - localImplementation(libs.log4jApi) - localImplementation(libs.log4jBom) { + localImplementation(platform(libs.log4j.bom)) { because("Spigot provides Log4J (sort of, not in API, implicitly part of server)") } + localImplementation(libs.log4j.api) - // Plugins + implementation(libs.paperLib) compileOnly(libs.vault) { isTransitive = false } compileOnly(libs.dummypermscompat) { exclude("com.github.MilkBowl", "VaultAPI") } + implementation(libs.bstats.bukkit) { isTransitive = false } + implementation(libs.bstats.base) { isTransitive = false } + implementation(libs.fastutil) + + project.project(":worldedit-bukkit:adapters").subprojects.forEach { + "adapters"(project(it.path)) + } compileOnly(libs.worldguard) { exclude("com.sk89q.worldedit", "worldedit-bukkit") exclude("com.sk89q.worldedit", "worldedit-core") exclude("com.sk89q.worldedit.worldedit-libs", "bukkit") exclude("com.sk89q.worldedit.worldedit-libs", "core") } - compileOnly(libs.mapmanager) { isTransitive = false } + compileOnly("org.inventivetalent", "mapmanager", "1.8.0-SNAPSHOT") { isTransitive = false } compileOnly(libs.griefprevention) { isTransitive = false } compileOnly(libs.griefdefender) { isTransitive = false } compileOnly(libs.residence) { isTransitive = false } compileOnly(libs.towny) { isTransitive = false } - compileOnly(libs.plotSquaredBukkit) { isTransitive = false } - compileOnly(libs.plotSquaredCore) { isTransitive = false } + compileOnly(libs.plotsquared.bukkit) { isTransitive = false } + compileOnly(libs.plotsquared.core) { isTransitive = false } // Third party - implementation(libs.paperlib) - implementation(libs.bstatsBukkit) { isTransitive = false } - implementation(libs.bstatsBase) { isTransitive = false } implementation(libs.serverlib) implementation(libs.paster) { isTransitive = false } api(libs.lz4Java) { isTransitive = false } @@ -124,35 +136,42 @@ dependencies { compileOnlyApi(libs.checkerqual) // Tests - testImplementation(libs.mockito) + testImplementation(libs.mockito.core) testImplementation(libs.adventureApi) testImplementation(libs.checkerqual) - testImplementation(libs.paper) { isTransitive = true } } tasks.named("processResources") { val internalVersion = project.ext["internalVersion"] inputs.property("internalVersion", internalVersion) filesMatching("plugin.yml") { - expand("internalVersion" to internalVersion) + expand(mapOf("internalVersion" to internalVersion)) } } -tasks.named("jar") { - manifest { - attributes("Class-Path" to CLASSPATH, - "WorldEdit-Version" to project.version) - } -} - -addJarManifest(WorldEditKind.Plugin, includeClasspath = true) - tasks.register("reobfShadowJar") { + // The `fawe.properties` file from `worldedit-core` is not automatically + // included, so we explicitly add the `worldedit-core` source set output. + from(project(":worldedit-core").sourceSets.main.get().output) archiveFileName.set("${rootProject.name}-Bukkit-${project.version}.${archiveExtension.getOrElse("jar")}") configurations = listOf( project.configurations.runtimeClasspath.get(), // as is done by shadow for the default shadowJar adaptersReobf ) + relocate("com.sk89q.jchronic", "com.sk89q.worldedit.jchronic") + + dependencies { + include(project(":worldedit-libs:core")) + include(project(":worldedit-libs:${project.name.replace("worldedit-", "")}")) + include(project(":worldedit-core")) + include(dependency(libs.jchronic)) + exclude(dependency(libs.jsr305)) + } + minimize { + // jchronic + lz4-java uses reflection to load things, so we need to exclude it from minimizing + exclude(dependency(libs.jchronic)) + exclude(dependency(libs.lz4Java)) + } // as is done by shadow for the default shadowJar from(sourceSets.main.map { it.output }) @@ -182,7 +201,6 @@ tasks.withType().configureEach { // In tandem with not bundling log4j, we shouldn't relocate base package here. // relocate("org.apache.logging", "com.sk89q.worldedit.log4j") relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4") - exclude(dependency("$group:$name")) include(dependency(":worldedit-core")) @@ -191,36 +209,35 @@ tasks.withType().configureEach { // If it turns out not to be true for Spigot/Paper, our only two official platforms, this can be uncommented. // include(dependency("org.apache.logging.log4j:log4j-api")) include(dependency("org.antlr:antlr4-runtime")) + + exclude(dependency("$group:$name")) // ZSTD does not work if relocated. https://github.com/luben/zstd-jni/issues/189 Use not latest as it can be difficult // to obtain latest ZSTD lib - include(dependency("com.github.luben:zstd-jni:1.4.8-1")) + include(dependency(libs.zstd)) relocate("org.bstats", "com.sk89q.worldedit.bstats") { - include(dependency("org.bstats:")) + include(dependency(libs.bstats.bukkit)) + include(dependency(libs.bstats.base)) } relocate("io.papermc.lib", "com.sk89q.worldedit.bukkit.paperlib") { include(dependency("io.papermc:paperlib")) } - relocate("it.unimi.dsi.fastutil", "com.sk89q.worldedit.bukkit.fastutil") { - include(dependency("it.unimi.dsi:fastutil")) + relocate("net.royawesome.jlibnoise", "com.sk89q.worldedit.jlibnoise") { + include(dependency("com.sk89q.lib:jlibnoise")) } - relocate("net.royawesome.jlibnoise", "com.sk89q.worldedit.jlibnoise") relocate("org.incendo.serverlib", "com.fastasyncworldedit.serverlib") { - include(dependency("dev.notmyfault.serverlib:ServerLib:2.3.6")) + include(dependency(libs.serverlib)) } relocate("com.intellectualsites.paster", "com.fastasyncworldedit.paster") { - include(dependency("com.intellectualsites.paster:Paster")) - } - relocate("org.lz4", "com.fastasyncworldedit.core.lz4") { - include(dependency("org.lz4:lz4-java:1.8.0")) + include(dependency(libs.paster)) } + include(dependency(libs.lz4Java)) relocate("com.zaxxer", "com.fastasyncworldedit.core.math") { - include(dependency("com.zaxxer:SparseBitSet:1.3")) + include(dependency(libs.sparsebitset)) } relocate("org.anarres", "com.fastasyncworldedit.core.internal.io") { - include(dependency("org.anarres:parallelgzip:1.0.5")) + include(dependency(libs.parallelgzip)) } } - project.project(":worldedit-bukkit:adapters").subprojects.forEach { dependencies { include(dependency("${it.group}:${it.name}")) @@ -246,13 +263,13 @@ publishMods { val common = modrinthOptions { accessToken.set(System.getenv("MODRINTH_TOKEN")) projectId.set("z4HZZnLr") - projectDescription.set(rootProject.file("README.md").readText()) + projectDescription.set(providers.fileContents { layout.projectDirectory.file("README.md") as File }.asText) } // We publish the reobfJar twice to ensure that the modrinth download menu picks the right jar for the platform regardless // of minecraft version. - val mojmapPaperVersions = listOf("1.20.6", "1.21.1", "1.21.3", "1.21.4") + val mojmapPaperVersions = listOf("1.20.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10") val spigotMappedPaperVersions = listOf("1.20.2", "1.20.4") // Mark reobfJar as spigot only for 1.20.5+ @@ -281,3 +298,9 @@ publishMods { // dryRun.set(true) // For testing } + +configure { + publications.named("maven") { + from(components["java"]) + } +} diff --git a/worldedit-cli/build.gradle.kts b/worldedit-cli/build.gradle.kts index 6f0335e0e9..dcb67ecad1 100644 --- a/worldedit-cli/build.gradle.kts +++ b/worldedit-cli/build.gradle.kts @@ -2,41 +2,33 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { `java-library` - + id("buildlogic.platform") alias(libs.plugins.pluginyml) } project.description = "CLI" -applyPlatformAndCoreConfiguration() -applyShadowConfiguration() - -addJarManifest( - WorldEditKind.Standalone("com.sk89q.worldedit.cli.CLIWorldEdit"), - extraAttributes = mapOf( - // We don't have any multi-release stuff, but Log4J does. - "Multi-Release" to "true", - ), -) +platform { + kind = buildlogic.WorldEditKind.Standalone("com.sk89q.worldedit.cli.CLIWorldEdit") + extraAttributes = mapOf( + // We don't have any multi-release stuff, but Log4J does. + "Multi-Release" to "true", + ) +} dependencies { - // Modules - api(projects.worldeditCore) - compileOnly(projects.worldeditLibs.core.ap) - annotationProcessor(projects.worldeditLibs.core.ap) - - // Minecraft expectations + compileOnly(project(":worldedit-libs:core:ap")) + annotationProcessor(project(":worldedit-libs:core:ap")) annotationProcessor(libs.guava) - implementation(libs.guava) - implementation(libs.gson) - - // Logging - implementation(libs.log4jBom) { + api(project(":worldedit-core")) + implementation(platform(libs.log4j.bom)) { because("We control Log4J on this platform") } - implementation(libs.log4jApi) - implementation(libs.log4jCore) + implementation(libs.log4j.api) + implementation(libs.log4j.core) implementation(libs.commonsCli) + implementation(libs.guava) + implementation(libs.gson) api(libs.parallelgzip) { isTransitive = false } api(libs.lz4Java) } @@ -48,6 +40,7 @@ tasks.named("shadowJar") { relocate("net.jpountz", "com.fastasyncworldedit.core.jpountz") relocate("org.lz4", "com.fastasyncworldedit.core.lz4") } + //TODO Upstream doesn't include the line below so we should see if we need it or not. archiveFileName.set(moduleIdentifier) minimize { exclude(dependency("org.apache.logging.log4j:log4j-core")) @@ -58,9 +51,16 @@ tasks.named("assemble").configure { dependsOn("shadowJar") } +configure { + publications.named("maven") { + artifactId = the().archivesName.get() + from(components["java"]) + } +} + val moduleIdentifier = "${rootProject.name}-${project.description}-${project.version}.jar" val decoration = "\n****************************************" -val websiteURL = "https://www.spigotmc.org/resources/13932/" +val websiteURL = "https://modrinth.com/plugin/fastasyncworldedit/" bukkit { name = "FastAsyncWorldEdit-COMMAND_LINE_INTERFACE_NOT_A_PLUGIN" @@ -71,7 +71,7 @@ bukkit { "* Stop your server, delete `$moduleIdentifier`" + " and download the proper one from:\n" + "* $websiteURL\n" + - "* (contains `-Bukkit-` instead of `-CLI-` in the name ;)" + + "* (contains `-Paper-` instead of `-CLI-` in the name ;)" + decoration version = rootProject.version.toString() website = websiteURL diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index d5839d99fe..3584f77653 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -3,12 +3,11 @@ import org.gradle.plugins.ide.idea.model.IdeaModel plugins { `java-library` antlr + id("buildlogic.core-and-platform") } project.description = "Core" -applyPlatformAndCoreConfiguration() - dependencies { constraints { implementation(libs.snakeyaml) { @@ -17,34 +16,40 @@ dependencies { } } - // Modules - api(projects.worldeditLibs.core) - compileOnly(projects.worldeditLibs.core.ap) - annotationProcessor(projects.worldeditLibs.core.ap) - - // Minecraft expectations - implementation(libs.fastutil) + api(project(":worldedit-libs:core")) + compileOnly(libs.trueZip) + implementation(libs.rhino) + implementation(libs.snakeyaml) implementation(libs.guava) + compileOnlyApi(libs.jsr305) implementation(libs.gson) - // Platform expectations - implementation(libs.snakeyaml) + implementation(libs.jchronic) { + exclude(group = "junit", module = "junit") + } + implementation(libs.jlibnoise) - // Logging - implementation(libs.log4jApi) + implementation(libs.log4j.api) - // Plugins - compileOnly(libs.plotSquaredCore) { isTransitive = false } + compileOnly(libs.plotsquared.core) { isTransitive = false } + implementation(libs.fastutil) + + antlr(libs.antlr4) + implementation(libs.antlr4.runtime) + + compileOnly(project(":worldedit-libs:core:ap")) + annotationProcessor(project(":worldedit-libs:core:ap")) // ensure this is on the classpath for the AP annotationProcessor(libs.guava) - compileOnly(libs.autoValueAnnotations) + compileOnly(libs.autoValue.annotations) annotationProcessor(libs.autoValue) - // Third party - compileOnly(libs.truezip) - implementation(libs.findbugs) - implementation(libs.rhino) + compileOnly(libs.autoService) { + because("Needed to resolve annotations in Piston") + } + + compileOnly(libs.adventureApi) compileOnlyApi(libs.adventureMiniMessage) implementation(libs.zstd) { isTransitive = false } @@ -52,31 +57,29 @@ dependencies { compileOnly(libs.lz4Java) { isTransitive = false } compileOnly(libs.sparsebitset) compileOnly(libs.parallelgzip) { isTransitive = false } - antlr(libs.antlr4) - implementation(libs.antlr4Runtime) - implementation(libs.jsonSimple) { isTransitive = false } - implementation(platform(libs.linBus.bom)) + implementation(libs.json.simple) { isTransitive = false } // Tests - testRuntimeOnly(libs.log4jCore) + testRuntimeOnly(libs.log4j.core) testImplementation(libs.parallelgzip) } -tasks.named("test") { +tasks.test { maxHeapSize = "1G" } -tasks.withType().configureEach { +tasks.compileJava { dependsOn(":worldedit-libs:build") options.compilerArgs.add("-Aarg.name.key.prefix=") + options.compilerArgs.add("--add-modules=jdk.incubator.vector") } -tasks.named("generateGrammarSource").configure { +tasks.generateGrammarSource { val pkg = "com.sk89q.worldedit.antlr" outputDirectory = file("build/generated-src/antlr/main/${pkg.replace('.', '/')}") arguments = listOf( - "-visitor", "-package", pkg, - "-Xexact-output-dir" + "-visitor", "-package", pkg, + "-Xexact-output-dir" ) } @@ -103,8 +106,17 @@ sourceSets.named("main") { tasks.named("processResources") { filesMatching("fawe.properties") { - expand("version" to "$version", + expand( + "version" to "$version", "commit" to "${rootProject.ext["revision"]}", - "date" to "${rootProject.ext["date"]}") + "date" to "${rootProject.ext["date"]}" + ) + } +} + +configure { + publications.named("maven") { + artifactId = the().archivesName.get() + from(components["java"]) } } diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 9bd557d7d0..44086b846b 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -1,163 +1,107 @@ +import buildlogic.getLibrary +import buildlogic.stringyLibs import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.fabricmc.loom.LoomGradleExtension import net.fabricmc.loom.task.RemapJarTask +import net.fabricmc.loom.task.RunGameTask -buildscript { - repositories { - mavenCentral() - maven { - name = "Fabric" - url = uri("https://maven.fabricmc.net/") - } - } - dependencies { - classpath("net.fabricmc:fabric-loom:${versions.loom}") - } +plugins { + id("fabric-loom") + `java-library` + id("buildlogic.platform") } -applyPlatformAndCoreConfiguration() -applyShadowConfiguration() - -apply(plugin = "fabric-loom") -apply(plugin = "java-library") - -configure { - accessWidener("src/main/resources/worldedit.accesswidener") +platform { + kind = buildlogic.WorldEditKind.Mod + includeClasspath = true } -val minecraftVersion = "1.16.3" -val yarnMappings = "1.16.3+build.1:v2" -val loaderVersion = "0.10.8" +val fabricApiConfiguration: Configuration = configurations.create("fabricApi") -configurations.all { - resolutionStrategy { - force("com.google.guava:guava:21.0") - } +loom { + accessWidenerPath.set(project.file("src/main/resources/worldedit.accesswidener")) } -val fabricApiConfiguration: Configuration = configurations.create("fabricApi") +tasks.withType().configureEach { + javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) +} repositories { - maven { - name = "Fabric" - url = uri("https://maven.fabricmc.net/") + afterEvaluate { + verifyEngineHubRepositories() } } dependencies { "api"(project(":worldedit-core")) - "implementation"("org.apache.logging.log4j:log4j-slf4j-impl:2.8.1") - "minecraft"("com.mojang:minecraft:$minecraftVersion") - "mappings"("net.fabricmc:yarn:$yarnMappings") - "modImplementation"("net.fabricmc:fabric-loader:$loaderVersion") + "minecraft"(libs.fabric.minecraft) + "mappings"(loom.layered { + officialMojangMappings() + parchment("org.parchmentmc.data:parchment-${libs.versions.parchment.minecraft.get()}:${libs.versions.parchment.mappings.get()}@zip") + }) + "modImplementation"(libs.fabric.loader) + "include"(libs.cuiProtocol.fabric) + "modImplementation"(libs.cuiProtocol.fabric) - // [1] declare fabric-api dependency... - "fabricApi"("net.fabricmc.fabric-api:fabric-api:0.29.3+1.16") - - // [2] Load the API dependencies from the fabric mod json... + // [1] Load the API dependencies from the fabric mod json... @Suppress("UNCHECKED_CAST") val fabricModJson = file("src/main/resources/fabric.mod.json").bufferedReader().use { groovy.json.JsonSlurper().parse(it) as Map> } val wantedDependencies = (fabricModJson["depends"] ?: error("no depends in fabric.mod.json")).keys .filter { it == "fabric-api-base" || it.contains(Regex("v\\d$")) } - .map { "net.fabricmc.fabric-api:$it" } - logger.lifecycle("Looking for these dependencies:") + .toSet() + // [2] Request the matching dependency from fabric-loom for (wantedDependency in wantedDependencies) { - logger.lifecycle(wantedDependency) - } - // [3] and now we resolve it to pick out what we want :D - val fabricApiDependencies = fabricApiConfiguration.incoming.resolutionResult.allDependencies - .onEach { - if (it is UnresolvedDependencyResult) { - throw kotlin.IllegalStateException("Failed to resolve Fabric API", it.failure) - } - } - .filterIsInstance() - // pick out transitive dependencies - .flatMap { - it.selected.dependencies - } - // grab the requested versions - .map { it.requested } - .filterIsInstance() - // map to standard notation - .associateByTo( - mutableMapOf(), - keySelector = { "${it.group}:${it.module}" }, - valueTransform = { "${it.group}:${it.module}:${it.version}" } - ) - fabricApiDependencies.keys.retainAll(wantedDependencies) - // sanity check - for (wantedDep in wantedDependencies) { - check(wantedDep in fabricApiDependencies) { "Fabric API library $wantedDep is missing!" } - } - - fabricApiDependencies.values.forEach { - "include"(it) - "modImplementation"(it) + val dep = fabricApi.module(wantedDependency, libs.versions.fabric.api.get()) + "include"(dep) + "modImplementation"(dep) } // No need for this at runtime - "modCompileOnly"("me.lucko:fabric-permissions-api:0.3.3") + "modCompileOnly"(libs.fabric.permissions.api) - // Hook these up manually, because Fabric doesn't seem to quite do it properly. - "compileOnly"("net.fabricmc:sponge-mixin:${project.versions.mixin}") - "annotationProcessor"("net.fabricmc:sponge-mixin:${project.versions.mixin}") - "annotationProcessor"("net.fabricmc:fabric-loom:${project.versions.loom}") + // Silence some warnings, since apparently this isn't on the compile classpath like it should be. + "compileOnly"(libs.errorprone.annotations) } -configure { - archivesBaseName = "$archivesBaseName-mc$minecraftVersion" +configure { + archivesName.set("${project.name}-mc${libs.fabric.minecraft.get().version}") } -tasks.named("processResources") { - // this will ensure that this task is redone when the versions change. - inputs.property("version", project.ext["internalVersion"]) - - from(sourceSets["main"].resources.srcDirs) { - include("fabric.mod.json") - expand("version" to project.ext["internalVersion"]) +configure { + publications.named("maven") { + artifactId = the().archivesName.get() + from(components["java"]) } +} - // copy everything else except the mod json - from(sourceSets["main"].resources.srcDirs) { - exclude("fabric.mod.json") +tasks.named("processResources") { + val internalVersion = project.ext["internalVersion"] + // this will ensure that this task is redone when the versions change. + inputs.property("version", internalVersion) + filesMatching("fabric.mod.json") { + this.expand("version" to internalVersion) } } -addJarManifest(includeClasspath = true) - tasks.named("shadowJar") { archiveClassifier.set("dist-dev") dependencies { - relocate("org.slf4j", "com.sk89q.worldedit.slf4j") - relocate("org.apache.logging.slf4j", "com.sk89q.worldedit.log4jbridge") relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4") + relocate("net.royawesome.jlibnoise", "com.sk89q.worldedit.jlibnoise") - include(dependency("org.slf4j:slf4j-api")) - include(dependency("org.apache.logging.log4j:log4j-slf4j-impl")) include(dependency("org.antlr:antlr4-runtime")) + include(dependency("com.sk89q.lib:jlibnoise")) } } -tasks.register("deobfJar") { - from(sourceSets["main"].output) - archiveClassifier.set("dev") -} - -artifacts { - add("archives", tasks.named("deobfJar")) -} - tasks.register("remapShadowJar") { val shadowJar = tasks.getByName("shadowJar") dependsOn(shadowJar) - input.set(shadowJar.archiveFile) + inputFile.set(shadowJar.archiveFile) archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-dev\\.jar$"), ".jar")) addNestedDependencies.set(true) - remapAccessWidener.set(true) } tasks.named("assemble").configure { diff --git a/worldedit-libs/bukkit/build.gradle.kts b/worldedit-libs/bukkit/build.gradle.kts index e623ff2b5c..1efe39cef8 100644 --- a/worldedit-libs/bukkit/build.gradle.kts +++ b/worldedit-libs/bukkit/build.gradle.kts @@ -1,13 +1,7 @@ -applyLibrariesConfiguration() -constrainDependenciesToLibsCore() - -repositories { - maven { - name = "SpigotMC" - url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") - } +plugins { + id("buildlogic.libs") } dependencies { - "shade"(libs.adventureTextAdapterBukkit) + "shade"(libs.kyoriText.adapter.bukkit) } diff --git a/worldedit-libs/cli/build.gradle.kts b/worldedit-libs/cli/build.gradle.kts index 388618cea1..3f6c7e06cb 100644 --- a/worldedit-libs/cli/build.gradle.kts +++ b/worldedit-libs/cli/build.gradle.kts @@ -1 +1,3 @@ -applyLibrariesConfiguration() +plugins { + id("buildlogic.libs") +} diff --git a/worldedit-libs/core/ap/build.gradle.kts b/worldedit-libs/core/ap/build.gradle.kts index d147de6be2..9d30deaea5 100644 --- a/worldedit-libs/core/ap/build.gradle.kts +++ b/worldedit-libs/core/ap/build.gradle.kts @@ -1,6 +1,9 @@ -applyLibrariesConfiguration() +plugins { + id("buildlogic.libs") +} dependencies { - "shade"(libs.pistonAnnotations) - "shade"(libs.pistonProcessor) + // These are here because they use net.kyori:text-api -- so they need to be relocated too + "shade"(libs.piston.coreAp.annotations) + "shade"(libs.piston.coreAp.processor) } diff --git a/worldedit-libs/core/build.gradle.kts b/worldedit-libs/core/build.gradle.kts index cace30cd08..f8e7a76e8d 100644 --- a/worldedit-libs/core/build.gradle.kts +++ b/worldedit-libs/core/build.gradle.kts @@ -1,17 +1,16 @@ -applyLibrariesConfiguration() +plugins { + id("buildlogic.libs") +} dependencies { - "shade"(libs.adventureTextApi) - "shade"(libs.adventureTextSerializerGson) - "shade"(libs.adventureTextSerializerLegacy) - "shade"(libs.adventureTextSerializerPlain) - "shade"(libs.jchronic) { - exclude(group = "junit", module = "junit") - } - "shade"(libs.jlibnoise) - "shade"(libs.piston) - "shade"(libs.pistonRuntime) - "shade"(libs.pistonImpl) + "shade"(libs.kyoriText.api) + "shade"(libs.kyoriText.serializer.gson) + "shade"(libs.kyoriText.serializer.legacy) + "shade"(libs.kyoriText.serializer.plain) + // These are here because they use net.kyori:text-api -- so they need to be relocated too + "shade"(libs.piston.core) + "shade"(libs.piston.coreAp.runtime) + "shade"(libs.piston.defaultImpl) // Linbus "shade"(platform(libs.linBus.bom)) "shade"(libs.linBus.common) diff --git a/worldedit-libs/fabric/build.gradle.kts b/worldedit-libs/fabric/build.gradle.kts index 388618cea1..3f6c7e06cb 100644 --- a/worldedit-libs/fabric/build.gradle.kts +++ b/worldedit-libs/fabric/build.gradle.kts @@ -1 +1,3 @@ -applyLibrariesConfiguration() +plugins { + id("buildlogic.libs") +} diff --git a/worldedit-libs/sponge/build.gradle.kts b/worldedit-libs/sponge/build.gradle.kts index dc241d185d..3f6c7e06cb 100644 --- a/worldedit-libs/sponge/build.gradle.kts +++ b/worldedit-libs/sponge/build.gradle.kts @@ -1,12 +1,3 @@ -applyLibrariesConfiguration() -constrainDependenciesToLibsCore() - -repositories { - maven { - name = "Sponge" - url = uri("https://repo.spongepowered.org/maven") - } -} -dependencies { - "shade"("net.kyori:text-adapter-spongeapi:3.0.6") +plugins { + id("buildlogic.libs") } diff --git a/worldedit-mod/build.gradle.kts b/worldedit-mod/build.gradle.kts index 66fa8cd67b..e9d64c7453 100644 --- a/worldedit-mod/build.gradle.kts +++ b/worldedit-mod/build.gradle.kts @@ -1,21 +1,127 @@ import net.fabricmc.loom.task.RemapJarTask +import java.util.jar.Attributes +import java.util.jar.Manifest plugins { base + id("buildlogic.common") } -applyCommonConfiguration() +open class MergeManifests : DefaultTask() { + @InputFiles + val inputManifests: ConfigurableFileCollection = project.objects.fileCollection() + + @OutputFile + val outputManifest: RegularFileProperty = project.objects.fileProperty() + + companion object { + private fun assertEqual(old: Any?, new: Any?, key: Attributes.Name): Any? { + assert(old == new) { "$key mismatch: $old != $new" } + return old + } + + private fun throwException(old: Any?, new: Any?, key: Attributes.Name) { + throw IllegalStateException("Duplicate $key: was $old, trying to add $new") + } + + private val MERGE_LOGIC = mapOf( + Attributes.Name.MANIFEST_VERSION to ::assertEqual, + Attributes.Name.IMPLEMENTATION_VERSION to ::assertEqual, + Attributes.Name.MAIN_CLASS to ::assertEqual, + Attributes.Name("WorldEdit-Version") to ::assertEqual, + Attributes.Name("WorldEdit-Kind") to ::assertEqual, + ) + } + + private fun mergeAttributes(aggregate: Attributes, input: Attributes) { + input.forEach { (key, value) -> + aggregate.merge(key, value) { old, new -> + val mergeLogic = MERGE_LOGIC[key] ?: ::throwException + mergeLogic(old, new, key as Attributes.Name) + } + } + } + + @TaskAction + fun merge() { + val manifest = Manifest() + inputManifests.forEach { manifestFile -> + val inputManifest = manifestFile.inputStream().use { Manifest(it) } + mergeAttributes(manifest.mainAttributes, inputManifest.mainAttributes) + inputManifest.entries.forEach { (key, value) -> + val aggregate = manifest.entries.computeIfAbsent(key) { Attributes() } + mergeAttributes(aggregate, value) + } + } + outputManifest.asFile.get().outputStream().use { + manifest.write(it) + } + } +} + +val fabricZipTree = zipTree( + project(":worldedit-fabric").tasks.named("remapShadowJar").flatMap { it.archiveFile } +) + +val mergeManifests = tasks.register("mergeManifests") { + // TODO Extract forgeZipTree outside of this task when possible + val forgeZipTree = zipTree( + project(":worldedit-neoforge").tasks.named("jarJar").map { it.outputs.files.singleFile } + ) + + dependsOn( + project(":worldedit-fabric").tasks.named("remapShadowJar"), + project(":worldedit-neoforge").tasks.named("jarJar") + ) + inputManifests.from( + fabricZipTree.matching { include("META-INF/MANIFEST.MF") }, + forgeZipTree.matching { include("META-INF/MANIFEST.MF") } + ) + outputManifest.set(project.layout.buildDirectory.file("mergeManifests/MANIFEST.MF")) +} tasks.register("jar") { - val remapFabric = project(":worldedit-fabric").tasks.named("remapShadowJar") + val forgeZipTree = zipTree( + project(":worldedit-neoforge").tasks.named("jarJar").map { it.outputs.files.singleFile } + ) + dependsOn( - remapFabric, - project(":worldedit-forge").tasks.named("reobfShadowJar") + project(":worldedit-fabric").tasks.named("remapShadowJar"), + project(":worldedit-neoforge").tasks.named("jarJar"), + mergeManifests ) - from(zipTree({remapFabric.get().archiveFile})) - from(zipTree({project(":worldedit-forge").tasks.getByName("shadowJar").outputs.files.singleFile})) + from(fabricZipTree) { + exclude("META-INF/MANIFEST.MF") + } + from(forgeZipTree) { + exclude("META-INF/MANIFEST.MF") + // Duplicated first-party files + exclude("META-INF/services/org.enginehub.piston.CommandManagerService") + exclude("lang/") + // No-brainer library excludes + exclude("com/sk89q/jchronic/") + exclude("com/sk89q/jnbt/") + exclude("com/sk89q/minecraft/") + exclude("com/sk89q/util/") + exclude("com/thoughtworks/") + exclude("net/royawesome/") + exclude("org/enginehub/piston/") + exclude("org/enginehub/linbus/") + exclude("net/kyori/examination/") + // Exclude worldedit-core + exclude { + val pathString = it.relativePath.pathString + pathString.startsWith("com/sk89q/worldedit/") && !pathString.startsWith("com/sk89q/worldedit/neoforge/") + } + // Questionable excludes. So far the two files from each jar are the same. + exclude("defaults/worldedit.properties") + exclude("pack.mcmeta") + } + manifest { + from(mergeManifests.flatMap { it.outputManifest }) + } - duplicatesStrategy = DuplicatesStrategy.EXCLUDE + duplicatesStrategy = DuplicatesStrategy.FAIL archiveClassifier.set("dist") } diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 7f5464a2ae..9fa57c9dc1 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -1,63 +1,98 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.spongepowered.gradle.plugin.config.PluginLoaders +import org.spongepowered.plugin.metadata.model.PluginDependency plugins { - id("org.spongepowered.gradle.plugin") + alias(libs.plugins.sponge.spongegradle) + id("org.spongepowered.gradle.vanilla") + `java-library` + id("buildlogic.platform") } -applyPlatformAndCoreConfiguration() -applyShadowConfiguration() - -// I can't believe sponge sets this in a base plugin with no opt-out -convention.getPlugin(JavaPluginConvention::class.java).apply { - setSourceCompatibility(null) - setTargetCompatibility(null) +platform { + kind = buildlogic.WorldEditKind.Mod + includeClasspath = true } -repositories { - maven { url = uri("https://repo.codemc.org/repository/maven-public") } +minecraft { + injectRepositories(false) + version(libs.versions.sponge.minecraft.get()) } -dependencies { - api(project(":worldedit-core")) - api(project(":worldedit-libs:sponge")) - api("org.spongepowered:spongeapi:7.1.0") { - exclude(group = "org.slf4j", module = "slf4j-api") +repositories { + maven { + name = "EngineHub Repository" + url = uri("https://maven.enginehub.org/repo/") } - implementation(enforcedPlatform("org.apache.logging.log4j:log4j-bom:2.8.1") { - because("Sponge 8 provides Log4J at 2.8.1") - }) - api("org.apache.logging.log4j:log4j-api") - api("org.bstats:bstats-sponge:1.7") - testImplementation("org.mockito:mockito-core:5.15.2") -} - -<<<<<<< HEAD -addJarManifest(WorldEditKind.Mod, includeClasspath = true) -======= -tasks.named("jar") { - manifest { - attributes("Class-Path" to CLASSPATH, - "WorldEdit-Version" to project.version) + mavenCentral() + verifyEngineHubRepositories() + afterEvaluate { + verifyEngineHubRepositories() } } ->>>>>>> 18a55bc14... Add new experimental snapshot API (#524) -tasks.named("shadowJar") { - dependencies { - relocate ("org.bstats", "com.sk89q.worldedit.sponge.bstats") { - include(dependency("org.bstats:bstats-sponge:1.5")) +sponge { + injectRepositories(false) + apiVersion(libs.versions.sponge.api.asProvider().get()) + license("GPL-3.0-or-later") + plugin("worldedit") { + loader { + name(PluginLoaders.JAVA_PLAIN) + version("1.0") + } + displayName("WorldEdit") + version(project.ext["internalVersion"].toString()) + entrypoint("com.sk89q.worldedit.sponge.SpongeWorldEdit") + description("WorldEdit is an easy-to-use in-game world editor for Minecraft, supporting both single- and multi-player.") + links { + homepage("https://enginehub.org/worldedit/") + source("https://github.com/EngineHub/WorldEdit") + issues("https://github.com/EngineHub/WorldEdit/issues") + } + contributor("EngineHub") { + description("Various members of the EngineHub team") + } + dependency("spongeapi") { + loadOrder(PluginDependency.LoadOrder.AFTER) + optional(false) } } } -if (project.hasProperty("signing")) { - apply(plugin = "signing") +dependencies { + "api"(project(":worldedit-core")) + "api"(project(":worldedit-libs:sponge")) + + "api"(libs.log4j.api) + "implementation"(libs.bstats.sponge) + "implementation"(libs.fastutil) + "testImplementation"(libs.mockito.core) + + // Silence some warnings, since apparently this isn't on the compile classpath like it should be. + "compileOnly"(libs.errorprone.annotations) +} + +configure { + archivesName.set("${project.name}-api${libs.versions.sponge.api.major.get()}") +} + +tasks.named("shadowJar") { + dependencies { + include(dependency("org.bstats:")) + include(dependency("org.antlr:antlr4-runtime")) + include(dependency("com.sk89q.lib:jlibnoise")) - configure { - sign("shadowJar") + relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4") + relocate("org.bstats", "com.sk89q.worldedit.sponge.bstats") + relocate("net.royawesome.jlibnoise", "com.sk89q.worldedit.jlibnoise") } +} +tasks.named("assemble").configure { + dependsOn("shadowJar") +} - tasks.named("build").configure { - dependsOn("signShadowJar") +configure { + publications.named("maven") { + from(components["java"]) } }