diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 2cbac18ad..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-language: java
-dist: trusty
-jdk:
- - oraclejdk11
-notifications:
- email: false
-before_install: chmod +x gradlew
-script: ./gradlew build -S
diff --git a/CHANGELOG.md b/CHANGELOG.md
index daf51917b..327baa8e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,29 @@
# Changelog
+## 7.0.13 (beta)
+
+* Update to 1.21.3
+* Remove max-stack-size bypass in stack command
+* Fix a falling block metadata leak. (May still be problematic on Spigot, use Paper.)
+* Fix flame enchant being blocked as entity damage on the arrow itself.
+* More Paper-specific performance enhancements for hoppers.
+
+## 7.0.12
+
+* Fix a change in the default behavior of explosion flag handling.
+
+## 7.0.11
+
+* Add support for MC 1.21.
+* Add wind-charge-burst flag which is checked along with `use` (for the interaction) or `pvp` (for the knockback).
+* Add breeze-charge-explosion flag for breeze charges (i.e. from the mob, not player wind charges).
+* Add moisture-change flag and config options.
+* Fix an error if a player logged in to an unloaded world.
+* Fix chest boat usage always being counted as ride.
+* Consider potions thrown by mobs as mob-damage.
+* Workaround spigot no longer sending block change events when a book is placed on a lectern.
+* Improve accuracy of target blocks in blacklist/build-perms events.
+
## 7.0.10
* Add support for MC 1.20.5 and 1.20.6, drop support for other 1.20 versions
diff --git a/README.md b/README.md
index a2fea6cfb..10091e9bd 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,14 @@ Please read CONTRIBUTING.md for important guidelines to follow.
Submissions must be licensed under the GNU Lesser General Public License v3.
+# Folia Inquisitors
+This Folia support is maintained by the following organizations and people:
+
+[](https://github.com/orgs/Folia-Inquisitors/repositories)
+[](https://github.com/TechnicallyCoded)
+[](https://github.com/Yomamaeatstoes)
+[](https://github.com/Loving11ish)
+
Links
-----
diff --git a/buildSrc/build.gradle.kts b/build-logic/build.gradle.kts
similarity index 51%
rename from buildSrc/build.gradle.kts
rename to build-logic/build.gradle.kts
index 5e97f6833..8c51ba4c2 100644
--- a/buildSrc/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -1,28 +1,28 @@
plugins {
`kotlin-dsl`
- kotlin("jvm") version embeddedKotlinVersion
}
repositories {
- mavenCentral()
gradlePluginPortal()
}
dependencies {
implementation(gradleApi())
- implementation("gradle.plugin.org.cadixdev.gradle:licenser:0.6.1")
- implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
- implementation("com.github.johnrengelman:shadow:8.1.1")
- implementation("org.jfrog.buildinfo:build-info-extractor-gradle:5.2.0")
+ implementation(libs.licenser)
+ implementation(libs.grgit)
+ implementation(libs.shadow)
+ implementation(libs.jfrog.buildinfo)
+ implementation(libs.gson)
+
constraints {
- val asmVersion = "[9.7,)"
+ 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:[2.10,)") {
+ 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 000000000..aa5e146f1
--- /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.artifactory-root.gradle.kts b/build-logic/src/main/kotlin/buildlogic.artifactory-root.gradle.kts
new file mode 100644
index 000000000..698fb424b
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic.artifactory-root.gradle.kts
@@ -0,0 +1,32 @@
+import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention
+import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask
+
+plugins {
+ id("com.jfrog.artifactory")
+}
+
+val ARTIFACTORY_CONTEXT_URL = "artifactory_contextUrl"
+val ARTIFACTORY_USER = "artifactory_user"
+val ARTIFACTORY_PASSWORD = "artifactory_password"
+
+if (!project.hasProperty(ARTIFACTORY_CONTEXT_URL)) ext[ARTIFACTORY_CONTEXT_URL] = "http://localhost"
+if (!project.hasProperty(ARTIFACTORY_USER)) ext[ARTIFACTORY_USER] = "guest"
+if (!project.hasProperty(ARTIFACTORY_PASSWORD)) ext[ARTIFACTORY_PASSWORD] = ""
+
+configure {
+ setContextUrl("${project.property(ARTIFACTORY_CONTEXT_URL)}")
+ clientConfig.publisher.run {
+ repoKey = when {
+ "${project.version}".contains("SNAPSHOT") -> "libs-snapshot-local"
+ else -> "libs-release-local"
+ }
+ username = "${project.property(ARTIFACTORY_USER)}"
+ password = "${project.property(ARTIFACTORY_PASSWORD)}"
+ isMaven = true
+ isIvy = false
+ }
+}
+
+tasks.named("artifactoryPublish") {
+ isSkip = true
+}
diff --git a/build-logic/src/main/kotlin/buildlogic.artifactory-sub.gradle.kts b/build-logic/src/main/kotlin/buildlogic.artifactory-sub.gradle.kts
new file mode 100644
index 000000000..966409761
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic.artifactory-sub.gradle.kts
@@ -0,0 +1,10 @@
+plugins {
+ id("com.jfrog.artifactory")
+}
+
+// Artifactory eagerly evaluates publications, so this must run after all changes to artifacts are done
+afterEvaluate {
+ tasks.named("artifactoryPublish") {
+ publications("maven")
+ }
+}
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 000000000..89526875c
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts
@@ -0,0 +1,65 @@
+import buildlogic.getLibrary
+import buildlogic.stringyLibs
+
+plugins {
+ id("eclipse")
+ id("idea")
+ id("checkstyle")
+ id("buildlogic.common")
+}
+
+tasks
+ .withType()
+ .matching { it.name == "compileJava" || it.name == "compileTestJava" }
+ .configureEach {
+ val disabledLint = listOf(
+ "processing", "path", "fallthrough", "serial", "overloads",
+ )
+ 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("-Werror")
+ }
+
+configure {
+ configFile = rootProject.file("config/checkstyle/checkstyle.xml")
+ toolVersion = "10.16.0"
+}
+
+tasks.withType().configureEach {
+ useJUnitPlatform()
+}
+
+dependencies {
+ "compileOnly"(stringyLibs.getLibrary("jsr305"))
+ "testImplementation"(platform(stringyLibs.getLibrary("junit-bom")))
+ "testImplementation"(stringyLibs.getLibrary("junit-jupiter-api"))
+ "testImplementation"(stringyLibs.getLibrary("junit-jupiter-params"))
+ "testRuntimeOnly"(stringyLibs.getLibrary("junit-jupiter-engine"))
+}
+
+// Java 8 turns on doclint which we fail
+tasks.withType().configureEach {
+ options.encoding = "UTF-8"
+ (options as StandardJavadocDocletOptions).apply {
+ //addBooleanOption("Werror", true)
+ addBooleanOption("Xdoclint:all", true)
+ addBooleanOption("Xdoclint:-missing", true)
+ tags(
+ "apiNote:a:API Note:",
+ "implSpec:a:Implementation Requirements:",
+ "implNote:a:Implementation Note:"
+ )
+ }
+}
+
+configure {
+ withJavadocJar()
+ withSourcesJar()
+}
+
+tasks.named("check").configure {
+ dependsOn("checkstyleMain", "checkstyleTest")
+}
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 000000000..be15302b1
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic.common.gradle.kts
@@ -0,0 +1,73 @@
+import buildlogic.getLibrary
+import buildlogic.stringyLibs
+import org.gradle.plugins.ide.idea.model.IdeaModel
+
+plugins {
+ id("org.cadixdev.licenser")
+}
+
+group = rootProject.group
+version = rootProject.version
+
+repositories {
+ mavenCentral()
+ maven {
+ name = "EngineHub"
+ url = uri("https://maven.enginehub.org/repo/")
+ }
+ maven {
+ name = "devmart-other"
+ url = uri("https://nexuslite.gcnt.net/repos/other/")
+ }
+}
+
+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")) {
+ because("Mojang provides Guava")
+ }
+ add(conf, stringyLibs.getLibrary("gson")) {
+ because("Mojang provides Gson")
+ }
+ add(conf, stringyLibs.getLibrary("fastutil")) {
+ because("Mojang provides FastUtil")
+ }
+ }
+ }
+}
+
+license {
+ header(rootProject.file("HEADER.txt"))
+ include("**/*.java")
+ include("**/*.kt")
+}
+
+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 000000000..ce369ccec
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic.core-and-platform.gradle.kts
@@ -0,0 +1,23 @@
+plugins {
+ id("java")
+ id("maven-publish")
+ id("buildlogic.common-java")
+ id("buildlogic.artifactory-sub")
+}
+
+ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
+
+publishing {
+ publications {
+ register("maven") {
+ versionMapping {
+ usage("java-api") {
+ fromResolutionOf("runtimeClasspath")
+ }
+ usage("java-runtime") {
+ fromResolutionResult()
+ }
+ }
+ }
+ }
+}
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 000000000..ca37db667
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic.libs.gradle.kts
@@ -0,0 +1,179 @@
+plugins {
+ id("java-base")
+ id("maven-publish")
+ id("com.github.johnrengelman.shadow")
+ id("com.jfrog.artifactory")
+ id("buildlogic.common")
+ id("buildlogic.artifactory-sub")
+}
+
+// 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}.worldguard-libs"
+
+val relocations = mapOf(
+ "org.enginehub.squirrelid" to "com.sk89q.worldguard.util.profile",
+)
+
+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")
+}
+
+tasks.named("assemble").configure {
+ dependsOn("jar", "sourcesJar")
+}
+
+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"))
+}
+
+libsComponent.addVariantsFromConfiguration(apiElements.get()) {
+ mapToMavenScope("compile")
+}
+
+libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
+ mapToMavenScope("runtime")
+}
+
+libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
+ mapToMavenScope("runtime")
+}
+
+configure {
+ publications {
+ register("maven") {
+ from(libsComponent)
+ }
+ }
+}
+
+if (project != project(":worldguard-libs:core")) {
+ evaluationDependsOn(":worldguard-libs:core")
+ configurations["shade"].shouldResolveConsistentlyWith(project(":worldguard-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 000000000..b1221c82d
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts
@@ -0,0 +1,39 @@
+plugins {
+ id("com.github.johnrengelman.shadow")
+ id("buildlogic.core-and-platform")
+}
+
+tasks.named("shadowJar") {
+ archiveClassifier.set("dist")
+ dependencies {
+ include(project(":worldguard-libs:core"))
+ include(project(":worldguard-core"))
+
+ relocate("org.flywaydb", "com.sk89q.worldguard.internal.flywaydb") {
+ include(dependency("org.flywaydb:flyway-core"))
+ }
+ exclude("com.google.code.findbugs:jsr305")
+ }
+ exclude("GradleStart**")
+ exclude(".cache")
+ exclude("LICENSE*")
+ exclude("META-INF/maven/**")
+ minimize()
+}
+val javaComponent = components["java"] as AdhocComponentWithVariants
+// I don't think we want this published (it's the shadow jar)
+javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
+ skip()
+}
+
+afterEvaluate {
+ tasks.named("jar") {
+ val version = project(":worldguard-core").version
+ inputs.property("version", version)
+ val attributes = mutableMapOf(
+ "Implementation-Version" to version,
+ "WorldGuard-Version" to version,
+ )
+ 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 000000000..dcc537fa3
--- /dev/null
+++ b/build-logic/src/main/kotlin/buildlogic/GradleExtras.kt
@@ -0,0 +1,24 @@
+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.provider.Provider
+import org.gradle.kotlin.dsl.getByType
+
+val Project.ext: ExtraPropertiesExtension
+ get() = extensions.getByType()
+
+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.gradle.kts b/build.gradle.kts
index caa15ac54..aa62db092 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,26 +1,17 @@
import org.ajoberstar.grgit.Grgit
-logger.lifecycle("""
-*******************************************
- You are building WorldGuard!
- If you encounter trouble:
- 1) Try running 'build' in a separate Gradle run
- 2) Use gradlew and not gradle
- 3) If you still need help, ask on Discord! https://discord.gg/enginehub
-
- Output files will be in [subproject]/build/libs
-*******************************************
-""")
-
-applyRootArtifactoryConfig()
+plugins {
+ id("buildlogic.common")
+ id("buildlogic.artifactory-root")
+}
if (!project.hasProperty("gitCommitHash")) {
apply(plugin = "org.ajoberstar.grgit")
ext["gitCommitHash"] = try {
- Grgit.open(mapOf("currentDir" to project.rootDir))?.head()?.abbreviatedId
+ extensions.getByName("grgit").head()?.abbreviatedId
} catch (e: Exception) {
logger.warn("Error getting commit hash", e)
"no.git.id"
}
-}
\ No newline at end of file
+}
diff --git a/buildSrc/src/main/kotlin/ArtifactoryConfig.kt b/buildSrc/src/main/kotlin/ArtifactoryConfig.kt
deleted file mode 100644
index 929bab7af..000000000
--- a/buildSrc/src/main/kotlin/ArtifactoryConfig.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-import org.gradle.api.Project
-import org.gradle.kotlin.dsl.apply
-import org.gradle.kotlin.dsl.configure
-import org.gradle.kotlin.dsl.named
-import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention
-import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask
-
-private const val ARTIFACTORY_CONTEXT_URL = "artifactory_contextUrl"
-private const val ARTIFACTORY_USER = "artifactory_user"
-private const val ARTIFACTORY_PASSWORD = "artifactory_password"
-
-fun Project.applyRootArtifactoryConfig() {
- if (!project.hasProperty(ARTIFACTORY_CONTEXT_URL)) ext[ARTIFACTORY_CONTEXT_URL] = "http://localhost"
- if (!project.hasProperty(ARTIFACTORY_USER)) ext[ARTIFACTORY_USER] = "guest"
- if (!project.hasProperty(ARTIFACTORY_PASSWORD)) ext[ARTIFACTORY_PASSWORD] = ""
-
- apply(plugin = "com.jfrog.artifactory")
- configure {
- setContextUrl("${project.property(ARTIFACTORY_CONTEXT_URL)}")
- clientConfig.publisher.run {
- repoKey = when {
- "${project.version}".contains("SNAPSHOT") -> "libs-snapshot-local"
- else -> "libs-release-local"
- }
- username = "${project.property(ARTIFACTORY_USER)}"
- password = "${project.property(ARTIFACTORY_PASSWORD)}"
- isMaven = true
- isIvy = false
- }
- }
- tasks.named("artifactoryPublish") {
- isSkip = true
- }
-}
-
-fun Project.applyCommonArtifactoryConfig() {
- tasks.named("artifactoryPublish") {
- publications("maven")
- }
-}
diff --git a/buildSrc/src/main/kotlin/CommonConfig.kt b/buildSrc/src/main/kotlin/CommonConfig.kt
deleted file mode 100644
index 543514320..000000000
--- a/buildSrc/src/main/kotlin/CommonConfig.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-import org.cadixdev.gradle.licenser.LicenseExtension
-import org.gradle.api.Project
-import org.gradle.api.plugins.JavaPluginExtension
-import org.gradle.jvm.toolchain.JavaLanguageVersion
-import org.gradle.kotlin.dsl.apply
-import org.gradle.kotlin.dsl.configure
-import org.gradle.kotlin.dsl.repositories
-import org.gradle.kotlin.dsl.the
-
-fun Project.applyCommonConfiguration() {
- group = rootProject.group
- version = rootProject.version
-
- repositories {
- mavenCentral()
- maven { url = uri("https://maven.enginehub.org/repo/") }
- maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") }
- }
-
- configurations.all {
- resolutionStrategy {
- cacheChangingModulesFor(5, "MINUTES")
- }
- }
-
- plugins.withId("java") {
- the().toolchain {
- languageVersion.set(JavaLanguageVersion.of(21))
- }
- }
-
- apply(plugin = "org.cadixdev.licenser")
- configure {
- header(rootProject.file("HEADER.txt"))
- include("**/*.java")
- include("**/*.kt")
- }
-}
diff --git a/buildSrc/src/main/kotlin/GradleExtras.kt b/buildSrc/src/main/kotlin/GradleExtras.kt
deleted file mode 100644
index beedf1607..000000000
--- 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 9acb5a109..000000000
--- a/buildSrc/src/main/kotlin/LibsConfig.kt
+++ /dev/null
@@ -1,187 +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.register
-import javax.inject.Inject
-
-fun Project.applyLibrariesConfiguration() {
- applyCommonConfiguration()
- apply(plugin = "java-base")
- apply(plugin = "maven-publish")
- apply(plugin = "com.github.johnrengelman.shadow")
- apply(plugin = "com.jfrog.artifactory")
-
- configurations {
- create("shade")
- }
-
- group = "${rootProject.group}.worldguard-libs"
-
- val relocations = mapOf(
- "org.enginehub.squirrelid" to "com.sk89q.worldguard.util.profile"
- )
-
- tasks.register("jar") {
- configurations = listOf(project.configurations["shade"])
- archiveClassifier.set("")
-
- dependencies {
- exclude(dependency("com.google.code.findbugs:jsr305"))
- }
-
- relocations.forEach { (from, to) ->
- relocate(from, to)
- }
- }
- val altConfigFiles = { artifactType: String ->
- val deps = configurations["shade"].incoming.dependencies
- .filterIsInstance()
- .map { it.copy() }
- .map { dependency ->
- dependency.artifact {
- name = dependency.name
- type = artifactType
- extension = "jar"
- classifier = artifactType
- }
- dependency
- }
-
- files(configurations.detachedConfiguration(*deps.toTypedArray())
- .resolvedConfiguration.lenientConfiguration.artifacts
- .filter { it.classifier == artifactType }
- .map { zipTree(it.file) })
- }
- tasks.register("sourcesJar") {
- from({
- altConfigFiles("sources")
- })
- 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")
- }
-
- tasks.named("assemble").configure {
- dependsOn("jar", "sourcesJar")
- }
-
- 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, 8)
- }
- 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, 8)
- }
- 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"))
- }
-
- libsComponent.addVariantsFromConfiguration(apiElements.get()) {
- mapToMavenScope("compile")
- }
-
- libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
- mapToMavenScope("runtime")
- }
-
- libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
- mapToMavenScope("runtime")
- }
-
- configure {
- publications {
- register("maven") {
- from(libsComponent)
- }
- }
- }
-
- applyCommonArtifactoryConfig()
-}
-
-// 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(":worldguard-libs:core")
- val coreDeps = project(":worldguard-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 9b49b6f57..000000000
--- a/buildSrc/src/main/kotlin/PlatformConfig.kt
+++ /dev/null
@@ -1,68 +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.publish.PublishingExtension
-import org.gradle.api.publish.maven.MavenPublication
-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.register
-
-fun Project.applyPlatformAndCoreConfiguration(javaRelease: Int = 17) {
- applyCommonConfiguration()
- apply(plugin = "java")
- apply(plugin = "maven-publish")
- apply(plugin = "com.jfrog.artifactory")
- applyCommonJavaConfiguration(
- sourcesJar = true,
- javaRelease = javaRelease,
- banSlf4j = false
- )
-
- ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
-
- configure {
- publications {
- register("maven") {
- from(components["java"])
- versionMapping {
- usage("java-api") {
- fromResolutionOf("runtimeClasspath")
- }
- usage("java-runtime") {
- fromResolutionResult()
- }
- }
- }
- }
- }
-
- applyCommonArtifactoryConfig()
-}
-
-fun Project.applyShadowConfiguration() {
- apply(plugin = "com.github.johnrengelman.shadow")
- tasks.named("shadowJar") {
- archiveClassifier.set("dist")
- dependencies {
- include(project(":worldguard-libs:core"))
- //include(project(":worldguard-libs:${project.name.replace("worldguard-", "")}"))
- include(project(":worldguard-core"))
-
- relocate("org.flywaydb", "com.sk89q.worldguard.internal.flywaydb") {
- include(dependency("org.flywaydb:flyway-core:3.0"))
- }
- exclude("com.google.code.findbugs:jsr305")
- }
- exclude("GradleStart**")
- exclude(".cache")
- exclude("LICENSE*")
- exclude("META-INF/maven/**")
- }
- val javaComponent = components["java"] as AdhocComponentWithVariants
- // I don't think we want this published (it's the shadow jar)
- javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
- skip()
- }
-}
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
deleted file mode 100644
index 105af054f..000000000
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-object Versions {
- // const val PISTON = "0.4.3"
- // const val AUTO_VALUE = "1.6.5"
- const val WORLDEDIT = "7.3.0"
- const val JUNIT = "5.9.1"
- const val MOCKITO = "4.9.0"
- const val SQUIRRELID = "0.3.2"
- const val GUAVA = "31.1-jre"
- const val FINDBUGS = "3.0.2"
-}
diff --git a/config/checkstyle/import-control.xml b/config/checkstyle/import-control.xml
index b00f80c27..13e7f8f79 100644
--- a/config/checkstyle/import-control.xml
+++ b/config/checkstyle/import-control.xml
@@ -7,10 +7,10 @@
-
+
diff --git a/gradle.properties b/gradle.properties
index 2c13f50cb..30f75f29d 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,4 @@
group=com.sk89q.worldguard
-version=7.1.0-SNAPSHOT
+version=7.0.13-SNAPSHOT
+
+org.gradle.parallel=true
diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties
new file mode 100644
index 000000000..63e5bbdf4
--- /dev/null
+++ b/gradle/gradle-daemon-jvm.properties
@@ -0,0 +1,2 @@
+#This file is generated by updateDaemonJvm
+toolchainVersion=21
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 000000000..a874fa203
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,66 @@
+[versions]
+worldedit = "7.3.0"
+
+# Minimum versions we apply to make dependencies support newer Java
+minimumAsm = "9.7"
+minimumJdependency = "2.10"
+minimumTinyRemapper = "0.8.11"
+
+# lang-version = ""
+
+[libraries]
+
+licenser = "gradle.plugin.org.cadixdev.gradle:licenser:0.6.1"
+grgit = "org.ajoberstar.grgit:grgit-gradle:5.2.2"
+shadow = "com.github.johnrengelman:shadow:8.1.1"
+jfrog-buildinfo = "org.jfrog.buildinfo:build-info-extractor-gradle:5.2.0"
+
+squirrelid = "org.enginehub:squirrelid:0.3.2"
+
+autoService = "com.google.auto.service:auto-service:1.1.1"
+
+jsr305 = "com.google.code.findbugs:jsr305:3.0.2"
+jetbrains-annotations = "org.jetbrains:annotations:24.1.0"
+
+junit-bom = "org.junit:junit-bom:5.10.2"
+junit-jupiter-api.module = "org.junit.jupiter:junit-jupiter-api"
+junit-jupiter-params.module = "org.junit.jupiter:junit-jupiter-params"
+junit-jupiter-engine.module = "org.junit.jupiter:junit-jupiter-engine"
+
+spigot = "org.spigotmc:spigot-api:1.21.3-R0.1-SNAPSHOT"
+paperApi = "io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT"
+paperLib = "io.papermc:paperlib:1.0.8"
+
+dummypermscompat = "com.sk89q:dummypermscompat:1.10"
+bstats-bukkit = "org.bstats:bstats-bukkit:2.2.1"
+
+prtree = "org.khelekore:prtree:1.5.0"
+
+flyway-core = "org.flywaydb:flyway-core:3.0"
+
+commandbook = "com.sk89q:commandbook:2.3"
+
+hamcrest-library = "org.hamcrest:hamcrest-library:2.2"
+
+# Mojang-provided libraries, CHECK AGAINST MINECRAFT for versions
+guava = "com.google.guava:guava:32.1.3-jre!!"
+log4j-bom = "org.apache.logging.log4j:log4j-bom:2.22.1!!"
+gson = "com.google.code.gson:gson:2.10.1!!"
+fastutil = "it.unimi.dsi:fastutil:8.5.12!!"
+
+# Bukkit-provided libraries, CHECK AGAINST SPIGOT for versions
+# Note that we need to balance support for older MC versus working at all on newer ones, so the exact versions here
+# may not be the same as the ones in the latest Bukkit API.
+snakeyaml = "org.yaml:snakeyaml:2.0"
+
+[libraries.worldedit-core]
+module = "com.sk89q.worldedit:worldedit-core"
+version.ref = "worldedit"
+
+[libraries.worldedit-bukkit]
+module = "com.sk89q.worldedit:worldedit-bukkit"
+version.ref = "worldedit"
+
+[libraries.worldedit-libs-ap]
+module = "com.sk89q.worldedit.worldedit-libs:ap"
+version.ref = "worldedit"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index b82aa23a4..a4413138c 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.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/settings.gradle.kts b/settings.gradle.kts
index ead83aeae..d0ca0d3e0 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,7 +1,33 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ }
+}
+plugins {
+ id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
+}
+
+logger.lifecycle("""
+*******************************************
+ You are building WorldGuard!
+
+ If you encounter trouble:
+ 1) Read COMPILING.md 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/enginehub
+
+ Output files will be in [subproject]/build/libs
+*******************************************
+""")
+
rootProject.name = "worldguard"
+includeBuild("build-logic")
+
include("worldguard-libs")
include("worldguard-libs:core")
-include("worldguard-core")
-//include("worldguard-libs:bukkit")
-include("worldguard-bukkit")
+
+listOf("bukkit", "core").forEach {
+ include("worldguard-$it")
+}
diff --git a/worldguard-bukkit/build.gradle.kts b/worldguard-bukkit/build.gradle.kts
index ed1cdd272..8ee0092af 100644
--- a/worldguard-bukkit/build.gradle.kts
+++ b/worldguard-bukkit/build.gradle.kts
@@ -2,38 +2,41 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
`java-library`
+ id("buildlogic.platform")
}
-applyPlatformAndCoreConfiguration()
-applyShadowConfiguration()
-
-repositories {
- maven {
- name = "paper"
- url = uri("https://repo.papermc.io/repository/maven-public/")
- }
- maven {
- // TODO: Remove this once paper updated to adventure release
- name = "adventure-snapshots"
- url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
- }
-}
-
-configurations {
- compileClasspath.get().extendsFrom(create("shadeOnly"))
+val localImplementation = configurations.create("localImplementation") {
+ description = "Dependencies used locally, but provided by the runtime Bukkit implementation"
+ isCanBeConsumed = false
+ isCanBeResolved = false
}
+configurations["compileOnly"].extendsFrom(localImplementation)
+configurations["testImplementation"].extendsFrom(localImplementation)
dependencies {
"api"(project(":worldguard-core"))
- "compileOnly"("io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT")
- "runtimeOnly"("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") {
+ "api"(libs.worldedit.bukkit) { isTransitive = false }
+ "compileOnly"(libs.commandbook) { isTransitive = false }
+ // Technically this is api, but everyone should already have some form of the bukkit API
+ // Avoid pulling in another one, especially one so outdated.
+ "localImplementation"(libs.spigot) {
exclude("junit", "junit")
}
- "api"("com.sk89q.worldedit:worldedit-bukkit:${Versions.WORLDEDIT}") { isTransitive = false }
- "implementation"("com.google.guava:guava:${Versions.GUAVA}")
- "compileOnly"("com.sk89q:commandbook:2.3") { isTransitive = false }
- "shadeOnly"("io.papermc:paperlib:1.0.8")
- "shadeOnly"("org.bstats:bstats-bukkit:3.0.1")
+
+ "compileOnly"(libs.jetbrains.annotations) {
+ because("Resolving Spigot annotations")
+ }
+ "testCompileOnly"(libs.jetbrains.annotations) {
+ because("Resolving Spigot annotations")
+ }
+ "compileOnly"(libs.paperApi) {
+ exclude("org.slf4j", "slf4j-api")
+ exclude("junit", "junit")
+ }
+
+ "implementation"("com.tcoded:FoliaLib:0.3.2")
+ "implementation"(libs.paperLib)
+ "implementation"(libs.bstats.bukkit)
}
tasks.named("processResources") {
@@ -44,31 +47,26 @@ tasks.named("processResources") {
}
}
-tasks.named("jar") {
- val projectVersion = project.version
- inputs.property("projectVersion", projectVersion)
- manifest {
- attributes("Implementation-Version" to projectVersion)
- }
-}
-
tasks.named("shadowJar") {
- configurations = listOf(project.configurations["shadeOnly"], project.configurations["runtimeClasspath"])
-
dependencies {
include(dependency(":worldguard-core"))
- relocate("org.bstats", "com.sk89q.worldguard.bukkit.bstats") {
- include(dependency("org.bstats:"))
- }
- relocate ("io.papermc.lib", "com.sk89q.worldguard.bukkit.paperlib") {
- include(dependency("io.papermc:paperlib"))
- }
- relocate ("co.aikar.timings.lib", "com.sk89q.worldguard.bukkit.timingslib") {
- include(dependency("co.aikar:minecraft-timings"))
+ include(dependency("org.bstats:"))
+ include(dependency("io.papermc:paperlib"))
+
+ relocate ("com.tcoded.folialib", "com.sk89q.worldguard.bukkit.folialib") {
+ include(dependency("com.tcoded:FoliaLib"))
}
+ relocate("org.bstats", "com.sk89q.worldguard.bukkit.bstats")
+ relocate("io.papermc.lib", "com.sk89q.worldguard.bukkit.paperlib")
}
}
tasks.named("assemble").configure {
dependsOn("shadowJar")
}
+
+configure {
+ publications.named("maven") {
+ from(components["java"])
+ }
+}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitRegionContainer.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitRegionContainer.java
index 79d7b3446..065fa0d98 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitRegionContainer.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitRegionContainer.java
@@ -40,6 +40,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
@@ -94,7 +95,10 @@ public void onChunkUnload(ChunkUnloadEvent event) {
}
}, plugin);
- Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, cache::invalidateAll, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
+ int interval = CACHE_INVALIDATION_INTERVAL * 50;
+ plugin.getFoliaLib().getImpl().runTimerAsync(cache::invalidateAll, interval, interval, TimeUnit.MILLISECONDS);
+
+// Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, cache::invalidateAll, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
}
public void shutdown() {
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java
index c290b7cfe..2d43d2080 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java
@@ -55,23 +55,6 @@ public static int getPotionEffectBits(ItemStack item) {
return item.getDurability() & 0x3F;
}
- /**
- * Get a blacklist target for the given block.
- *
- * @param block the block
- * @param effectiveMaterial The effective material, if different
- * @return a target
- */
- public static Target createTarget(Block block, Material effectiveMaterial) {
- checkNotNull(block);
- checkNotNull(block.getType());
- if (block.getType() == effectiveMaterial) {
- return createTarget(block.getType());
- } else {
- return createTarget(effectiveMaterial);
- }
- }
-
/**
* Get a blacklist target for the given block.
*
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java
index ba58b48ed..08ffd0b61 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java
@@ -215,6 +215,7 @@ public void loadConfiguration() {
blockEnderDragonPortalCreation = getBoolean("mobs.block-enderdragon-portal-creation", false);
blockFireballExplosions = getBoolean("mobs.block-fireball-explosions", false);
blockFireballBlockDamage = getBoolean("mobs.block-fireball-block-damage", false);
+ blockWindChargeExplosions = getBoolean("mobs.block-windcharge-explosions", false);
antiWolfDumbness = getBoolean("mobs.anti-wolf-dumbness", false);
allowTamedSpawns = getBoolean("mobs.allow-tamed-spawns", true);
disableEndermanGriefing = getBoolean("mobs.disable-enderman-griefing", false);
@@ -282,6 +283,7 @@ public void loadConfiguration() {
disableSculkGrowth = getBoolean("dynamics.disable-sculk-growth", false);
disableCropGrowth = getBoolean("dynamics.disable-crop-growth", false);
disableSoilDehydration = getBoolean("dynamics.disable-soil-dehydration", false);
+ disableSoilMoistureChange = getBoolean("dynamics.disable-soil-moisture-change", false);
disableCoralBlockFade = getBoolean("dynamics.disable-coral-block-fade", false);
disableCopperBlockFade = getBoolean("dynamics.disable-copper-block-fade", false);
allowedSnowFallOver = new HashSet<>(convertLegacyBlocks(getStringList("dynamics.snow-fall-blocks", null)));
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldGuardPlatform.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldGuardPlatform.java
index 37e7f07ac..f1e70e051 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldGuardPlatform.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldGuardPlatform.java
@@ -171,9 +171,10 @@ public Path getConfigDir() {
return WorldGuardPlugin.inst().getDataFolder().toPath();
}
+ @SuppressWarnings("removal")
@Override
public void stackPlayerInventory(LocalPlayer localPlayer) {
- boolean ignoreMax = localPlayer.hasPermission("worldguard.stack.illegitimate");
+ boolean ignoreMax = false; // localPlayer.hasPermission("worldguard.stack.illegitimate");
Player player = ((BukkitPlayer) localPlayer).getPlayer();
@@ -191,7 +192,7 @@ public void stackPlayerInventory(LocalPlayer localPlayer) {
continue;
}
- int max = ignoreMax ? 64 : item.getMaxStackSize();
+ int max = /*ignoreMax ? 64 :*/ item.getMaxStackSize();
if (item.getAmount() < max) {
int needed = max - item.getAmount(); // Number of needed items until max
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java
index 3ba997921..0741415a3 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java
@@ -75,6 +75,7 @@
import com.sk89q.worldguard.protection.managers.storage.sql.SQLDriver;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
+import com.tcoded.folialib.FoliaLib;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.DrilldownPie;
import org.bstats.charts.SimplePie;
@@ -96,6 +97,7 @@
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -111,6 +113,9 @@ public class WorldGuardPlugin extends JavaPlugin {
private static final int BSTATS_PLUGIN_ID = 3283;
+
+ private FoliaLib foliaLib;
+
/**
* Construct objects. Actual loading occurs when the plugin is enabled, so
* this merely instantiates the objects.
@@ -138,6 +143,10 @@ public static WorldGuardPlugin inst() {
*/
@Override
public void onEnable() {
+
+ // FoliaLib Util
+ foliaLib = new FoliaLib(this);
+
// Catch bad things being done by naughty plugins that include WorldGuard's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
verifier.reportMismatches(ImmutableList.of(WorldGuard.class, ProtectedRegion.class, Flag.class));
@@ -164,7 +173,9 @@ public void onEnable() {
reg.register(GeneralCommands.class);
}
- getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
+ int runDelayMs = BukkitSessionManager.RUN_DELAY * 50;
+ foliaLib.getImpl().runTimerAsync(sessionManager, runDelayMs, runDelayMs, TimeUnit.MILLISECONDS);
+// getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
// Register events
getServer().getPluginManager().registerEvents(sessionManager, this);
@@ -205,12 +216,28 @@ public void onEnable() {
}
worldListener.registerEvents();
- Bukkit.getScheduler().runTask(this, () -> {
- for (Player player : Bukkit.getServer().getOnlinePlayers()) {
+ for (Player player : Bukkit.getServer().getOnlinePlayers()) {
+ foliaLib.getImpl().runAtEntity(player, (task) -> {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
- }
- });
+ });
+ }
+// if (foliaLib.isFolia()) {
+// for (Player player : Bukkit.getServer().getOnlinePlayers()) {
+// foliaLib.getImpl().runAtEntity(player, (task) -> {
+// ProcessPlayerEvent event = new ProcessPlayerEvent(player);
+// Events.fire(event);
+// });
+// }
+// }
+// else {
+// Bukkit.getScheduler().runTask(this, () -> {
+// for (Player player : Bukkit.getServer().getOnlinePlayers()) {
+// ProcessPlayerEvent event = new ProcessPlayerEvent(player);
+// Events.fire(event);
+// }
+// });
+// }
((SimpleFlagRegistry) WorldGuard.getInstance().getFlagRegistry()).setInitialized(true);
((SimpleDomainRegistry) WorldGuard.getInstance().getDomainRegistry()).setInitialized(true);
@@ -266,7 +293,10 @@ private void setupCustomCharts(Metrics metrics) {
@Override
public void onDisable() {
WorldGuard.getInstance().disable();
- this.getServer().getScheduler().cancelTasks(this);
+ if (!foliaLib.isFolia()) {
+ this.getServer().getScheduler().cancelTasks(this);
+ }
+ foliaLib.getImpl().cancelAllTasks();
}
@Override
@@ -526,4 +556,7 @@ public PlayerMoveListener getPlayerMoveListener() {
return playerMoveListener;
}
+ public FoliaLib getFoliaLib() {
+ return foliaLib;
+ }
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/cause/Cause.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/cause/Cause.java
index f3847b33a..84f0c3f60 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/cause/Cause.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/cause/Cause.java
@@ -32,8 +32,10 @@
import org.bukkit.entity.AnimalTamer;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.Creature;
+import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
+import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Firework;
import org.bukkit.entity.LightningStrike;
import org.bukkit.entity.Player;
@@ -326,15 +328,21 @@ private void addAll(@Nullable Object... element) {
addAll(player.getPlayer()); // player object if online, else null
}
}
- } else if (o instanceof Creature && ((Creature) o).getTarget() != null) {
+ } else if (o instanceof Creeper c) {
indirect = true;
- addAll(((Creature) o).getTarget());
+ addAll(c.getTarget(), c.getIgniter());
+ } else if (o instanceof Creature c) {
+ indirect = true;
+ addAll(c.getTarget());
} else if (o instanceof BlockProjectileSource) {
addAll(((BlockProjectileSource) o).getBlock());
} else if (o instanceof LightningStrike && PaperLib.isPaper() &&
((LightningStrike) o).getCausingEntity() != null) {
indirect = true;
addAll(((LightningStrike) o).getCausingEntity());
+ } else if (o instanceof FallingBlock f && PaperLib.isPaper() && f.getOrigin() != null) {
+ indirect = true;
+ addAll(f.getOrigin().getBlock());
}
// Add manually tracked parent causes
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BlacklistListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BlacklistListener.java
index bfb569f5a..3b9077175 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BlacklistListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BlacklistListener.java
@@ -96,7 +96,7 @@ public void onBreakBlock(final BreakBlockEvent event) {
event.filter(target -> {
if (!wcfg.getBlacklist().check(
new BlockBreakBlacklistEvent(localPlayer, BukkitAdapter.asBlockVector(target),
- createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false)) {
+ createTarget(target.getBlock())), false, false)) {
return false;
} else if (!wcfg.getBlacklist().check(
new ItemDestroyWithBlacklistEvent(localPlayer, BukkitAdapter.asBlockVector(target),
@@ -124,7 +124,7 @@ public void onPlaceBlock(final PlaceBlockEvent event) {
final LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
event.filter(target -> wcfg.getBlacklist().check(new BlockPlaceBlacklistEvent(
- localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false));
+ localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock())), false, false));
}
@EventHandler(ignoreCancelled = true)
@@ -143,7 +143,7 @@ public void onUseBlock(final UseBlockEvent event) {
final LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
event.filter(target -> wcfg.getBlacklist().check(new BlockInteractBlacklistEvent(
- localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false));
+ localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock())), false, false));
}
@EventHandler(ignoreCancelled = true)
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BuildPermissionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BuildPermissionListener.java
index 2ad78b4b1..7958b685c 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BuildPermissionListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/BuildPermissionListener.java
@@ -101,12 +101,14 @@ public void onUseBlock(final UseBlockEvent event) {
if (rootCause instanceof Player) {
final Player player = (Player) rootCause;
- final Material material = event.getEffectiveMaterial();
- if (!hasBuildPermission(player, "block." + material.name().toLowerCase() + ".interact")
- && !hasBuildPermission(player, "block.interact." + material.name().toLowerCase())) {
+ boolean blocked = event.filter(loc -> {
+ String blacklistName = loc.getBlock().getType().name().toLowerCase();
+ return hasBuildPermission(player, "block." + blacklistName + ".interact") ||
+ hasBuildPermission(player, "block.interact." + blacklistName);
+ }, true);
+ if (blocked && !event.isSilent()) {
tellErrorMessage(player, event.getWorld());
- event.setCancelled(true);
}
}
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java
index e39a4c3cf..72e837581 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java
@@ -50,6 +50,7 @@
import io.papermc.paper.event.player.PlayerOpenSignEvent;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
+import org.bukkit.ExplosionResult;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -66,6 +67,8 @@
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Dispenser;
import org.bukkit.entity.AreaEffectCloud;
+import org.bukkit.entity.Arrow;
+import org.bukkit.entity.BreezeWindCharge;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -79,6 +82,7 @@
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.ThrownPotion;
+import org.bukkit.entity.WindCharge;
import org.bukkit.entity.minecart.HopperMinecart;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
@@ -112,8 +116,10 @@
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
+import org.bukkit.event.entity.EntityEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityInteractEvent;
+import org.bukkit.event.entity.EntityKnockbackByEntityEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.EntityTameEvent;
import org.bukkit.event.entity.EntityUnleashEvent;
@@ -152,6 +158,7 @@
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class EventAbstractionListener extends AbstractListener {
@@ -176,9 +183,11 @@ public EventAbstractionListener(WorldGuardPlugin plugin) {
public void registerEvents() {
super.registerEvents();
+ PluginManager pm = getPlugin().getServer().getPluginManager();
if (PaperLib.isPaper()) {
- PluginManager pm = getPlugin().getServer().getPluginManager();
pm.registerEvents(new EventAbstractionListener.PaperListener(), getPlugin());
+ } else {
+ pm.registerEvents(new EventAbstractionListener.SpigotListener(), getPlugin());
}
}
@@ -218,8 +227,8 @@ public void onBlockPlace(BlockPlaceEvent event) {
Events.fireToCancel(event, new BreakBlockEvent(event, create(event.getPlayer()), previousState.getLocation(), previousState.getType()));
}
- if (!event.isCancelled()) {
- ItemStack itemStack = new ItemStack(event.getBlockPlaced().getType(), 1);
+ ItemStack itemStack = event.getItemInHand();
+ if (!event.isCancelled() && itemStack.getType() != Material.AIR) {
Events.fireToCancel(event, new UseItemEvent(event, create(event.getPlayer()), event.getPlayer().getWorld(), itemStack));
}
@@ -323,10 +332,10 @@ public void onEntityChangeBlock(EntityChangeBlockEvent event) {
// Fire two events: one as BREAK and one as PLACE
if (toType != Material.AIR && fromType != Material.AIR) {
- BreakBlockEvent breakDelagate = new BreakBlockEvent(event, cause, block);
- setDelegateEventMaterialOptions(breakDelagate, fromType, toType);
+ BreakBlockEvent breakDelegate = new BreakBlockEvent(event, cause, block);
+ setDelegateEventMaterialOptions(breakDelegate, fromType, toType);
boolean denied;
- if (!(denied = Events.fireToCancel(event, breakDelagate))) {
+ if (!(denied = Events.fireToCancel(event, breakDelegate))) {
PlaceBlockEvent placeDelegate = new PlaceBlockEvent(event, cause, block.getLocation(), toType);
setDelegateEventMaterialOptions(placeDelegate, fromType, toType);
denied = Events.fireToCancel(event, placeDelegate);
@@ -339,7 +348,10 @@ public void onEntityChangeBlock(EntityChangeBlockEvent event) {
} else if (toType == Material.AIR) {
// Track the source so later we can create a proper chain of causes
if (entity instanceof FallingBlock) {
- Cause.trackParentCause(entity, block);
+ if (!PaperLib.isPaper()) {
+ // On paper we use FallingBlock#getOrigin to get the origin location, on spigot we store it.
+ Cause.trackParentCause(entity, block);
+ }
// Switch around the event
Events.fireToCancel(event, new SpawnEntityEvent(event, create(block), entity));
@@ -354,10 +366,29 @@ public void onEntityChangeBlock(EntityChangeBlockEvent event) {
}
+ private static void handleKnockback(T event, Entity damager) {
+ final DamageEntityEvent eventToFire = new DamageEntityEvent(event, create(damager), event.getEntity());
+ if (damager instanceof BreezeWindCharge) {
+ eventToFire.getRelevantFlags().add(Flags.BREEZE_WIND_CHARGE);
+ } else if (damager instanceof WindCharge) {
+ eventToFire.getRelevantFlags().add(Flags.WIND_CHARGE_BURST);
+ }
+ Events.fireToCancel(event, eventToFire);
+ }
+
+ @SuppressWarnings("UnstableApiUsage")
@EventHandler(ignoreCancelled = true)
public void onEntityExplode(EntityExplodeEvent event) {
Entity entity = event.getEntity();
- Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR));
+ if (event.getExplosionResult() == ExplosionResult.TRIGGER_BLOCK) {
+ UseBlockEvent useEvent = new UseBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR);
+ useEvent.getRelevantFlags().add(Entities.getExplosionFlag(entity));
+ useEvent.setSilent(true);
+ Events.fireBulkEventToCancel(event, useEvent);
+ } else if (event.getExplosionResult() == ExplosionResult.DESTROY || event.getExplosionResult() == ExplosionResult.DESTROY_WITH_DECAY) {
+ Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR));
+ }
+
if (entity instanceof Creeper) {
Cause.untrackParentCause(entity);
}
@@ -576,7 +607,7 @@ public void onEntityInteract(EntityInteractEvent event) {
@EventHandler(ignoreCancelled = true)
public void onBlockFertilize(BlockFertilizeEvent event) {
- if (event.getBlocks().isEmpty()) return;
+ if (event.getBlocks().isEmpty()) return;
Cause cause = create(event.getPlayer(), event.getBlock());
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getWorld(), event.getBlocks()));
}
@@ -742,7 +773,7 @@ public void onHangingBreak(HangingBreakEvent event) {
if (event.isCancelled() && remover instanceof Player) {
playDenyEffect((Player) remover, event.getEntity().getLocation());
}
- } else if (event.getCause() == HangingBreakEvent.RemoveCause.EXPLOSION){
+ } else if (event.getCause() == HangingBreakEvent.RemoveCause.EXPLOSION) {
DestroyEntityEvent destroyEntityEvent = new DestroyEntityEvent(event, Cause.unknown(), event.getEntity());
destroyEntityEvent.getRelevantFlags().add(Flags.OTHER_EXPLOSION);
if (event.getEntity() instanceof ItemFrame) {
@@ -837,12 +868,7 @@ public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
if (matchingItem != null && hasInteractBypass(world, matchingItem)) {
useEntityEvent.setAllowed(true);
}
- if (!Events.fireToCancel(event, useEntityEvent)) {
- // so this is a hack but CreeperIgniteEvent doesn't actually tell us who, so we need to do it here
- if (item.getType() == Material.FLINT_AND_STEEL && entity.getType() == EntityType.CREEPER) {
- Cause.trackParentCause(entity, player);
- }
- }
+ Events.fireToCancel(event, useEntityEvent);
}
@EventHandler(ignoreCancelled = true)
@@ -887,11 +913,19 @@ public void onEntityDamage(EntityDamageEvent event) {
@EventHandler(ignoreCancelled = true)
public void onEntityCombust(EntityCombustEvent event) {
- if (event instanceof EntityCombustByBlockEvent) {
+ if (event instanceof EntityCombustByBlockEvent combustByBlockEvent) {
// at the time of writing, spigot is throwing null for the event's combuster. this causes lots of issues downstream.
// whenever (i mean if ever) it is fixed, use getCombuster again instead of the current block
- Events.fireToCancel(event, new DamageEntityEvent(event, create(event.getEntity().getLocation().getBlock()), event.getEntity()));
+ Block combuster = combustByBlockEvent.getCombuster();
+ Events.fireToCancel(event, new DamageEntityEvent(event,
+ create(combuster == null ? event.getEntity().getLocation().getBlock() : combuster), event.getEntity()));
} else if (event instanceof EntityCombustByEntityEvent) {
+ if (event.getEntity() instanceof Arrow) {
+ // this only happens from the Flame enchant. igniting arrows in other ways (eg with lava) doesn't even
+ // throw the combust event, not even the CombustByBlock event... they're also very buggy and don't even
+ // show as lit on the client consistently
+ return;
+ }
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityCombustByEntityEvent) event).getCombuster()), event.getEntity()));
}
}
@@ -990,8 +1024,16 @@ public void onInventoryMoveItem(InventoryMoveItemEvent event) {
handleInventoryHolderUse(event, cause, targetHolder);
if (event.isCancelled() && causeHolder instanceof Hopper && wcfg.breakDeniedHoppers) {
- Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(),
- () -> ((Hopper) causeHolder).getBlock().breakNaturally());
+ Hopper hopperCauseHolder = (Hopper) causeHolder;
+ Location location = hopperCauseHolder.getLocation();
+
+ getPlugin().getFoliaLib().getImpl().runAtLocationLater(location, () -> {
+ Block block = location.getBlock();
+ if (block.getType() == Material.HOPPER) {
+ block.breakNaturally();
+ }
+ }, 50, TimeUnit.MILLISECONDS);
+
} else {
entry.setCancelled(event.isCancelled());
}
@@ -1007,7 +1049,6 @@ public void onPotionSplash(PotionSplashEvent event) {
// Fire item interaction event
Events.fireToCancel(event, new UseItemEvent(event, cause, world, potion.getItem()));
-
// Fire entity interaction event
if (!event.isCancelled()) {
int blocked = 0;
@@ -1019,8 +1060,11 @@ public void onPotionSplash(PotionSplashEvent event) {
? new DamageEntityEvent(event, cause, affected) :
new UseEntityEvent(event, cause, affected);
- // Consider the potion splash flag
+ // Consider extra relevant flags
delegate.getRelevantFlags().add(Flags.POTION_SPLASH);
+ if (potion.getShooter() instanceof LivingEntity shooter && !(shooter instanceof Player) && affected instanceof Player) {
+ delegate.getRelevantFlags().add(Flags.MOB_DAMAGE);
+ }
if (Events.fireAndTestCancel(delegate)) {
event.setIntensity(affected, 0);
@@ -1102,7 +1146,7 @@ public void onLingeringApply(AreaEffectCloudApplyEvent event) {
}
@EventHandler(ignoreCancelled = true)
- public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event){
+ public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
onPlayerInteractEntity(event);
}
@@ -1161,7 +1205,7 @@ private static void handleBlockRightClick(T even
// Handle created boats
if (item != null && Materials.isBoat(item.getType())) {
- Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.BOAT));
+ Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), Materials.getRelatedEntity(item.getType())));
return;
}
@@ -1213,9 +1257,9 @@ private static void handleInventoryHolderUse(T o
useBlockEvent.setAllowed(true);
}
Events.fireToCancel(originalEvent, useBlockEvent);
- } else if (holder instanceof DoubleChest) {
- InventoryHolder left = ((DoubleChest) holder).getLeftSide();
- InventoryHolder right = ((DoubleChest) holder).getRightSide();
+ } else if (holder instanceof DoubleChest doubleChest) {
+ InventoryHolder left = PaperLib.isPaper() ? doubleChest.getLeftSide(false) : doubleChest.getLeftSide();
+ InventoryHolder right = PaperLib.isPaper() ? doubleChest.getRightSide(false) : doubleChest.getRightSide();
if (left instanceof Chest) {
Events.fireToCancel(originalEvent, new UseBlockEvent(originalEvent, cause, ((Chest) left).getBlock()));
}
@@ -1261,7 +1305,7 @@ private static void playDenyEffect(Location location) {
}
}
- private class PaperListener implements Listener {
+ private static class PaperListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onEntityTransform(EntityZapEvent event) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(event.getBolt()), event.getEntity()));
@@ -1274,5 +1318,18 @@ public void onSignOpen(PlayerOpenSignEvent event) {
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), event.getSign().getBlock()));
}
}
+
+ @EventHandler(ignoreCancelled = true)
+ public void onEntityKnockbackByEntity(com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent event) {
+ handleKnockback(event, event.getHitBy());
+ }
+ }
+
+ @SuppressWarnings("removal")
+ private static class SpigotListener implements Listener {
+ @EventHandler(ignoreCancelled = true)
+ public void onEntityKnockbackByEntity(EntityKnockbackByEntityEvent event) {
+ handleKnockback(event, event.getSourceEntity());
+ }
}
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/PlayerMoveListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/PlayerMoveListener.java
index 7b95a5743..ede19224b 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/PlayerMoveListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/PlayerMoveListener.java
@@ -25,7 +25,6 @@
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
-import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Entity;
@@ -40,6 +39,7 @@
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector;
+import java.util.concurrent.TimeUnit;
public class PlayerMoveListener extends AbstractListener {
@@ -127,7 +127,10 @@ public void onPlayerMove(PlayerMoveEvent event) {
player.teleport(override.clone().add(0, 1, 0));
- Bukkit.getScheduler().runTaskLater(getPlugin(), () -> player.teleport(override.clone().add(0, 1, 0)), 1);
+ getPlugin().getFoliaLib().getImpl().runAtEntityLater(player, () -> {
+ player.teleport(override.clone().add(0, 1, 0));
+ }, 50, TimeUnit.MILLISECONDS);
+// Bukkit.getScheduler().runTaskLater(getPlugin(), () -> player.teleport(override.clone().add(0, 1, 0)), 1);
}
}
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java
index 9ec21272d..698bea903 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java
@@ -61,6 +61,8 @@
import org.bukkit.event.Event;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityMountEvent;
+import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerTakeLecternBookEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
@@ -173,7 +175,7 @@ public void onPlaceBlock(final PlaceBlockEvent event) {
/* Flint and steel, fire charge, etc. */
if (Materials.isFire(type)) {
Block block = event.getCause().getFirstBlock();
- boolean fire = block != null && Materials.isFire(type);
+ boolean fire = block != null && Materials.isFire(block.getType());
boolean lava = block != null && Materials.isLava(block.getType());
List flags = new ArrayList<>();
flags.add(Flags.BLOCK_PLACE);
@@ -244,13 +246,13 @@ public void onUseBlock(final UseBlockEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
- final Material type = event.getEffectiveMaterial();
final RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
final RegionAssociable associable = createRegionAssociable(event.getCause());
event.filter((Predicate) target -> {
boolean canUse;
String what;
+ final Material type = target.getBlock().getType();
/* Saplings, etc. */
if (Materials.isConsideredBuildingIfUsed(type)) {
@@ -410,13 +412,15 @@ public void onUseEntity(UseEntityEvent event) {
canUse = event.getRelevantFlags().isEmpty() || query.queryState(BukkitAdapter.adapt(target), associable, combine(event)) != State.DENY;
what = "use that";
/* Paintings, item frames, etc. */
- } else if (Entities.isConsideredBuildingIfUsed(entity)) {
+ } else if (Entities.isConsideredBuildingIfUsed(entity)
+ // weird case since sneak+interact is chest access and not ride
+ || event.getOriginalEvent() instanceof InventoryOpenEvent) {
if ((type == EntityType.ITEM_FRAME || type == EntityType.GLOW_ITEM_FRAME)
&& event.getCause().getFirstPlayer() != null
&& ((ItemFrame) entity).getItem().getType() != Material.AIR) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.ITEM_FRAME_ROTATE));
what = "change that";
- } else if (Entities.isMinecart(type)) {
+ } else if (event.getOriginalEvent() instanceof InventoryOpenEvent) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.CHEST_ACCESS));
what = "open that";
} else {
@@ -425,9 +429,10 @@ public void onUseEntity(UseEntityEvent event) {
}
/* Ridden on use */
} else if (Entities.isRiddenOnUse(entity)) {
- canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.RIDE, Flags.INTERACT));
+ // this is bypassed here as it's handled by the entity mount listener below
+ // bukkit actually gives three events in this case - in order: PlayerInteractAtEntity, VehicleEnter, EntityMount
+ canUse = true;
what = "ride that";
-
/* Everything else */
} else {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.INTERACT));
@@ -516,6 +521,27 @@ public void onDamageEntity(DamageEntityEvent event) {
}
}
+ @EventHandler
+ public void onEntityMount(EntityMountEvent event) {
+ Entity vehicle = event.getMount();
+ if (!isRegionSupportEnabled(vehicle.getWorld())) return; // Region support disabled
+ if (!(event.getEntity() instanceof Player player)) {
+ return;
+ }
+ Cause cause = Cause.create(player);
+ if (isWhitelisted(cause, vehicle.getWorld(), false)) {
+ return;
+ }
+ RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
+ Location location = vehicle.getLocation();
+ LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
+ if (!query.testBuild(BukkitAdapter.adapt(location), localPlayer, Flags.RIDE, Flags.INTERACT)) {
+ event.setCancelled(true);
+ DelegateEvent dummy = new UseEntityEvent(event, cause, vehicle);
+ tellErrorMessage(dummy, cause, vehicle.getLocation(), "ride that");
+ }
+ }
+
@EventHandler(ignoreCancelled = true)
public void onVehicleExit(VehicleExitEvent event) {
Entity vehicle = event.getVehicle();
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardBlockListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardBlockListener.java
index ad8e11c6e..a9dd5866f 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardBlockListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardBlockListener.java
@@ -56,6 +56,7 @@
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.block.LeavesDecayEvent;
+import org.bukkit.event.block.MoistureChangeEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
@@ -726,4 +727,24 @@ public void onBlockExplode(BlockExplodeEvent event) {
}
}
+ /**
+ * Called when the moisture level of a block changes
+ */
+ @EventHandler(ignoreCancelled = true)
+ public void onMoistureChange(MoistureChangeEvent event) {
+ WorldConfiguration wcfg = getWorldConfig(event.getBlock().getWorld());
+
+ if (wcfg.disableSoilMoistureChange) {
+ event.setCancelled(true);
+ return;
+ }
+
+ if (wcfg.useRegions) {
+ if (!StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
+ .queryState(BukkitAdapter.adapt(event.getBlock().getLocation()), (RegionAssociable) null, Flags.MOISTURE_CHANGE))) {
+ event.setCancelled(true);
+ }
+ }
+ }
+
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java
index 7ea3bf477..080a68db5 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java
@@ -44,6 +44,7 @@
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
+import org.bukkit.entity.AbstractWindCharge;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderCrystal;
@@ -60,6 +61,7 @@
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
+import org.bukkit.entity.WindCharge;
import org.bukkit.entity.Wither;
import org.bukkit.entity.WitherSkull;
import org.bukkit.entity.Wolf;
@@ -311,13 +313,17 @@ private void onEntityDamageByProjectile(EntityDamageByEntityEvent event) {
return;
}
}
- if (event.getDamager() instanceof Fireball) {
- Fireball fireball = (Fireball) event.getDamager();
+ if (event.getDamager() instanceof Fireball fireball) {
if (fireball instanceof WitherSkull) {
if (wcfg.blockWitherSkullExplosions) {
event.setCancelled(true);
return;
}
+ } else if (fireball instanceof AbstractWindCharge) {
+ if (wcfg.blockWindChargeExplosions) {
+ event.setCancelled(true);
+ return;
+ }
} else {
if (wcfg.blockFireballExplosions) {
event.setCancelled(true);
@@ -326,7 +332,7 @@ private void onEntityDamageByProjectile(EntityDamageByEntityEvent event) {
}
if (wcfg.useRegions) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
- if (!query.testState(localPlayer.getLocation(), localPlayer, Flags.GHAST_FIREBALL) && wcfg.explosionFlagCancellation) {
+ if (!query.testState(localPlayer.getLocation(), localPlayer, Entities.getExplosionFlag(event.getDamager())) && wcfg.explosionFlagCancellation) {
event.setCancelled(true);
return;
}
@@ -483,6 +489,11 @@ public void onEntityExplode(EntityExplodeEvent event) {
event.blockList().clear();
return;
}
+ } else if (ent instanceof AbstractWindCharge) {
+ if (wcfg.blockWindChargeExplosions) {
+ event.setCancelled(true);
+ return;
+ }
} else {
if (wcfg.blockFireballExplosions) {
event.setCancelled(true);
@@ -493,10 +504,10 @@ public void onEntityExplode(EntityExplodeEvent event) {
return;
}
}
- // allow wither skull blocking since there is no dedicated flag atm
- if (wcfg.useRegions) {
+ if (wcfg.useRegions && !(ent instanceof WindCharge)) {
for (Block block : event.blockList()) {
- if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation())).testState(null, Flags.GHAST_FIREBALL)) {
+ if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
+ .testState(BukkitAdapter.adapt(block.getLocation()), null, Entities.getExplosionFlag(ent))) {
event.blockList().clear();
if (wcfg.explosionFlagCancellation) event.setCancelled(true);
return;
@@ -514,8 +525,8 @@ public void onEntityExplode(EntityExplodeEvent event) {
}
if (wcfg.useRegions) {
for (Block block : event.blockList()) {
- if (!StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().queryState(BukkitAdapter.adapt(block.getLocation()),
- (RegionAssociable) null, Flags.WITHER_DAMAGE))) {
+ if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
+ .testState(BukkitAdapter.adapt(block.getLocation()), null, Flags.WITHER_DAMAGE)) {
event.blockList().clear();
event.setCancelled(true);
return;
@@ -530,7 +541,8 @@ public void onEntityExplode(EntityExplodeEvent event) {
}
if (wcfg.useRegions) {
for (Block block : event.blockList()) {
- if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation())).testState(null, Flags.OTHER_EXPLOSION)) {
+ if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
+ .testState(BukkitAdapter.adapt(block.getLocation()), null, Flags.OTHER_EXPLOSION)) {
event.blockList().clear();
if (wcfg.explosionFlagCancellation) event.setCancelled(true);
return;
@@ -539,7 +551,6 @@ public void onEntityExplode(EntityExplodeEvent event) {
}
}
-
if (wcfg.signChestProtection) {
for (Block block : event.blockList()) {
if (wcfg.isChestProtected(BukkitAdapter.adapt(block.getLocation()))) {
@@ -592,6 +603,11 @@ public void onExplosionPrime(ExplosionPrimeEvent event) {
event.setCancelled(true);
return;
}
+ } else if (event.getEntity() instanceof AbstractWindCharge) {
+ if (wcfg.blockWindChargeExplosions) {
+ event.setCancelled(true);
+ return;
+ }
}
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardPlayerListener.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardPlayerListener.java
index d9daa9e8e..1656ab323 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardPlayerListener.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardPlayerListener.java
@@ -350,6 +350,11 @@ public void onItemHeldChange(PlayerItemHeldEvent event) {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
+ if (event.getTo() == null) {
+ // The target location for PlayerTeleportEvents can be null.
+ // Those events will be ignored by the server, so we can ignore them too.
+ return;
+ }
Player player = event.getPlayer();
if (com.sk89q.worldguard.bukkit.util.Entities.isNPC(player)) return;
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/session/BukkitSessionManager.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/session/BukkitSessionManager.java
index df589cbc0..21168afcf 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/session/BukkitSessionManager.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/session/BukkitSessionManager.java
@@ -28,6 +28,8 @@
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.session.AbstractSessionManager;
import com.sk89q.worldguard.session.Session;
+import com.tcoded.folialib.FoliaLib;
+import com.tcoded.folialib.impl.ServerImplementation;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -68,7 +70,13 @@ public void onPlayerProcess(ProcessPlayerEvent event) {
public void run() {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
- get(localPlayer).tick(localPlayer);
+ Session session = get(localPlayer);
+
+ FoliaLib foliaLib = WorldGuardPlugin.inst().getFoliaLib();
+ ServerImplementation impl = foliaLib.getImpl();
+
+ if (foliaLib.isFolia()) impl.runAtEntity(player, (task) -> session.tick(localPlayer));
+ else session.tick(localPlayer);
}
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java
index 8a89e7a77..d8292c701 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java
@@ -19,15 +19,21 @@
package com.sk89q.worldguard.bukkit.util;
+import com.sk89q.worldguard.protection.flags.Flags;
+import com.sk89q.worldguard.protection.flags.StateFlag;
import org.bukkit.entity.Allay;
import org.bukkit.entity.Ambient;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Arrow;
+import org.bukkit.entity.BreezeWindCharge;
import org.bukkit.entity.Creature;
+import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Fireball;
+import org.bukkit.entity.Firework;
import org.bukkit.entity.Flying;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.LivingEntity;
@@ -43,11 +49,14 @@
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Vehicle;
+import org.bukkit.entity.WindCharge;
+import org.bukkit.entity.Wither;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.projectiles.ProjectileSource;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class Entities {
@@ -113,8 +122,11 @@ public static boolean isVehicle(EntityType type) {
* @return true if the type is a Boat type
*/
public static boolean isBoat(EntityType type) {
- return switch(type) {
- case BOAT, CHEST_BOAT -> true;
+ return switch (type) {
+ case OAK_BOAT, DARK_OAK_BOAT, SPRUCE_BOAT, ACACIA_BOAT, CHERRY_BOAT, JUNGLE_BOAT, MANGROVE_BOAT,
+ BIRCH_BOAT, PALE_OAK_BOAT, BAMBOO_RAFT, OAK_CHEST_BOAT, DARK_OAK_CHEST_BOAT, SPRUCE_CHEST_BOAT,
+ ACACIA_CHEST_BOAT, CHERRY_CHEST_BOAT, JUNGLE_CHEST_BOAT, MANGROVE_CHEST_BOAT, BIRCH_CHEST_BOAT,
+ PALE_OAK_CHEST_BOAT, BAMBOO_CHEST_RAFT -> true;
default -> false;
};
}
@@ -237,7 +249,7 @@ public static boolean isAoECloud(EntityType type) {
* This is true for custom creations or the summon command.
*
* @param spawnReason the reason
- * @return true if considerd plugin spawning
+ * @return true if considered plugin spawning
*/
public static boolean isPluginSpawning(CreatureSpawnEvent.SpawnReason spawnReason) {
return switch (spawnReason) {
@@ -245,4 +257,24 @@ public static boolean isPluginSpawning(CreatureSpawnEvent.SpawnReason spawnReaso
default -> false;
};
}
+
+ /**
+ * Get the explosion flag relevant for an entity type.
+ * @param entity the entity
+ * @return the relevant StateFlag or OTHER_EXPLOSION if none is matching
+ */
+ public static @Nonnull StateFlag getExplosionFlag(Entity entity) {
+ return switch (entity) {
+ case BreezeWindCharge breezeWindCharge -> Flags.BREEZE_WIND_CHARGE;
+ case WindCharge windCharge -> Flags.WIND_CHARGE_BURST;
+ case Firework firework -> Flags.FIREWORK_DAMAGE;
+ case Fireball fireball -> Flags.GHAST_FIREBALL;
+ case Wither wither -> Flags.WITHER_DAMAGE;
+ case Creeper creeper -> Flags.CREEPER_EXPLOSION;
+ case TNTPrimed tnt -> Flags.TNT;
+ case ExplosiveMinecart minecart -> Flags.TNT;
+ case EnderDragon dragon -> Flags.ENDERDRAGON_BLOCK_DAMAGE;
+ case null, default -> Flags.OTHER_EXPLOSION;
+ };
+ }
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java
index 6cdd49245..04d48dc98 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java
@@ -23,6 +23,7 @@
import com.google.common.collect.HashBiMap;
import com.sk89q.worldguard.protection.flags.Flags;
import org.bukkit.Material;
+import org.bukkit.Registry;
import org.bukkit.Tag;
import org.bukkit.entity.EntityType;
import org.bukkit.potion.PotionEffect;
@@ -69,7 +70,6 @@ private static void putMaterialTag(Tag tag, Integer value) {
ENTITY_ITEMS.put(EntityType.TNT, Material.TNT);
ENTITY_ITEMS.put(EntityType.FIREWORK_ROCKET, Material.FIREWORK_ROCKET);
ENTITY_ITEMS.put(EntityType.COMMAND_BLOCK_MINECART, Material.COMMAND_BLOCK_MINECART);
- ENTITY_ITEMS.put(EntityType.BOAT, Material.OAK_BOAT);
ENTITY_ITEMS.put(EntityType.MINECART, Material.MINECART);
ENTITY_ITEMS.put(EntityType.CHEST_MINECART, Material.CHEST_MINECART);
ENTITY_ITEMS.put(EntityType.FURNACE_MINECART, Material.FURNACE_MINECART);
@@ -80,6 +80,19 @@ private static void putMaterialTag(Tag tag, Integer value) {
ENTITY_ITEMS.put(EntityType.ARMOR_STAND, Material.ARMOR_STAND);
ENTITY_ITEMS.put(EntityType.END_CRYSTAL, Material.END_CRYSTAL);
+ for (String wood : new String[]{"OAK", "SPRUCE", "BIRCH", "JUNGLE", "ACACIA", "DARK_OAK", "MANGROVE", "CHERRY", "PALE_OAK"}) {
+ String regular = wood + "_BOAT";
+ String chest = wood + "_CHEST_BOAT";
+ ENTITY_ITEMS.put(EntityType.valueOf(regular), Material.getMaterial(regular));
+ ENTITY_ITEMS.put(EntityType.valueOf(chest), Material.getMaterial(chest));
+ }
+ ENTITY_ITEMS.put(EntityType.BAMBOO_RAFT, Material.BAMBOO_RAFT);
+ ENTITY_ITEMS.put(EntityType.BAMBOO_CHEST_RAFT, Material.BAMBOO_CHEST_RAFT);
+
+ // preset some tags to a default value, override some of them:
+ putMaterialTag(Tag.DOORS, MODIFIED_ON_RIGHT);
+ putMaterialTag(Tag.TRAPDOORS, MODIFIED_ON_RIGHT);
+
MATERIAL_FLAGS.put(Material.AIR, 0);
MATERIAL_FLAGS.put(Material.STONE, 0);
MATERIAL_FLAGS.put(Material.GRASS_BLOCK, 0);
@@ -150,12 +163,6 @@ private static void putMaterialTag(Tag tag, Integer value) {
MATERIAL_FLAGS.put(Material.CAKE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REPEATER, MODIFIED_ON_RIGHT);
// MATERIAL_FLAGS.put(Material.STAINED_GLASS, 0);
- MATERIAL_FLAGS.put(Material.ACACIA_TRAPDOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.BIRCH_TRAPDOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.DARK_OAK_TRAPDOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.JUNGLE_TRAPDOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.OAK_TRAPDOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.SPRUCE_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.INFESTED_STONE, 0);
MATERIAL_FLAGS.put(Material.INFESTED_STONE_BRICKS, 0);
MATERIAL_FLAGS.put(Material.INFESTED_MOSSY_STONE_BRICKS, 0);
@@ -227,11 +234,6 @@ private static void putMaterialTag(Tag tag, Integer value) {
MATERIAL_FLAGS.put(Material.IRON_TRAPDOOR, 0);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE, 0);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE_STAIRS, 0);
- MATERIAL_FLAGS.put(Material.SPRUCE_DOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.BIRCH_DOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.JUNGLE_DOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.ACACIA_DOOR, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.DARK_OAK_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DIRT_PATH, 0);
MATERIAL_FLAGS.put(Material.CHORUS_PLANT, 0);
@@ -247,7 +249,7 @@ private static void putMaterialTag(Tag tag, Integer value) {
MATERIAL_FLAGS.put(Material.PURPUR_SLAB, 0);
MATERIAL_FLAGS.put(Material.STRUCTURE_BLOCK, MODIFIED_ON_LEFT | MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REPEATING_COMMAND_BLOCK, MODIFIED_ON_RIGHT);
- MATERIAL_FLAGS.put(Material.CHAIN_COMMAND_BLOCK , MODIFIED_ON_RIGHT);
+ MATERIAL_FLAGS.put(Material.CHAIN_COMMAND_BLOCK, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.MAGMA_BLOCK, 0);
MATERIAL_FLAGS.put(Material.NETHER_WART_BLOCK, 0);
@@ -677,7 +679,6 @@ private static void putMaterialTag(Tag tag, Integer value) {
MATERIAL_FLAGS.put(Material.CRIMSON_FUNGUS, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_NYLIUM, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_ROOTS, 0);
- MATERIAL_FLAGS.put(Material.CRIMSON_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CRYING_OBSIDIAN, 0);
MATERIAL_FLAGS.put(Material.GILDED_BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.LODESTONE, 0);
@@ -718,7 +719,6 @@ private static void putMaterialTag(Tag tag, Integer value) {
MATERIAL_FLAGS.put(Material.WARPED_FUNGUS_ON_A_STICK, 0);
MATERIAL_FLAGS.put(Material.WARPED_NYLIUM, 0);
MATERIAL_FLAGS.put(Material.WARPED_ROOTS, 0);
- MATERIAL_FLAGS.put(Material.WARPED_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.WARPED_WART_BLOCK, 0);
MATERIAL_FLAGS.put(Material.WEEPING_VINES, 0);
MATERIAL_FLAGS.put(Material.WEEPING_VINES_PLANT, 0);
@@ -843,11 +843,50 @@ private static void putMaterialTag(Tag tag, Integer value) {
MATERIAL_FLAGS.put(Material.ARMADILLO_SCUTE, 0);
MATERIAL_FLAGS.put(Material.WOLF_ARMOR, 0);
- // Generated via tag
- putMaterialTag(Tag.WOODEN_DOORS, MODIFIED_ON_RIGHT);
- putMaterialTag(Tag.WOODEN_TRAPDOORS, MODIFIED_ON_RIGHT);
+ // 1.21
+ MATERIAL_FLAGS.put(Material.CHISELED_TUFF, 0);
+ MATERIAL_FLAGS.put(Material.POLISHED_TUFF, 0);
+ MATERIAL_FLAGS.put(Material.TUFF_BRICKS, 0);
+ MATERIAL_FLAGS.put(Material.CHISELED_TUFF_BRICKS, 0);
+ MATERIAL_FLAGS.put(Material.HEAVY_CORE, 0);
+ MATERIAL_FLAGS.put(Material.CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.EXPOSED_CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.WEATHERED_CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.OXIDIZED_CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_EXPOSED_CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_WEATHERED_CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_OXIDIZED_CHISELED_COPPER, 0);
+ MATERIAL_FLAGS.put(Material.CRAFTER, 0);
+ MATERIAL_FLAGS.put(Material.FLOW_BANNER_PATTERN, 0);
+ MATERIAL_FLAGS.put(Material.GUSTER_BANNER_PATTERN, 0);
+ MATERIAL_FLAGS.put(Material.COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.WEATHERED_COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.EXPOSED_COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.OXIDIZED_COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_WEATHERED_COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_EXPOSED_COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_OXIDIZED_COPPER_GRATE, 0);
+ MATERIAL_FLAGS.put(Material.COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.WEATHERED_COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.EXPOSED_COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.OXIDIZED_COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_WEATHERED_COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_EXPOSED_COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.WAXED_OXIDIZED_COPPER_BULB, 0);
+ MATERIAL_FLAGS.put(Material.TRIAL_SPAWNER, 0);
+ MATERIAL_FLAGS.put(Material.TRIAL_KEY, 0);
+ MATERIAL_FLAGS.put(Material.OMINOUS_TRIAL_KEY, 0);
+ MATERIAL_FLAGS.put(Material.VAULT, MODIFIED_ON_RIGHT);
+ MATERIAL_FLAGS.put(Material.OMINOUS_BOTTLE, 0);
+ MATERIAL_FLAGS.put(Material.BREEZE_ROD, 0);
+ MATERIAL_FLAGS.put(Material.WIND_CHARGE, 0);
+
putMaterialTag(Tag.SHULKER_BOXES, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.ITEMS_BOATS, 0);
+ putMaterialTag(Tag.ITEMS_CHEST_BOATS, 0);
putMaterialTag(Tag.BANNERS, 0);
putMaterialTag(Tag.SLABS, 0);
putMaterialTag(Tag.PLANKS, 0);
@@ -864,7 +903,6 @@ private static void putMaterialTag(Tag tag, Integer value) {
putMaterialTag(Tag.ALL_SIGNS, 0);
putMaterialTag(Tag.SMALL_FLOWERS, 0);
putMaterialTag(Tag.BEDS, MODIFIED_ON_RIGHT);
- putMaterialTag(Tag.ITEMS_MUSIC_DISCS, 0);
putMaterialTag(Tag.ITEMS_BANNERS, 0);
putMaterialTag(Tag.FENCE_GATES, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.FENCES, 0);
@@ -897,28 +935,30 @@ private static void putMaterialTag(Tag tag, Integer value) {
});
// Check for missing items/blocks
- for (Material material : Material.values()) {
- if (material.isLegacy()) continue;
+ Registry.MATERIAL.stream().forEach(material -> {
// Add spawn eggs
if (isSpawnEgg(material)) {
MATERIAL_FLAGS.put(material, 0);
}
+ if (material.name().startsWith("MUSIC_DISC_")) {
+ MATERIAL_FLAGS.put(material, 0);
+ }
if (!MATERIAL_FLAGS.containsKey(material)) {
logger.fine("Missing material definition for " + (material.isBlock() ? "block " : "item ") + material.name());
}
- }
+ });
// DAMAGE_EFFECTS.add(PotionEffectType.SPEED);
DAMAGE_EFFECTS.add(PotionEffectType.SLOWNESS);
-// DAMAGE_EFFECTS.add(PotionEffectType.FAST_DIGGING);
+// DAMAGE_EFFECTS.add(PotionEffectType.HASTE);
DAMAGE_EFFECTS.add(PotionEffectType.MINING_FATIGUE);
-// DAMAGE_EFFECTS.add(PotionEffectType.INCREASE_DAMAGE);
-// DAMAGE_EFFECTS.add(PotionEffectType.HEAL);
+// DAMAGE_EFFECTS.add(PotionEffectType.STRENGTH);
+// DAMAGE_EFFECTS.add(PotionEffectType.INSTANT_HEALTH);
DAMAGE_EFFECTS.add(PotionEffectType.INSTANT_DAMAGE);
-// DAMAGE_EFFECTS.add(PotionEffectType.JUMP);
+// DAMAGE_EFFECTS.add(PotionEffectType.JUMP_BOOST);
DAMAGE_EFFECTS.add(PotionEffectType.NAUSEA);
// DAMAGE_EFFECTS.add(PotionEffectType.REGENERATION);
-// DAMAGE_EFFECTS.add(PotionEffectType.DAMAGE_RESISTANCE);
+// DAMAGE_EFFECTS.add(PotionEffectType.RESISTANCE);
// DAMAGE_EFFECTS.add(PotionEffectType.FIRE_RESISTANCE);
// DAMAGE_EFFECTS.add(PotionEffectType.WATER_BREATHING);
// DAMAGE_EFFECTS.add(PotionEffectType.INVISIBILITY);
@@ -941,6 +981,11 @@ private static void putMaterialTag(Tag tag, Integer value) {
DAMAGE_EFFECTS.add(PotionEffectType.BAD_OMEN);
// DAMAGE_EFFECTS.add(PotionEffectType.HERO_OF_THE_VILLAGE);
DAMAGE_EFFECTS.add(PotionEffectType.DARKNESS);
+ DAMAGE_EFFECTS.add(PotionEffectType.TRIAL_OMEN);
+ DAMAGE_EFFECTS.add(PotionEffectType.WIND_CHARGED);
+ DAMAGE_EFFECTS.add(PotionEffectType.WEAVING);
+ DAMAGE_EFFECTS.add(PotionEffectType.OOZING);
+ DAMAGE_EFFECTS.add(PotionEffectType.INFESTED);
}
private Materials() {
@@ -1127,6 +1172,7 @@ public static boolean isInventoryBlock(Material material) {
|| material == Material.BLAST_FURNACE
|| material == Material.SMOKER
|| material == Material.CHISELED_BOOKSHELF
+ || material == Material.CRAFTER
|| Tag.ITEMS_CHEST_BOATS.isTagged(material)
|| Tag.SHULKER_BOXES.isTagged(material);
}
@@ -1140,10 +1186,11 @@ public static EntityType getEntitySpawnEgg(Material material) {
case ALLAY_SPAWN_EGG -> EntityType.ALLAY;
case ARMADILLO_SPAWN_EGG -> EntityType.ARMADILLO;
case AXOLOTL_SPAWN_EGG -> EntityType.AXOLOTL;
- case SPIDER_SPAWN_EGG -> EntityType.SPIDER;
case BAT_SPAWN_EGG -> EntityType.BAT;
case BEE_SPAWN_EGG -> EntityType.BEE;
case BLAZE_SPAWN_EGG -> EntityType.BLAZE;
+ case BOGGED_SPAWN_EGG -> EntityType.BOGGED;
+ case BREEZE_SPAWN_EGG -> EntityType.BREEZE;
case CAT_SPAWN_EGG -> EntityType.CAT;
case CAMEL_SPAWN_EGG -> EntityType.CAMEL;
case CAVE_SPIDER_SPAWN_EGG -> EntityType.CAVE_SPIDER;
@@ -1193,6 +1240,7 @@ public static EntityType getEntitySpawnEgg(Material material) {
case SLIME_SPAWN_EGG -> EntityType.SLIME;
case SNIFFER_SPAWN_EGG -> EntityType.SNIFFER;
case SNOW_GOLEM_SPAWN_EGG -> EntityType.SNOW_GOLEM;
+ case SPIDER_SPAWN_EGG -> EntityType.SPIDER;
case SQUID_SPAWN_EGG -> EntityType.SQUID;
case STRAY_SPAWN_EGG -> EntityType.STRAY;
case STRIDER_SPAWN_EGG -> EntityType.STRIDER;
@@ -1276,15 +1324,15 @@ public static boolean isVine(Material newType) {
*/
public static boolean isUseFlagApplicable(Material material) {
if (Tag.BUTTONS.isTagged(material)
- || Tag.WOODEN_DOORS.isTagged(material)
- || Tag.WOODEN_TRAPDOORS.isTagged(material)
+ || Tag.DOORS.isTagged(material)
+ || Tag.TRAPDOORS.isTagged(material)
|| Tag.FENCE_GATES.isTagged(material)
|| Tag.PRESSURE_PLATES.isTagged(material)) {
return true;
}
return switch (material) {
case LEVER, LECTERN, ENCHANTING_TABLE, BELL, LOOM,
- CARTOGRAPHY_TABLE, STONECUTTER, GRINDSTONE -> true;
+ CARTOGRAPHY_TABLE, STONECUTTER, GRINDSTONE, VAULT -> true;
default -> false;
};
}
@@ -1367,15 +1415,13 @@ public static boolean hasDamageEffect(Collection effects) {
* @return true if equippable armor
*/
public static boolean isArmor(Material type) {
+ if (Tag.ITEMS_HEAD_ARMOR.isTagged(type) || Tag.ITEMS_CHEST_ARMOR.isTagged(type) ||
+ Tag.ITEMS_LEG_ARMOR.isTagged(type) || Tag.ITEMS_FOOT_ARMOR.isTagged(type) ||
+ Tag.ITEMS_SKULLS.isTagged(type)) {
+ return true;
+ }
return switch (type) {
- case LEATHER_HELMET, LEATHER_CHESTPLATE, LEATHER_LEGGINGS, LEATHER_BOOTS,
- CHAINMAIL_HELMET, CHAINMAIL_CHESTPLATE, CHAINMAIL_LEGGINGS, CHAINMAIL_BOOTS,
- IRON_HELMET, IRON_CHESTPLATE, IRON_LEGGINGS, IRON_BOOTS,
- DIAMOND_HELMET, DIAMOND_CHESTPLATE, DIAMOND_LEGGINGS, DIAMOND_BOOTS,
- GOLDEN_HELMET, GOLDEN_CHESTPLATE, GOLDEN_LEGGINGS, GOLDEN_BOOTS,
- NETHERITE_HELMET, NETHERITE_CHESTPLATE, NETHERITE_LEGGINGS, NETHERITE_BOOTS,
- TURTLE_HELMET, ELYTRA ->
- true;
+ case CARVED_PUMPKIN, ELYTRA -> true;
default -> false;
};
}
@@ -1458,6 +1504,9 @@ public static boolean isToolApplicable(Material toolMaterial, Material targetMat
case SUSPICIOUS_GRAVEL, SUSPICIOUS_SAND -> true;
default -> false;
};
+ case WRITTEN_BOOK:
+ case WRITABLE_BOOK:
+ return targetMaterial == Material.LECTERN;
default:
return false;
}
@@ -1466,27 +1515,18 @@ public static boolean isToolApplicable(Material toolMaterial, Material targetMat
public static boolean isFire(Material type) {
return type == Material.FIRE || type == Material.SOUL_FIRE;
}
-
+
public static boolean isWaxedCopper(Material type) {
- return switch (type) {
- case WAXED_COPPER_BLOCK, WAXED_EXPOSED_COPPER, WAXED_WEATHERED_COPPER, WAXED_OXIDIZED_COPPER,
- WAXED_CUT_COPPER, WAXED_EXPOSED_CUT_COPPER, WAXED_WEATHERED_CUT_COPPER,
- WAXED_OXIDIZED_CUT_COPPER, WAXED_CUT_COPPER_STAIRS, WAXED_EXPOSED_CUT_COPPER_STAIRS,
- WAXED_WEATHERED_CUT_COPPER_STAIRS, WAXED_OXIDIZED_CUT_COPPER_STAIRS, WAXED_CUT_COPPER_SLAB,
- WAXED_EXPOSED_CUT_COPPER_SLAB, WAXED_WEATHERED_CUT_COPPER_SLAB, WAXED_OXIDIZED_CUT_COPPER_SLAB ->
- true;
- default -> false;
- };
+ // copied from the MaterialTags class in Paper
+ return type.name().startsWith("WAXED_") && type.name().contains("COPPER");
}
-
+
public static boolean isUnwaxedCopper(Material type) {
+ // copied from the MaterialTags class in Paper
return switch (type) {
- case COPPER_BLOCK, EXPOSED_COPPER, WEATHERED_COPPER, OXIDIZED_COPPER, CUT_COPPER,
- EXPOSED_CUT_COPPER, WEATHERED_CUT_COPPER, OXIDIZED_CUT_COPPER, CUT_COPPER_STAIRS,
- EXPOSED_CUT_COPPER_STAIRS, WEATHERED_CUT_COPPER_STAIRS, OXIDIZED_CUT_COPPER_STAIRS,
- CUT_COPPER_SLAB, EXPOSED_CUT_COPPER_SLAB, WEATHERED_CUT_COPPER_SLAB, OXIDIZED_CUT_COPPER_SLAB ->
- true;
- default -> false;
+ case COPPER_BLOCK, CHISELED_COPPER, COPPER_DOOR, COPPER_TRAPDOOR, COPPER_GRATE, COPPER_BULB -> true;
+ default -> type.name().startsWith("EXPOSED_") || type.name().startsWith("WEATHERED_") ||
+ type.name().startsWith("OXIDIZED_") || type.name().startsWith("CUT_COPPER");
};
}
diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/report/SchedulerReport.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/report/SchedulerReport.java
index d897162cf..23cee36be 100644
--- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/report/SchedulerReport.java
+++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/util/report/SchedulerReport.java
@@ -24,8 +24,9 @@
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.sk89q.worldedit.util.report.DataReport;
-import org.bukkit.Bukkit;
-import org.bukkit.scheduler.BukkitTask;
+import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
+import com.tcoded.folialib.FoliaLib;
+import com.tcoded.folialib.wrapper.task.WrappedTask;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
@@ -35,6 +36,8 @@
public class SchedulerReport extends DataReport {
+ private FoliaLib foliaLib = WorldGuardPlugin.inst().getFoliaLib();
+
private LoadingCache, Optional> taskFieldCache = CacheBuilder.newBuilder()
.build(new CacheLoader, Optional>() {
@Override
@@ -49,27 +52,78 @@ public Optional load(Class> clazz) throws Exception {
}
});
+ private LoadingCache, Optional> foliaTaskFieldCache = CacheBuilder.newBuilder()
+ .build(new CacheLoader, Optional>() {
+ @Override
+ public Optional load(Class> clazz) throws Exception {
+ try {
+ Field field = clazz.getDeclaredField("run");
+ field.setAccessible(true);
+ return Optional.ofNullable(field);
+ } catch (NoSuchFieldException ignored) {
+ return Optional.empty();
+ }
+ }
+ });
+
public SchedulerReport() {
super("Scheduler");
- List tasks = Bukkit.getServer().getScheduler().getPendingTasks();
+ List tasks = foliaLib.getImpl().getAllTasks();
append("Pending Task Count", tasks.size());
- for (BukkitTask task : tasks) {
- Class> taskClass = getTaskClass(task);
+ for (WrappedTask task : tasks) {
+ Object handle = getTaskHandle(task);
+ Class> taskClass;
+ if (foliaLib.isFolia()) {
+ taskClass = getFoliaTaskClass(handle);
+ } else {
+ taskClass = getBukkitTaskClass(handle);
+ }
- DataReport report = new DataReport("Task: #" + task.getTaskId());
- report.append("Owner", task.getOwner().getName());
+ DataReport report = new DataReport("Task: #" + handle.hashCode());
+ report.append("Owner", task.getOwningPlugin().getName());
report.append("Runnable", taskClass != null ? taskClass.getName() : "");
- report.append("Synchronous?", task.isSync());
+ report.append("Synchronous?", !task.isAsync());
append(report.getTitle(), report);
}
}
+ private Object getTaskHandle(WrappedTask task) {
+ try {
+ Field field = task.getClass().getDeclaredField("task");
+ field.setAccessible(true);
+ return field.get(task);
+ } catch (IllegalAccessException | NoSuchFieldException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ private Class> getFoliaTaskClass(Object task) {
+ try {
+ Class> clazz = task.getClass();
+ Set> classes = (Set) TypeToken.of(clazz).getTypes().rawTypes();
+
+ for (Class> type : classes) {
+ Optional field = foliaTaskFieldCache.getUnchecked(type);
+ if (field.isPresent()) {
+ Object res = field.get().get(task);
+ return res == null ? null : res.getClass();
+ }
+ }
+ } catch (IllegalAccessException | NoClassDefFoundError ignored) {
+ }
+
+ return null;
+ }
+
@SuppressWarnings("unchecked")
@Nullable
- private Class> getTaskClass(BukkitTask task) {
+ private Class> getBukkitTaskClass(Object task) {
try {
Class> clazz = task.getClass();
Set> classes = (Set) TypeToken.of(clazz).getTypes().rawTypes();
diff --git a/worldguard-bukkit/src/main/resources/plugin.yml b/worldguard-bukkit/src/main/resources/plugin.yml
index 223be72f7..95bb45bc9 100644
--- a/worldguard-bukkit/src/main/resources/plugin.yml
+++ b/worldguard-bukkit/src/main/resources/plugin.yml
@@ -3,4 +3,5 @@ main: com.sk89q.worldguard.bukkit.WorldGuardPlugin
version: "${internalVersion}"
depend: [WorldEdit]
softdepend: [CommandBook]
-api-version: "1.20"
+api-version: "1.21"
+folia-supported: true
diff --git a/worldguard-core/build.gradle.kts b/worldguard-core/build.gradle.kts
index 9e5666162..d6f7eac53 100644
--- a/worldguard-core/build.gradle.kts
+++ b/worldguard-core/build.gradle.kts
@@ -1,20 +1,51 @@
+import org.cadixdev.gradle.licenser.LicenseExtension
+
plugins {
`java-library`
+ id("buildlogic.core-and-platform")
}
-applyPlatformAndCoreConfiguration()
-
dependencies {
+ constraints {
+ "implementation"(libs.snakeyaml) {
+ because("Bukkit provides SnakeYaml")
+ }
+ }
+
"api"(project(":worldguard-libs:core"))
- "api"("com.sk89q.worldedit:worldedit-core:${Versions.WORLDEDIT}")
- "implementation"("org.flywaydb:flyway-core:3.0")
- "implementation"("org.yaml:snakeyaml:2.0")
- "implementation"("com.google.guava:guava:${Versions.GUAVA}")
+ "api"(libs.worldedit.core)
+ "implementation"(libs.flyway.core)
+ "implementation"(libs.snakeyaml)
+ "implementation"(libs.guava)
+ "compileOnlyApi"(libs.jsr305)
+ "implementation"(libs.gson)
+
+ "compileOnly"(libs.worldedit.libs.ap)
+ "annotationProcessor"(libs.worldedit.libs.ap)
+ // ensure this is on the classpath for the AP
+ "annotationProcessor"(libs.guava)
+
+ "compileOnly"(libs.autoService) {
+ because("Needed to resolve annotations in Piston")
+ }
- "compileOnly"("com.google.code.findbugs:jsr305:${Versions.FINDBUGS}")
- "testImplementation"("org.hamcrest:hamcrest-library:2.2")
+ "testImplementation"(libs.hamcrest.library)
}
-tasks.withType().configureEach {
+tasks.compileJava {
dependsOn(":worldguard-libs:build")
-}
\ No newline at end of file
+ options.compilerArgs.add("-Aarg.name.key.prefix=")
+}
+
+configure {
+ exclude {
+ it.file.startsWith(project.layout.buildDirectory.get().asFile)
+ }
+}
+
+configure {
+ publications.named("maven") {
+ artifactId = the().archivesName.get()
+ from(components["java"])
+ }
+}
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/GeneralCommands.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/GeneralCommands.java
index 1b8fffcef..61aa037c0 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/GeneralCommands.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/GeneralCommands.java
@@ -70,7 +70,7 @@ public void god(CommandContext args, Actor sender) throws CommandException, Auth
// Keep track of this
included = true;
- } else {
+ } else if (!args.hasFlag('s')) {
player.print("God enabled by " + sender.getDisplayName() + ".");
}
@@ -79,7 +79,7 @@ public void god(CommandContext args, Actor sender) throws CommandException, Auth
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
- if (!included && args.hasFlag('s')) {
+ if (!included) {
sender.print("Players now have god mode.");
}
}
@@ -113,7 +113,7 @@ public void ungod(CommandContext args, Actor sender) throws CommandException, Au
// Keep track of this
included = true;
- } else {
+ } else if (!args.hasFlag('s')) {
player.print("God disabled by " + sender.getDisplayName() + ".");
}
@@ -122,7 +122,7 @@ public void ungod(CommandContext args, Actor sender) throws CommandException, Au
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
- if (!included && args.hasFlag('s')) {
+ if (!included) {
sender.print("Players no longer have god mode.");
}
}
@@ -158,7 +158,7 @@ public void heal(CommandContext args, Actor sender) throws CommandException, Aut
// Keep track of this
included = true;
- } else {
+ } else if (!args.hasFlag('s')) {
player.print("Healed by " + sender.getDisplayName() + ".");
}
@@ -166,7 +166,7 @@ public void heal(CommandContext args, Actor sender) throws CommandException, Aut
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
- if (!included && args.hasFlag('s')) {
+ if (!included) {
sender.print("Players healed.");
}
}
@@ -199,7 +199,7 @@ public void slay(CommandContext args, Actor sender) throws CommandException, Aut
// Keep track of this
included = true;
- } else {
+ } else if (!args.hasFlag('s')) {
player.print("Slain by " + sender.getDisplayName() + ".");
}
@@ -207,7 +207,7 @@ public void slay(CommandContext args, Actor sender) throws CommandException, Aut
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
- if (!included && args.hasFlag('s')) {
+ if (!included) {
sender.print("Players slain.");
}
}
@@ -229,6 +229,7 @@ public void locate(CommandContext args, Actor sender) throws CommandException {
}
}
+ @SuppressWarnings("removal")
@Command(aliases = {"stack", ";"}, usage = "", desc = "Stack items", max = 0)
@CommandPermissions({"worldguard.stack"})
public void stack(CommandContext args, Actor sender) throws CommandException {
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java b/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java
index df3d5fc18..c98f23c6e 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java
@@ -101,6 +101,7 @@ public abstract class WorldConfiguration {
public boolean blockEnderDragonPortalCreation;
public boolean blockFireballExplosions;
public boolean blockFireballBlockDamage;
+ public boolean blockWindChargeExplosions;
public boolean blockOtherExplosions;
public boolean blockEntityPaintingDestroy;
public boolean blockEntityItemFrameDestroy;
@@ -166,6 +167,7 @@ public abstract class WorldConfiguration {
public boolean disableEndermanGriefing;
public boolean disableSnowmanTrails;
public boolean disableSoilDehydration;
+ public boolean disableSoilMoistureChange;
public boolean disableCoralBlockFade;
public boolean disableCopperBlockFade;
public Set allowedSnowFallOver;
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/internal/platform/WorldGuardPlatform.java b/worldguard-core/src/main/java/com/sk89q/worldguard/internal/platform/WorldGuardPlatform.java
index 71e26a4d6..0bbaaa94d 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/internal/platform/WorldGuardPlatform.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/internal/platform/WorldGuardPlatform.java
@@ -145,6 +145,7 @@ public interface WorldGuardPlatform {
*
* @param localPlayer The player
*/
+ @Deprecated(forRemoval = true)
void stackPlayerInventory(LocalPlayer localPlayer);
/**
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/Flags.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/Flags.java
index 24cc675ed..3aacacd97 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/Flags.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/Flags.java
@@ -74,6 +74,7 @@ public final class Flags {
public static final StateFlag FIREWORK_DAMAGE = register(new StateFlag("firework-damage", false));
public static final StateFlag USE_ANVIL = register(new StateFlag("use-anvil", false));
public static final StateFlag USE_DRIPLEAF = register(new StateFlag("use-dripleaf", false));
+ public static final StateFlag WIND_CHARGE_BURST = register(new StateFlag("wind-charge-burst", false));
// These flags are similar to the ones above (used in tandem with BUILD),
// but their defaults are set to TRUE because it is more user friendly.
@@ -93,6 +94,7 @@ public final class Flags {
public static final StateFlag ENDERDRAGON_BLOCK_DAMAGE = register(new StateFlag("enderdragon-block-damage", true));
public static final StateFlag GHAST_FIREBALL = register(new StateFlag("ghast-fireball", true));
public static final StateFlag OTHER_EXPLOSION = register(new StateFlag("other-explosion", true));
+ public static final StateFlag BREEZE_WIND_CHARGE = register(new StateFlag("breeze-charge-explosion", true));
public static final StateFlag WITHER_DAMAGE = register(new StateFlag("wither-damage", true));
public static final StateFlag ENDER_BUILD = register(new StateFlag("enderman-grief", true));
public static final StateFlag SNOWMAN_TRAILS = register(new StateFlag("snowman-trails", true));
@@ -128,6 +130,7 @@ public final class Flags {
public static final StateFlag COPPER_FADE = register(new StateFlag("copper-fade", true));
public static final StateFlag WATER_FLOW = register(new StateFlag("water-flow", true));
public static final StateFlag LAVA_FLOW = register(new StateFlag("lava-flow", true));
+ public static final StateFlag MOISTURE_CHANGE = register(new StateFlag("moisture-change", true));
public static final RegistryFlag WEATHER_LOCK = register(new RegistryFlag<>("weather-lock", WeatherType.REGISTRY));
public static final StringFlag TIME_LOCK = register(new StringFlag("time-lock"));
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/session/AbstractSessionManager.java b/worldguard-core/src/main/java/com/sk89q/worldguard/session/AbstractSessionManager.java
index 68bfac198..0f9a05882 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/session/AbstractSessionManager.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/session/AbstractSessionManager.java
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.session;
+import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@@ -67,10 +68,9 @@ public abstract class AbstractSessionManager implements SessionManager {
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(CacheLoader.from(tuple -> BYPASS_PERMISSION_TEST.test(tuple.getWorld(), tuple.getPlayer())));
- private final LoadingCache sessions = CacheBuilder.newBuilder()
+ private final Cache sessions = CacheBuilder.newBuilder()
.expireAfterAccess(SESSION_LIFETIME, TimeUnit.MINUTES)
- .build(CacheLoader.from(key ->
- createSession(key.playerRef.get())));
+ .build();
private boolean hasCustom = false;
private List> handlers = new LinkedList<>();
@@ -152,7 +152,7 @@ public boolean hasBypass(LocalPlayer player, World world) {
@Override
public void resetState(LocalPlayer player) {
checkNotNull(player, "player");
- @Nullable Session session = sessions.getIfPresent(new CacheKey(player));
+ @Nullable Session session = getIfPresentInternal(new CacheKey(player));
if (session != null) {
session.resetState(player);
}
@@ -161,22 +161,35 @@ public void resetState(LocalPlayer player) {
@Override
@Nullable
public Session getIfPresent(LocalPlayer player) {
- return sessions.getIfPresent(new CacheKey(player));
+ return getIfPresentInternal(new CacheKey(player));
+ }
+
+ private Session getIfPresentInternal(CacheKey cacheKey) {
+ @Nullable Session session = sessions.getIfPresent(cacheKey);
+ if (session != null) {
+ session.ensureInitialized(cacheKey.playerRef.get(), this::initializeSession);
+ return session;
+ }
+ return null;
}
@Override
public Session get(LocalPlayer player) {
- return sessions.getUnchecked(new CacheKey(player));
+ Session session = sessions.asMap().computeIfAbsent(new CacheKey(player), (k) -> new Session(this));
+ session.ensureInitialized(player, this::initializeSession);
+ return session;
}
@Override
public Session createSession(LocalPlayer player) {
- Session session = new Session(this);
+ return get(player);
+ }
+
+ private void initializeSession(Session session, LocalPlayer player) {
for (Handler.Factory extends Handler> factory : handlers) {
session.register(factory.create(session));
}
session.initialize(player);
- return session;
}
protected static final class CacheKey {
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/session/Session.java b/worldguard-core/src/main/java/com/sk89q/worldguard/session/Session.java
index cdc8401a3..f52f00cc7 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/session/Session.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/session/Session.java
@@ -38,6 +38,7 @@
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiConsumer;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -52,6 +53,7 @@ public class Session {
private Location lastValid;
private Set lastRegionSet;
private final AtomicBoolean needRefresh = new AtomicBoolean(false);
+ private boolean initialized;
/**
* Create a new session.
@@ -110,7 +112,7 @@ public void initialize(LocalPlayer player) {
disableBypass = cfg.disableDefaultBypass;
if (cfg.announceBypassStatus && player.hasPermission("worldguard.region.toggle-bypass")) {
player.printInfo(TextComponent.of(
- "You are " + (disableBypass ? "not" : "") + " bypassing region protection. " +
+ "You are " + (disableBypass ? "not " : "") + "bypassing region protection. " +
"You can toggle this with /rg bypass", TextColor.DARK_PURPLE));
}
@@ -120,6 +122,14 @@ public void initialize(LocalPlayer player) {
}
}
+ synchronized void ensureInitialized(LocalPlayer player, BiConsumer initializer) {
+ if (initialized) {
+ return;
+ }
+ initialized = true;
+ initializer.accept(this, player);
+ }
+
/**
* Uninitialize the session.
*
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/session/SessionManager.java b/worldguard-core/src/main/java/com/sk89q/worldguard/session/SessionManager.java
index bd34f7ec2..fce2bf340 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/session/SessionManager.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/session/SessionManager.java
@@ -95,7 +95,9 @@ public interface SessionManager {
*
* @param player The player
* @return The new session
+ * @deprecated Use {@link SessionManager#get} instead
*/
+ @Deprecated
Session createSession(LocalPlayer player);
/**
diff --git a/worldguard-libs/build.gradle.kts b/worldguard-libs/build.gradle.kts
index 33c839af1..152530cb0 100644
--- a/worldguard-libs/build.gradle.kts
+++ b/worldguard-libs/build.gradle.kts
@@ -1,3 +1,3 @@
tasks.register("build") {
dependsOn(subprojects.map { it.tasks.named("build") })
-}
\ No newline at end of file
+}
diff --git a/worldguard-libs/bukkit/build.gradle.kts b/worldguard-libs/bukkit/build.gradle.kts
deleted file mode 100644
index 7eb9124f2..000000000
--- a/worldguard-libs/bukkit/build.gradle.kts
+++ /dev/null
@@ -1,2 +0,0 @@
-applyLibrariesConfiguration()
-constrainDependenciesToLibsCore()
\ No newline at end of file
diff --git a/worldguard-libs/core/build.gradle.kts b/worldguard-libs/core/build.gradle.kts
index 035191ede..ebfc595b0 100644
--- a/worldguard-libs/core/build.gradle.kts
+++ b/worldguard-libs/core/build.gradle.kts
@@ -1,18 +1,10 @@
-import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
-
-applyLibrariesConfiguration()
-
-dependencies {
- "shade"("org.enginehub:squirrelid:${Versions.SQUIRRELID}")
- "shade"("org.khelekore:prtree:1.5.0")
+plugins {
+ id("buildlogic.libs")
}
-tasks.named("jar") {
- dependencies {
- relocate("org.enginehub.squirrelid", "com.sk89q.worldguard.util.profile") {
- include(dependency("org.enginehub:squirrelid"))
- }
-
- include(dependency("org.khelekore:prtree"))
+dependencies {
+ "shade"(libs.squirrelid) {
+ isTransitive = false
}
+ "shade"(libs.prtree)
}