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: + +[Folia-Inquisitors](https://github.com/orgs/Folia-Inquisitors/repositories) +[TechnicallyCoded](https://github.com/TechnicallyCoded) +[Yomamaeatstoes](https://github.com/Yomamaeatstoes) +[Loving11ish](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 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) }