Compare commits

...
59 Commits
Author SHA1 Message Date
Maddy Miller 578e802368 Merge branch 'version/7.0.x' 2026-08-01 14:01:38 +10:00
Maddy Miller 49ebc79b7d Add a GH Actions run to do a simple Gradle build 2026-08-01 13:55:29 +10:00
Maddy Miller 31c9320db3 Require MC 26.2 and add additional material definitions 2026-08-01 13:53:52 +10:00
Maddy Miller 8ec5e8a7e0 Back to SNAPSHOT for continued development 2026-07-31 21:46:47 +10:00
Maddy Miller fa605e6a19 Release 7.0.18 2026-07-31 21:46:22 +10:00
TomyLobo 048bd2addd Synchronize YamlRegionFile#saveAll (#2014)
* Synchronize YamlRegionFile#saveAll

This prevents multiple invocations of the method from intersecting, which could potentially cause the .tmp file to be overwritten before being renamed, thus corrupting the region storage

* Synchronize on the class instead of the instance

I didn't realize it before, but it looks like there is at least one instance of YamlRegionFile per world, so synchronizing on the instance wouldn't necessarily help.
2026-07-30 18:54:31 +10:00
Maddy Miller d002474ec6 Remove strict versions from MC libs 2026-07-29 21:25:05 +10:00
Maddy Miller a156c07ab3 Filter "standing in" regions list by permission access. Fixes #2262 (#2293)
* Filter "standing in" regions list by permission access. Fixes #2262

* Don't filter the actual result, just the output
2026-07-28 19:06:12 +10:00
Maddy Miller f0239b632c Use new Enemy interface for hostile detection 2026-07-18 17:15:33 +10:00
Maddy Miller 7c38af4c7a Migrate PigZapEvent for Paper. Fixes #2290 (#2292) 2026-07-12 13:54:52 +10:00
TomyLobo da6bfb3b95 Add lava-harden flag (#2275)
* Rename type to newType and extract oldType variable

* Add lava-harden flag

This covers the forming of cobblestone, stone, obsidian and basalt.
2026-07-12 13:49:11 +10:00
Maddy Miller 1439345adc Fix gradle publish with Shadow 9 2026-07-11 17:57:48 +10:00
RVSkeLe f310e93a5b perf: avoid unnecessary isNPC checks (#2285) 2026-07-11 17:26:33 +10:00
Maddy Miller ab33d3fdc5 Migrate to Crankcase (and drop <MC 26.1) (#2291)
* Migrate to Crankcase (and drop <MC 26.1)

* missed java 21 refs

* May as well populate the single material flag for 26.1 here
2026-07-11 16:50:08 +10:00
Maddy Miller d1a3193754 Back to SNAPSHOT for continued development 2026-05-30 13:04:55 +10:00
Maddy Miller e42d8bcda7 Release 7.0.17 2026-05-30 13:04:28 +10:00
JMKohnagel 20eb298cac fix: detect cocoa as a crop (#2278) 2026-05-20 21:59:36 +10:00
TomyLobo b4914ef8cd Fix checkstyle problems 2026-05-18 20:38:16 +02:00
Maddy Miller 3e9e1c84ef Replace PaperLib functionality that no longer works properly on 26.1+ 2026-05-09 14:39:36 +10:00
Brite 8783e2bac6 Only store originalGameMode if NULL (#2265) 2026-04-22 21:16:30 +10:00
Maddy Miller aa5160334b Cleanup Folia handlers to use more shared code 2026-04-07 16:46:29 +10:00
Maddy Miller caa121c12a Back to SNAPSHOT for continued development 2026-03-24 19:01:00 +10:00
Maddy Miller f7fded2f64 Release 7.0.16 2026-03-24 19:00:28 +10:00
CatTeaA dd8d2ff576 Generating an End Portal should not trigger BlockMultiPlaceEvent (#2266)
* Allow end_portal generation if player can interact with block

* add some comments

* concise comment
2026-03-24 18:52:10 +10:00
Euphyllia 88db0e5070 Basic Folia Support (#2259)
* Basic Folia Support

* Teleport async only with Folia server

* restore

* Extract the location for teleportation and add the {}

* Extract the location for teleportation

* Revert worldedit version
2026-03-16 19:10:12 +10:00
Maddy Miller 039e9af06e Manually deserialize block/item names during blacklist handling. Fixes #2255 2026-02-07 23:41:08 +10:00
Maddy Miller 6b994f085c Merge branch 'version/7.0.x' of github.com:EngineHub/WorldGuard into version/7.0.x 2026-01-06 15:50:48 +10:00
Maddy Miller 999fb12e8a Back to SNAPSHOT for continued development 2026-01-06 15:50:16 +10:00
Maddy Miller ce4622f13b Release 7.0.16 Beta 1 2026-01-06 15:47:24 +10:00
Aaron Beier 94b752246a Fix tiny typo (#2217) 2026-01-06 15:46:07 +10:00
aerulion 4405a29790 Bump API version to 1.21.11 2026-01-06 15:42:20 +10:00
aerulion 6697bab390 Updated material definitions and dependencies for 1.21.11
- Updated Mojang-provided libraries to the correct version
- Added new Material and SpawnEgg definitions
- Fixed some missing item materials i missed during the previous commit, since I did not know items should also be covered
2026-01-06 15:41:56 +10:00
Maddy Miller 5baf085ae7 Back to SNAPSHOT for continued development 2026-01-06 15:33:38 +10:00
Maddy Miller 5fafea6787 Release 7.0.15 2026-01-06 15:31:47 +10:00
Maddy Miller 480afaeb52 Merge branch 'pr/2249' into version/7.0.x 2026-01-06 15:31:03 +10:00
aerulion cff2510cd1 Bump API version to 1.21.11 2025-12-27 17:10:12 +01:00
aerulion af09868673 Updated material definitions and dependencies for 1.21.11
- Updated Mojang-provided libraries to the correct version
- Added new Material and SpawnEgg definitions
- Fixed some missing item materials i missed during the previous commit, since I did not know items should also be covered
2025-12-27 16:20:38 +01:00
Maddy Miller b7e9c4c7f1 Back to SNAPSHOT for continued development 2025-11-01 19:19:39 +10:00
Maddy Miller 445a1d7352 Release 7.0.15 Beta 1 2025-11-01 19:13:34 +10:00
aerulion 56427c7157 Updated material definitions up to 1.21.10 (#2239)
* Updated material definitions up to 1.21.10

* Remove commented-out materials
2025-10-30 17:48:18 +10:00
Maddy Miller 8191e5dfef Improve region file loading compatibility with NIO Java APIs 2025-10-27 22:12:41 +10:00
Joo200 86a1fa6ee9 Merge branch 'version/7.0.x'
# Conflicts:
#	gradle.properties
2025-08-24 21:20:09 +02:00
Maddy Miller f8415edfcd Skip handling notify flags on false values 2025-07-27 16:13:58 +10:00
Maddy Miller c4c17a2e4f Remove weird files 2025-06-12 23:17:17 +10:00
Maddy Miller e2f21b66ed Back to SNAPSHOT for continued development 2025-06-12 23:10:23 +10:00
Joo200 ab48a66237 Merge branch 'refs/heads/version/7.0.x'
# Conflicts:
#	buildSrc/src/main/kotlin/GradleExtras.kt
#	buildSrc/src/main/kotlin/LibsConfig.kt
#	buildSrc/src/main/kotlin/PlatformConfig.kt
#	gradle.properties
#	worldguard-libs/bukkit/build.gradle.kts
2024-09-16 20:08:34 +02:00
Joo200 aa254c80e0 Merge branch 'refs/heads/version/7.0.x'
# Conflicts:
#	buildSrc/build.gradle.kts
2024-05-03 19:57:42 +02:00
Madeline Miller f6a0a0b415 Add outline to logo SVG akin to WorldEdit and CraftBook 2024-05-01 23:08:16 +10:00
Joo200 0a9eb447d6 store custom domains thread safe, improve api usability 2023-08-20 11:06:36 +02:00
Joo200 02a8fd4c17 Merge remote-tracking branch 'origin/version/7.0.x'
# Conflicts:
#	gradle.properties
2023-08-14 14:21:50 +02:00
Joo200 8cbce96a2c Merge branch 'version/7.0.x' 2023-06-18 18:47:29 +02:00
Joo200 bb3fdcc880 Renamed InvalidFlagFormat to InvalidFlagFormatException 2023-06-04 18:55:01 +02:00
JOO200 8d5953a550 apidomains: Added custom domains to WorldGuard
This change allows third party plugins to dynamically add custom domains to WorldGuard.
2023-06-04 18:55:01 +02:00
wizjany 129ae6c971 Merge branch 'version/7.0.x'
# Conflicts:
#	gradle.properties
2023-05-27 13:49:05 -04:00
Joo200 b67fd01ebd Merge branch 'version/7.0.x'
# Conflicts:
#	buildSrc/src/main/kotlin/Versions.kt
#	gradle/wrapper/gradle-wrapper.jar
#	gradle/wrapper/gradle-wrapper.properties
#	gradlew.bat
#	worldguard-core/build.gradle.kts
2023-03-26 15:17:06 +02:00
Joo200 62be386626 Merge branch 'version/7.0.x' 2022-11-27 10:52:54 +01:00
Joo200 741f9e231b Merge branch 'version/7.0.x'
# Conflicts:
#	buildSrc/build.gradle.kts
#	buildSrc/src/main/kotlin/PlatformConfig.kt
#	buildSrc/src/main/kotlin/Versions.kt
2022-09-19 11:56:50 +02:00
wizjany bc63119373 Fix publish. 2022-03-12 17:32:40 -05:00
wizjany 3549f04a33 Build script updates.
Bump gradle. Copy a bunch from WE. Hopefully nothing breaks.
2022-03-12 17:21:50 -05:00
109 changed files with 2059 additions and 658 deletions

No files matched your search

+33 -1
View File
@@ -1,2 +1,34 @@
*.java diff=java
* text=auto eol=lf
# Force Batch files to CRLF
*.bat eol=crlf -text
# Java sources
*.java text diff=java
*.kt text diff=java
*.gradle text diff=java
*.gradle.kts text diff=java
# These files are text and should be normalized (Convert crlf => lf)
*.css text diff=css
*.df text
*.htm text diff=html
*.html text diff=html
*.js text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.tld text
*.tag text
*.tagx text
*.xml text
# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.jar binary
*.so binary
*.war binary
*.jks binary
+48
View File
@@ -0,0 +1,48 @@
name: Gradle Build
on:
push:
branches:
- 'master'
- 'version/*'
pull_request:
merge_group:
jobs:
build:
name: Build WorldGuard on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v6
- name: Set up JDK
uses: actions/setup-java@v5
with:
java-version: 25
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
with:
cache-read-only: ${{ !(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/version/')) }}
- name: Execute Gradle build
run: ./gradlew build -s
- uses: actions/upload-artifact@v6
name: Archive Reports
if: always()
with:
name: reports for ${{ matrix.os }}
path: '**/build/reports/**'
- uses: actions/upload-artifact@v6
name: Archive Logs
if: always()
with:
name: logs for ${{ matrix.os }}
path: '**/*.log'
+26
View File
@@ -1,5 +1,31 @@
# Changelog
## 7.0.18
* Add lava-harden flag for cobblestone/stone/obsidian/basalt forming.
* Replace PigZapEvent on Paper to avoid startup warnings.
* Avoid unnecessary NPC checks to improve performance in some situations.
* Filtered "multiple regions" messages in commands to only show regions that the player has permission to use the command on.
* Fixed potential corruption that can occur in extreme region / slow hardware setups where it hasn't finished saving by the next save attempt.
## 7.0.17
* Fix cocoa not being treated as a crop in relevant flags.
* Fix overlapping game mode flags sometimes not storing the expected previous game mode.
* Replace PaperLib functionality that doesn't behave as expected on MC 26.1+.
## 7.0.16
* Update to 1.21.11.
* Added experimental Folia support.
* Workaround an issue where some item/block names aren't adequately translated by the client.
* Workaround a duplication bug in Paper.
## 7.0.15
* Update to 1.21.10
* Improve region file loading compatibility with NIO Java APIs
## 7.0.14
* Update to 1.21.5
+2 -2
View File
@@ -1,8 +1,8 @@
Compiling
=========
You can compile WorldGuard as long as you have some version of Java greater than or equal to 21 installed.
Gradle will download JDK 21 specifically if needed, but it needs some version of Java to bootstrap from.
You can compile WorldGuard as long as you have some version of Java greater than or equal to 25 installed.
Gradle will download JDK 25 specifically if needed, but it needs some version of Java to bootstrap from.
The build process uses Gradle, which you do *not* need to download. WorldGuard is a multi-module project with three modules:
+10 -6
View File
@@ -3,19 +3,23 @@ plugins {
}
repositories {
gradlePluginPortal()
maven {
name = "EngineHub Repository"
url = uri("https://maven.enginehub.org/repo/")
name = "EngineHub"
url = uri("https://repo.enginehub.org/libs-release/")
}
mavenCentral()
gradlePluginPortal()
}
dependencies {
implementation(gradleApi())
implementation(libs.licenser)
implementation(libs.grgit)
implementation(libs.crankcase.java)
implementation(libs.crankcase.javaLibrary)
implementation(libs.crankcase.common)
implementation(libs.crankcase.licensing)
implementation(libs.crankcase.git)
implementation(libs.crankcase.publishing)
implementation(libs.shadow)
implementation(libs.jfrog.buildinfo)
implementation(libs.gson)
constraints {
@@ -1,32 +0,0 @@
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<ArtifactoryPluginConvention> {
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<ArtifactoryTask>("artifactoryPublish") {
isSkip = true
}
@@ -1,10 +0,0 @@
plugins {
id("com.jfrog.artifactory")
}
// Artifactory eagerly evaluates publications, so this must run after all changes to artifacts are done
afterEvaluate {
tasks.named<org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask>("artifactoryPublish") {
publications("maven")
}
}
@@ -0,0 +1,4 @@
plugins {
id("org.enginehub.crankcase.java-library")
id("buildlogic.common-java")
}
@@ -5,61 +5,25 @@ plugins {
id("eclipse")
id("idea")
id("checkstyle")
id("org.enginehub.crankcase.java")
id("buildlogic.common")
}
tasks
.withType<JavaCompile>()
.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")
}
crankcaseJava {
javaRelease = 25
disabledLints = listOf("processing", "path", "fallthrough", "serial", "overloads")
}
tasks.withType<JavaCompile>().configureEach {
// TODO Remove this when we're able
options.compilerArgs.remove("-Werror")
}
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "10.16.0"
}
tasks.withType<Test>().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<Javadoc>().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<JavaPluginExtension> {
withJavadocJar()
withSourcesJar()
}
tasks.named("check").configure {
dependsOn("checkstyleMain", "checkstyleTest")
}
@@ -1,37 +1,15 @@
import buildlogic.getLibrary
import buildlogic.stringyLibs
import org.gradle.plugins.ide.idea.model.IdeaModel
plugins {
id("org.cadixdev.licenser")
id("org.enginehub.crankcase.common")
id("org.enginehub.crankcase.licensing")
id("org.enginehub.crankcase.git")
}
group = rootProject.group
version = rootProject.version
repositories {
maven {
name = "EngineHub"
url = uri("https://maven.enginehub.org/repo/")
}
mavenCentral()
afterEvaluate {
killNonEngineHubRepositories()
}
}
configurations.all {
resolutionStrategy {
cacheChangingModulesFor(1, TimeUnit.DAYS)
}
}
plugins.withId("java") {
the<JavaPluginExtension>().toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
dependencies {
for (conf in listOf("implementation", "api")) {
if (!configurations.names.contains(conf)) {
@@ -55,18 +33,3 @@ dependencies {
}
}
}
license {
header(rootProject.file("HEADER.txt"))
include("**/*.java")
include("**/*.kt")
}
plugins.withId("idea") {
configure<IdeaModel> {
module {
isDownloadSources = true
isDownloadJavadoc = true
}
}
}
@@ -1,12 +1,9 @@
plugins {
id("java")
id("maven-publish")
id("buildlogic.common-java")
id("buildlogic.artifactory-sub")
id("buildlogic.common-java-library")
id("org.enginehub.crankcase.publishing")
}
ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
publishing {
publications {
register<MavenPublication>("maven") {
@@ -1,10 +1,9 @@
plugins {
id("java-base")
id("maven-publish")
id("com.github.johnrengelman.shadow")
id("com.jfrog.artifactory")
id("com.gradleup.shadow")
id("buildlogic.common")
id("buildlogic.artifactory-sub")
id("org.enginehub.crankcase.publishing")
}
// A horrible hack because `softwareComponentFactory` has to be gotten via plugin
@@ -119,7 +118,7 @@ val apiElements = project.configurations.register("apiElements") {
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)
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25)
}
outgoing.artifact(tasks.named("jar"))
}
@@ -134,7 +133,7 @@ val runtimeElements = project.configurations.register("runtimeElements") {
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)
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25)
}
outgoing.artifact(tasks.named("jar"))
}
@@ -1,8 +1,12 @@
plugins {
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
id("buildlogic.core-and-platform")
}
shadow {
addShadowVariantIntoJavaComponent = false
}
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
archiveClassifier.set("dist")
dependencies {
@@ -20,11 +24,6 @@ tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJ
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>("jar") {
@@ -7,7 +7,9 @@ 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.enginehub.crankcase.git.GitExtension
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the
val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
@@ -15,6 +17,12 @@ val Project.ext: ExtraPropertiesExtension
val Project.stringyLibs: VersionCatalog
get() = extensions.getByType<VersionCatalogsExtension>().named("libs")
val Project.internalVersion: Provider<String>
get() {
val version = version.toString()
return the<GitExtension>().commitHash.map { "$version+$it" }
}
fun VersionCatalog.getLibrary(name: String): Provider<MinimalExternalModuleDependency> = findLibrary(name).orElseThrow {
error("Library $name not found in version catalog")
}
@@ -1,26 +0,0 @@
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.logging.Logging
// The primary point of this is repository up-time. We replace most other repositories with EngineHub's repository.
// This is because we have stronger up-time guarantees for our repository. However, Maven Central and Sonatype are
// clearly even better, so we allow those as well. We also allow Gradle's plugin repository.
private val ALLOWED_PREFIXES = listOf(
"https://maven.enginehub.org",
"https://repo.maven.apache.org/maven2/",
"https://s01.oss.sonatype.org/content/repositories/snapshots/",
"https://plugins.gradle.org",
"file:"
)
private val LOGGER = Logging.getLogger("repositoriesHelper")
fun RepositoryHandler.killNonEngineHubRepositories() {
val toRemove = mutableListOf<MavenArtifactRepository>()
for (repo in this) {
if (repo is MavenArtifactRepository && !ALLOWED_PREFIXES.any { repo.url.toString().startsWith(it) }) {
LOGGER.info("Removing non-EngineHub repository: {}", repo.url)
toRemove.add(repo)
}
}
toRemove.forEach { remove(it) }
}
-14
View File
@@ -1,17 +1,3 @@
import org.ajoberstar.grgit.Grgit
plugins {
id("buildlogic.common")
id("buildlogic.artifactory-root")
}
if (!project.hasProperty("gitCommitHash")) {
apply(plugin = "org.ajoberstar.grgit")
ext["gitCommitHash"] = try {
extensions.getByName<Grgit>("grgit").head()?.abbreviatedId
} catch (e: Exception) {
logger.warn("Error getting commit hash", e)
"no.git.id"
}
}
@@ -0,0 +1,86 @@
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.withType
fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, javaRelease: Int = 8, banSlf4j: Boolean = true) {
applyCommonConfiguration()
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "checkstyle")
tasks
.withType<JavaCompile>()
.matching { it.name == "compileJava" || it.name == "compileTestJava" }
.configureEach {
val disabledLint = listOf(
"processing", "path", "fallthrough", "serial"
)
options.release.set(javaRelease)
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
options.isDeprecation = true
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
}
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "9.1"
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
"compileOnly"("com.google.code.findbugs:jsr305:${Versions.FINDBUGS}")
"testImplementation"("org.junit.jupiter:junit-jupiter-api:${Versions.JUNIT}")
"testImplementation"("org.junit.jupiter:junit-jupiter-params:${Versions.JUNIT}")
"testImplementation"("org.mockito:mockito-core:${Versions.MOCKITO}")
"testImplementation"("org.mockito:mockito-junit-jupiter:${Versions.MOCKITO}")
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:${Versions.JUNIT}")
}
// Java 8 turns on doclint which we fail
tasks.withType<Javadoc>().configureEach {
options.encoding = "UTF-8"
(options as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:none", "-quiet")
tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
}
}
configure<JavaPluginExtension> {
disableAutoTargetJvm()
withJavadocJar()
if (sourcesJar) {
withSourcesJar()
}
}
if (banSlf4j) {
configurations["compileClasspath"].apply {
resolutionStrategy.componentSelection {
withModule("org.slf4j:slf4j-api") {
reject("No SLF4J allowed on compile classpath")
}
}
}
}
tasks.named("check").configure {
dependsOn("checkstyleMain", "checkstyleTest")
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
group=com.sk89q.worldguard
version=7.0.14
version=7.1.0-SNAPSHOT
org.gradle.parallel=true
+1 -1
View File
@@ -1,2 +1,2 @@
#This file is generated by updateDaemonJvm
toolchainVersion=21
toolchainVersion=25
+16 -16
View File
@@ -1,5 +1,6 @@
[versions]
worldedit = "7.3.9"
worldedit = "7.4.4"
crankcase = "0.1.0"
# Minimum versions we apply to make dependencies support newer Java
minimumAsm = "9.7"
@@ -10,10 +11,14 @@ minimumTinyRemapper = "0.8.11"
[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"
crankcase-java = { module = "org.enginehub.crankcase:java", version.ref = "crankcase" }
crankcase-javaLibrary = { module = "org.enginehub.crankcase:java-library", version.ref = "crankcase" }
crankcase-common = { module = "org.enginehub.crankcase:common", version.ref = "crankcase" }
crankcase-licensing = { module = "org.enginehub.crankcase:licensing", version.ref = "crankcase" }
crankcase-git = { module = "org.enginehub.crankcase:git", version.ref = "crankcase" }
crankcase-publishing = { module = "org.enginehub.crankcase:publishing", version.ref = "crankcase" }
shadow = "com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.3.2"
squirrelid = "org.enginehub:squirrelid:0.3.2"
@@ -22,16 +27,11 @@ 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"
paperApi = "io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT"
paperApi = "io.papermc.paper:paper-api:26.2.build.+"
paperLib = "io.papermc:paperlib:1.0.8"
dummypermscompat = "com.sk89q:dummypermscompat:1.10"
bstats-bukkit = "org.bstats:bstats-bukkit:2.2.1"
bstats-bukkit = "org.bstats:bstats-bukkit:3.2.1"
prtree = "org.khelekore:prtree:1.5.0"
@@ -42,10 +42,10 @@ 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:33.3.1-jre!!"
log4j-bom = "org.apache.logging.log4j:log4j-bom:2.24.1!!"
gson = "com.google.code.gson:gson:2.11.0!!"
fastutil = "it.unimi.dsi:fastutil:8.5.15!!"
guava = "com.google.guava:guava:33.6.0-jre"
log4j-bom = "org.apache.logging.log4j:log4j-bom:2.25.2"
gson = "com.google.code.gson:gson:2.14.0"
fastutil = "it.unimi.dsi:fastutil:8.5.18"
# 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
+3 -1
View File
@@ -1,7 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+40 -20
View File
@@ -1,38 +1,58 @@
pluginManagement {
// pluginManagement repositories resolve plugins before the repo-reconfiguration plugin can
// apply, so they must point at EngineHub mirrors directly rather than upstream URLs.
repositories {
gradlePluginPortal()
maven {
name = "EngineHub"
url = uri("https://maven.enginehub.org/repo/")
url = uri("https://repo.enginehub.org/libs-release/")
mavenContent {
releasesOnly()
includeGroupAndSubgroups("com.sk89q")
includeGroupAndSubgroups("org.enginehub")
}
}
maven {
name = "EngineHub Maven Central Mirror"
url = uri("https://repo.enginehub.org/internal/maven-central-proxy/")
mavenContent {
releasesOnly()
}
}
maven {
name = "EngineHub Gradle Plugin Portal Mirror"
url = uri("https://repo.enginehub.org/internal/plugin-portal-proxy/")
mavenContent {
releasesOnly()
}
}
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
id("org.enginehub.crankcase.repo-reconfiguration") version "0.1.0"
}
dependencyResolutionManagement {
repositories {
maven {
name = "EngineHub"
url = uri("https://maven.enginehub.org/repo/")
name = "PaperMC"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
gradle.settingsEvaluated {
// Duplicates repositoriesHelper.kt, since we can't import it
val allowedPrefixes = listOf(
"https://maven.enginehub.org",
"https://repo.maven.apache.org/maven2/",
"file:"
)
for (repo in this@repositories) {
if (repo is MavenArtifactRepository) {
val urlString = repo.url.toString()
check(allowedPrefixes.any { urlString.startsWith(it) }) {
"Only EngineHub/Central repositories are allowed: ${repo.url} found"
}
}
maven {
name = "EngineHub (Non-Mirrored)"
url = uri("https://repo.enginehub.org/libs-release/")
}
maven {
name = "EngineHub Legacy Third-Party"
url = uri("https://repo.enginehub.org/artifactory/libs-release/")
content {
includeGroup("org.khelekore")
}
}
mavenCentral()
maven {
name = "Minecraft Libraries"
url = uri("https://libraries.minecraft.net/")
}
}
}
+5 -4
View File
@@ -1,7 +1,7 @@
import buildlogic.internalVersion
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
`java-library`
id("buildlogic.platform")
}
@@ -26,17 +26,18 @@ dependencies {
}
tasks.named<Copy>("processResources") {
val internalVersion = project.ext["internalVersion"]
val internalVersion = project.internalVersion
inputs.property("internalVersion", internalVersion)
filesMatching("plugin.yml") {
expand("internalVersion" to internalVersion)
expand("internalVersion" to internalVersion.get())
}
}
tasks.named<ShadowJar>("shadowJar") {
dependencies {
include(dependency(":worldguard-core"))
include(dependency("org.bstats:"))
include(dependency("org.bstats:bstats-bukkit"))
include(dependency("org.bstats:bstats-base"))
include(dependency("io.papermc:paperlib"))
relocate("org.bstats", "com.sk89q.worldguard.bukkit.bstats")
@@ -25,6 +25,7 @@ import com.sk89q.worldedit.world.weather.WeatherType;
import com.sk89q.worldedit.world.weather.WeatherTypes;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.util.PaperInterop;
import com.sk89q.worldguard.util.MessagingUtil;
import io.papermc.lib.PaperLib;
import org.bukkit.BanList.Type;
@@ -188,7 +189,7 @@ public class BukkitPlayer extends com.sk89q.worldedit.bukkit.BukkitPlayer implem
@Override
public void teleport(Location location, String successMessage, String failMessage) {
PaperLib.teleportAsync(getPlayer(), BukkitAdapter.adapt(location))
PaperInterop.teleportAsync(getPlayer(), BukkitAdapter.adapt(location))
.thenApply(success -> {
if (success) {
// The success message can be cleared via flag
@@ -40,6 +40,7 @@ import org.bukkit.event.world.WorldUnloadEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nullable;
@@ -62,6 +63,7 @@ public class BukkitRegionContainer extends RegionContainer {
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void initialize() {
super.initialize();
Bukkit.getPluginManager().registerEvents(new Listener() {
@@ -94,7 +96,16 @@ public class BukkitRegionContainer extends RegionContainer {
}
}, plugin);
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, cache::invalidateAll, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
if (WorldGuardPlugin.inst().isFolia()) {
Bukkit.getGlobalRegionScheduler().runAtFixedRate(plugin, new Consumer() {
@Override
public void accept(Object ignored) {
cache.invalidateAll();
}
}, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
} else {
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, cache::invalidateAll, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
}
}
public void shutdown() {
@@ -286,6 +286,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableSoilMoistureChange = getBoolean("dynamics.disable-soil-moisture-change", false);
disableCoralBlockFade = getBoolean("dynamics.disable-coral-block-fade", false);
disableCopperBlockFade = getBoolean("dynamics.disable-copper-block-fade", false);
disableLavaHarden = getBoolean("dynamics.disable-lava-harden", false);
allowedSnowFallOver = new HashSet<>(convertLegacyBlocks(getStringList("dynamics.snow-fall-blocks", null)));
useRegions = getBoolean("regions.enable", true);
@@ -33,6 +33,8 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitCommandSender;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.blacklist.Blacklist;
@@ -65,6 +67,7 @@ import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.commands.GeneralCommands;
import com.sk89q.worldguard.commands.ProtectionCommands;
import com.sk89q.worldguard.commands.ToggleCommands;
import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry;
@@ -74,6 +77,8 @@ import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver
import com.sk89q.worldguard.protection.managers.storage.sql.SQLDriver;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
import io.papermc.lib.PaperLib;
import io.papermc.paper.ServerBuildInfo;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.DrilldownPie;
import org.bstats.charts.SimplePie;
@@ -95,6 +100,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -103,6 +109,7 @@ import java.util.logging.Logger;
*/
public class WorldGuardPlugin extends JavaPlugin {
private static final org.apache.logging.log4j.Logger LOGGER = LogManagerCompat.getLogger();
private static WorldGuardPlugin inst;
private static BukkitWorldGuardPlatform platform;
private final CommandsManager<Actor> commands;
@@ -136,6 +143,7 @@ public class WorldGuardPlugin extends JavaPlugin {
* Called on plugin enable.
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void onEnable() {
// Catch bad things being done by naughty plugins that include WorldGuard's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
@@ -163,7 +171,16 @@ public class WorldGuardPlugin extends JavaPlugin {
reg.register(GeneralCommands.class);
}
getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
if (this.isFolia()) {
getServer().getGlobalRegionScheduler().runAtFixedRate(this, new Consumer() {
@Override
public void accept(Object ignored) {
sessionManager.run();
}
}, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
} else {
getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
}
// Register events
getServer().getPluginManager().registerEvents(sessionManager, this);
@@ -204,14 +221,27 @@ public class WorldGuardPlugin extends JavaPlugin {
}
worldListener.registerEvents();
Bukkit.getScheduler().runTask(this, () -> {
if (this.isFolia()) {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
player.getScheduler().run(this, new Consumer() {
@Override
public void accept(Object ignored) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
}
}, null);
}
});
} 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);
// Enable metrics
final Metrics metrics = new Metrics(this, BSTATS_PLUGIN_ID); // bStats plugin id
@@ -264,7 +294,12 @@ public class WorldGuardPlugin extends JavaPlugin {
@Override
public void onDisable() {
WorldGuard.getInstance().disable();
this.getServer().getScheduler().cancelTasks(this);
if (this.isFolia()) {
this.getServer().getGlobalRegionScheduler().cancelTasks(this);
this.getServer().getAsyncScheduler().cancelTasks(this);
} else {
this.getServer().getScheduler().cancelTasks(this);
}
}
@Override
@@ -524,4 +559,22 @@ public class WorldGuardPlugin extends JavaPlugin {
return playerMoveListener;
}
private final LazyReference<Boolean> folia = LazyReference.from(() -> {
try {
// Folia is Paper-based, so this is a good first check.
if (PaperLib.isPaper()) {
return ServerBuildInfo.buildInfo().isBrandCompatible(net.kyori.adventure.key.Key.key("papermc", "folia"));
}
} catch (Throwable t) {
// Ignore, this likely means an outdated version.
LOGGER.warn("Failed to check if server is running Folia", t);
}
return false;
});
public boolean isFolia() {
return folia.getValue();
}
}
@@ -44,6 +44,7 @@ import com.sk89q.worldguard.bukkit.util.Blocks;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.bukkit.util.PaperInterop;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.protection.flags.Flags;
import io.papermc.lib.PaperLib;
@@ -163,6 +164,7 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class EventAbstractionListener extends AbstractListener {
@@ -209,8 +211,21 @@ public class EventAbstractionListener extends AbstractListener {
}
}
private boolean isExemptBlock(Material material) {
// Generating an End Portal from Bedrock/End_Portal_Frame should not trigger BlockMultiPlaceEvent
// Canceling this event for these blocks causes an upstream item duplication bug.
// https://github.com/PaperMC/Paper/issues/13586
return switch (material) {
case BEDROCK, END_PORTAL_FRAME -> true;
default -> false;
};
}
@EventHandler(ignoreCancelled = true)
public void onBlockMultiPlace(BlockMultiPlaceEvent event) {
if (isExemptBlock(event.getBlockPlaced().getType())) {
return;
}
List<Block> placed = event.getReplacedBlockStates().stream().map(BlockState::getBlock).collect(Collectors.toList());
int origAmt = placed.size();
PlaceBlockEvent delegateEvent = new PlaceBlockEvent(event, create(event.getPlayer()), event.getBlock().getWorld(),
@@ -1001,15 +1016,16 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onInventoryOpen(InventoryOpenEvent event) {
InventoryHolder holder = PaperLib.getHolder(event.getInventory(), false).getHolder();
InventoryHolder holder = PaperInterop.getHolder(event.getInventory(), false);
if (holder instanceof Entity && holder == event.getPlayer()) return;
handleInventoryHolderUse(event, create(event.getPlayer()), holder);
}
@EventHandler(ignoreCancelled = true)
@SuppressWarnings({"rawtypes", "unchecked"})
public void onInventoryMoveItem(InventoryMoveItemEvent event) {
InventoryHolder causeHolder = PaperLib.getHolder(event.getInitiator(), false).getHolder();
InventoryHolder causeHolder = PaperInterop.getHolder(event.getInitiator(), false);
WorldConfiguration wcfg = null;
if (causeHolder instanceof Hopper
@@ -1023,8 +1039,8 @@ public class EventAbstractionListener extends AbstractListener {
Entry entry;
if ((entry = moveItemDebounce.tryDebounce(event)) != null) {
InventoryHolder sourceHolder = PaperLib.getHolder(event.getSource(), false).getHolder();
InventoryHolder targetHolder = PaperLib.getHolder(event.getDestination(), false).getHolder();
InventoryHolder sourceHolder = PaperInterop.getHolder(event.getSource(), false);
InventoryHolder targetHolder = PaperInterop.getHolder(event.getDestination(), false);
Cause cause;
@@ -1044,9 +1060,19 @@ public class EventAbstractionListener extends AbstractListener {
handleInventoryHolderUse(event, cause, targetHolder);
}
if (event.isCancelled() && causeHolder instanceof Hopper && wcfg.breakDeniedHoppers) {
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(),
() -> ((Hopper) causeHolder).getBlock().breakNaturally());
if (event.isCancelled() && causeHolder instanceof Hopper hopper && wcfg.breakDeniedHoppers) {
Runnable task = () -> hopper.getBlock().breakNaturally();
if (WorldGuardPlugin.inst().isFolia()) {
Bukkit.getRegionScheduler().run(getPlugin(), hopper.getLocation(), new Consumer() {
@Override
public void accept(Object ignored) {
task.run();
}
});
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), task);
}
} else {
entry.setCancelled(event.isCancelled());
}
@@ -58,28 +58,27 @@ public class InvincibilityListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
Entity victim = event.getEntity();
if (Entities.isNPC(victim)) return;
if (!(victim instanceof Player player)) return;
if (Entities.isNPC(player)) return;
if (victim instanceof Player player) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (isInvincible(localPlayer)) {
player.setFireTicks(0);
event.setCancelled(true);
if (isInvincible(localPlayer)) {
player.setFireTicks(0);
event.setCancelled(true);
if (event instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent byEntityEvent = (EntityDamageByEntityEvent) event;
Entity attacker = byEntityEvent.getDamager();
if (event instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent byEntityEvent = (EntityDamageByEntityEvent) event;
Entity attacker = byEntityEvent.getDamager();
if (attacker instanceof Projectile && ((Projectile) attacker).getShooter() instanceof Entity) {
attacker = (Entity) ((Projectile) attacker).getShooter();
}
if (attacker instanceof Projectile && ((Projectile) attacker).getShooter() instanceof Entity) {
attacker = (Entity) ((Projectile) attacker).getShooter();
}
if (getWorldConfig(player.getWorld()).regionInvinciblityRemovesMobs
&& attacker instanceof LivingEntity && !(attacker instanceof Player)
&& !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) {
attacker.remove();
}
if (getWorldConfig(player.getWorld()).regionInvinciblityRemovesMobs
&& attacker instanceof LivingEntity && !(attacker instanceof Player)
&& !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) {
attacker.remove();
}
}
}
@@ -88,27 +87,25 @@ public class InvincibilityListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityCombust(EntityCombustEvent event) {
Entity entity = event.getEntity();
if (Entities.isNPC(entity)) return;
if (!(entity instanceof Player player)) return;
if (Entities.isNPC(player)) return;
if (entity instanceof Player player) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (isInvincible(localPlayer)) {
event.setCancelled(true);
}
if (isInvincible(localPlayer)) {
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onFoodLevelChange(FoodLevelChangeEvent event) {
if (Entities.isNPC(event.getEntity())) return;
if (!(event.getEntity() instanceof Player player)) return;
if (Entities.isNPC(player)) return;
if (event.getEntity() instanceof Player player) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(localPlayer)) {
event.setCancelled(true);
}
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(localPlayer)) {
event.setCancelled(true);
}
}
@@ -23,8 +23,10 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.PaperInterop;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.AbstractHorse;
@@ -41,6 +43,8 @@ import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector;
import java.util.function.Consumer;
public class PlayerMoveListener extends AbstractListener {
public PlayerMoveListener(WorldGuardPlugin plugin) {
@@ -76,6 +80,7 @@ public class PlayerMoveListener extends AbstractListener {
}
@EventHandler(priority = EventPriority.HIGH)
@SuppressWarnings({"rawtypes", "unchecked"})
public void onPlayerMove(PlayerMoveEvent event) {
Location from = event.getFrom();
Location to = event.getTo();
@@ -118,16 +123,31 @@ public class PlayerMoveListener extends AbstractListener {
current.eject();
vehicle.setVelocity(new Vector());
if (vehicle instanceof LivingEntity) {
vehicle.teleport(override.clone());
Location vehicleTeleportLocation = override.clone();
teleport(vehicle, vehicleTeleportLocation);
} else {
vehicle.teleport(override.clone().add(0, 1, 0));
Location dismountLocation = override.clone().add(0, 1, 0);
teleport(vehicle, dismountLocation);
}
current = current.getVehicle();
}
player.teleport(override.clone().add(0, 1, 0));
Location playerDismountLocation = override.clone().add(0, 1, 0);
teleport(player, playerDismountLocation);
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> player.teleport(override.clone().add(0, 1, 0)), 1);
Location delayedDismountLocation = override.clone().add(0, 1, 0);
Runnable task = () -> teleport(player, delayedDismountLocation);
if (getPlugin().isFolia()) {
player.getScheduler().runDelayed(getPlugin(), new Consumer() {
@Override
public void accept(Object ignored) {
task.run();
}
}, null, 1);
} else {
Bukkit.getScheduler().runTaskLater(getPlugin(), task, 1);
}
}
}
}
@@ -141,12 +161,32 @@ public class PlayerMoveListener extends AbstractListener {
com.sk89q.worldedit.util.Location loc = session.testMoveTo(localPlayer,
BukkitAdapter.adapt(event.getPlayer().getLocation()), MoveType.OTHER_CANCELLABLE); // white lie
if (loc != null) {
player.teleport(BukkitAdapter.adapt(loc));
if (getPlugin().isFolia()) {
PaperInterop.teleportAsync(player, BukkitAdapter.adapt(loc));
} else {
player.teleport(BukkitAdapter.adapt(loc));
}
}
session.uninitialize(localPlayer);
}
/**
* Small utility method to teleport via async or sync methods depending on platform.
*
* <p>Ideally we can make this use PaperLib in the future once it's better tested.</p>
*
* @param entity The entity to teleport
* @param location The location to teleport to
*/
private void teleport(Entity entity, Location location) {
if (getPlugin().isFolia()) {
PaperInterop.teleportAsync(entity, location);
} else {
entity.teleport(location);
}
}
@EventHandler
public void onEntityMount(EntityMountEvent event) {
Entity entity = event.getEntity();
@@ -119,8 +119,8 @@ public class RegionFlagsListener extends AbstractListener {
World world = entity.getWorld();
if (!isRegionSupportEnabled(world)) return; // Region support disabled
if (Entities.isNPC(entity)) return;
if (!(entity instanceof Player player)) return;
if (Entities.isNPC(player)) return;
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
@@ -410,7 +410,7 @@ public class RegionProtectionListener extends AbstractListener {
final Entity entity = event.getEntity();
final EntityType type = entity.getType();
if (Entities.isHostile(entity) || Entities.isAmbient(entity)
|| Entities.isNPC(entity) || entity instanceof Player) {
|| entity instanceof Player || Entities.isNPC(entity)) {
canUse = event.getRelevantFlags().isEmpty() || query.queryState(BukkitAdapter.adapt(target), associable, combine(event)) != State.DENY;
what = "use that";
/* Paintings, item frames, etc. */
@@ -478,7 +478,8 @@ public class WorldGuardBlockListener extends AbstractListener {
WorldConfiguration wcfg = getWorldConfig(event.getBlock().getWorld());
Material type = event.getNewState().getType();
Material oldType = event.getBlock().getType();
Material newType = event.getNewState().getType();
if (event instanceof EntityBlockFormEvent) {
if (((EntityBlockFormEvent) event).getEntity() instanceof Snowman) {
@@ -490,7 +491,7 @@ public class WorldGuardBlockListener extends AbstractListener {
return;
}
if (type == Material.ICE) {
if (newType == Material.ICE) {
if (wcfg.disableIceFormation) {
event.setCancelled(true);
return;
@@ -502,7 +503,7 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
if (type == Material.SNOW) {
if (newType == Material.SNOW) {
if (wcfg.disableSnowFormation) {
event.setCancelled(true);
return;
@@ -522,7 +523,7 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
if (Materials.isUnwaxedCopper(event.getBlock().getType())) {
if (Materials.isUnwaxedCopper(oldType)) {
if (wcfg.disableCopperBlockFade) {
event.setCancelled(true);
return;
@@ -533,6 +534,19 @@ public class WorldGuardBlockListener extends AbstractListener {
return;
}
}
if (oldType == Material.LAVA && !Materials.isLiquid(newType)) {
if (wcfg.disableLavaHarden) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && !StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.queryState(BukkitAdapter.adapt(event.getBlock().getLocation()), (RegionAssociable) null, Flags.LAVA_HARDEN))) {
event.setCancelled(true);
return;
}
}
}
/*
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.bukkit.listener;
import com.destroystokyo.paper.event.entity.EntityZapEvent;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.LocalPlayer;
@@ -39,6 +40,7 @@ import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import io.papermc.lib.PaperLib;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
@@ -66,8 +68,10 @@ import org.bukkit.entity.Wither;
import org.bukkit.entity.WitherSkull;
import org.bukkit.entity.Wolf;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.event.Cancellable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.CreeperPowerEvent;
@@ -90,6 +94,7 @@ import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.event.world.PortalCreateEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import org.bukkit.projectiles.ProjectileSource;
import java.util.Set;
@@ -108,6 +113,18 @@ public class WorldGuardEntityListener extends AbstractListener {
super(plugin);
}
@Override
public void registerEvents() {
super.registerEvents();
PluginManager pm = getPlugin().getServer().getPluginManager();
if (PaperLib.isPaper()) {
pm.registerEvents(new PaperListener(), getPlugin());
} else {
pm.registerEvents(new SpigotListener(), getPlugin());
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityInteract(EntityInteractEvent event) {
Block block = event.getBlock();
@@ -741,9 +758,7 @@ public class WorldGuardEntityListener extends AbstractListener {
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPigZap(PigZapEvent event) {
final Entity entity = event.getEntity();
private static void handlePigZap(Entity entity, Cancellable event) {
WorldConfiguration wcfg = getWorldConfig(entity.getWorld());
if (wcfg.disablePigZap) {
@@ -789,8 +804,8 @@ public class WorldGuardEntityListener extends AbstractListener {
public void onFoodChange(FoodLevelChangeEvent event) {
if (event.getItem() != null) return;
HumanEntity ent = event.getEntity();
if (Entities.isNPC(ent)) return;
if (!(ent instanceof Player bukkitPlayer)) return;
if (Entities.isNPC(bukkitPlayer)) return;
if (event.getFoodLevel() > ent.getFoodLevel()) return;
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer(bukkitPlayer);
@@ -883,4 +898,20 @@ public class WorldGuardEntityListener extends AbstractListener {
return false;
}
private static class PaperListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityZap(EntityZapEvent event) {
if (event.getEntityType() == EntityType.PIG) {
handlePigZap(event.getEntity(), event);
}
}
}
private static class SpigotListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPigZap(PigZapEvent event) {
handlePigZap(event.getEntity(), event);
}
}
}
@@ -25,6 +25,7 @@ import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.PaperInterop;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.util.Locations;
@@ -55,21 +56,31 @@ public class WorldGuardVehicleListener extends AbstractListener {
}
World world = vehicle.getWorld();
WorldConfiguration wcfg = getWorldConfig(world);
org.bukkit.Location from = event.getFrom();
org.bukkit.Location to = event.getTo();
if (wcfg.useRegions) {
// Did we move a block?
if (Locations.isDifferentBlock(BukkitAdapter.adapt(event.getFrom()), BukkitAdapter.adapt(event.getTo()))) {
if (Locations.isDifferentBlock(BukkitAdapter.adapt(from), BukkitAdapter.adapt(to))) {
for (Player player : playerPassengers) {
if (Entities.isNPC(player)) continue;
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
Location lastValid;
if ((lastValid = WorldGuard.getInstance().getPlatform().getSessionManager().get(localPlayer)
.testMoveTo(localPlayer, BukkitAdapter.adapt(event.getTo()), MoveType.RIDE)) != null) {
.testMoveTo(localPlayer, BukkitAdapter.adapt(to), MoveType.RIDE)) != null) {
vehicle.setVelocity(new Vector(0, 0, 0));
vehicle.teleport(event.getFrom());
if (Locations.isDifferentBlock(lastValid, BukkitAdapter.adapt(event.getFrom()))) {
if (getPlugin().isFolia()) {
PaperInterop.teleportAsync(vehicle, from);
} else {
vehicle.teleport(from);
}
if (Locations.isDifferentBlock(lastValid, BukkitAdapter.adapt(from))) {
Vector dir = player.getLocation().getDirection();
player.teleport(BukkitAdapter.adapt(lastValid).setDirection(dir));
org.bukkit.Location playerTeleportLocation = BukkitAdapter.adapt(lastValid).setDirection(dir);
if (getPlugin().isFolia()) {
PaperInterop.teleportAsync(player, playerTeleportLocation);
} else {
player.teleport(playerTeleportLocation);
}
}
return;
}
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.bukkit.listener.debounce.legacy;
import com.sk89q.worldguard.bukkit.listener.debounce.legacy.InventoryMoveItemEventDebounce.Key;
import com.sk89q.worldguard.bukkit.util.PaperInterop;
import io.papermc.lib.PaperLib;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -45,9 +46,9 @@ public class InventoryMoveItemEventDebounce extends AbstractEventDebounce<Key> {
private final Object target;
public Key(InventoryMoveItemEvent event) {
cause = transform(PaperLib.getHolder(event.getInitiator(), false).getHolder());
source = transform(PaperLib.getHolder(event.getSource(), false).getHolder());
target = transform(PaperLib.getHolder(event.getDestination(), false).getHolder());
cause = transform(PaperInterop.getHolder(event.getInitiator(), false));
source = transform(PaperInterop.getHolder(event.getSource(), false));
target = transform(PaperInterop.getHolder(event.getDestination(), false));
}
private Object transform(InventoryHolder holder) {
@@ -33,7 +33,8 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import java.util.Collection;
import java.util.function.Consumer;
/**
* Keeps tracks of sessions and also does session-related handling
@@ -46,13 +47,25 @@ public class BukkitSessionManager extends AbstractSessionManager implements Runn
* information for all players.
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void resetAllStates() {
Collection<? extends Player> players = Bukkit.getServer().getOnlinePlayers();
for (Player player : players) {
BukkitPlayer bukkitPlayer = new BukkitPlayer(WorldGuardPlugin.inst(), player);
Session session = getIfPresent(bukkitPlayer);
if (session != null) {
session.resetState(bukkitPlayer);
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
Runnable task = () -> {
BukkitPlayer bukkitPlayer = new BukkitPlayer(WorldGuardPlugin.inst(), player);
Session session = getIfPresent(bukkitPlayer);
if (session != null) {
session.resetState(bukkitPlayer);
}
};
if (WorldGuardPlugin.inst().isFolia()) {
player.getScheduler().run(WorldGuardPlugin.inst(), new Consumer() {
@Override
public void accept(Object ignored) {
task.run();
}
}, null);
} else {
task.run();
}
}
}
@@ -65,10 +78,23 @@ public class BukkitSessionManager extends AbstractSessionManager implements Runn
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void run() {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
get(localPlayer).tick(localPlayer);
Runnable task = () -> {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
get(localPlayer).tick(localPlayer);
};
if (WorldGuardPlugin.inst().isFolia()) {
player.getScheduler().run(WorldGuardPlugin.inst(), new Consumer() {
@Override
public void accept(Object ignored) {
task.run();
}
}, null);
} else {
task.run();
}
}
}
@@ -79,7 +105,7 @@ public class BukkitSessionManager extends AbstractSessionManager implements Runn
&& WorldGuard.getInstance().getPlatform().getGlobalStateManager().get(world).fakePlayerBuildOverride) {
return true;
}
if (!((BukkitPlayer) player).getPlayer().isOnline()) {
if (!bukkitPlayer.getPlayer().isOnline()) {
return false;
}
}
@@ -19,7 +19,6 @@
package com.sk89q.worldguard.bukkit.util;
import io.papermc.lib.PaperLib;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
@@ -46,15 +45,13 @@ public final class Blocks {
* @return a list of connected blocks, not including the given block
*/
public static List<Block> getConnected(Block block) {
BlockState state = PaperLib.getBlockState(block, false).getState();
BlockState state = PaperInterop.getBlockState(block, false);
BlockData data = state.getBlockData();
if (data instanceof Bed) {
Bed bed = (Bed) data;
if (data instanceof Bed bed) {
return Collections.singletonList(block.getRelative(bed.getPart() == Bed.Part.FOOT
? bed.getFacing() : bed.getFacing().getOppositeFace()));
} else if (data instanceof Chest) {
final Chest chest = (Chest) data;
} else if (data instanceof Chest chest) {
Chest.Type type = chest.getType();
if (type == Chest.Type.SINGLE) {
return Collections.emptyList();
@@ -30,20 +30,17 @@ import org.bukkit.entity.Creature;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Enemy;
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;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Monster;
import org.bukkit.entity.NPC;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Shulker;
import org.bukkit.entity.Slime;
import org.bukkit.entity.SpectralArrow;
import org.bukkit.entity.Steerable;
import org.bukkit.entity.TNTPrimed;
@@ -173,11 +170,7 @@ public final class Entities {
* @return true if hostile
*/
public static boolean isHostile(Entity entity) {
return entity instanceof Monster
|| entity instanceof Slime
|| entity instanceof Flying
|| entity instanceof EnderDragon
|| entity instanceof Shulker;
return entity instanceof Enemy;
}
/**
@@ -176,7 +176,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.CHISELED_STONE_BRICKS, 0);
MATERIAL_FLAGS.put(Material.BROWN_MUSHROOM_BLOCK, 0);
MATERIAL_FLAGS.put(Material.RED_MUSHROOM_BLOCK, 0);
MATERIAL_FLAGS.put(Material.IRON_BARS, 0);
MATERIAL_FLAGS.put(Material.GLASS_PANE, 0);
MATERIAL_FLAGS.put(Material.MELON, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN_STEM, 0);
@@ -259,55 +258,9 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.BARRIER, 0);
MATERIAL_FLAGS.put(Material.STRUCTURE_VOID, 0);
// 1.12
MATERIAL_FLAGS.put(Material.BLACK_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.BLUE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.BROWN_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.CYAN_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.GRAY_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.GREEN_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.YELLOW_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.LIME_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.MAGENTA_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.ORANGE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.PINK_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.PURPLE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.RED_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.WHITE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.BLACK_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.BLUE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.BROWN_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.CYAN_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.GRAY_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.GREEN_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.YELLOW_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.LIME_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.MAGENTA_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.ORANGE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.PINK_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.PURPLE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.RED_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.WHITE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.WHITE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.ORANGE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.MAGENTA_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.YELLOW_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.LIME_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.PINK_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.GRAY_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.CYAN_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.PURPLE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.BLUE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.BROWN_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.GREEN_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.RED_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.BLACK_GLAZED_TERRACOTTA, 0);
putMaterialTag(Tag.CONCRETE, 0);
putMaterialTag(Tag.CONCRETE_POWDERS, 0);
putMaterialTag(Tag.GLAZED_TERRACOTTA, 0);
// 1.13
MATERIAL_FLAGS.put(Material.ANDESITE, 0);
@@ -413,7 +366,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.FLETCHING_TABLE, 0);
MATERIAL_FLAGS.put(Material.GRINDSTONE, 0);
MATERIAL_FLAGS.put(Material.JIGSAW, MODIFIED_ON_RIGHT | MODIFIED_ON_LEFT);
MATERIAL_FLAGS.put(Material.LANTERN, 0);
MATERIAL_FLAGS.put(Material.LECTERN, 0);
MATERIAL_FLAGS.put(Material.LOOM, 0);
MATERIAL_FLAGS.put(Material.SCAFFOLDING, 0);
@@ -672,7 +624,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.ANCIENT_DEBRIS, 0);
MATERIAL_FLAGS.put(Material.BASALT, 0);
MATERIAL_FLAGS.put(Material.BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.CHAIN, 0);
MATERIAL_FLAGS.put(Material.CHISELED_NETHER_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_POLISHED_BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.CRACKED_NETHER_BRICKS, 0);
@@ -708,7 +659,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.SHROOMLIGHT, 0);
MATERIAL_FLAGS.put(Material.SOUL_CAMPFIRE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SOUL_FIRE, 0);
MATERIAL_FLAGS.put(Material.SOUL_LANTERN, 0);
MATERIAL_FLAGS.put(Material.SOUL_SOIL, 0);
MATERIAL_FLAGS.put(Material.SOUL_TORCH, 0);
MATERIAL_FLAGS.put(Material.SOUL_WALL_TORCH, 0);
@@ -730,7 +680,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.POLISHED_DEEPSLATE, 0);
MATERIAL_FLAGS.put(Material.CALCITE, 0);
MATERIAL_FLAGS.put(Material.TUFF, 0);
MATERIAL_FLAGS.put(Material.DRIPSTONE_BLOCK, 0);
MATERIAL_FLAGS.put(Material.ROOTED_DIRT, 0);
MATERIAL_FLAGS.put(Material.RAW_IRON_BLOCK, 0);
@@ -773,7 +722,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.CHISELED_DEEPSLATE, 0);
MATERIAL_FLAGS.put(Material.GLOW_LICHEN, 0);
MATERIAL_FLAGS.put(Material.LIGHT, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.LIGHTNING_ROD, 0);
MATERIAL_FLAGS.put(Material.SCULK_SENSOR, 0);
MATERIAL_FLAGS.put(Material.AMETHYST_SHARD, 0);
MATERIAL_FLAGS.put(Material.RAW_IRON, 0);
@@ -950,6 +898,56 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.BLUE_EGG, 0);
MATERIAL_FLAGS.put(Material.BROWN_EGG, 0);
// 1.21.6
MATERIAL_FLAGS.put(Material.DRIED_GHAST, 0);
putMaterialTag(Tag.ITEMS_HARNESSES, 0);
// 1.21.9
MATERIAL_FLAGS.put(Material.COPPER_TORCH, 0);
MATERIAL_FLAGS.put(Material.COPPER_WALL_TORCH, 0);
MATERIAL_FLAGS.put(Material.COPPER_HELMET, 0);
MATERIAL_FLAGS.put(Material.COPPER_CHESTPLATE, 0);
MATERIAL_FLAGS.put(Material.COPPER_LEGGINGS, 0);
MATERIAL_FLAGS.put(Material.COPPER_BOOTS, 0);
MATERIAL_FLAGS.put(Material.COPPER_HORSE_ARMOR, 0);
MATERIAL_FLAGS.put(Material.COPPER_SWORD, 0);
MATERIAL_FLAGS.put(Material.COPPER_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.COPPER_AXE, 0);
MATERIAL_FLAGS.put(Material.COPPER_SHOVEL, 0);
MATERIAL_FLAGS.put(Material.COPPER_HOE, 0);
MATERIAL_FLAGS.put(Material.COPPER_NUGGET, 0);
putMaterialTag(Tag.BARS, 0);
putMaterialTag(Tag.CHAINS, 0);
putMaterialTag(Tag.COPPER_CHESTS, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.COPPER_GOLEM_STATUES, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.LANTERNS, 0);
putMaterialTag(Tag.LIGHTNING_RODS, 0);
putMaterialTag(Tag.WOODEN_SHELVES, MODIFIED_ON_RIGHT);
// 1.21.11
MATERIAL_FLAGS.put(Material.COPPER_NAUTILUS_ARMOR, 0);
MATERIAL_FLAGS.put(Material.IRON_NAUTILUS_ARMOR, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_NAUTILUS_ARMOR, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_NAUTILUS_ARMOR, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_NAUTILUS_ARMOR, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_HORSE_ARMOR, 0);
putMaterialTag(Tag.ITEMS_SPEARS, 0);
// 26.1
MATERIAL_FLAGS.put(Material.GOLDEN_DANDELION, 0);
// 26.2
MATERIAL_FLAGS.put(Material.CINNABAR, 0);
MATERIAL_FLAGS.put(Material.POLISHED_CINNABAR, 0);
MATERIAL_FLAGS.put(Material.CINNABAR_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_CINNABAR, 0);
MATERIAL_FLAGS.put(Material.POTENT_SULFUR, 0);
MATERIAL_FLAGS.put(Material.SULFUR, 0);
MATERIAL_FLAGS.put(Material.POLISHED_SULFUR, 0);
MATERIAL_FLAGS.put(Material.SULFUR_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_SULFUR, 0);
putMaterialTag(Tag.SPELEOTHEMS, 0);
Stream.concat(Stream.concat(
Tag.CORAL_BLOCKS.getValues().stream(),
Tag.CORALS.getValues().stream()),
@@ -1204,6 +1202,8 @@ public final class Materials {
|| material == Material.CHISELED_BOOKSHELF
|| material == Material.CRAFTER
|| material == Material.DECORATED_POT
|| Tag.WOODEN_SHELVES.isTagged(material)
|| Tag.COPPER_CHESTS.isTagged(material)
|| Tag.ITEMS_CHEST_BOATS.isTagged(material)
|| Tag.SHULKER_BOXES.isTagged(material);
}
@@ -1222,11 +1222,13 @@ public final class Materials {
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_HUSK_SPAWN_EGG -> EntityType.CAMEL_HUSK;
case CAMEL_SPAWN_EGG -> EntityType.CAMEL;
case CAT_SPAWN_EGG -> EntityType.CAT;
case CAVE_SPIDER_SPAWN_EGG -> EntityType.CAVE_SPIDER;
case CHICKEN_SPAWN_EGG -> EntityType.CHICKEN;
case COD_SPAWN_EGG -> EntityType.COD;
case COPPER_GOLEM_SPAWN_EGG -> EntityType.COPPER_GOLEM;
case COW_SPAWN_EGG -> EntityType.COW;
case CREAKING_SPAWN_EGG -> EntityType.CREAKING;
case CREEPER_SPAWN_EGG -> EntityType.CREEPER;
@@ -1234,9 +1236,9 @@ public final class Materials {
case DONKEY_SPAWN_EGG -> EntityType.DONKEY;
case DROWNED_SPAWN_EGG -> EntityType.DROWNED;
case ELDER_GUARDIAN_SPAWN_EGG -> EntityType.ELDER_GUARDIAN;
case ENDER_DRAGON_SPAWN_EGG -> EntityType.ENDER_DRAGON;
case ENDERMAN_SPAWN_EGG -> EntityType.ENDERMAN;
case ENDERMITE_SPAWN_EGG -> EntityType.ENDERMITE;
case ENDER_DRAGON_SPAWN_EGG -> EntityType.ENDER_DRAGON;
case EVOKER_SPAWN_EGG -> EntityType.EVOKER;
case FOX_SPAWN_EGG -> EntityType.FOX;
case FROG_SPAWN_EGG -> EntityType.FROG;
@@ -1244,6 +1246,7 @@ public final class Materials {
case GLOW_SQUID_SPAWN_EGG -> EntityType.GLOW_SQUID;
case GOAT_SPAWN_EGG -> EntityType.GOAT;
case GUARDIAN_SPAWN_EGG -> EntityType.GUARDIAN;
case HAPPY_GHAST_SPAWN_EGG -> EntityType.HAPPY_GHAST;
case HOGLIN_SPAWN_EGG -> EntityType.HOGLIN;
case HORSE_SPAWN_EGG -> EntityType.HORSE;
case HUSK_SPAWN_EGG -> EntityType.HUSK;
@@ -1252,12 +1255,15 @@ public final class Materials {
case MAGMA_CUBE_SPAWN_EGG -> EntityType.MAGMA_CUBE;
case MOOSHROOM_SPAWN_EGG -> EntityType.MOOSHROOM;
case MULE_SPAWN_EGG -> EntityType.MULE;
case NAUTILUS_SPAWN_EGG -> EntityType.NAUTILUS;
case OCELOT_SPAWN_EGG -> EntityType.OCELOT;
case PANDA_SPAWN_EGG -> EntityType.PANDA;
case PARCHED_SPAWN_EGG -> EntityType.PARCHED;
case PARROT_SPAWN_EGG -> EntityType.PARROT;
case PHANTOM_SPAWN_EGG -> EntityType.PHANTOM;
case PIGLIN_BRUTE_SPAWN_EGG -> EntityType.PIGLIN_BRUTE;
case PIGLIN_SPAWN_EGG -> EntityType.PIGLIN;
case PIG_SPAWN_EGG -> EntityType.PIG;
case PILLAGER_SPAWN_EGG -> EntityType.PILLAGER;
case POLAR_BEAR_SPAWN_EGG -> EntityType.POLAR_BEAR;
case PUFFERFISH_SPAWN_EGG -> EntityType.PUFFERFISH;
@@ -1276,6 +1282,7 @@ public final class Materials {
case SQUID_SPAWN_EGG -> EntityType.SQUID;
case STRAY_SPAWN_EGG -> EntityType.STRAY;
case STRIDER_SPAWN_EGG -> EntityType.STRIDER;
case SULFUR_CUBE_SPAWN_EGG -> EntityType.SULFUR_CUBE;
case TADPOLE_SPAWN_EGG -> EntityType.TADPOLE;
case TRADER_LLAMA_SPAWN_EGG -> EntityType.TRADER_LLAMA;
case TROPICAL_FISH_SPAWN_EGG -> EntityType.TROPICAL_FISH;
@@ -1286,15 +1293,15 @@ public final class Materials {
case WANDERING_TRADER_SPAWN_EGG -> EntityType.WANDERING_TRADER;
case WARDEN_SPAWN_EGG -> EntityType.WARDEN;
case WITCH_SPAWN_EGG -> EntityType.WITCH;
case WITHER_SPAWN_EGG -> EntityType.WITHER;
case WITHER_SKELETON_SPAWN_EGG -> EntityType.WITHER_SKELETON;
case WITHER_SPAWN_EGG -> EntityType.WITHER;
case WOLF_SPAWN_EGG -> EntityType.WOLF;
case ZOGLIN_SPAWN_EGG -> EntityType.ZOGLIN;
case ZOMBIE_HORSE_SPAWN_EGG -> EntityType.ZOMBIE_HORSE;
case ZOMBIFIED_PIGLIN_SPAWN_EGG -> EntityType.ZOMBIFIED_PIGLIN;
case ZOMBIE_NAUTILUS_SPAWN_EGG -> EntityType.ZOMBIE_NAUTILUS;
case ZOMBIE_SPAWN_EGG -> EntityType.ZOMBIE;
case ZOMBIE_VILLAGER_SPAWN_EGG -> EntityType.ZOMBIE_VILLAGER;
case PIG_SPAWN_EGG -> EntityType.PIG;
case ZOMBIFIED_PIGLIN_SPAWN_EGG -> EntityType.ZOMBIFIED_PIGLIN;
default -> null;
};
}
@@ -1324,7 +1331,7 @@ public final class Materials {
// yea, that's not all, there are some more
return switch (type) {
case PUMPKIN, MELON, CACTUS, SUGAR_CANE, BAMBOO, BAMBOO_SAPLING,
SWEET_BERRY_BUSH, NETHER_WART, CAVE_VINES, CAVE_VINES_PLANT ->
SWEET_BERRY_BUSH, NETHER_WART, CAVE_VINES, CAVE_VINES_PLANT, COCOA ->
true;
default -> false;
};
@@ -1472,6 +1479,7 @@ public final class Materials {
switch (toolMaterial) {
case WOODEN_HOE:
case STONE_HOE:
case COPPER_HOE:
case IRON_HOE:
case GOLDEN_HOE:
case DIAMOND_HOE:
@@ -1483,6 +1491,7 @@ public final class Materials {
};
case WOODEN_AXE:
case STONE_AXE:
case COPPER_AXE:
case IRON_AXE:
case GOLDEN_AXE:
case DIAMOND_AXE:
@@ -1497,6 +1506,7 @@ public final class Materials {
};
case WOODEN_SHOVEL:
case STONE_SHOVEL:
case COPPER_SHOVEL:
case IRON_SHOVEL:
case GOLDEN_SHOVEL:
case DIAMOND_SHOVEL:
@@ -1556,7 +1566,8 @@ public final class Materials {
public static boolean isUnwaxedCopper(Material type) {
// copied from the MaterialTags class in Paper
return switch (type) {
case COPPER_BLOCK, CHISELED_COPPER, COPPER_DOOR, COPPER_TRAPDOOR, COPPER_GRATE, COPPER_BULB -> true;
case COPPER_BLOCK, CHISELED_COPPER, COPPER_DOOR, COPPER_TRAPDOOR, COPPER_GRATE, COPPER_BULB, COPPER_BARS,
COPPER_TORCH, COPPER_CHEST, COPPER_CHAIN, COPPER_WALL_TORCH, COPPER_LANTERN, COPPER_GOLEM_STATUE -> true;
default -> type.name().startsWith("EXPOSED_") || type.name().startsWith("WEATHERED_") ||
type.name().startsWith("OXIDIZED_") || type.name().startsWith("CUT_COPPER");
};
@@ -0,0 +1,64 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import io.papermc.lib.PaperLib;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.concurrent.CompletableFuture;
/**
* This class is mainly here to replace PaperLib, as it no longer fully functions on MC 26.1+.
*/
public class PaperInterop {
private PaperInterop() {
}
public static @Nullable InventoryHolder getHolder(@Nonnull Inventory inventory, boolean useSnapshot) {
if (PaperLib.isPaper()) {
return inventory.getHolder(useSnapshot);
}
return inventory.getHolder();
}
public static BlockState getBlockState(@Nonnull Block block, boolean useSnapshot) {
if (PaperLib.isPaper()) {
return block.getState(useSnapshot);
}
return block.getState();
}
public static CompletableFuture<Boolean> teleportAsync(@Nonnull Entity entity, @Nonnull Location location) {
if (PaperLib.isPaper()) {
return entity.teleportAsync(location);
}
return CompletableFuture.completedFuture(entity.teleport(location));
}
}
@@ -24,6 +24,7 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.sk89q.worldedit.util.report.DataReport;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
@@ -51,6 +52,9 @@ public class SchedulerReport extends DataReport {
public SchedulerReport() {
super("Scheduler");
if (WorldGuardPlugin.inst().isFolia()) {
return; // Todo Add support Schedulers
}
List<BukkitTask> tasks = Bukkit.getServer().getScheduler().getPendingTasks();
@@ -2,4 +2,5 @@ name: WorldGuard
main: com.sk89q.worldguard.bukkit.WorldGuardPlugin
version: "${internalVersion}"
depend: [WorldEdit]
api-version: "1.21.5"
api-version: "26.2"
folia-supported: true
-9
View File
@@ -1,7 +1,4 @@
import org.cadixdev.gradle.licenser.LicenseExtension
plugins {
`java-library`
id("buildlogic.core-and-platform")
}
@@ -37,12 +34,6 @@ tasks.compileJava {
options.compilerArgs.add("-Aarg.name.key.prefix=")
}
configure<LicenseExtension> {
exclude {
it.file.startsWith(project.layout.buildDirectory.get().asFile)
}
}
configure<PublishingExtension> {
publications.named<MavenPublication>("maven") {
artifactId = the<BasePluginExtension>().archivesName.get()
@@ -24,6 +24,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldguard.domains.registry.DomainRegistry;
import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry;
import com.sk89q.worldguard.util.profile.cache.HashMapCache;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import com.sk89q.worldguard.util.profile.cache.SQLiteCache;
@@ -55,6 +57,7 @@ public final class WorldGuard {
private WorldGuardPlatform platform;
private final SimpleFlagRegistry flagRegistry = new SimpleFlagRegistry();
private final SimpleDomainRegistry domainRegistry = new SimpleDomainRegistry();
private final Supervisor supervisor = new SimpleSupervisor();
private ProfileCache profileCache;
private ProfileService profileService;
@@ -116,6 +119,16 @@ public final class WorldGuard {
return this.flagRegistry;
}
/**
* Get the domain registry.
*
* @return the domain registry
*/
public DomainRegistry getDomainRegistry() {
return this.domainRegistry;
}
/**
* Get the supervisor.
*
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -42,10 +43,12 @@ public class BanAction implements Action {
if (event.getPlayer() != null) {
String message = entry.getMessage();
String friendlyName = PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent());
if (message != null) {
event.getPlayer().ban("Banned: " + String.format(message, event.getTarget().getFriendlyName()));
event.getPlayer().ban("Banned: " + String.format(message, friendlyName));
} else {
event.getPlayer().ban("Banned: You can't " + event.getDescription() + " " + event.getTarget().getFriendlyName());
event.getPlayer().ban("Banned: You can't " + event.getDescription() + " " + friendlyName);
}
}
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -42,10 +43,12 @@ public class KickAction implements Action {
if (event.getPlayer() != null) {
String message = entry.getMessage();
String friendlyName = PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent());
if (message != null) {
event.getPlayer().kick(String.format(message, event.getTarget().getFriendlyName()));
event.getPlayer().kick(String.format(message, friendlyName));
} else {
event.getPlayer().kick("You can't " + event.getDescription() + " " + event.getTarget().getFriendlyName());
event.getPlayer().kick("You can't " + event.getDescription() + " " + friendlyName);
}
}
@@ -19,6 +19,8 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -44,9 +46,10 @@ public class TellAction extends RepeatGuardedAction {
if (event.getPlayer() != null) {
if (message != null) {
message = message.replaceAll("(?!<\\\\)\\\\n", "\n").replaceAll("\\\\\\\\n", "\\n");
event.getPlayer().print(String.format(message, event.getTarget().getFriendlyName()));
// TODO Find a better way to do this String.format call that doesn't require a string.
event.getPlayer().print(TextComponent.of(String.format(message, PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent()))));
} else {
event.getPlayer().printError("You're not allowed to " + event.getDescription() + " " + event.getTarget().getFriendlyName() + ".");
event.getPlayer().printError(TextComponent.of("You're not allowed to " + event.getDescription() + " ").append(event.getTarget().getFriendlyNameComponent()).append(TextComponent.of(".")));
}
}
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -40,7 +41,7 @@ abstract class BlockBlacklistEvent extends AbstractBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPlayerName() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPlayerName() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -45,7 +46,7 @@ public final class BlockDispenseBlacklistEvent extends BlockBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPosition() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPosition() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -40,7 +41,7 @@ abstract class ItemBlacklistEvent extends AbstractBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPlayerName() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPlayerName() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.logger;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -225,7 +226,7 @@ public class FileHandler implements LoggerHandler {
}
private void logEvent(BlacklistEvent event, String text, Target target, BlockVector3 pos, String comment) {
log(event.getPlayer(), "Tried to " + text + " " + target.getFriendlyName() + " " + getCoordinates(pos), comment);
log(event.getPlayer(), "Tried to " + text + " " + PlainComponentSerializer.INSTANCE.serialize(target.getFriendlyNameComponent()) + " " + getCoordinates(pos), comment);
}
@Override
@@ -19,11 +19,12 @@
package com.sk89q.worldguard.blacklist.target;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.block.BlockType;
public class BlockTarget implements Target {
private BlockType type;
private final BlockType type;
public BlockTarget(BlockType type) {
this.type = type;
@@ -31,11 +32,16 @@ public class BlockTarget implements Target {
@Override
public String getTypeId() {
return type.getId();
return type.id();
}
@Override
public String getFriendlyName() {
return type.getName();
}
@Override
public Component getFriendlyNameComponent() {
return type.getRichName();
}
}
@@ -19,11 +19,12 @@
package com.sk89q.worldguard.blacklist.target;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.item.ItemType;
public class ItemTarget implements Target {
private ItemType type;
private final ItemType type;
public ItemTarget(ItemType type) {
this.type = type;
@@ -31,7 +32,7 @@ public class ItemTarget implements Target {
@Override
public String getTypeId() {
return type.getId();
return type.id();
}
@Override
@@ -39,4 +40,8 @@ public class ItemTarget implements Target {
return type.getName();
}
@Override
public Component getFriendlyNameComponent() {
return type.getRichName();
}
}
@@ -19,6 +19,9 @@
package com.sk89q.worldguard.blacklist.target;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
/**
* A target is something that can have events attached to it.
*/
@@ -35,7 +38,18 @@ public interface Target {
* Get a friendly name to be printed.
*
* @return a friendly name
* @deprecated Use {@link #getFriendlyNameComponent()} instead, which supports more complex formatting.
*/
@Deprecated
String getFriendlyName();
/**
* Get a friendly name to be printed.
*
* @return a friendly name
*/
default Component getFriendlyNameComponent() {
return TextComponent.of(getFriendlyName());
}
}
@@ -0,0 +1,111 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.commands;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.LocalPlayer;
import javax.annotation.Nullable;
import java.util.Map;
public abstract class CommandInputContext<T extends Exception> {
protected final Actor sender;
protected final String input;
protected Map<String, Object> context;
protected CommandInputContext(Actor sender, String input, Map<String, Object> values) {
this.sender = sender;
this.input = input;
this.context = values;
}
public void put(String name, Object value) {
context.put(name, value);
}
public Actor getSender() {
return sender;
}
public String getUserInput() {
return input;
}
/**
* Gets the CommandSender as a player.
*
* @return Player
* @throws T if the sender is not a player
*/
public LocalPlayer getPlayerSender() throws T {
if (sender.isPlayer() && sender instanceof LocalPlayer) {
return (LocalPlayer) sender;
} else {
throw createException("Not a player");
}
}
public Integer getUserInputAsInt() throws T {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw createException("Not a number: " + input);
}
}
public Double getUserInputAsDouble() throws T {
try {
return Double.parseDouble(input);
} catch (NumberFormatException e) {
throw createException("Not a number: " + input);
}
}
protected abstract T createException(String str);
/**
* Get an object from the context by key name.
* May return null if the object does not exist in the context.
*
* @param name key name of the object
* @return the object matching the key, or null
*/
@Nullable
public Object get(String name) {
return get(name, null);
}
/**
* Get an object from the context by key name.
* Will only return null if
* a) you provide null as the default
* b) the key has explicity been set to null
*
* @param name key name of the object
* @return the object matching the key
*/
@Nullable
public Object get(String name, Object defaultValue) {
Object obj;
return (((obj = context.get(name)) != null) || context.containsKey(name)
? obj : defaultValue);
}
}
@@ -25,16 +25,27 @@ import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.worldedit.command.util.AsyncCommandBuilder;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.domains.registry.DomainFactory;
import com.sk89q.worldguard.domains.registry.DomainRegistry;
import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.util.DomainInputResolver;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
public class MemberCommands extends RegionCommandsBase {
@@ -67,6 +78,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
resolver.setActor(sender);
resolver.setRegion(region);
final String description = String.format("Adding members to the region '%s' on '%s'", region.getId(), world.getName());
@@ -101,7 +114,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
resolver.setActor(sender);
resolver.setRegion(region);
final String description = String.format("Adding owners to the region '%s' on '%s'", region.getId(), world.getName());
AsyncCommandBuilder.wrap(checkedAddOwners(sender, manager, region, world, resolver), sender)
@@ -174,6 +188,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
resolver.setActor(sender);
resolver.setRegion(region);
callable = resolver;
}
@@ -217,6 +233,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
resolver.setActor(sender);
resolver.setRegion(region);
callable = resolver;
}
@@ -59,7 +59,7 @@ import com.sk89q.worldguard.protection.FlagValueCalculator;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormatException;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.RegionGroupFlag;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
@@ -76,7 +76,6 @@ import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import com.sk89q.worldguard.protection.util.WorldEditRegionConverter;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.util.Enums;
@@ -160,7 +159,7 @@ public final class RegionCommands extends RegionCommandsBase {
region = checkRegionFromSelection(sender, id);
}
RegionAdder task = new RegionAdder(manager, region);
RegionAdder task = new RegionAdder(manager, region, sender);
task.addOwnersFromCommand(args, 2);
final String description = String.format("Adding region '%s'", region.getId());
@@ -214,7 +213,7 @@ public final class RegionCommands extends RegionCommandsBase {
region.copyFrom(existing);
RegionAdder task = new RegionAdder(manager, region);
RegionAdder task = new RegionAdder(manager, region, sender);
final String description = String.format("Updating region '%s'", region.getId());
AsyncCommandBuilder.wrap(task, sender)
@@ -351,6 +350,7 @@ public final class RegionCommands extends RegionCommandsBase {
World world = checkWorld(args, sender, 'w');
RegionManager manager = checkRegionManager(world);
ProtectedRegion existing;
RegionPermissionModel permissionModel = getPermissionModel(sender);
// If no arguments were given, get the region that the player is inside
if (args.argsLength() == 0) {
@@ -359,13 +359,13 @@ public final class RegionCommands extends RegionCommandsBase {
throw new CommandException("Please specify a region name."); // just don't allow that
}
world = player.getWorld();
existing = checkRegionStandingIn(manager, player, "/rg select -w \"" + world.getName() + "\" %id%");
existing = checkRegionStandingIn(manager, player, "/rg select -w \"" + world.getName() + "\" %id%", permissionModel::maySelect);
} else {
existing = checkExistingRegion(manager, args.getString(0), false);
}
// Check permissions
if (!getPermissionModel(sender).maySelect(existing)) {
if (!permissionModel.maySelect(existing)) {
throw new CommandPermissionsException();
}
@@ -401,7 +401,7 @@ public final class RegionCommands extends RegionCommandsBase {
}
existing = checkRegionStandingIn(manager, (LocalPlayer) sender, true,
"/rg info -w \"" + world.getName() + "\" %id%" + (args.hasFlag('u') ? " -u" : "") + (args.hasFlag('s') ? " -s" : ""));
"/rg info -w \"" + world.getName() + "\" %id%" + (args.hasFlag('u') ? " -u" : "") + (args.hasFlag('s') ? " -s" : ""), permModel::mayLookup);
} else { // Get region from the ID
existing = checkExistingRegion(manager, args.getString(0), true);
}
@@ -587,7 +587,7 @@ public final class RegionCommands extends RegionCommandsBase {
// the [value] part throws an error.
try {
groupValue = groupFlag.parseInput(FlagContext.create().setSender(sender).setInput(group).setObject("region", existing).build());
} catch (InvalidFlagFormat e) {
} catch (InvalidFlagFormatException e) {
throw new CommandException(e.getMessage());
}
@@ -598,7 +598,7 @@ public final class RegionCommands extends RegionCommandsBase {
// Set the flag if [value] was given even if [-g group] was given as well
try {
value = setFlag(existing, foundFlag, sender, value).toString();
} catch (InvalidFlagFormat e) {
} catch (InvalidFlagFormatException e) {
throw new CommandException(e.getMessage());
}
@@ -661,18 +661,19 @@ public final class RegionCommands extends RegionCommandsBase {
// Lookup the existing region
RegionManager manager = checkRegionManager(world);
ProtectedRegion region;
final RegionPermissionModel perms = getPermissionModel(sender);
if (args.argsLength() == 0) { // Get region from where the player is
if (!(sender instanceof LocalPlayer)) {
throw new CommandException("Please specify the region with /region flags -w world_name region_name.");
}
region = checkRegionStandingIn(manager, (LocalPlayer) sender, true,
"/rg flags -w \"" + world.getName() + "\" %id%");
"/rg flags -w \"" + world.getName() + "\" %id%", perms::mayLookup);
} else { // Get region from the ID
region = checkExistingRegion(manager, args.getString(0), true);
}
final RegionPermissionModel perms = getPermissionModel(sender);
if (!perms.mayLookup(region)) {
throw new CommandPermissionsException();
}
@@ -32,15 +32,12 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.util.formatting.text.format.TextDecoration;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
@@ -48,7 +45,7 @@ import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormatException;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
@@ -59,6 +56,7 @@ import com.sk89q.worldguard.protection.regions.RegionQuery.QueryOption;
import com.sk89q.worldguard.protection.util.WorldEditRegionConverter;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
class RegionCommandsBase {
@@ -178,11 +176,13 @@ class RegionCommandsBase {
*
* @param regionManager the region manager
* @param player the player
* @param rgCmd the command to construct when clicking one of multiple items
* @param permissionPredicate a predicate to filter regions based on permission access
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, String rgCmd) throws CommandException {
return checkRegionStandingIn(regionManager, player, false, rgCmd);
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, String rgCmd, Predicate<ProtectedRegion> permissionPredicate) throws CommandException {
return checkRegionStandingIn(regionManager, player, false, rgCmd, permissionPredicate);
}
/**
@@ -197,10 +197,12 @@ class RegionCommandsBase {
* @param regionManager the region manager
* @param player the player
* @param allowGlobal whether to search for a global region if no others are found
* @param rgCmd the command to construct when clicking one of multiple items
* @param permissionPredicate a predicate to filter regions based on permission access
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, boolean allowGlobal, String rgCmd) throws CommandException {
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, boolean allowGlobal, String rgCmd, Predicate<ProtectedRegion> permissionPredicate) throws CommandException {
ApplicableRegionSet set = regionManager.getApplicableRegions(player.getLocation().toVector().toBlockPoint(), QueryOption.SORT);
if (set.size() == 0) {
@@ -215,20 +217,30 @@ class RegionCommandsBase {
"Specify an ID if you want to select a specific region.");
} else if (set.size() > 1) {
boolean first = true;
Set<ProtectedRegion> filteredRegions = set.getRegions().stream().filter(permissionPredicate).collect(Collectors.toSet());
int hiddenRegions = set.size() - filteredRegions.size();
final TextComponent.Builder builder = TextComponent.builder("");
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
for (ProtectedRegion region : set) {
if (!first) {
builder.append(TextComponent.of(", "));
if (!filteredRegions.isEmpty()) {
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
for (ProtectedRegion region : filteredRegions) {
if (!first) {
builder.append(TextComponent.of(", "));
}
first = false;
TextComponent regionComp = TextComponent.of(region.getId(), TextColor.AQUA);
if (rgCmd != null && rgCmd.contains("%id%")) {
regionComp = regionComp.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to pick this region")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, rgCmd.replace("%id%", region.getId())));
}
builder.append(regionComp);
}
first = false;
TextComponent regionComp = TextComponent.of(region.getId(), TextColor.AQUA);
if (rgCmd != null && rgCmd.contains("%id%")) {
regionComp = regionComp.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to pick this region")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, rgCmd.replace("%id%", region.getId())));
if (hiddenRegions > 0) {
builder.append(TextComponent.of(", and " + hiddenRegions + " hidden regions", TextColor.GRAY));
}
builder.append(regionComp);
} else {
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
builder.append(TextComponent.of(hiddenRegions + " hidden regions", TextColor.GRAY));
}
player.print(builder.build());
throw new CommandException("You're standing in several regions (please pick one).");
@@ -418,9 +430,9 @@ class RegionCommandsBase {
* @param flag the flag
* @param sender the sender
* @param value the value
* @throws InvalidFlagFormat thrown if the value is invalid
* @throws InvalidFlagFormatException thrown if the value is invalid
*/
protected static <V> V setFlag(ProtectedRegion region, Flag<V> flag, Actor sender, String value) throws InvalidFlagFormat {
protected static <V> V setFlag(ProtectedRegion region, Flag<V> flag, Actor sender, String value) throws InvalidFlagFormatException {
V val = flag.parseInput(FlagContext.create().setSender(sender).setInput(value).setObject("region", region).build());
region.setFlag(flag, val);
return val;
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.commands.task;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.managers.RegionManager;
@@ -39,6 +40,7 @@ public class RegionAdder implements Callable<ProtectedRegion> {
private final RegionManager manager;
private final ProtectedRegion region;
private final Actor actor;
@Nullable
private String[] ownersInput;
private UserLocatorPolicy locatorPolicy = UserLocatorPolicy.UUID_ONLY;
@@ -46,15 +48,26 @@ public class RegionAdder implements Callable<ProtectedRegion> {
/**
* Create a new instance.
*
* @param manager the manage
* @param manager the manager
* @param region the region
*/
public RegionAdder(RegionManager manager, ProtectedRegion region) {
this(manager, region, null);
}
/**
* Create a new instance.
* @param manager the manager
* @param region the region
* @param actor the actor
*/
public RegionAdder(RegionManager manager, ProtectedRegion region, Actor actor) {
checkNotNull(manager);
checkNotNull(region);
this.manager = manager;
this.region = region;
this.actor = actor;
}
/**
@@ -75,6 +88,9 @@ public class RegionAdder implements Callable<ProtectedRegion> {
if (ownersInput != null) {
DomainInputResolver resolver = new DomainInputResolver(WorldGuard.getInstance().getProfileService(), ownersInput);
resolver.setLocatorPolicy(locatorPolicy);
resolver.setActor(actor);
resolver.setRegion(region);
DefaultDomain domain = resolver.call();
region.getOwners().addAll(domain);
}
@@ -170,6 +170,7 @@ public abstract class WorldConfiguration {
public boolean disableSoilMoistureChange;
public boolean disableCoralBlockFade;
public boolean disableCopperBlockFade;
public boolean disableLavaHarden;
public Set<String> allowedSnowFallOver;
public boolean regionInvinciblityRemovesMobs;
public boolean regionCancelEmptyChatEvents;
@@ -0,0 +1,108 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.domains.registry.CustomDomainContext;
import com.sk89q.worldguard.domains.registry.InvalidDomainFormatException;
import com.sk89q.worldguard.util.ChangeTracked;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class CustomDomain implements Domain, ChangeTracked {
private static final Pattern VALID_NAME = Pattern.compile("^[a-z0-9\\-]{1,40}$");
private final String name;
private boolean dirty;
public CustomDomain(String name) {
if (name == null ||!isValidName(name)) {
throw new IllegalArgumentException("Invalid Domain name used.");
}
this.name = name;
}
/**
* Get the name of the domain resolver.
*
* @return The name of the domain
*/
public String getName() {
return name;
}
/**
* Parse a given input to fill the context of the CustomDomain.
*
* @param context the {@link CustomDomainContext}
* @throws InvalidDomainFormatException Raised if the input is invalid
*/
public abstract void parseInput(CustomDomainContext context) throws InvalidDomainFormatException;
/**
* Convert a raw type that was loaded (from a YAML file, for example)
* into the custom domain.
*
* @param o The object
*/
public abstract void unmarshal(Object o);
/**
* Convert the current Domain to a storable foramt
*
* @return The marshalled type
*/
public abstract Object marshal();
/**
* Test whether a flag name is valid.
*
* @param name The flag name
* @return Whether the name is valid
*/
public static boolean isValidName(String name) {
checkNotNull(name, "name");
// g is already reserved by the group domain
return VALID_NAME.matcher(name).matches() && !name.equalsIgnoreCase("g");
}
@Override
public boolean contains(LocalPlayer player) {
return contains(player.getUniqueId());
}
@Override
public int size() {
return 1;
}
@Override
public boolean isDirty() {
return dirty;
}
@Override
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
}
@@ -22,8 +22,6 @@ package com.sk89q.worldguard.domains;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sk89q.worldguard.util.profile.Profile;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
@@ -31,14 +29,19 @@ import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.util.ChangeTracked;
import com.sk89q.worldguard.util.profile.Profile;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -50,6 +53,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
private PlayerDomain playerDomain = new PlayerDomain();
private GroupDomain groupDomain = new GroupDomain();
private final Map<String, CustomDomain> customDomains = new ConcurrentHashMap<>();
private boolean customDomainsChanged = false;
/**
* Create a new domain.
*/
@@ -64,6 +70,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
public DefaultDomain(DefaultDomain existing) {
setPlayerDomain(existing.getPlayerDomain());
setGroupDomain(existing.getGroupDomain());
setCustomDomains(existing.customDomains);
}
/**
@@ -104,6 +111,72 @@ public class DefaultDomain implements Domain, ChangeTracked {
this.groupDomain = new GroupDomain(groupDomain);
}
/**
* Add new custom domains
*
* @param customDomain a domain
*/
public void addCustomDomain(CustomDomain customDomain) {
checkNotNull(customDomain);
this.customDomains.put(customDomain.getName(), customDomain);
this.customDomainsChanged = true;
}
/**
* Remove a custom domain matched by the name
*
* @param name the name
*/
public void removeCustomDomain(String name) {
checkNotNull(name);
if (this.customDomains.remove(name) != null) {
this.customDomainsChanged = true;
}
}
/**
* Remove a custom domain
*
* @param customDomain a domain
*/
public void removeCustomDomain(CustomDomain customDomain) {
checkNotNull(customDomain);
if (this.customDomains.remove(customDomain.getName()) != null) {
this.customDomainsChanged = true;
}
}
/**
* Set the api domains to a specified value
*
* @param customDomains the domains
*/
public void setCustomDomains(Map<String, CustomDomain> customDomains) {
checkNotNull(customDomains);
this.customDomains.clear();
this.customDomains.putAll(customDomains);
this.customDomainsChanged = true;
}
/**
* Get all api domains
*
* @return a unmodifiable copy of the domains
*/
public Collection<CustomDomain> getCustomDomains() {
return Collections.unmodifiableCollection(this.customDomains.values());
}
/**
* Get the api domain specified by its name
*
* @param name the name of the domain
* @return the custom domain
*/
public @Nullable CustomDomain getCustomDomain(String name) {
return this.customDomains.get(name);
}
/**
* Add the given player to the domain, identified by the player's name.
*
@@ -175,6 +248,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
for (String group : other.getGroups()) {
addGroup(group);
}
for (CustomDomain domain : other.getCustomDomains()) {
addCustomDomain(domain);
}
}
/**
@@ -193,6 +269,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
for (String group : other.getGroups()) {
removeGroup(group);
}
for (CustomDomain domain : other.getCustomDomains()) {
removeCustomDomain(domain.getName());
}
}
/**
@@ -242,12 +321,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
@Override
public boolean contains(LocalPlayer player) {
return playerDomain.contains(player) || groupDomain.contains(player);
return playerDomain.contains(player) || groupDomain.contains(player) || customDomains.values().stream().anyMatch(d -> d.contains(player));
}
@Override
public boolean contains(UUID uniqueId) {
return playerDomain.contains(uniqueId);
return playerDomain.contains(uniqueId) || customDomains.values().stream().anyMatch(d -> d.contains(uniqueId));
}
@Override
@@ -257,7 +336,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
@Override
public int size() {
return groupDomain.size() + playerDomain.size();
return groupDomain.size() + playerDomain.size() + customDomains.size();
}
@Override
@@ -275,7 +354,6 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
public String toPlayersString(@Nullable ProfileCache cache) {
StringBuilder str = new StringBuilder();
List<String> output = new ArrayList<>();
for (String name : playerDomain.getPlayers()) {
@@ -299,13 +377,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
output.sort(String.CASE_INSENSITIVE_ORDER);
for (Iterator<String> it = output.iterator(); it.hasNext();) {
str.append(it.next());
if (it.hasNext()) {
str.append(", ");
}
}
return str.toString();
return String.join(", ", output);
}
public String toGroupsString() {
@@ -320,25 +392,20 @@ public class DefaultDomain implements Domain, ChangeTracked {
return str.toString();
}
public String toUserFriendlyString() {
StringBuilder str = new StringBuilder();
if (playerDomain.size() > 0) {
str.append(toPlayersString());
public String toCustomDomainsString() {
List<String> output = new ArrayList<>();
for (CustomDomain customDomain : customDomains.values()) {
output.add(customDomain.getName() + ":" + customDomain.toString());
}
if (groupDomain.size() > 0) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toGroupsString());
}
return str.toString();
output.sort(String.CASE_INSENSITIVE_ORDER);
return String.join(", ", output);
}
public String toUserFriendlyString(ProfileCache cache) {
public String toUserFriendlyString() {
return toUserFriendlyString(null);
}
public String toUserFriendlyString(@Nullable ProfileCache cache) {
StringBuilder str = new StringBuilder();
if (playerDomain.size() > 0) {
@@ -352,6 +419,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
str.append(toGroupsString());
}
if (!customDomains.isEmpty()) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toCustomDomainsString());
}
return str.toString();
}
@@ -367,6 +440,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
builder.append(toGroupsComponent());
}
if (!customDomains.isEmpty()) {
if (playerDomain.size() > 0 || groupDomain.size() > 0) {
builder.append(TextComponent.of("; "));
}
builder.append(toCustomDomainsComponent());
}
return builder.build();
}
@@ -442,21 +521,39 @@ public class DefaultDomain implements Domain, ChangeTracked {
return builder.build();
}
private Component toCustomDomainsComponent() {
final TextComponent.Builder builder = TextComponent.builder("");
for (Iterator<CustomDomain> it = customDomains.values().iterator(); it.hasNext(); ) {
CustomDomain domain = it.next();
builder.append(TextComponent.of(domain.getName() + ":", TextColor.LIGHT_PURPLE))
.append(TextComponent.of(domain.toString(), TextColor.GOLD));
if (it.hasNext()) {
builder.append(TextComponent.of(", "));
}
}
return builder.build().hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("CustomDomain")));
}
@Override
public boolean isDirty() {
return playerDomain.isDirty() || groupDomain.isDirty();
return playerDomain.isDirty() || groupDomain.isDirty() ||
customDomainsChanged || customDomains.values().stream().anyMatch(ChangeTracked::isDirty);
}
@Override
public void setDirty(boolean dirty) {
playerDomain.setDirty(dirty);
groupDomain.setDirty(dirty);
customDomainsChanged = dirty;
customDomains.values().forEach(d -> d.setDirty(dirty));
}
@Override
public String toString() {
return "{players=" + playerDomain +
", groups=" + groupDomain +
", custom=" + customDomains +
'}';
}
@@ -0,0 +1,98 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.commands.CommandInputContext;
import javax.annotation.Nullable;
import java.util.Map;
public final class CustomDomainContext extends CommandInputContext<InvalidDomainFormatException> {
private CustomDomainContext(Actor sender, String input, Map<String, Object> values) {
super(sender, input, values);
}
public static CustomDomainContext.CustomDomainContextBuilder create() {
return new CustomDomainContext.CustomDomainContextBuilder();
}
/**
* Create a copy of this CustomDomainContext, with optional substitutions for values
*
* <p>If any supplied variable is null, it will be ignored.
* If a map is supplied, it will override this CustomDomainContext's values of the same key,
* but unprovided keys will not be overriden and will be returned as shallow copies.</p>
*
* @param commandSender CommandSender for the new CustomDomainContext to run under
* @param s String of the user input for the new CustomDomainContext
* @param values map of values to override from the current CustomDomainContext
* @return a copy of this CustomDomainContext
*/
public CustomDomainContext copyWith(@Nullable Actor commandSender, @Nullable String s, @Nullable Map<String, Object> values) {
Map<String, Object> map = Maps.newHashMap();
map.putAll(context);
if (values != null) {
map.putAll(values);
}
return new CustomDomainContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map);
}
@Override
protected InvalidDomainFormatException createException(String str) {
return new InvalidDomainFormatException(str);
}
public static class CustomDomainContextBuilder {
private Actor sender;
private String input;
private Map<String, Object> map = Maps.newHashMap();
public CustomDomainContextBuilder setSender(Actor sender) {
this.sender = sender;
return this;
}
public CustomDomainContextBuilder setInput(String input) {
this.input = input;
return this;
}
public CustomDomainContextBuilder setObject(String key, Object value) {
this.map.put(key, value);
return this;
}
public boolean tryAddToMap(String key, Object value) {
if (map.containsKey(key)) return false;
this.map.put(key, value);
return true;
}
public CustomDomainContext build() {
return new CustomDomainContext(sender, input, map);
}
}
}
@@ -0,0 +1,26 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
public class DomainConflictException extends RuntimeException {
public DomainConflictException(String message) {
super(message);
}
}
@@ -0,0 +1,28 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
@FunctionalInterface
public interface DomainFactory<T extends CustomDomain> {
T create(String name);
}
@@ -0,0 +1,94 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
public interface DomainRegistry extends Iterable<DomainFactory<?>> {
/**
* Register a new Domain
*
* <p>There may be an appropiate time to register domains. if domains are
* registered outside this time, then an exception may be thrown.</p>
*
* @param domain The domain
* @throws DomainConflictException Thrown when already an existing domain exists with the same name
* @throws IllegalStateException If it is not the right time to register new domains
*/
void register(String name, DomainFactory<?> domain) throws DomainConflictException;
/**
* Register a collection of domains.
*
* <p>There may be an appropriate time to register domains. If domains are
* registered outside this time, then an exception may be thrown.</p>
*
* <p>If there is a domain conflict, then an error will be logged but
* no exception will be thrown.</p>
*
* @param domains a collection of domain factories
* @throws IllegalStateException If it is not the right time to register new domains
*/
void registerAll(Map<String, DomainFactory<?>> domains);
/**
* Get the domain by its name.
*
* @param name The name
* @return The domain, if it has been registered
*/
@Nullable
DomainFactory<?> get(String name);
/**
* Try to get a domain by its name
*/
@Nullable
CustomDomain createDomain(String name);
/**
* Get all domains keyed by the registered name
*
* @return All domains
*/
Map<String, DomainFactory<?>> getAll();
/**
* Unmarshal a raw map of values into a list of domains with their
* unmarshalled values.
*
* @param rawValues The raw values map
* @param createUnknown Whether "just in time" domains should be created for unknown domains
* @return The unmarshalled domain list
*/
Map<String, CustomDomain> unmarshal(Map<String, Object> rawValues, boolean createUnknown);
/**
* Get the number of registered domains.
*
* @return The number of registered domains
*/
int size();
}
@@ -0,0 +1,28 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
public class InvalidDomainFormatException extends Exception {
private static final long serialVersionUID = 8101615074524004172L;
public InvalidDomainFormatException(String msg) {
super(msg);
}
}
@@ -0,0 +1,166 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.sk89q.worldguard.domains.CustomDomain;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
public class SimpleDomainRegistry implements DomainRegistry {
private static final Logger log = Logger.getLogger(SimpleDomainRegistry.class.getCanonicalName());
private final Object lock = new Object();
private final ConcurrentMap<String, DomainFactory<?>> domains = Maps.newConcurrentMap();
private boolean initialized = false;
public boolean isInitialized() {
return initialized;
}
public void setInitialized(boolean initialized) {
this.initialized = initialized;
}
@Override
public void register(String name, DomainFactory<?> domain) throws DomainConflictException {
synchronized (lock) {
if (initialized) {
throw new IllegalStateException("New domains cannot be registered at this time");
}
forceRegister(name, domain);
}
}
@Override
public void registerAll(Map<String, DomainFactory<?>> domains) {
synchronized (lock) {
for (Map.Entry<String, DomainFactory<?>> entry : domains.entrySet()) {
try {
register(entry.getKey(), entry.getValue());
} catch (DomainConflictException e) {
log.log(Level.WARNING, e.getMessage());
}
}
}
}
private <T extends DomainFactory<?>> T forceRegister(String name, T domain) throws DomainConflictException {
checkNotNull(domain, "domain");
checkNotNull(name, "name");
if (!CustomDomain.isValidName(name)) {
throw new IllegalArgumentException("Invalid Domain name used.");
}
synchronized (lock) {
if (domains.containsKey(name)) {
throw new DomainConflictException("A domain already exists by the name " + name);
}
domains.put(name, domain);
}
return domain;
}
@Nullable
@Override
public DomainFactory<?> get(String name) {
checkNotNull(name, "name");
return domains.get(name.toLowerCase());
}
@Nullable
@Override
public CustomDomain createDomain(String name) {
DomainFactory<?> factory = get(name);
if (factory == null) return null;
return factory.create(name);
}
@Override
public Map<String, DomainFactory<?>> getAll() {
return ImmutableMap.copyOf(domains);
}
private CustomDomain getOrCreate(String name, Object value, boolean createUnknown) {
CustomDomain customDomain = createDomain(name);
if (customDomain != null) {
customDomain.unmarshal(value);
return customDomain;
}
synchronized (lock) {
customDomain = createDomain(name); // Load again because the previous load was not synchronized
if (customDomain != null) {
customDomain.unmarshal(value);
return customDomain;
}
if (createUnknown) {
DomainFactory<UnknownDomain> unknownFactory = forceRegister(name, UnknownDomain.FACTORY);
if (unknownFactory != null) {
customDomain = unknownFactory.create(name);
if (customDomain != null) customDomain.unmarshal(value);
return customDomain;
}
}
}
return null;
}
public Map<String, CustomDomain> unmarshal(Map<String, Object> rawValues, boolean createUnknown) {
checkNotNull(rawValues, "rawValues");
Map<String, CustomDomain> domains = new HashMap<>();
for (Map.Entry<String, Object> entry : rawValues.entrySet()) {
try {
CustomDomain domain = getOrCreate(entry.getKey(), entry.getValue(), createUnknown);
domains.put(domain.getName(), domain);
} catch (Throwable e) {
log.log(Level.WARNING, "Failed to unmarshal domain for " + entry.getKey(), e);
}
}
return domains;
}
@Override
public int size() {
return domains.size();
}
@Override
public Iterator<DomainFactory<?>> iterator() {
return Iterators.unmodifiableIterator(domains.values().iterator());
}
}
@@ -0,0 +1,88 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
import java.util.UUID;
public class UnknownDomain extends CustomDomain {
public static DomainFactory<UnknownDomain> FACTORY = UnknownDomain::new;
private boolean isDirty = false;
private Object o;
public UnknownDomain(String name) {
super(name);
}
@Override
public void parseInput(CustomDomainContext context) throws InvalidDomainFormatException {
throw new InvalidDomainFormatException("The plugin that registered this domain is not currently installed");
}
@Override
public void unmarshal(Object o) {
this.o = o;
}
@Override
public Object marshal() {
return o;
}
@Override
public boolean contains(UUID uniqueId) {
return false;
}
@Override
public boolean contains(String playerName) {
return false;
}
@Override
public int size() {
return 0;
}
@Override
public void clear() {
isDirty = true;
o = null;
}
@Override
public void setDirty(boolean dirty) {
isDirty = dirty;
}
@Override
public boolean isDirty() {
return isDirty;
}
@Override
public String toString() {
return "UnknownDomain{" +
"o=" + o +
'}';
}
}
@@ -176,13 +176,14 @@ public class RegionPermissionModel extends AbstractPermissionModel {
public boolean mayRemoveOwners(ProtectedRegion region) {
return hasPatternPermission("removeowner", region);
}
/**
* Checks to see if the given sender has permission to modify the given region
* using the region permission pattern.
*
* @param perm the name of the node
* @param region the region
* @return whether the actor has the permission
*/
private boolean hasPatternPermission(String perm, ProtectedRegion region) {
if (!(getSender() instanceof Player)) {
@@ -33,7 +33,7 @@ public class BooleanFlag extends Flag<Boolean> {
}
@Override
public Boolean parseInput(FlagContext context) throws InvalidFlagFormat {
public Boolean parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if (input.equalsIgnoreCase("true") || input.equalsIgnoreCase("yes")
@@ -45,7 +45,7 @@ public class BooleanFlag extends Flag<Boolean> {
|| input.equalsIgnoreCase("0")) {
return false;
} else {
throw new InvalidFlagFormat("Not a yes/no value: " + input);
throw new InvalidFlagFormatException("Not a yes/no value: " + input);
}
}
@@ -33,7 +33,7 @@ public class CommandStringFlag extends Flag<String> {
}
@Override
public String parseInput(FlagContext context) throws InvalidFlagFormat {
public String parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
if (!input.startsWith("/")) {
@@ -33,7 +33,7 @@ public class DoubleFlag extends NumberFlag<Double> {
}
@Override
public Double parseInput(FlagContext context) throws InvalidFlagFormat {
public Double parseInput(FlagContext context) throws InvalidFlagFormatException {
return context.getUserInputAsDouble();
}
@@ -40,12 +40,12 @@ public class EntityTypeFlag extends Flag<EntityType> {
}
@Override
public EntityType parseInput(FlagContext context) throws InvalidFlagFormat {
public EntityType parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
EntityType entityType = unmarshal(input);
if (entityType == null) {
throw new InvalidFlagFormat("Unknown entity type: " + input);
throw new InvalidFlagFormatException("Unknown entity type: " + input);
}
return entityType;
}
@@ -74,12 +74,12 @@ public class EnumFlag<T extends Enum<T>> extends Flag<T> {
}
@Override
public T parseInput(FlagContext context) throws InvalidFlagFormat {
public T parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
try {
return findValue(input);
} catch (IllegalArgumentException e) {
throw new InvalidFlagFormat("Unknown value '" + input + "' in "
throw new InvalidFlagFormatException("Unknown value '" + input + "' in "
+ enumClass.getName());
}
}
@@ -181,9 +181,9 @@ public abstract class Flag<T> {
*
* @param context the {@link FlagContext}
* @return The coerced type
* @throws InvalidFlagFormat Raised if the input is invalid
* @throws InvalidFlagFormatException Raised if the input is invalid
*/
public abstract T parseInput(FlagContext context) throws InvalidFlagFormat;
public abstract T parseInput(FlagContext context) throws InvalidFlagFormatException;
/**
* Convert a raw type that was loaded (from a YAML file, for example)
@@ -21,106 +21,28 @@ package com.sk89q.worldguard.protection.flags;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import java.util.Map;
import com.sk89q.worldguard.commands.CommandInputContext;
import javax.annotation.Nullable;
import java.util.Map;
public final class FlagContext {
private final Actor sender;
private final String input;
private Map<String, Object> context;
public final class FlagContext extends CommandInputContext<InvalidFlagFormatException> {
private FlagContext(Actor sender, String input, Map<String, Object> values) {
this.sender = sender;
this.input = input;
this.context = values;
super(sender, input, values);
}
public static FlagContextBuilder create() {
public static FlagContext.FlagContextBuilder create() {
return new FlagContextBuilder();
}
public void put(String name, Object value) {
context.put(name, value);
}
public Actor getSender() {
return sender;
}
public String getUserInput() {
return input;
}
/**
* Gets the CommandSender as a player.
*
* @return Player
* @throws InvalidFlagFormat if the sender is not a player
*/
public LocalPlayer getPlayerSender() throws InvalidFlagFormat {
if (sender.isPlayer() && sender instanceof LocalPlayer) {
return (LocalPlayer) sender;
} else {
throw new InvalidFlagFormat("Not a player");
}
}
public Integer getUserInputAsInt() throws InvalidFlagFormat {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw new InvalidFlagFormat("Not a number: " + input);
}
}
public Double getUserInputAsDouble() throws InvalidFlagFormat {
try {
return Double.parseDouble(input);
} catch (NumberFormatException e) {
throw new InvalidFlagFormat("Not a number: " + input);
}
}
/**
* Get an object from the context by key name.
* May return null if the object does not exist in the context.
*
* @param name key name of the object
* @return the object matching the key, or null
*/
@Nullable
public Object get(String name) {
return get(name, null);
}
/**
* Get an object from the context by key name.
* Will only return null if
* a) you provide null as the default
* b) the key has explicity been set to null
*
* @param name key name of the object
* @return the object matching the key
*/
@Nullable
public Object get(String name, Object defaultValue) {
Object obj;
return (((obj = context.get(name)) != null) || context.containsKey(name)
? obj : defaultValue);
}
/**
* Create a copy of this FlagContext, with optional substitutions for values
*
* If any supplied variable is null, it will be ignored.
* <p>If any supplied variable is null, it will be ignored.
* If a map is supplied, it will override this FlagContext's values of the same key,
* but unprovided keys will not be overriden and will be returned as shallow copies.
* but unprovided keys will not be overriden and will be returned as shallow copies.</p>
*
* @param commandSender CommandSender for the new FlagContext to run under
* @param s String of the user input for the new FlagContext
@@ -136,6 +58,11 @@ public final class FlagContext {
return new FlagContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map);
}
@Override
protected InvalidFlagFormatException createException(String str) {
return new InvalidFlagFormatException(str);
}
public static class FlagContextBuilder {
private Actor sender;
private String input;
@@ -131,6 +131,7 @@ public final class Flags {
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 StateFlag LAVA_HARDEN = register(new StateFlag("lava-harden", true));
public static final RegistryFlag<WeatherType> WEATHER_LOCK = register(new RegistryFlag<>("weather-lock", WeatherType.REGISTRY));
public static final StringFlag TIME_LOCK = register(new StringFlag("time-lock"));
@@ -40,12 +40,12 @@ public class GameModeTypeFlag extends Flag<GameMode> {
}
@Override
public GameMode parseInput(FlagContext context) throws InvalidFlagFormat {
public GameMode parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
GameMode gamemode = unmarshal(input);
if (gamemode == null) {
throw new InvalidFlagFormat("Unknown game mode: " + input);
throw new InvalidFlagFormatException("Unknown game mode: " + input);
}
return gamemode;
}
@@ -33,7 +33,7 @@ public class IntegerFlag extends NumberFlag<Integer> {
}
@Override
public Integer parseInput(FlagContext context) throws InvalidFlagFormat {
public Integer parseInput(FlagContext context) throws InvalidFlagFormatException {
return context.getUserInputAsInt();
}
@@ -19,6 +19,10 @@
package com.sk89q.worldguard.protection.flags;
/**
* @deprecated replaced by {@link InvalidFlagFormatException}. Will be removed in WorldGuard 8
*/
@Deprecated(forRemoval = true)
public class InvalidFlagFormat extends Exception {
private static final long serialVersionUID = 8101615074524004172L;
@@ -0,0 +1,28 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.protection.flags;
public class InvalidFlagFormatException extends InvalidFlagFormat {
private static final long serialVersionUID = 8101615074524004172L;
public InvalidFlagFormatException(String msg) {
super(msg);
}
}
@@ -41,7 +41,7 @@ public class LocationFlag extends Flag<Location> {
}
@Override
public Location parseInput(FlagContext context) throws InvalidFlagFormat {
public Location parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
Player player = context.getPlayerSender();
@@ -76,7 +76,7 @@ public class LocationFlag extends Flag<Location> {
player.printDebug("WARNING: Flag location is outside of region.");
} else {
// no permission
throw new InvalidFlagFormat("You can't set that flag outside of the region boundaries.");
throw new InvalidFlagFormatException("You can't set that flag outside of the region boundaries.");
}
}
// clamp height to world limits
@@ -86,7 +86,7 @@ public class LocationFlag extends Flag<Location> {
}
return loc;
}
throw new InvalidFlagFormat("Expected 'here' or x,y,z.");
throw new InvalidFlagFormatException("Expected 'here' or x,y,z.");
}
@Override
@@ -70,7 +70,7 @@ public class MapFlag<K, V> extends Flag<Map<K, V>> {
}
@Override
public Map<K, V> parseInput(final FlagContext context) throws InvalidFlagFormat {
public Map<K, V> parseInput(final FlagContext context) throws InvalidFlagFormatException {
final String input = context.getUserInput();
if (input.isEmpty()) {
@@ -83,7 +83,7 @@ public class MapFlag<K, V> extends Flag<Map<K, V>> {
final char split = str.indexOf('=') == -1 ? ':' : '=';
final String[] keyVal = str.split(String.valueOf(split));
if (keyVal.length != 2) {
throw new InvalidFlagFormat("Input must be in a 'key:value,key1=value1' format. Either ':' or '=' can be used.");
throw new InvalidFlagFormatException("Input must be in a 'key:value,key1=value1' format. Either ':' or '=' can be used.");
}
final FlagContext key = context.copyWith(null, keyVal[0], null);
@@ -44,10 +44,10 @@ public class RegistryFlag<T extends Keyed> extends Flag<T> {
}
@Override
public T parseInput(FlagContext context) throws InvalidFlagFormat {
public T parseInput(FlagContext context) throws InvalidFlagFormatException {
final String key = context.getUserInput().trim().toLowerCase(Locale.ROOT);
return Optional.ofNullable(registry.get(key))
.orElseThrow(() -> new InvalidFlagFormat("Unknown " + registry.getName() + ": " + key));
.orElseThrow(() -> new InvalidFlagFormatException("Unknown " + registry.getName() + ": " + key));
}
public Registry<T> getRegistry() {
@@ -58,7 +58,7 @@ public class SetFlag<T> extends Flag<Set<T>> {
}
@Override
public Set<T> parseInput(FlagContext context) throws InvalidFlagFormat {
public Set<T> parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if (input.isEmpty()) {
return Sets.newHashSet();
@@ -78,7 +78,7 @@ public class StateFlag extends Flag<StateFlag.State> {
}
@Override
public State parseInput(FlagContext context) throws InvalidFlagFormat {
public State parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if (input.equalsIgnoreCase("allow")) {
@@ -88,7 +88,7 @@ public class StateFlag extends Flag<StateFlag.State> {
} else if (input.equalsIgnoreCase("none")) {
return null;
} else {
throw new InvalidFlagFormat("Expected none/allow/deny but got '" + input + "'");
throw new InvalidFlagFormatException("Expected none/allow/deny but got '" + input + "'");
}
}
@@ -57,7 +57,7 @@ public class StringFlag extends Flag<String> {
}
@Override
public String parseInput(FlagContext context) throws InvalidFlagFormat {
public String parseInput(FlagContext context) throws InvalidFlagFormatException {
String lines = context.getUserInput().replaceAll("(?<!\\\\)\\\\n", "\n").replaceAll("\\\\\\\\n", "\\\\n");
// Add color codes
lines = CommandUtils.replaceColorMacros(lines);
@@ -48,7 +48,7 @@ public class TimestampFlag extends Flag<Instant> {
}
@Override
public Instant parseInput(FlagContext context) throws InvalidFlagFormat {
public Instant parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if ("now".equalsIgnoreCase(input)) {
return Instant.now();
@@ -61,10 +61,10 @@ public class TimestampFlag extends Flag<Instant> {
} else if (parsed instanceof ZonedDateTime) {
return ((ZonedDateTime) parsed).toInstant();
} else {
throw new InvalidFlagFormat("Unrecognized input.");
throw new InvalidFlagFormatException("Unrecognized input.");
}
} catch (DateTimeParseException ignored) {
throw new InvalidFlagFormat("Expected 'now' or ISO 8601 formatted input.");
throw new InvalidFlagFormatException("Expected 'now' or ISO 8601 formatted input.");
}
}
}
@@ -33,7 +33,7 @@ public class UUIDFlag extends Flag<UUID> {
}
@Override
public UUID parseInput(FlagContext context) throws InvalidFlagFormat {
public UUID parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if ("self".equalsIgnoreCase(input)) {
return context.getSender().getUniqueId();
@@ -41,7 +41,7 @@ public class UUIDFlag extends Flag<UUID> {
try {
return UUID.fromString(input);
} catch (IllegalArgumentException e) {
throw new InvalidFlagFormat("Not a valid uuid: " + input);
throw new InvalidFlagFormatException("Not a valid uuid: " + input);
}
}
@@ -38,7 +38,7 @@ public class VectorFlag extends Flag<Vector3> {
}
@Override
public Vector3 parseInput(FlagContext context) throws InvalidFlagFormat {
public Vector3 parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if ("here".equalsIgnoreCase(input)) {
@@ -56,7 +56,7 @@ public class VectorFlag extends Flag<Vector3> {
}
}
throw new InvalidFlagFormat("Expected 'here' or x,y,z.");
throw new InvalidFlagFormatException("Expected 'here' or x,y,z.");
}
}
@@ -40,12 +40,12 @@ public class WeatherTypeFlag extends Flag<WeatherType> {
}
@Override
public WeatherType parseInput(FlagContext context) throws InvalidFlagFormat {
public WeatherType parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
WeatherType weatherType = unmarshal(input);
if (weatherType == null) {
throw new InvalidFlagFormat("Unknown weather type: " + input);
throw new InvalidFlagFormatException("Unknown weather type: " + input);
}
return weatherType;
}
@@ -21,7 +21,7 @@ package com.sk89q.worldguard.protection.flags.registry;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormatException;
import javax.annotation.Nullable;
@@ -32,8 +32,8 @@ public class UnknownFlag extends Flag<Object> {
}
@Override
public Object parseInput(FlagContext context) throws InvalidFlagFormat {
throw new InvalidFlagFormat("The plugin that registered this flag is not currently installed");
public Object parseInput(FlagContext context) throws InvalidFlagFormatException {
throw new InvalidFlagFormatException("The plugin that registered this flag is not currently installed");
}
@Override
@@ -224,7 +224,7 @@ public final class RegionManager {
}
/**
* Aad a region to the manager.
* Add a region to the manager.
*
* <p>The parents of the region will also be added to the index.</p>
*
@@ -27,6 +27,8 @@ import com.sk89q.util.yaml.YAMLProcessor;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.CustomDomain;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.flags.FlagUtil;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
@@ -50,6 +52,7 @@ import org.yaml.snakeyaml.representer.Representer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -118,7 +121,7 @@ public class YamlRegionFile implements RegionDatabase {
YAMLProcessor config = createYamlProcessor(file);
try {
config.load();
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
return new HashSet<>(loaded.values());
} catch (IOException | ParserException e) {
throw new StorageException("Failed to load region data from '" + file + "'", e);
@@ -193,64 +196,66 @@ public class YamlRegionFile implements RegionDatabase {
public void saveAll(Set<ProtectedRegion> regions) throws StorageException {
checkNotNull(regions);
File tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
YAMLProcessor config = createYamlProcessor(tempFile);
synchronized (YamlRegionFile.class) {
File tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
YAMLProcessor config = createYamlProcessor(tempFile);
config.clear();
config.clear();
YAMLNode regionsNode = config.addNode("regions");
Map<String, Object> map = regionsNode.getMap();
YAMLNode regionsNode = config.addNode("regions");
Map<String, Object> map = regionsNode.getMap();
for (ProtectedRegion region : regions) {
Map<String, Object> nodeMap = new HashMap<>();
map.put(region.getId(), nodeMap);
YAMLNode node = new YAMLNode(nodeMap, false);
for (ProtectedRegion region : regions) {
Map<String, Object> nodeMap = new HashMap<>();
map.put(region.getId(), nodeMap);
YAMLNode node = new YAMLNode(nodeMap, false);
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
node.setProperty("type", "cuboid");
node.setProperty("min", cuboid.getMinimumPoint());
node.setProperty("max", cuboid.getMaximumPoint());
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly = (ProtectedPolygonalRegion) region;
node.setProperty("type", "poly2d");
node.setProperty("min-y", poly.getMinimumPoint().y());
node.setProperty("max-y", poly.getMaximumPoint().y());
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
node.setProperty("type", "cuboid");
node.setProperty("min", cuboid.getMinimumPoint());
node.setProperty("max", cuboid.getMaximumPoint());
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly = (ProtectedPolygonalRegion) region;
node.setProperty("type", "poly2d");
node.setProperty("min-y", poly.getMinimumPoint().y());
node.setProperty("max-y", poly.getMaximumPoint().y());
List<Map<String, Object>> points = new ArrayList<>();
for (BlockVector2 point : poly.getPoints()) {
Map<String, Object> data = new HashMap<>();
data.put("x", point.x());
data.put("z", point.z());
points.add(data);
List<Map<String, Object>> points = new ArrayList<>();
for (BlockVector2 point : poly.getPoints()) {
Map<String, Object> data = new HashMap<>();
data.put("x", point.x());
data.put("z", point.z());
points.add(data);
}
node.setProperty("points", points);
} else if (region instanceof GlobalProtectedRegion) {
node.setProperty("type", "global");
} else {
node.setProperty("type", region.getClass().getCanonicalName());
}
node.setProperty("points", points);
} else if (region instanceof GlobalProtectedRegion) {
node.setProperty("type", "global");
} else {
node.setProperty("type", region.getClass().getCanonicalName());
node.setProperty("priority", region.getPriority());
node.setProperty("flags", getFlagData(region));
node.setProperty("owners", getDomainData(region.getOwners()));
node.setProperty("members", getDomainData(region.getMembers()));
ProtectedRegion parent = region.getParent();
if (parent != null) {
node.setProperty("parent", parent.getId());
}
}
node.setProperty("priority", region.getPriority());
node.setProperty("flags", getFlagData(region));
node.setProperty("owners", getDomainData(region.getOwners()));
node.setProperty("members", getDomainData(region.getMembers()));
config.setHeader(FILE_HEADER);
config.save();
ProtectedRegion parent = region.getParent();
if (parent != null) {
node.setProperty("parent", parent.getId());
//noinspection ResultOfMethodCallIgnored
file.delete();
if (!tempFile.renameTo(file)) {
throw new StorageException("Failed to rename temporary regions file to " + file.getAbsolutePath());
}
}
config.setHeader(FILE_HEADER);
config.save();
//noinspection ResultOfMethodCallIgnored
file.delete();
if (!tempFile.renameTo(file)) {
throw new StorageException("Failed to rename temporary regions file to " + file.getAbsolutePath());
}
}
@Override
@@ -285,6 +290,12 @@ public class YamlRegionFile implements RegionDatabase {
}
}
YAMLNode apiDomains = node.getNode("custom");
if (apiDomains != null) {
Map<String, CustomDomain> parsedDomains = WorldGuard.getInstance().getDomainRegistry().unmarshal(apiDomains.getMap(), true);
domain.setCustomDomains(parsedDomains);
}
return domain;
}
@@ -305,6 +316,14 @@ public class YamlRegionFile implements RegionDatabase {
setDomainData(domainData, "unique-ids", domain.getUniqueIds());
setDomainData(domainData, "groups", domain.getGroups());
if (!domain.getCustomDomains().isEmpty()) {
Map<String, Object> values = new HashMap<>();
for (CustomDomain customDomain : domain.getCustomDomains()) {
values.put(customDomain.getName(), customDomain.marshal());
}
domainData.put("custom", values);
}
return domainData;
}
Loaded 100 of 109 files, more files were not shown because too many files have changed in this diff. Show more