From 0e0dba927e3ebc8df8ad50bf87e4f11c3ce6cb47 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:02:50 -0500 Subject: [PATCH 01/14] build(gradle): modernize plugin tooling and shaded artifact --- .gitattributes | 11 + build.gradle.kts | 376 +++++++++++------- gradle.properties | 9 +- gradle/libs.versions.toml | 58 +++ gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- settings.gradle.kts | 60 ++- .../java/me/glaremasters/guilds/Guilds.java | 28 -- 8 files changed, 374 insertions(+), 172 deletions(-) create mode 100644 .gitattributes create mode 100644 gradle/libs.versions.toml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..83fcd720b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* text=auto + +*.sh text eol=lf +gradlew text eol=lf +*.bat text eol=crlf +*.ps1 text eol=crlf + +*.jar binary +*.png binary +*.jpg binary +*.gif binary \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 59ba55526..72d363949 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,181 +1,283 @@ -import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin -import net.kyori.indra.IndraPlugin -import net.kyori.indra.IndraPublishingPlugin -import org.jetbrains.dokka.gradle.DokkaTask -import java.net.URL +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.gradle.language.jvm.tasks.ProcessResources +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("java") - id("org.jetbrains.kotlin.jvm") version "2.1.0" - id("net.kyori.indra") version "3.1.3" - id("net.kyori.indra.publishing") version "3.1.3" - id("net.kyori.indra.license-header") version "3.1.3" - id("com.gradleup.shadow") version "8.3.5" - id("io.github.slimjar") version "1.3.0" - id("xyz.jpenilla.run-paper") version "2.3.1" - id("com.github.ben-manes.versions") version "0.51.0" - id("org.jetbrains.dokka") version "1.9.20" + `java-library` + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.indra) + alias(libs.plugins.indra.publishing) + // TODO: Reintroduce license header enforcement with a Gradle 9-compatible plugin. + // alias(libs.plugins.indra.license.header) + alias(libs.plugins.shadow) + alias(libs.plugins.versions) + alias(libs.plugins.dokka) } group = "me.glaremasters" version = "3.5.7.2-SNAPSHOT" +val pluginVersion = version.toString() + base { - archivesBaseName = "Guilds" + archivesName.set("Guilds") } -apply { - plugin() - plugin() - plugin() +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } + + withSourcesJar() + withJavadocJar() } -repositories { - mavenCentral() - maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") { - content { - includeGroup("org.bukkit") - includeGroup("org.spigotmc") - } - } - maven("https://oss.sonatype.org/content/groups/public/") - maven("https://repo.aikar.co/content/groups/aikar/") { - content { includeGroup("co.aikar") } - } - maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") +kotlin { + jvmToolchain(21) +} - maven("https://repo.codemc.org/repository/maven-public/") { - content { includeGroup("org.codemc.worldguardwrapper") } +dependencies { + /* + * Bundled into the final plugin jar by shadowJar. + */ + implementation(libs.acf.paper) + implementation(libs.bstats.bukkit) + implementation(libs.taskchain.bukkit) + implementation(libs.worldguardwrapper) + implementation(libs.configme) + implementation(libs.jsonconfiguration) + implementation(libs.xseries) + implementation(libs.adventure.platform.bukkit) + implementation(libs.triumph.gui) + implementation(libs.hikaricp) + implementation(libs.jdbi.core) + implementation(libs.jdbi.sqlobject) + implementation(libs.mariadb.client) + implementation(libs.kotlin.stdlib) + + /* + * Provided by the server or by other plugins at runtime. + * These must not be bundled or relocated. + */ + compileOnly(libs.spigot.api) + compileOnly(libs.vault) + compileOnly(libs.placeholderapi) + compileOnly(libs.authlib) +} + +tasks.withType().configureEach { + compilerOptions { + javaParameters.set(true) + jvmTarget.set(JvmTarget.JVM_1_8) } - maven("https://repo.glaremasters.me/repository/public/") } -dependencies { - implementation("io.github.slimjar:slimjar:1.2.7") - implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT") - implementation("org.bstats:bstats-bukkit:3.0.2") - implementation("co.aikar:taskchain-bukkit:3.7.2") - implementation("org.codemc.worldguardwrapper:worldguardwrapper:1.1.9-SNAPSHOT") - implementation("ch.jalu:configme:1.3.0") - implementation("com.dumptruckman.minecraft:JsonConfiguration:1.1") - implementation("com.github.cryptomorin:XSeries:12.1.0") - implementation("net.kyori:adventure-platform-bukkit:4.3.4") - implementation("dev.triumphteam:triumph-gui:3.1.10") - implementation("com.zaxxer:HikariCP:4.0.3") - implementation("org.jdbi:jdbi3-core:3.8.2") - implementation("org.jdbi:jdbi3-sqlobject:3.8.2") - implementation("org.mariadb.jdbc:mariadb-java-client:2.7.2") - - compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") - compileOnly("net.milkbowl:vault:1.7") - compileOnly("me.clip:placeholderapi:2.11.6") - compileOnly("com.mojang:authlib:1.5.21") - - slim("org.jetbrains.kotlin:kotlin-stdlib") +tasks.withType().configureEach { + options.release.set(8) + options.encoding = "UTF-8" + options.compilerArgs.addAll( + listOf( + "-parameters", + "-Xlint:-classfile" + ) + ) +} + +tasks.named("jar") { + enabled = false } -tasks.withType().configureEach { - dokkaSourceSets { - named("main") { - moduleName.set("Guilds") +tasks.named("processResources") { + filteringCharset = "UTF-8" - includes.from(project.files(), "Module.md") + /* + * Configuration-cache safe: + * - compute a plain serializable value during configuration + * - declare it as an input + * - capture only this map in the CopySpec action + */ + val resourceTokens = mapOf( + "version" to version.toString() + ) - sourceLink { - localDirectory.set(projectDir.resolve("src")) - remoteUrl.set(URL("https://github.com/guilds-plugin/Guilds/tree/master/src")) - remoteLineSuffix.set("#L") - } - } + inputs.properties(resourceTokens) + + filesMatching("plugin.yml") { + expand(resourceTokens) } } -tasks { - build { - dependsOn(named("shadowJar")) - dependsOn(named("slimJar")) +tasks.named("shadowJar") { + archiveClassifier.set("") + archiveBaseName.set("Guilds") + archiveVersion.set(pluginVersion) + + /* + * Shadow's default is already runtimeClasspath, but keeping this explicit makes + * the intent clear: implementation/runtime dependencies are shaded; compileOnly + * APIs are not. + */ + configurations = project.configurations.runtimeClasspath.map { listOf(it) } + + /* + * Required for libraries that use META-INF/services, such as JDBC drivers and + * libraries with service-loader based discovery. + */ + mergeServiceFiles() + + /* + * Avoid invalid signature metadata after classes/resources are transformed. + */ + exclude( + "META-INF/*.SF", + "META-INF/*.DSA", + "META-INF/*.RSA", + "META-INF/INDEX.LIST", + "module-info.class" + ) + + /* + * Reproducible jar output. + */ + isReproducibleFileOrder = true + isPreserveFileTimestamps = false + + val relocationRoot = "me.glaremasters.guilds.libs" + + /* + * ACF + */ + relocate("co.aikar.commands", "$relocationRoot.acf.commands") { + skipStringConstants = true + } + relocate("co.aikar.locales", "$relocationRoot.acf.locales") { + skipStringConstants = true } - indra { - mitLicense() + /* + * TaskChain + */ + relocate("co.aikar.taskchain", "$relocationRoot.taskchain") { + skipStringConstants = true + } - javaVersions { - target(8) - } + /* + * bStats + */ + relocate("org.bstats", "$relocationRoot.bstats") { + skipStringConstants = true + } - github("guilds-plugin", "guilds") { - publishing(true) - } + /* + * WorldGuardWrapper. + * + * Do not relocate WorldGuard, WorldEdit, Bukkit, or Spigot APIs themselves. + * Only relocate the wrapper library. + */ + relocate("org.codemc.worldguardwrapper", "$relocationRoot.worldguardwrapper") { + skipStringConstants = true + } - publishAllTo("guilds", "https://repo.glaremasters.me/repository/guilds/") + /* + * Config libraries + */ + relocate("ch.jalu.configme", "$relocationRoot.configme") { + skipStringConstants = true + } + relocate("com.dumptruckman.minecraft", "$relocationRoot.jsonconfiguration") { + skipStringConstants = true } - compileKotlin { - kotlinOptions.javaParameters = true - kotlinOptions.jvmTarget = "1.8" + /* + * XSeries + */ + relocate("com.cryptomorin.xseries", "$relocationRoot.xseries") { + skipStringConstants = true } - compileJava { - options.compilerArgs = listOf("-parameters") + /* + * Adventure platform and Kyori internals. + * + * This is safe when Adventure is used internally by the plugin. + * If your public API exposes Adventure Component types to other plugins, + * do not relocate net.kyori.adventure. + */ + relocate("net.kyori.adventure", "$relocationRoot.adventure") { + skipStringConstants = true + } + relocate("net.kyori.examination", "$relocationRoot.examination") { + skipStringConstants = true + } + relocate("net.kyori.option", "$relocationRoot.kyori.option") { + skipStringConstants = true } - runServer { - minecraftVersion("1.21.1") + /* + * Triumph GUI + */ + relocate("dev.triumphteam.gui", "$relocationRoot.triumph.gui") { + skipStringConstants = true } - license { - header.set(resources.text.fromFile(rootProject.file("LICENSE"))) - exclude("me/glaremasters/guilds/scanner/ZISScanner.java") - exclude("me/glaremasters/guilds/updater/UpdateChecker.java") - exclude("me/glaremasters/guilds/utils/PremiumFun.java") + /* + * Database stack + */ + relocate("com.zaxxer.hikari", "$relocationRoot.hikari") { + skipStringConstants = true + } + relocate("org.jdbi", "$relocationRoot.jdbi") { + skipStringConstants = true + } + relocate("org.mariadb.jdbc", "$relocationRoot.mariadb") { + skipStringConstants = true } - shadowJar { - fun relocates(vararg dependencies: String) { - dependencies.forEach { - val split = it.split(".") - val name = split.last() - relocate(it, "me.glaremasters.guilds.libs.$name") - } - } + /* + * Common transitive libraries pulled by the database/config stack. + * These are intentionally narrow to avoid relocating server/plugin APIs. + */ + relocate("org.antlr", "$relocationRoot.antlr") { + skipStringConstants = true + } + relocate("org.checkerframework", "$relocationRoot.checkerframework") { + skipStringConstants = true + } + relocate("org.intellij.lang.annotations", "$relocationRoot.intellij.annotations") { + skipStringConstants = true + } + relocate("org.jetbrains.annotations", "$relocationRoot.jetbrains.annotations") { + skipStringConstants = true + } +} - relocates( - "io.github.slimjar" - ) +tasks.named("assemble") { + dependsOn(tasks.named("shadowJar")) +} - minimize() - - archiveClassifier.set(null as String?) - archiveFileName.set("Guilds-${project.version}.jar") - destinationDirectory.set(rootProject.tasks.shadowJar.get().destinationDirectory.get()) - } - - slimJar { - fun relocates(vararg dependencies: String) { - dependencies.forEach { - val split = it.split(".") - val name = split.last() - relocate(it, "me.glaremasters.guilds.libs.$name") - } - } - - relocates( - "org.bstats", - "co.aikar.commands", - "co.aikar.locales", - "co.aikar.taskchain", - "ch.jalu.configme", - "com.zaxxer.hikari", - "org.jdbi", - "org.mariadb.jdbc", - "dev.triumphteam.gui", - "net.kyori", - "com.cryptomorin.xseries", - "kotlin" - ) +tasks.named("build") { + dependsOn(tasks.named("shadowJar")) +} + +indra { + // TODO: Re-enable after replacing legacy license-header enforcement. + // mitLicense() + + javaVersions { + target(8) } - processResources { - expand("version" to rootProject.version) + github("guilds-plugin", "guilds") { + publishing(true) } + + publishAllTo("guilds", "https://repo.glaremasters.me/repository/guilds/") } + +// TODO: Reintroduce license header enforcement with a Gradle 9-compatible plugin. +// license { +// header.set(resources.text.fromFile(rootProject.file("LICENSE"))) +// exclude("me/glaremasters/guilds/scanner/ZISScanner.java") +// exclude("me/glaremasters/guilds/updater/UpdateChecker.java") +// exclude("me/glaremasters/guilds/utils/PremiumFun.java") +// } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index e110e410f..0d0e0bb71 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,8 @@ -org.gradle.jvmargs='-Dfile.encoding=UTF-8' +org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configuration-cache=true + +kotlin.code.style=official +kotlin.incremental=true +kotlin.stdlib.default.dependency=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..6c79d0097 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,58 @@ +[versions] +kotlin = "2.1.0" +indra = "3.1.3" +shadow = "9.4.1" +run-paper = "3.0.2" +versions-plugin = "0.52.0" +dokka = "2.2.0" + +minecraft-spigot-api = "26.1.2-R0.1-SNAPSHOT" +minecraft-run = "26.1.2" + +slimjar = "1.2.7" +acf = "0.5.1-SNAPSHOT" +bstats = "3.0.2" +taskchain = "3.7.2" +worldguardwrapper = "1.1.9-SNAPSHOT" +configme = "1.3.0" +jsonconfiguration = "1.1" +xseries = "12.1.0" +adventure-platform-bukkit = "4.3.4" +triumph-gui = "3.1.10" +hikaricp = "4.0.3" +jdbi = "3.8.2" +mariadb = "2.7.2" +vault = "1.7" +placeholderapi = "2.11.6" +authlib = "1.5.21" + +[libraries] +kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } +acf-paper = { module = "co.aikar:acf-paper", version.ref = "acf" } +bstats-bukkit = { module = "org.bstats:bstats-bukkit", version.ref = "bstats" } +taskchain-bukkit = { module = "co.aikar:taskchain-bukkit", version.ref = "taskchain" } +worldguardwrapper = { module = "org.codemc.worldguardwrapper:worldguardwrapper", version.ref = "worldguardwrapper" } +configme = { module = "ch.jalu:configme", version.ref = "configme" } +jsonconfiguration = { module = "com.dumptruckman.minecraft:JsonConfiguration", version.ref = "jsonconfiguration" } +xseries = { module = "com.github.cryptomorin:XSeries", version.ref = "xseries" } +adventure-platform-bukkit = { module = "net.kyori:adventure-platform-bukkit", version.ref = "adventure-platform-bukkit" } +triumph-gui = { module = "dev.triumphteam:triumph-gui", version.ref = "triumph-gui" } +hikaricp = { module = "com.zaxxer:HikariCP", version.ref = "hikaricp" } +jdbi-core = { module = "org.jdbi:jdbi3-core", version.ref = "jdbi" } +jdbi-sqlobject = { module = "org.jdbi:jdbi3-sqlobject", version.ref = "jdbi" } +mariadb-client = { module = "org.mariadb.jdbc:mariadb-java-client", version.ref = "mariadb" } + +spigot-api = { module = "org.spigotmc:spigot-api", version.ref = "minecraft-spigot-api" } +vault = { module = "net.milkbowl:vault", version.ref = "vault" } +placeholderapi = { module = "me.clip:placeholderapi", version.ref = "placeholderapi" } +authlib = { module = "com.mojang:authlib", version.ref = "authlib" } + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +indra = { id = "net.kyori.indra", version.ref = "indra" } +indra-publishing = { id = "net.kyori.indra.publishing", version.ref = "indra" } +indra-license-header = { id = "net.kyori.indra.license-header", version.ref = "indra" } +shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } +run-paper = { id = "xyz.jpenilla.run-paper", version.ref = "run-paper" } +versions = { id = "com.github.ben-manes.versions", version.ref = "versions-plugin" } +dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4413138c..5dd3c0121 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.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a426..b740cf133 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/settings.gradle.kts b/settings.gradle.kts index efa889075..a437cb83f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,57 @@ -/* - * This file was generated by the Gradle 'init' task. - */ +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + } +} -rootProject.name = "Guilds" +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + + repositories { + mavenCentral() + + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") { + content { + includeGroup("org.bukkit") + includeGroup("org.spigotmc") + } + } + + maven("https://oss.sonatype.org/content/groups/public/") + + maven("https://repo.aikar.co/content/groups/aikar/") { + content { + includeGroup("co.aikar") + } + } + + maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") { + content { + includeGroup("me.clip") + } + } + + maven("https://repo.codemc.org/repository/maven-public/") { + content { + includeGroup("org.codemc.worldguardwrapper") + } + } + + maven("https://repo.glaremasters.me/repository/public/") { + name = "glaremasters" + + metadataSources { + mavenPom() + artifact() + ignoreGradleMetadataRedirection() + } + } + } +} + +rootProject.name = "Guilds" \ No newline at end of file diff --git a/src/main/java/me/glaremasters/guilds/Guilds.java b/src/main/java/me/glaremasters/guilds/Guilds.java index 924b0411c..4ea402ca8 100644 --- a/src/main/java/me/glaremasters/guilds/Guilds.java +++ b/src/main/java/me/glaremasters/guilds/Guilds.java @@ -30,9 +30,6 @@ import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import io.github.slimjar.app.builder.ApplicationBuilder; -import io.github.slimjar.resolver.data.Repository; -import io.github.slimjar.resolver.mirrors.SimpleMirrorSelector; import me.glaremasters.guilds.acf.ACFHandler; import me.glaremasters.guilds.actions.ActionHandler; import me.glaremasters.guilds.api.GuildsAPI; @@ -110,31 +107,6 @@ public static GuildsAPI getApi() { return Guilds.api; } - @Override - public void onLoad() { - final Logger logger = getLogger(); - final File dependencyDirectory = new File(getDataFolder(), "Libraries"); - logger.log(Level.INFO, "Loading Libraries..."); - logger.log(Level.INFO, "Note: This might take a few minutes on first run. Kindly ensure internet connectivity."); - final Instant startInstant = Instant.now(); - try { - ApplicationBuilder - .appending("Guilds") - .downloadDirectoryPath(dependencyDirectory.toPath()) - .internalRepositories(Lists.newArrayList( - new Repository(new URL("https://repo.glaremasters.me/repository/public/")), - new Repository(new URL(SimpleMirrorSelector.DEFAULT_CENTRAL_MIRROR_URL)))) - .build(); - final Instant endInstant = Instant.now(); - final long timeTaken = Duration.between(startInstant, endInstant).toMillis(); - final double timeTakenSeconds = timeTaken / 1000.0; - logger.log(Level.INFO, "Loaded libraries in {0} seconds", timeTakenSeconds); - } catch (IOException | ReflectiveOperationException | URISyntaxException | NoSuchAlgorithmException exception) { - logger.log(Level.SEVERE, "Unable to load dependencies... Please ensure an active Internet connection on first run!"); - exception.printStackTrace(); - } - } - @Override public void onDisable() { if (checkVault() && economy != null) { From d0d67da2b0aa23022dbe8ca220b59526b9de9be0 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:07:48 -0500 Subject: [PATCH 02/14] build(gradle): restore license headers with spotless --- ...kotlin-compiler-3627957346424093207.salive | 0 HEADER.txt | 8 ++ build.gradle.kts | 88 +++++++++++++++---- gradle/libs.versions.toml | 10 ++- 4 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 .kotlin/sessions/kotlin-compiler-3627957346424093207.salive create mode 100644 HEADER.txt diff --git a/.kotlin/sessions/kotlin-compiler-3627957346424093207.salive b/.kotlin/sessions/kotlin-compiler-3627957346424093207.salive new file mode 100644 index 000000000..e69de29bb diff --git a/HEADER.txt b/HEADER.txt new file mode 100644 index 000000000..cd2238be4 --- /dev/null +++ b/HEADER.txt @@ -0,0 +1,8 @@ +/* + * This file is part of Guilds. + * + * Guilds is free software: you can redistribute it and/or modify + * it under the terms of the MIT License. + * + * Copyright (c) GlareMasters + */ \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 72d363949..92d6c4cc1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,7 @@ +import com.diffplug.gradle.spotless.FormatExtension +import com.diffplug.gradle.spotless.SpotlessExtension import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import net.kyori.indra.licenser.spotless.IndraSpotlessLicenserExtension import org.gradle.language.jvm.tasks.ProcessResources import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -8,8 +11,8 @@ plugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.indra) alias(libs.plugins.indra.publishing) - // TODO: Reintroduce license header enforcement with a Gradle 9-compatible plugin. - // alias(libs.plugins.indra.license.header) + alias(libs.plugins.spotless) + alias(libs.plugins.indra.licenser.spotless) alias(libs.plugins.shadow) alias(libs.plugins.versions) alias(libs.plugins.dokka) @@ -63,7 +66,67 @@ dependencies { compileOnly(libs.spigot.api) compileOnly(libs.vault) compileOnly(libs.placeholderapi) - compileOnly(libs.authlib) + compileOnly(libs.jsr305) + compileOnly(libs.authlib) { + isTransitive = false + } +} + +extensions.configure { + fun FormatExtension.standardOptions() { + endWithNewline() + trimTrailingWhitespace() + leadingTabsToSpaces(4) + toggleOffOn("@formatter:off", "@formatter:on") + } + + java { + target("src/**/*.java") + + targetExclude( + "src/**/me/glaremasters/guilds/scanner/ZISScanner.java", + "src/**/me/glaremasters/guilds/updater/UpdateChecker.java", + "src/**/me/glaremasters/guilds/utils/PremiumFun.java" + ) + + standardOptions() + formatAnnotations() + removeUnusedImports() + } + + kotlin { + target("src/**/*.kt") + + standardOptions() + } + + kotlinGradle { + target("*.gradle.kts", "gradle/**/*.gradle.kts") + + standardOptions() + } +} + +extensions.configure { + /* + * Create HEADER.txt at the project root. + * + * Example: + * + * /* + * * This file is part of Guilds. + * * + * * Guilds is free software: you can redistribute it and/or modify + * * it under the terms of the MIT License. + * * + * * Copyright (c) GlareMasters + * */ + */ + licenseHeaderFile(rootProject.file("HEADER.txt")) + + property("name", "Guilds") + property("organization", "GlareMasters") + property("url", "https://github.com/guilds-plugin/guilds") } tasks.withType().configureEach { @@ -98,7 +161,7 @@ tasks.named("processResources") { * - capture only this map in the CopySpec action */ val resourceTokens = mapOf( - "version" to version.toString() + "version" to pluginVersion ) inputs.properties(resourceTokens) @@ -259,9 +322,12 @@ tasks.named("build") { dependsOn(tasks.named("shadowJar")) } +tasks.named("check") { + dependsOn(tasks.named("spotlessCheck")) +} + indra { - // TODO: Re-enable after replacing legacy license-header enforcement. - // mitLicense() + mitLicense() javaVersions { target(8) @@ -272,12 +338,4 @@ indra { } publishAllTo("guilds", "https://repo.glaremasters.me/repository/guilds/") -} - -// TODO: Reintroduce license header enforcement with a Gradle 9-compatible plugin. -// license { -// header.set(resources.text.fromFile(rootProject.file("LICENSE"))) -// exclude("me/glaremasters/guilds/scanner/ZISScanner.java") -// exclude("me/glaremasters/guilds/updater/UpdateChecker.java") -// exclude("me/glaremasters/guilds/utils/PremiumFun.java") -// } \ No newline at end of file +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6c79d0097..e8c273deb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,10 +1,12 @@ [versions] kotlin = "2.1.0" -indra = "3.1.3" +indra = "4.0.0" shadow = "9.4.1" run-paper = "3.0.2" versions-plugin = "0.52.0" dokka = "2.2.0" +spotless = "7.2.1" +jsr305 = "3.0.2" minecraft-spigot-api = "26.1.2-R0.1-SNAPSHOT" minecraft-run = "26.1.2" @@ -46,13 +48,15 @@ spigot-api = { module = "org.spigotmc:spigot-api", version.ref = "minecraft-spig vault = { module = "net.milkbowl:vault", version.ref = "vault" } placeholderapi = { module = "me.clip:placeholderapi", version.ref = "placeholderapi" } authlib = { module = "com.mojang:authlib", version.ref = "authlib" } +jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } indra = { id = "net.kyori.indra", version.ref = "indra" } indra-publishing = { id = "net.kyori.indra.publishing", version.ref = "indra" } -indra-license-header = { id = "net.kyori.indra.license-header", version.ref = "indra" } +indra-licenser-spotless = { id = "net.kyori.indra.licenser.spotless", version.ref = "indra" } shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } run-paper = { id = "xyz.jpenilla.run-paper", version.ref = "run-paper" } versions = { id = "com.github.ben-manes.versions", version.ref = "versions-plugin" } -dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } \ No newline at end of file +dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } +spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } \ No newline at end of file From dd4d3657c35f9fbd58533610ca5f8b7283bbcc96 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:10:51 -0500 Subject: [PATCH 03/14] build(deps): update Gradle tooling plugins --- .kotlin/sessions/kotlin-compiler-3627957346424093207.salive | 0 gradle/libs.versions.toml | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 .kotlin/sessions/kotlin-compiler-3627957346424093207.salive diff --git a/.kotlin/sessions/kotlin-compiler-3627957346424093207.salive b/.kotlin/sessions/kotlin-compiler-3627957346424093207.salive deleted file mode 100644 index e69de29bb..000000000 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e8c273deb..03e1eb2fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,9 +3,9 @@ kotlin = "2.1.0" indra = "4.0.0" shadow = "9.4.1" run-paper = "3.0.2" -versions-plugin = "0.52.0" +versions-plugin = "0.54.0" dokka = "2.2.0" -spotless = "7.2.1" +spotless = "8.5.1" jsr305 = "3.0.2" minecraft-spigot-api = "26.1.2-R0.1-SNAPSHOT" From 3afa15b44c8ca6f81f71939a9b25fe52a2759dea Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:12:16 -0500 Subject: [PATCH 04/14] build(deps): update bundled runtime libraries --- gradle/libs.versions.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 03e1eb2fc..c6053e879 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,17 +13,17 @@ minecraft-run = "26.1.2" slimjar = "1.2.7" acf = "0.5.1-SNAPSHOT" -bstats = "3.0.2" +bstats = "3.2.1" taskchain = "3.7.2" worldguardwrapper = "1.1.9-SNAPSHOT" -configme = "1.3.0" +configme = "1.4.1" jsonconfiguration = "1.1" xseries = "12.1.0" -adventure-platform-bukkit = "4.3.4" -triumph-gui = "3.1.10" +adventure-platform-bukkit = "4.4.1" +triumph-gui = "3.1.11" hikaricp = "4.0.3" jdbi = "3.8.2" -mariadb = "2.7.2" +mariadb = "3.5.8" vault = "1.7" placeholderapi = "2.11.6" authlib = "1.5.21" From 8fa719be1f7e458fb249b19c4ca40a2ac0cbc253 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:22:36 -0500 Subject: [PATCH 05/14] build(deps): update placeholderapi --- .kotlin/sessions/kotlin-compiler-2217947863838202236.salive | 0 gradle/libs.versions.toml | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .kotlin/sessions/kotlin-compiler-2217947863838202236.salive diff --git a/.kotlin/sessions/kotlin-compiler-2217947863838202236.salive b/.kotlin/sessions/kotlin-compiler-2217947863838202236.salive new file mode 100644 index 000000000..e69de29bb diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c6053e879..67b83e83a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,12 +20,13 @@ configme = "1.4.1" jsonconfiguration = "1.1" xseries = "12.1.0" adventure-platform-bukkit = "4.4.1" +# 3.1.13 changes GUI constructor compatibility; current GUI classes still extend old constructors. triumph-gui = "3.1.11" hikaricp = "4.0.3" jdbi = "3.8.2" mariadb = "3.5.8" vault = "1.7" -placeholderapi = "2.11.6" +placeholderapi = "2.12.2" authlib = "1.5.21" [libraries] From 5ae5f9c47db40e1e0c69aa7763f5a9e7a6c1e23a Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:23:27 -0500 Subject: [PATCH 06/14] build(deps): update xseries --- .gitignore | 1 + .kotlin/sessions/kotlin-compiler-2217947863838202236.salive | 0 gradle/libs.versions.toml | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 .kotlin/sessions/kotlin-compiler-2217947863838202236.salive diff --git a/.gitignore b/.gitignore index bf9baa5a3..92ceca277 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ build # IntelliJ .idea +.kotlin out diff --git a/.kotlin/sessions/kotlin-compiler-2217947863838202236.salive b/.kotlin/sessions/kotlin-compiler-2217947863838202236.salive deleted file mode 100644 index e69de29bb..000000000 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 67b83e83a..154a2c428 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ taskchain = "3.7.2" worldguardwrapper = "1.1.9-SNAPSHOT" configme = "1.4.1" jsonconfiguration = "1.1" -xseries = "12.1.0" +xseries = "13.7.0" adventure-platform-bukkit = "4.4.1" # 3.1.13 changes GUI constructor compatibility; current GUI classes still extend old constructors. triumph-gui = "3.1.11" From a59d50d9d025b489063881c00c68c61435c0bc43 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:25:25 -0500 Subject: [PATCH 07/14] build(deps): update jdbi --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 154a2c428..4d2aee6df 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ adventure-platform-bukkit = "4.4.1" # 3.1.13 changes GUI constructor compatibility; current GUI classes still extend old constructors. triumph-gui = "3.1.11" hikaricp = "4.0.3" -jdbi = "3.8.2" +jdbi = "3.53.0" mariadb = "3.5.8" vault = "1.7" placeholderapi = "2.12.2" From dafe9a1c385ecef8d65b35fc5d8abe0815480843 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:42:57 -0500 Subject: [PATCH 08/14] build(run): add local minecraft server test tasks --- build.gradle.kts | 86 +++++++++++++++++++++++++++++++++++++++ gradle/libs.versions.toml | 2 - 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 92d6c4cc1..cc958cf38 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,7 @@ import net.kyori.indra.licenser.spotless.IndraSpotlessLicenserExtension import org.gradle.language.jvm.tasks.ProcessResources import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import xyz.jpenilla.runpaper.task.RunServer plugins { `java-library` @@ -16,6 +17,7 @@ plugins { alias(libs.plugins.shadow) alias(libs.plugins.versions) alias(libs.plugins.dokka) + alias(libs.plugins.run.paper) } group = "me.glaremasters" @@ -338,4 +340,88 @@ indra { } publishAllTo("guilds", "https://repo.glaremasters.me/repository/guilds/") +} + +val supportedMinecraftVersions = listOf( + "1.16.5", + "1.18.2", + "1.19.4", + "1.20.6", + "1.21.1", + "1.21.4", + "1.21.8" +) + +fun RunServer.configureGuildsRunServer( + minecraftVersion: String, + directoryName: String +) { + minecraftVersion(minecraftVersion) + runDirectory.set(layout.projectDirectory.dir("run/$directoryName")) + + pluginJars.from(tasks.named("shadowJar").flatMap { it.archiveFile }) + dependsOn(tasks.named("shadowJar")) + + downloadPlugins { + /* + * EssentialsX: + * Hangar marks this release as an external download, so run-task's + * Hangar downloader returns 404. Use GitHub Releases instead. + */ + github( + "EssentialsX", + "Essentials", + "2.21.2", + "EssentialsX-2.21.2.jar" + ) + + /* + * LuckPerms: + * Official Bukkit loader URL. + */ + url("https://download.luckperms.net/1638/bukkit/loader/LuckPerms-Bukkit-5.5.50.jar") + + /* + * Vault: + * No clean native Hangar source; use pinned release jar. + */ + url("https://github.com/MilkBowl/Vault/releases/download/1.7.3/Vault.jar") + } + + doFirst { + val serverDir = runDirectory.get().asFile + serverDir.mkdirs() + + serverDir.resolve("eula.txt").writeText( + """ + # Generated by Gradle run-paper for local Guilds development. + # By changing this setting to TRUE you are indicating your agreement to the Minecraft EULA. + # https://aka.ms/MinecraftEULA + eula=true + """.trimIndent() + System.lineSeparator() + ) + } +} + +tasks { + runServer { + configureGuildsRunServer( + minecraftVersion = supportedMinecraftVersions.last(), + directoryName = "latest" + ) + } + + supportedMinecraftVersions.forEach { minecraftVersion -> + val taskSuffix = minecraftVersion.replace(".", "_") + + register("runServer$taskSuffix") { + group = "run paper" + description = "Runs a Paper test server for Minecraft $minecraftVersion." + + configureGuildsRunServer( + minecraftVersion = minecraftVersion, + directoryName = minecraftVersion + ) + } + } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4d2aee6df..452854a5f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,9 +9,7 @@ spotless = "8.5.1" jsr305 = "3.0.2" minecraft-spigot-api = "26.1.2-R0.1-SNAPSHOT" -minecraft-run = "26.1.2" -slimjar = "1.2.7" acf = "0.5.1-SNAPSHOT" bstats = "3.2.1" taskchain = "3.7.2" From 8755fef7a979bb505a1d6b904429d39667477d6f Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:55:57 -0500 Subject: [PATCH 09/14] build(run): add minecraft test server matrix Configure local Paper test servers across the supported Minecraft range. - Add version-specific runServer tasks for legacy, modern, and latest Paper targets - Configure per-version Java toolchains for server runtime compatibility - Generate local eula.txt files before server startup - Explicitly attach the shaded Guilds jar to custom RunServer tasks - Preload Vault, LuckPerms, and EssentialsX where compatible - Exclude EssentialsX from 26.1.2 due to current Paper API version parsing issues --- build.gradle.kts | 61 +++++++++++++++++++++------------------ gradle/libs.versions.toml | 2 +- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index cc958cf38..0eb90211a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -342,22 +342,35 @@ indra { publishAllTo("guilds", "https://repo.glaremasters.me/repository/guilds/") } +val javaToolchains = extensions.getByType() + +data class MinecraftRunTarget( + val minecraftVersion: String, + val javaVersion: Int, + val directoryName: String = minecraftVersion +) + val supportedMinecraftVersions = listOf( - "1.16.5", - "1.18.2", - "1.19.4", - "1.20.6", - "1.21.1", - "1.21.4", - "1.21.8" + MinecraftRunTarget("1.8.8", 8), + MinecraftRunTarget("1.16.5", 16), + MinecraftRunTarget("1.18.2", 17), + MinecraftRunTarget("1.19.4", 17), + MinecraftRunTarget("1.20.6", 21), + MinecraftRunTarget("1.21.1", 21), + MinecraftRunTarget("1.21.4", 21), + MinecraftRunTarget("1.21.8", 21), + MinecraftRunTarget("26.1.2", 25) ) -fun RunServer.configureGuildsRunServer( - minecraftVersion: String, - directoryName: String -) { - minecraftVersion(minecraftVersion) - runDirectory.set(layout.projectDirectory.dir("run/$directoryName")) +fun RunServer.configureGuildsRunServer(target: MinecraftRunTarget) { + minecraftVersion(target.minecraftVersion) + runDirectory.set(layout.projectDirectory.dir("run/${target.directoryName}")) + + javaLauncher.set( + javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(target.javaVersion)) + } + ) pluginJars.from(tasks.named("shadowJar").flatMap { it.archiveFile }) dependsOn(tasks.named("shadowJar")) @@ -368,12 +381,7 @@ fun RunServer.configureGuildsRunServer( * Hangar marks this release as an external download, so run-task's * Hangar downloader returns 404. Use GitHub Releases instead. */ - github( - "EssentialsX", - "Essentials", - "2.21.2", - "EssentialsX-2.21.2.jar" - ) + url("https://ci.ender.zone/job/EssentialsX/lastSuccessfulBuild/artifact/jars/EssentialsX-2.22.0-dev+112-5baf239.jar") /* * LuckPerms: @@ -406,22 +414,19 @@ fun RunServer.configureGuildsRunServer( tasks { runServer { configureGuildsRunServer( - minecraftVersion = supportedMinecraftVersions.last(), - directoryName = "latest" + supportedMinecraftVersions.last().copy(directoryName = "latest") ) } - supportedMinecraftVersions.forEach { minecraftVersion -> - val taskSuffix = minecraftVersion.replace(".", "_") + supportedMinecraftVersions.forEach { target -> + val taskSuffix = target.minecraftVersion.replace(".", "_") register("runServer$taskSuffix") { group = "run paper" - description = "Runs a Paper test server for Minecraft $minecraftVersion." + description = + "Runs a Paper test server for Minecraft ${target.minecraftVersion} using Java ${target.javaVersion}." - configureGuildsRunServer( - minecraftVersion = minecraftVersion, - directoryName = minecraftVersion - ) + configureGuildsRunServer(target) } } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 452854a5f..3805b7465 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ acf = "0.5.1-SNAPSHOT" bstats = "3.2.1" taskchain = "3.7.2" worldguardwrapper = "1.1.9-SNAPSHOT" -configme = "1.4.1" +configme = "1.3.0" jsonconfiguration = "1.1" xseries = "13.7.0" adventure-platform-bukkit = "4.4.1" From 1902ab8c3fcaf098dd1fd8ee8984907ce5b300bd Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 17:59:20 -0500 Subject: [PATCH 10/14] ci(gradle): modernize github actions workflow Update the Gradle CI workflow to current GitHub Actions standards. - Use current checkout and setup-java actions - Replace deprecated gradle-build-action usage with gradle/actions/setup-gradle - Run the shaded plugin build with configuration cache enabled - Add workflow dispatch support for manual CI runs - Add concurrency control for branch and PR builds --- .github/workflows/gradle.yml | 43 +++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a47a580e3..901ab8630 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -2,23 +2,44 @@ name: Java CI with Gradle on: push: - branches: [ "master" ] + branches: + - master pull_request: - branches: [ "master" ] + branches: + - master + workflow_dispatch: permissions: contents: read + checks: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build: + name: Build runs-on: ubuntu-latest + timeout-minutes: 20 + steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '21' - - name: Setup Gradle - uses: gradle/gradle-build-action@v3 - - name: Build with Gradle - run: ./gradlew build + - name: Checkout sources + uses: actions/checkout@v6 + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: "21" + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v6 + with: + cache-provider: basic + + - name: Make Gradle wrapper executable + run: chmod +x ./gradlew + + - name: Build shaded plugin + run: ./gradlew clean shadowJar --configuration-cache --no-daemon --stacktrace \ No newline at end of file From b17ef3161a26b678d9a58d5fe51d6260e9da6f0b Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 18:37:20 -0500 Subject: [PATCH 11/14] build(deps): load kotlin runtime with quark Move Kotlin stdlib from the shaded plugin jar to Quark runtime dependency loading. - Add Quark Bukkit runtime and Gradle plugin configuration - Raise the plugin runtime baseline to Java 11 - Keep the Quark loader on the Bukkit platform for Spigot/Paper compatibility - Load Kotlin stdlib from Maven Central at plugin startup - Keep other implementation dependencies shaded and relocated - Validate runtime loading across the supported Paper test matrix --- build.gradle.kts | 32 ++++++++++++++++--- gradle/libs.versions.toml | 5 ++- settings.gradle.kts | 8 +++++ .../java/me/glaremasters/guilds/Guilds.java | 17 +++++----- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0eb90211a..bc0bf71b4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,6 +18,7 @@ plugins { alias(libs.plugins.versions) alias(libs.plugins.dokka) alias(libs.plugins.run.paper) + alias(libs.plugins.quark) } group = "me.glaremasters" @@ -42,6 +43,18 @@ kotlin { jvmToolchain(21) } +quark { + /* + * Use Bukkit for the main SpigotMC artifact. + * Paper can run Bukkit plugins, but Spigot cannot run Paper-specific loaders. + */ + platform = "bukkit" + + repositories { + maven("https://repo.maven.apache.org/maven2/") + } +} + dependencies { /* * Bundled into the final plugin jar by shadowJar. @@ -59,7 +72,14 @@ dependencies { implementation(libs.jdbi.core) implementation(libs.jdbi.sqlobject) implementation(libs.mariadb.client) - implementation(libs.kotlin.stdlib) + implementation(libs.quark.bukkit) + + /* + * Kotlin is compiled against locally, but downloaded and loaded at runtime + * by Quark to reduce the SpigotMC upload jar size. + */ + compileOnly(libs.kotlin.stdlib) + quark(libs.kotlin.stdlib) /* * Provided by the server or by other plugins at runtime. @@ -134,12 +154,12 @@ extensions.configure { tasks.withType().configureEach { compilerOptions { javaParameters.set(true) - jvmTarget.set(JvmTarget.JVM_1_8) + jvmTarget.set(JvmTarget.JVM_11) } } tasks.withType().configureEach { - options.release.set(8) + options.release.set(11) options.encoding = "UTF-8" options.compilerArgs.addAll( listOf( @@ -174,6 +194,8 @@ tasks.named("processResources") { } tasks.named("shadowJar") { + minimize() + archiveClassifier.set("") archiveBaseName.set("Guilds") archiveVersion.set(pluginVersion) @@ -332,7 +354,7 @@ indra { mitLicense() javaVersions { - target(8) + target(11) } github("guilds-plugin", "guilds") { @@ -351,7 +373,7 @@ data class MinecraftRunTarget( ) val supportedMinecraftVersions = listOf( - MinecraftRunTarget("1.8.8", 8), + MinecraftRunTarget("1.8.8", 11), MinecraftRunTarget("1.16.5", 16), MinecraftRunTarget("1.18.2", 17), MinecraftRunTarget("1.19.4", 17), diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3805b7465..6427a9997 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,6 +7,7 @@ versions-plugin = "0.54.0" dokka = "2.2.0" spotless = "8.5.1" jsr305 = "3.0.2" +quark = "1.3.0" minecraft-spigot-api = "26.1.2-R0.1-SNAPSHOT" @@ -48,6 +49,7 @@ vault = { module = "net.milkbowl:vault", version.ref = "vault" } placeholderapi = { module = "me.clip:placeholderapi", version.ref = "placeholderapi" } authlib = { module = "com.mojang:authlib", version.ref = "authlib" } jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" } +quark-bukkit = { module = "org.bxteam.quark:bukkit", version.ref = "quark" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } @@ -58,4 +60,5 @@ shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } run-paper = { id = "xyz.jpenilla.run-paper", version.ref = "run-paper" } versions = { id = "com.github.ben-manes.versions", version.ref = "versions-plugin" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } -spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } \ No newline at end of file +spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } +quark = { id = "org.bxteam.quark", version.ref = "quark" } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index a437cb83f..6f192eb17 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -51,6 +51,14 @@ dependencyResolutionManagement { ignoreGradleMetadataRedirection() } } + + maven("https://repo.bxteam.org/releases") { + name = "bxteam-releases" + + content { + includeGroup("org.bxteam.quark") + } + } } } diff --git a/src/main/java/me/glaremasters/guilds/Guilds.java b/src/main/java/me/glaremasters/guilds/Guilds.java index 4ea402ca8..5a7b9f036 100644 --- a/src/main/java/me/glaremasters/guilds/Guilds.java +++ b/src/main/java/me/glaremasters/guilds/Guilds.java @@ -27,7 +27,6 @@ import co.aikar.taskchain.BukkitTaskChainFactory; import co.aikar.taskchain.TaskChain; import co.aikar.taskchain.TaskChainFactory; -import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import me.glaremasters.guilds.acf.ACFHandler; @@ -67,16 +66,9 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; +import org.bxteam.quark.bukkit.BukkitLibraryManager; -import java.io.File; import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.security.NoSuchAlgorithmException; -import java.time.Duration; -import java.time.Instant; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Stream; public final class Guilds extends JavaPlugin { @@ -98,6 +90,7 @@ public final class Guilds extends JavaPlugin { private Permission permissions; private BukkitAudiences adventure; private ChatListener chatListener; + private BukkitLibraryManager libraryManager; public static Gson getGson() { return gson; @@ -107,6 +100,12 @@ public static GuildsAPI getApi() { return Guilds.api; } + @Override + public void onLoad() { + libraryManager = new BukkitLibraryManager(this); + libraryManager.loadFromGradle(); + } + @Override public void onDisable() { if (checkVault() && economy != null) { From 5dc18130bdd9b272861d6cb5350f28fb02ce5c09 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 18:39:52 -0500 Subject: [PATCH 12/14] docs(readme): modernize project documentation Refresh the README for the modernized Guilds build and runtime setup. - Document current Java 11+ runtime requirement - Clarify supported server environment expectations - Add Gradle build and local run-server task guidance - Mention Quark runtime dependency loading for Kotlin - Preserve support, contribution, addon, and special thanks sections --- README.md | 177 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 150 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index be417739d..d4cd33c67 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,167 @@ -[![Guilds](https://i.imgur.com/KE562QO.png)](https://github.com/guilds-plugin/Guilds) +# Guilds [![Discord](https://discordapp.com/api/guilds/164280494874165248/widget.png?style=banner2)](https://helpch.at/discord) - [![Crowdin](https://badges.crowdin.net/guilds/localized.svg)](https://crowdin.com/project/guilds) -### What is Guilds? -___ -The Guilds Project was created to offer a RPG type system to servers. -It was inspired by players like you who enjoy creating a fun and exciting environment for your server. -Guilds allows players to join interactive groups of other players, forge their own communities on your server, and compete with other guilds for dominance and control. +Guilds adds RPG-style player communities to Minecraft servers. Players can create and join guilds, build shared identities, compete with other groups, manage claims and roles, and connect with common server plugins such as Vault, LuckPerms, EssentialsX, PlaceholderAPI, and WorldGuard. + +For user documentation, see the [Guilds wiki](https://wiki.helpch.at/). +For API documentation, see the [Javadocs](https://guilds-plugin.github.io/javadocs/). + +--- + +## Requirements + +Guilds now requires **Java 11 or newer** at runtime. + +This applies even when running older Minecraft versions such as 1.8.8. The plugin may support legacy Minecraft server versions, but the JVM running the server must be Java 11+. + +Recommended Java versions for local testing: + +| Minecraft / Paper version | Recommended Java | +| --- | ---: | +| 1.8.8 | 11 | +| 1.16.5 | 16 | +| 1.18.2 | 17 | +| 1.19.4 | 17 | +| 1.20.6 | 21 | +| 1.21.1 | 21 | +| 1.21.4 | 21 | +| 1.21.8 | 21 | +| 26.1.2 | 25 | + +--- + +## Runtime dependencies + +Guilds uses [Quark](https://github.com/BX-Team/Quark) to load the Kotlin runtime at plugin startup instead of shading Kotlin directly into the plugin jar. This keeps the distributed jar smaller while preserving a normal Bukkit/Spigot/Paper plugin workflow. + +The Quark loader is configured for the **Bukkit** platform so the same artifact can run on Spigot-compatible and Paper-compatible servers. + +Server admins should allow the server to download runtime dependencies from Maven Central on first startup. If outbound network access is blocked, preload or mirror the required runtime dependencies before deploying. + +--- + +## Supported integrations + +Guilds is designed to work with common server plugins and APIs: + +| Integration | Purpose | +| --- | --- | +| Vault | Economy and permission bridge | +| LuckPerms | Permission provider through Vault | +| EssentialsX | Economy and chat-related compatibility | +| PlaceholderAPI | Placeholder expansion support | +| WorldGuard | Region and claim-related hooks | +| bStats | Anonymous plugin metrics | + +Vault is required for normal operation. Economy and permission providers must be available through Vault. + +--- + +## Building from source + +Use the Gradle wrapper: + +```bash +./gradlew clean shadowJar --no-configuration-cache +``` + +The shaded plugin jar is written to: -This plugin is for Minecraft Servers! +```text +build/libs/Guilds-.jar +``` -For more information, you can check out the [wiki](https://wiki.helpch.at/)! -Looking for the javadocs? You can see them [here](https://guilds-plugin.github.io/javadocs/)! +Configuration cache is intentionally disabled for Quark-enabled builds because Quark's generated-file task is not currently configuration-cache compatible. -### Support -___ +To check dependency updates: -Looking to get support for something? Join the Discord above to get help and discuss with others! +```bash +./gradlew dependencyUpdates --no-configuration-cache --no-parallel +``` -### Contributing -___ +--- -Do you want to help the project grow and achieve new goals? You can help us out in many ways! +## Local test servers -If you'd like to support our work and buy us a coffee, you could join our [Patreon](https://www.patreon.com/GlareMasters)! We totally understand if you can't do that so we have others ways you can help us out too: +The build includes local Paper test-server tasks powered by `run-paper`. -* Are you an active user of the plugin and want to help others with it? Check out the [issues](https://github.com/guilds-plugin/Guilds/issues) page to see if anyone has questions. You could also hop in our [Discord](https://glaremasters.me/discord) and help others out there too! -* Are you a person who speaks more than one language? Check out our translations page [here](https://crowdin.com/project/guilds) and see if you can help with your language! -* Are you a person who also likes to program? If so, you could look through the open [issues](https://github.com/guilds-plugin/Guilds/issues) and see if there's anything you'd ike to PR into the project. +Examples: -### Community Made Addons -___ +```bash +./gradlew runServer1_8_8 --no-configuration-cache +./gradlew runServer1_16_5 --no-configuration-cache +./gradlew runServer1_21_8 --no-configuration-cache +./gradlew runServer26_1_2 --no-configuration-cache +``` -* [GuildClaimAddons](https://github.com/Nerumir/GuildClaimsAddon) - An alternative addon for the claiming system in the plugin +These tasks: + +- build and attach the current Guilds jar +- create a local `eula.txt` +- run the target server with the configured Java toolchain +- preload common test plugins such as Vault, LuckPerms, and EssentialsX where compatible + +Run-server tasks are intended for local smoke testing. They are interactive and should not be used as normal CI checks. + +--- + +## Development notes + +Current modernization decisions: + +- Java runtime baseline: **Java 11+** +- Java bytecode target: **Java 11** +- Kotlin runtime: loaded at startup through Quark +- Kotlin stdlib: not shaded into the jar +- Shadow: still used for the remaining implementation dependencies +- ConfigMe: pinned to `1.3.0` for legacy Paper compatibility +- Triumph GUI: pinned to `3.1.11` until GUI constructors are migrated +- HikariCP: pinned to `4.0.3` for conservative compatibility + +Before opening a pull request, run: + +```bash +./gradlew clean shadowJar --no-configuration-cache +``` + +Optional formatting/license checks: + +```bash +./gradlew spotlessCheck --no-configuration-cache +``` + +--- + +## Contributing + +Contributions are welcome. + +Good places to help: + +- bug reports and reproduction cases +- compatibility testing across Minecraft versions +- translations on [Crowdin](https://crowdin.com/project/guilds) +- documentation improvements +- pull requests for open [GitHub issues](https://github.com/guilds-plugin/Guilds/issues) + +For support or project discussion, join the Discord linked at the top of this README. + +--- + +## Community add-ons + +- [GuildClaimsAddon](https://github.com/Nerumir/GuildClaimsAddon) — alternative addon for the claiming system + +--- + +## Special thanks -## Special Thanks ![YourKit](https://www.yourkit.com/images/yklogo.png) -YourKit supports open source projects with innovative and intelligent tools -for monitoring and profiling Java and .NET applications. -YourKit is the creator of [YourKit Java Profiler](https://www.yourkit.com/java/profiler/), [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/), and [YourKit YouMonitor](https://www.yourkit.com/youmonitor/). +YourKit supports open source projects with tools for monitoring and profiling Java and .NET applications. + +- [YourKit Java Profiler](https://www.yourkit.com/java/profiler/) +- [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/) +- [YourKit YouMonitor](https://www.yourkit.com/youmonitor/) From 4abb06ab7933b33a758ee777451add656fbc8c59 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 18:44:21 -0500 Subject: [PATCH 13/14] ci(gradle): disable configuration cache for quark build Disable Gradle configuration cache in CI while Quark is enabled. Quark's generateQuarkFiles task is not currently configuration-cache compatible and fails when Gradle attempts to serialize Project and Configuration references. - Run the CI shadowJar build with --no-configuration-cache - Keep the workflow on the modern Gradle setup action - Preserve the no-daemon stacktrace build flags --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 901ab8630..826d202b5 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -42,4 +42,4 @@ jobs: run: chmod +x ./gradlew - name: Build shaded plugin - run: ./gradlew clean shadowJar --configuration-cache --no-daemon --stacktrace \ No newline at end of file + run: ./gradlew clean shadowJar --no-configuration-cache --no-daemon --stacktrace \ No newline at end of file From 6714f02c1b5f1de0d55fa560d3ea0047ba66e5e3 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Sun, 24 May 2026 18:47:50 -0500 Subject: [PATCH 14/14] build(gradle): disable configuration cache by default Disable Gradle configuration cache while Quark is part of the normal build path. Quark's generateQuarkFiles task is not currently configuration-cache compatible, so keeping configuration cache enabled by default causes local and CI builds to fail unless every command opts out manually. - Set org.gradle.configuration-cache=false in gradle.properties - Allow normal Gradle commands to run without repeated --no-configuration-cache flags - Keep dependency and task caching unaffected --- .github/workflows/gradle.yml | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 826d202b5..2a86de945 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -42,4 +42,4 @@ jobs: run: chmod +x ./gradlew - name: Build shaded plugin - run: ./gradlew clean shadowJar --no-configuration-cache --no-daemon --stacktrace \ No newline at end of file + run: ./gradlew clean shadowJar --no-daemon --stacktrace \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 0d0e0bb71..f31d5df0d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 org.gradle.parallel=true org.gradle.caching=true -org.gradle.configuration-cache=true +org.gradle.configuration-cache=false kotlin.code.style=official kotlin.incremental=true