Compare commits

...
104 Commits
Author SHA1 Message Date
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
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
Maddy Miller 43997ecfdc Release 7.0.14 2025-06-12 23:09:40 +10:00
wizjany b0a98d4c38 Add material defs for 1.21.5. (#2204) 2025-05-17 16:08:40 -04:00
Wertík 98b52206a0 Listen to EntityPushedByEntityAttackEvent for knockback/push (#2193)
Listening to the push event instead of EntityKnockbackByEntity includes other sources of knockback/push in the internal DamageEntityEvent.

Closes #2190.
2025-03-16 10:35:14 -04:00
wizjany 65792ec37c Restore previous behavior of ride/interact. (#2196)
Closes #2194.
2025-03-16 10:34:42 -04:00
wizjany 656cda43f0 Point readme to compiling file so we don't have to update two places. 2025-03-10 13:15:48 -04:00
wizjany 4ec325ef31 Use chest-access for hoppers pulling from entities. (#2191)
Closes #2187.
2025-03-09 15:46:48 -04:00
wizjany a949b106c6 Skip the hopper doing the pulling. (#2186)
Closes #2185.
2025-03-02 11:37:17 -05:00
wizjany 33bbd93a13 Back to SNAPSHOT for development. 2025-02-16 17:51:25 -05:00
wizjany 82fdc65d0e Release 7.0.13. 2025-02-16 17:41:19 -05:00
wizjany 2d96cdb90e Consider decorated pots chest-access instead of interact.
Message is a bit awkward since it says "open that" but oh well.

Closes #2170.
2025-02-16 16:40:20 -05:00
wizjany 9eadfdbc4f More comprehensive fishing rod checks.
Checks the retrieve (caught entity) for all non-hostiles (i.e. including vehicles now, checked with vehicle-destroy).
Also checks the projectile hit event, to prevent hooks from attaching pre-emptively.

Closes #2157, #2155.
2025-02-16 16:31:34 -05:00
auroraandoctylFractal 38ce4d42fc Port outside repo usage elimination
Ports da223671a5e5d0107d502234d7378522db162e3c from WorldEdit to Worldguard and updates Gradle.

Co-authored-by: octylFractal <octavia.togami@gmail.com>
2025-01-25 09:35:01 -05:00
jquery-package f89b149557 Use PaperLib to get inventory holder 2025-01-05 21:44:42 -05:00
Joo200 910b241200 Drop spigot api as dependency in gradle 2025-01-05 20:56:53 -05:00
wizjany 5f8e5eaf92 Bump mojang libs.
Only affects api-users building against 1.21.4 mojang deps.
2024-12-21 11:43:20 -05:00
wizjany 675d86ce16 Back to snapshot. 2024-12-21 11:15:32 -05:00
wizjany 5c4848b8fd Release 7.0.13-beta-2. 2024-12-21 11:12:51 -05:00
wizjany acd4fda8ff Update to 1.21.4. 2024-12-21 11:08:51 -05:00
wizjany 89b6bdc16a Fix typo.
Only affected the config option, not the flag, so not too surprised it wasn't noticed earlier.

https://github.com/EngineHub/WorldGuard/pull/2115/files/679b56948f41869bd545564a8c57562f157a6b66#r1878791900
2024-12-10 16:27:24 -05:00
wizjany 7ae07a9497 Back to snapshot.
Also update changelog cuz I forgot.
2024-11-09 13:52:24 -05:00
wizjany 2f13ae0444 Release 7.0.13-beta-1 2024-11-09 13:48:02 -05:00
wizjany 1a59d1eb29 Update to 1.21.3. (#2153)
* Initial update to 1.21.3.

Compiles, launches, nothing tested yet.

* Boat tag includes chest boat tag.

* Avoid Material.values call.

* Split ride checks to separate event handler.

Bypass the interact entirely and let EntityMount handle it, since we can't discriminate usage in interact.
2024-11-09 13:29:04 -05:00
wizjany 764d258ed0 Fix deprecations on stack methods.
Also this was supposed to be on a branch but I just realized I forgot.
2024-10-28 08:49:59 -04:00
wizjany 5579d197ab Remove stack size bypassing perm.
Entire command should eventually be removed.
2024-10-28 08:24:28 -04:00
Joo200andaurora 3b9ab47a97 Avoid using metadata storage if possible (#2150)
* Avoid using metadata storage if possible

* Fix cause detection, use always on paper

* Fix fat fingers

Co-authored-by: aurora <21148213+aurorasmiles@users.noreply.github.com>
2024-10-16 19:43:27 -04:00
wizjany d9716a5bd8 Ignore arrow combustion.
Closes #2144.
2024-09-13 14:29:18 -04:00
wizjany a0e397e57f Use more snapshot-less holders on Paper.
This is already past the debounce so in theory it's not getting hit *often*, but I guess if it's really slow it'll still show up.
2024-09-13 14:15:32 -04:00
wizjany 02dc89b224 Bump to snapshot. 2024-09-13 11:58:55 -04:00
wizjany 829a4a42df Release 7.0.12. 2024-09-13 11:58:22 -04:00
wizjany 830472d36e Revert previous changes to explosion event handling.
Event abstraction sucks and everything needs rewriting.
2024-09-13 11:46:06 -04:00
wizjany 03aac83f4c Match explosion flag coverage with EntityListener. 2024-09-13 10:00:48 -04:00
wizjany fb88d56646 Bump to SNAPSHOT for dev.
Also update the changelog.
2024-09-09 16:56:05 -04:00
wizjany 068ad680fc Release 7.0.11. 2024-09-09 16:24:43 -04:00
ploppypersonandwizjany cb011a88cf Add moisture-change flag (#1879) (#2096)
* Create and implement moisture-change flag

* Fix imports

* Add comment

* Actually read the value from config.

Closes #1879 

---------

Co-authored-by: wizjany <wizjany@gmail.com>
2024-09-09 15:43:58 -04:00
wizjany 0f3ea5045e Merge pull request #2115 from EngineHub/feature/fix-breeze-stuff
Optimize and cleanup explosion events from entities

Fixes #2099 and #2097
2024-09-08 17:26:31 -04:00
wizjany 679b56948f Split wind charge into breeze/player flags.
Player flag is build-checked (default false) and breeze flag is not (default true).

Having multiple flags is ugly but if we need every bit of behavior to be manipulable this is the only way.
2024-09-08 16:46:50 -04:00
Joo200 9dd7d7c03e Fix wind-charge-burst flag for player knockback 2024-09-08 14:56:08 -04:00
Joo200 afb619d2ac Fix breeze damage flags 2024-09-08 14:56:04 -04:00
wizjany b73a0a7179 Check mob-damage for potion splashes from e.g. witches.
Note that bypass bypasses this if the player with bypass is the target of the potion, but only for the player with bypass.

Fixes #2134.
2024-09-08 13:40:13 -04:00
wizjany 2ea50689b9 Workaround books no longer sending change block for lecterns.
Fixes #2124.
2024-09-08 12:51:00 -04:00
wizjany 70d225ef2f Split chest boat ride/open. 2024-09-08 12:45:08 -04:00
wizjany aa46529ecb Extend use flag to all (trap)doors.
There's no tag which has wood+copper, but iron are not interactable anyway.

Relates to #2130.
2024-09-08 12:45:07 -04:00
Joo200 8ffc81ad74 Fix NPE for teleport events without target location
Fixes #2111
2024-07-22 21:42:44 +02:00
wizjany 16ea4625c9 Merge pull request #2100 from aurorasmiles/feat/buildlogic
Port buildlogic from WorldEdit
2024-07-21 23:30:40 -04:00
wizjany ca49458a44 A bit of cleanup.
Definitely did not accidentally make a 40MB jar halfway through.
2024-07-21 23:26:45 -04:00
aurora 574921089b Port build-logic from WorldEdit 2024-07-21 23:17:21 -04:00
CyberFlame c6fbfb87a3 remove double space 2024-07-05 17:02:51 +02:00
wizjany fa357f4681 Back to snapshot.
Idk why we even to this for betas, they're not getting a maven release.
2024-06-26 18:58:10 -04:00
wizjany a801a9d67a Release 7.0.11-beta1. 2024-06-26 18:50:12 -04:00
1bfae45484 Merge pull request #2089 from EngineHub/feat/mc-1.21
* Fix compilation for MC 1.21. Nothing tested yet.

* Update Materials.java with 1.21 tags and materials

* Fix ItemStack conversion on block place on MC 1.21 (#2093)

* Fix ItemStack conversion on block place

This issue is present in 1.21 because some materials do not convert 1:1 to item types.
This throws an exception in the ItemStack constructor.
Example: WALL_TORCH is a valid block but not a valid item, only TORCH is a valid item.

So, use the item in hand instead, creating a copy with quantity set to 1, for issueing the
use item event.

* Use ItemStack as-is.

Closes #2092.

* Fix ItemStack conversion for spigot compatibility

* Special handling for WindCharges

* Do not call as a bulk event, because it has to check every blocks type

* WindCharge -> AbstractWindCharge

* Fix UseBlockFlag for multiple uses at the same time, add windburst-flag

* Cleanup code

* Handle vaults as use, crafters as chest-access.

---------

Co-authored-by: Joo200 <github@joo200.de>
Co-authored-by: Lennart <1535717+lenis0012@users.noreply.github.com>
Co-authored-by: Brokkonaut <hannos17@gmx.de>
2024-06-26 18:48:35 -04:00
wizjany b269d7e264 Handle vaults as use, crafters as chest-access. 2024-06-26 18:17:55 -04:00
Joo200 af645ea2e4 Cleanup code 2024-06-26 22:34:29 +02:00
Joo200 a5ea5115f9 Fix UseBlockFlag for multiple uses at the same time, add windburst-flag 2024-06-26 22:30:33 +02:00
Brokkonaut 83298796ab WindCharge -> AbstractWindCharge 2024-06-26 21:39:21 +02:00
Brokkonaut 8aa37e389d Do not call as a bulk event, because it has to check every blocks type 2024-06-26 21:39:21 +02:00
Brokkonaut 887f3bfaec Special handling for WindCharges 2024-06-26 21:39:21 +02:00
Joo200 6898ad8674 Fix ItemStack conversion for spigot compatibility 2024-06-22 15:08:10 +02:00
Lennartandwizjany 7783e9ae3b Fix ItemStack conversion on block place on MC 1.21 (#2093)
* Fix ItemStack conversion on block place

This issue is present in 1.21 because some materials do not convert 1:1 to item types.
This throws an exception in the ItemStack constructor.
Example: WALL_TORCH is a valid block but not a valid item, only TORCH is a valid item.

So, use the item in hand instead, creating a copy with quantity set to 1, for issueing the
use item event.

* Use ItemStack as-is.

Closes #2092.

---------

Co-authored-by: wizjany <wizjany@gmail.com>
2024-06-19 12:00:35 -04:00
Joo200 2bd426baf8 Update Materials.java with 1.21 tags and materials 2024-06-17 20:00:03 +02:00
wizjany 27f009594a Fix compilation for MC 1.21. Nothing tested yet. 2024-06-16 21:48:35 -04:00
Joni Aromaa ead1e1b77c Fix checking bypass on initialize (#2082)
* Fix checking bypass on initialize

* Add SessionManager#createSession back as deprecated
2024-05-24 10:48:08 -04:00
auroraandWyatt Childers 8b7729e0e8 Fix silent flag for gameplay commands (#2081)
* Fix silent flag for gameplay commands

This issue has been fixed in CommandBook with
https://github.com/EngineHub/CommandBook/commit/644803182ed1765a9862d0a0cd0d3763d399efee
but never in WorldGuard.

Co-authored-by: Wyatt Childers <DarkArc@users.noreply.github.com>

* codestyle
2024-05-23 13:05:29 -04:00
Joo200 d6ef5e9398 Remove adventure snapshot repository 2024-05-17 18:05:37 +02:00
wizjany 6f5501f7be Bump to snapshot. 2024-05-14 18:14:06 -04:00
84 changed files with 1686 additions and 887 deletions

No files matched your search

-8
View File
@@ -1,8 +0,0 @@
language: java
dist: trusty
jdk:
- oraclejdk11
notifications:
email: false
before_install: chmod +x gradlew
script: ./gradlew build -S
+62
View File
@@ -1,5 +1,67 @@
# 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
* Fix hopper minecarts not being able to take items from containers in protected regions.
* Fix hopper minecarts not being able to take items from other hopper minecarts in protected regions.
* Fix non-members being able to leash boats in protected regions.
* Use new knockback event on Paper servers to better handle mace knockback in pvp and some other knockback situations.
## 7.0.13
* Update to 1.21.4
* Remove max-stack-size bypass in stack command
* Fix a falling block metadata leak. (May still be problematic on Spigot, use Paper.)
* Fix flame enchant being blocked as entity damage on the arrow itself.
* More Paper-specific performance enhancements for hoppers.
* Fix block-windcharge-explosions config option not doing anything.
* Improvements to fishing rod protection.
* More aggressive vehicle protection (vehicle-destroy now needs to be allowed for various non-destructive damage).
* Move decorated pot usage from interact to chest-access.
## 7.0.12
* Fix a change in the default behavior of explosion flag handling.
## 7.0.11
* Add support for MC 1.21.
* Add wind-charge-burst flag which is checked along with `use` (for the interaction) or `pvp` (for the knockback).
* Add breeze-charge-explosion flag for breeze charges (i.e. from the mob, not player wind charges).
* Add moisture-change flag and config options.
* Fix an error if a player logged in to an unloaded world.
* Fix chest boat usage always being counted as ride.
* Consider potions thrown by mobs as mob-damage.
* Workaround spigot no longer sending block change events when a book is placed on a lectern.
* Improve accuracy of target blocks in blacklist/build-perms events.
## 7.0.10
* Add support for MC 1.20.5 and 1.20.6, drop support for other 1.20 versions
+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:
+1 -4
View File
@@ -23,10 +23,7 @@ A Bukkit server implementation (such as [Paper](https://papermc.io)) and the [Wo
Compiling
---------
The project is written for Java 17 and our build process makes use of
[Gradle](http://gradle.org).
Dependencies are automatically handled by Gradle.
See [COMPILING.md](COMPILING.md).
Contributing
------------
+37
View File
@@ -0,0 +1,37 @@
plugins {
`kotlin-dsl`
}
repositories {
maven {
name = "EngineHub"
url = uri("https://repo.enginehub.org/libs-release/")
}
mavenCentral()
gradlePluginPortal()
}
dependencies {
implementation(gradleApi())
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.gson)
constraints {
val asmVersion = "[${libs.versions.minimumAsm.get()},)"
implementation("org.ow2.asm:asm:$asmVersion") {
because("Need Java 21 support in shadow")
}
implementation("org.ow2.asm:asm-commons:$asmVersion") {
because("Need Java 21 support in shadow")
}
implementation("org.vafer:jdependency:[${libs.versions.minimumJdependency.get()},)") {
because("Need Java 21 support in shadow")
}
}
}
+9
View File
@@ -0,0 +1,9 @@
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
rootProject.name = "build-logic"
@@ -0,0 +1,4 @@
plugins {
id("org.enginehub.crankcase.java-library")
id("buildlogic.common-java")
}
@@ -0,0 +1,29 @@
import buildlogic.getLibrary
import buildlogic.stringyLibs
plugins {
id("eclipse")
id("idea")
id("checkstyle")
id("org.enginehub.crankcase.java")
id("buildlogic.common")
}
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"
}
dependencies {
"compileOnly"(stringyLibs.getLibrary("jsr305"))
}
@@ -0,0 +1,35 @@
import buildlogic.getLibrary
import buildlogic.stringyLibs
plugins {
id("org.enginehub.crankcase.common")
id("org.enginehub.crankcase.licensing")
id("org.enginehub.crankcase.git")
}
group = rootProject.group
version = rootProject.version
dependencies {
for (conf in listOf("implementation", "api")) {
if (!configurations.names.contains(conf)) {
continue
}
add(conf, platform(stringyLibs.getLibrary("log4j-bom")).map {
val dep = create(it)
dep.because("Mojang provides Log4j")
dep
})
constraints {
add(conf, stringyLibs.getLibrary("guava")) {
because("Mojang provides Guava")
}
add(conf, stringyLibs.getLibrary("gson")) {
because("Mojang provides Gson")
}
add(conf, stringyLibs.getLibrary("fastutil")) {
because("Mojang provides FastUtil")
}
}
}
}
@@ -0,0 +1,20 @@
plugins {
id("maven-publish")
id("buildlogic.common-java-library")
id("org.enginehub.crankcase.publishing")
}
publishing {
publications {
register<MavenPublication>("maven") {
versionMapping {
usage("java-api") {
fromResolutionOf("runtimeClasspath")
}
usage("java-runtime") {
fromResolutionResult()
}
}
}
}
}
@@ -0,0 +1,178 @@
plugins {
id("java-base")
id("maven-publish")
id("com.gradleup.shadow")
id("buildlogic.common")
id("org.enginehub.crankcase.publishing")
}
// A horrible hack because `softwareComponentFactory` has to be gotten via plugin
// gradle why
internal open class LibsConfigPluginHack @Inject constructor(
private val softwareComponentFactory: SoftwareComponentFactory
) : Plugin<Project> {
override fun apply(project: Project) {
val libsComponents = softwareComponentFactory.adhoc("libs")
project.components.add(libsComponents)
}
}
configurations {
create("shade")
}
group = "${rootProject.group}.worldguard-libs"
val relocations = mapOf(
"org.enginehub.squirrelid" to "com.sk89q.worldguard.util.profile",
)
tasks.register<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("jar") {
configurations = listOf(project.configurations["shade"])
archiveClassifier.set("")
// Yeet module-info's
exclude("module-info.class")
dependencies {
exclude(dependency("com.google.guava:guava"))
exclude(dependency("com.google.code.gson:gson"))
exclude(dependency("com.google.errorprone:error_prone_annotations"))
exclude(dependency("com.google.guava:failureaccess"))
exclude(dependency("org.checkerframework:checker-qual"))
exclude(dependency("org.jetbrains:annotations"))
exclude(dependency("org.apache.logging.log4j:log4j-api"))
exclude(dependency("com.google.code.findbugs:jsr305"))
exclude {
it.moduleGroup == "org.jetbrains.kotlin"
}
}
relocations.forEach { (from, to) ->
relocate(from, to)
}
}
val altConfigFiles = { artifactType: String ->
val deps = configurations["shade"].incoming.dependencies
.filterIsInstance<ModuleDependency>()
.map { it.copy() }
.map { dependency ->
val category = dependency.attributes.getAttribute(Category.CATEGORY_ATTRIBUTE)?.name
if (category == Category.REGULAR_PLATFORM || category == Category.ENFORCED_PLATFORM) {
return@map dependency
}
try {
dependency.artifact {
name = dependency.name
type = artifactType
extension = "jar"
classifier = artifactType
}
} catch (e: Exception) {
throw RuntimeException("Failed to add artifact to dependency: $dependency", e)
}
dependency
}
files(configurations.detachedConfiguration(*deps.toTypedArray())
.resolvedConfiguration.lenientConfiguration.artifacts
.filter { it.classifier == artifactType }
.map { zipTree(it.file) })
}
tasks.register<Jar>("sourcesJar") {
from({
altConfigFiles("sources")
})
// Yeet module-info's
exclude("module-info.java")
relocations.forEach { (from, to) ->
val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)")
val textPattern = Regex.fromLiteral(from)
eachFile {
filter {
it.replaceFirst(textPattern, to)
}
path = path.replaceFirst(filePattern, "$1${to.replace('.', '/')}$2")
}
}
archiveClassifier.set("sources")
}
tasks.named("assemble").configure {
dependsOn("jar", "sourcesJar")
}
project.apply<LibsConfigPluginHack>()
val libsComponent = project.components["libs"] as AdhocComponentWithVariants
val apiElements = project.configurations.register("apiElements") {
isVisible = false
description = "API elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25)
}
outgoing.artifact(tasks.named("jar"))
}
val runtimeElements = project.configurations.register("runtimeElements") {
isVisible = false
description = "Runtime elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25)
}
outgoing.artifact(tasks.named("jar"))
}
val sourcesElements = project.configurations.register("sourcesElements") {
isVisible = false
description = "Source elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES))
}
outgoing.artifact(tasks.named("sourcesJar"))
}
libsComponent.addVariantsFromConfiguration(apiElements.get()) {
mapToMavenScope("compile")
}
libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
mapToMavenScope("runtime")
}
libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
mapToMavenScope("runtime")
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("maven") {
from(libsComponent)
}
}
}
if (project != project(":worldguard-libs:core")) {
evaluationDependsOn(":worldguard-libs:core")
configurations["shade"].shouldResolveConsistentlyWith(project(":worldguard-libs:core").configurations["shade"])
}
@@ -0,0 +1,38 @@
plugins {
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 {
include(project(":worldguard-libs:core"))
include(project(":worldguard-core"))
relocate("org.flywaydb", "com.sk89q.worldguard.internal.flywaydb") {
include(dependency("org.flywaydb:flyway-core"))
}
exclude("com.google.code.findbugs:jsr305")
}
exclude("GradleStart**")
exclude(".cache")
exclude("LICENSE*")
exclude("META-INF/maven/**")
minimize()
}
afterEvaluate {
tasks.named<Jar>("jar") {
val version = project(":worldguard-core").version
inputs.property("version", version)
val attributes = mutableMapOf(
"Implementation-Version" to version,
"WorldGuard-Version" to version,
)
manifest.attributes(attributes)
}
}
@@ -0,0 +1,32 @@
package buildlogic
import org.gradle.api.Project
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.artifacts.VersionCatalog
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.api.artifacts.VersionConstraint
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.provider.Provider
import org.enginehub.crankcase.git.GitExtension
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the
val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
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")
}
fun VersionCatalog.getVersion(name: String): VersionConstraint = findVersion(name).orElseThrow {
error("Version $name not found in version catalog")
}
+3 -26
View File
@@ -1,26 +1,3 @@
import org.ajoberstar.grgit.Grgit
logger.lifecycle("""
*******************************************
You are building WorldGuard!
If you encounter trouble:
1) Try running 'build' in a separate Gradle run
2) Use gradlew and not gradle
3) If you still need help, ask on Discord! https://discord.gg/enginehub
Output files will be in [subproject]/build/libs
*******************************************
""")
applyRootArtifactoryConfig()
if (!project.hasProperty("gitCommitHash")) {
apply(plugin = "org.ajoberstar.grgit")
ext["gitCommitHash"] = try {
Grgit.open(mapOf("currentDir" to project.rootDir))?.head()?.abbreviatedId
} catch (e: Exception) {
logger.warn("Error getting commit hash", e)
"no.git.id"
}
}
plugins {
id("buildlogic.common")
}
-29
View File
@@ -1,29 +0,0 @@
plugins {
`kotlin-dsl`
kotlin("jvm") version embeddedKotlinVersion
}
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
implementation(gradleApi())
implementation("gradle.plugin.org.cadixdev.gradle:licenser:0.6.1")
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
implementation("com.github.johnrengelman:shadow:8.1.1")
implementation("org.jfrog.buildinfo:build-info-extractor-gradle:5.2.0")
constraints {
val asmVersion = "[9.7,)"
implementation("org.ow2.asm:asm:$asmVersion") {
because("Need Java 21 support in shadow")
}
implementation("org.ow2.asm:asm-commons:$asmVersion") {
because("Need Java 21 support in shadow")
}
implementation("org.vafer:jdependency:[2.10,)") {
because("Need Java 21 support in shadow")
}
}
}
@@ -1,40 +0,0 @@
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.named
import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention
import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask
private const val ARTIFACTORY_CONTEXT_URL = "artifactory_contextUrl"
private const val ARTIFACTORY_USER = "artifactory_user"
private const val ARTIFACTORY_PASSWORD = "artifactory_password"
fun Project.applyRootArtifactoryConfig() {
if (!project.hasProperty(ARTIFACTORY_CONTEXT_URL)) ext[ARTIFACTORY_CONTEXT_URL] = "http://localhost"
if (!project.hasProperty(ARTIFACTORY_USER)) ext[ARTIFACTORY_USER] = "guest"
if (!project.hasProperty(ARTIFACTORY_PASSWORD)) ext[ARTIFACTORY_PASSWORD] = ""
apply(plugin = "com.jfrog.artifactory")
configure<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
}
}
fun Project.applyCommonArtifactoryConfig() {
tasks.named<ArtifactoryTask>("artifactoryPublish") {
publications("maven")
}
}
-38
View File
@@ -1,38 +0,0 @@
import org.cadixdev.gradle.licenser.LicenseExtension
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.repositories
import org.gradle.kotlin.dsl.the
fun Project.applyCommonConfiguration() {
group = rootProject.group
version = rootProject.version
repositories {
mavenCentral()
maven { url = uri("https://maven.enginehub.org/repo/") }
maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") }
}
configurations.all {
resolutionStrategy {
cacheChangingModulesFor(5, "MINUTES")
}
}
plugins.withId("java") {
the<JavaPluginExtension>().toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
apply(plugin = "org.cadixdev.licenser")
configure<LicenseExtension> {
header(rootProject.file("HEADER.txt"))
include("**/*.java")
include("**/*.kt")
}
}
-12
View File
@@ -1,12 +0,0 @@
import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the
val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
val Project.sourceSets: SourceSetContainer
get() = the<JavaPluginConvention>().sourceSets
-171
View File
@@ -1,171 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.DocsType
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.attributes.Usage
import org.gradle.api.attributes.java.TargetJvmVersion
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
import javax.inject.Inject
fun Project.applyLibrariesConfiguration() {
applyCommonConfiguration()
apply(plugin = "java-base")
apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "com.jfrog.artifactory")
configurations {
create("shade")
}
group = "${rootProject.group}.worldguard-libs"
val relocations = mapOf(
"org.enginehub.squirrelid" to "com.sk89q.worldguard.util.profile"
)
tasks.register<ShadowJar>("jar") {
configurations = listOf(project.configurations["shade"])
archiveClassifier.set("")
dependencies {
exclude(dependency("com.google.code.findbugs:jsr305"))
}
relocations.forEach { (from, to) ->
relocate(from, to)
}
}
val altConfigFiles = { artifactType: String ->
val deps = configurations["shade"].incoming.dependencies
.filterIsInstance<ModuleDependency>()
.map { it.copy() }
.map { dependency ->
dependency.artifact {
name = dependency.name
type = artifactType
extension = "jar"
classifier = artifactType
}
dependency
}
files(configurations.detachedConfiguration(*deps.toTypedArray())
.resolvedConfiguration.lenientConfiguration.artifacts
.filter { it.classifier == artifactType }
.map { zipTree(it.file) })
}
tasks.register<Jar>("sourcesJar") {
from({
altConfigFiles("sources")
})
relocations.forEach { (from, to) ->
val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)")
val textPattern = Regex.fromLiteral(from)
eachFile {
filter {
it.replaceFirst(textPattern, to)
}
path = path.replaceFirst(filePattern, "$1${to.replace('.', '/')}$2")
}
}
archiveClassifier.set("sources")
}
tasks.named("assemble").configure {
dependsOn("jar", "sourcesJar")
}
project.apply<LibsConfigPluginHack>()
val libsComponent = project.components["libs"] as AdhocComponentWithVariants
val apiElements = project.configurations.register("apiElements") {
isVisible = false
description = "API elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
}
outgoing.artifact(tasks.named("jar"))
}
val runtimeElements = project.configurations.register("runtimeElements") {
isVisible = false
description = "Runtime elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
}
outgoing.artifact(tasks.named("jar"))
}
val sourcesElements = project.configurations.register("sourcesElements") {
isVisible = false
description = "Source elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES))
}
outgoing.artifact(tasks.named("sourcesJar"))
}
libsComponent.addVariantsFromConfiguration(apiElements.get()) {
mapToMavenScope("compile")
}
libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
mapToMavenScope("runtime")
}
libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
mapToMavenScope("runtime")
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("maven") {
from(libsComponent)
}
}
}
applyCommonArtifactoryConfig()
}
internal open class LibsConfigPluginHack @Inject constructor(
private val softwareComponentFactory: SoftwareComponentFactory
) : Plugin<Project> {
override fun apply(project: Project) {
val libsComponents = softwareComponentFactory.adhoc("libs")
project.components.add(libsComponents)
}
}
-113
View File
@@ -1,113 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
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.named
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.withType
import org.gradle.kotlin.dsl.the
fun Project.applyPlatformAndCoreConfiguration() {
applyCommonConfiguration()
apply(plugin = "java")
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "maven-publish")
apply(plugin = "checkstyle")
apply(plugin = "com.jfrog.artifactory")
ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "10.3"
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
"compileOnly"("com.google.code.findbugs:jsr305:3.0.2")
"testCompileOnly"("com.google.code.findbugs:jsr305:3.0.2")
"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 as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:none", "-quiet")
tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
}
}
the<JavaPluginExtension>().withJavadocJar()
if (name == "worldguard-core" || name == "worldguard-bukkit") {
the<JavaPluginExtension>().withSourcesJar()
}
tasks.named("check").configure {
dependsOn("checkstyleMain", "checkstyleTest")
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("maven") {
from(components["java"])
versionMapping {
usage("java-api") {
fromResolutionOf("runtimeClasspath")
}
usage("java-runtime") {
fromResolutionResult()
}
}
}
}
}
applyCommonArtifactoryConfig()
}
fun Project.applyShadowConfiguration() {
apply(plugin = "com.github.johnrengelman.shadow")
tasks.named<ShadowJar>("shadowJar") {
archiveClassifier.set("dist")
dependencies {
include(project(":worldguard-libs:core"))
//include(project(":worldguard-libs:${project.name.replace("worldguard-", "")}"))
include(project(":worldguard-core"))
relocate("org.flywaydb", "com.sk89q.worldguard.internal.flywaydb") {
include(dependency("org.flywaydb:flyway-core:3.0"))
}
exclude("com.google.code.findbugs:jsr305")
}
exclude("GradleStart**")
exclude(".cache")
exclude("LICENSE*")
}
val javaComponent = components["java"] as AdhocComponentWithVariants
javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
skip()
}
}
-10
View File
@@ -1,10 +0,0 @@
object Versions {
// const val PISTON = "0.4.3"
// const val AUTO_VALUE = "1.6.5"
const val WORLDEDIT = "7.3.0"
const val JUNIT = "5.9.1"
const val MOCKITO = "4.9.0"
const val SQUIRRELID = "0.3.2"
const val GUAVA = "31.1-jre"
const val FINDBUGS = "3.0.2"
}
-1
View File
@@ -7,7 +7,6 @@
<allow pkg="javax"/>
<allow pkg="org.junit"/>
<allow pkg="org.hamcrest"/>
<allow pkg="org.mockito"/>
<allow pkg="junit.framework"/>
<allow pkg="com.sk89q"/>
<allow pkg="com.google.common"/>
+3 -1
View File
@@ -1,2 +1,4 @@
group=com.sk89q.worldguard
version=7.0.10
version=7.0.18
org.gradle.parallel=true
+2
View File
@@ -0,0 +1,2 @@
#This file is generated by updateDaemonJvm
toolchainVersion=25
+65
View File
@@ -0,0 +1,65 @@
[versions]
worldedit = "7.4.0"
crankcase = "0.1.0"
# Minimum versions we apply to make dependencies support newer Java
minimumAsm = "9.7"
minimumJdependency = "2.10"
minimumTinyRemapper = "0.8.11"
# lang-version = ""
[libraries]
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"
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"
paperApi = "io.papermc.paper:paper-api:26.1.2.build.+"
paperLib = "io.papermc:paperlib:1.0.8"
dummypermscompat = "com.sk89q:dummypermscompat:1.10"
bstats-bukkit = "org.bstats:bstats-bukkit:3.2.1"
prtree = "org.khelekore:prtree:1.5.0"
flyway-core = "org.flywaydb:flyway-core:3.0"
commandbook = "com.sk89q:commandbook:2.3"
hamcrest-library = "org.hamcrest:hamcrest-library:2.2"
# Mojang-provided libraries, CHECK AGAINST MINECRAFT for versions
guava = "com.google.guava:guava:33.5.0-jre"
log4j-bom = "org.apache.logging.log4j:log4j-bom:2.24.1"
gson = "com.google.code.gson:gson:2.13.2"
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
# may not be the same as the ones in the latest Bukkit API.
snakeyaml = "org.yaml:snakeyaml:2.0"
[libraries.worldedit-core]
module = "com.sk89q.worldedit:worldedit-core"
version.ref = "worldedit"
[libraries.worldedit-bukkit]
module = "com.sk89q.worldedit:worldedit-bukkit"
version.ref = "worldedit"
[libraries.worldedit-libs-ap]
module = "com.sk89q.worldedit.worldedit-libs:ap"
version.ref = "worldedit"
+3 -1
View File
@@ -1,7 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+1 -1
View File
@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
+78 -3
View File
@@ -1,7 +1,82 @@
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 {
maven {
name = "EngineHub"
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 "1.0.0"
id("org.enginehub.crankcase.repo-reconfiguration") version "0.1.0"
}
dependencyResolutionManagement {
repositories {
maven {
name = "PaperMC"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
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/")
}
}
}
logger.lifecycle("""
*******************************************
You are building WorldGuard!
If you encounter trouble:
1) Read COMPILING.md if you haven't yet
2) Try running 'build' in a separate Gradle run
3) Use gradlew and not gradle
4) If you still need help, ask on Discord! https://discord.gg/enginehub
Output files will be in [subproject]/build/libs
*******************************************
""")
rootProject.name = "worldguard"
includeBuild("build-logic")
include("worldguard-libs")
include("worldguard-libs:core")
include("worldguard-core")
//include("worldguard-libs:bukkit")
include("worldguard-bukkit")
listOf("bukkit", "core").forEach {
include("worldguard-$it")
}
+30 -48
View File
@@ -1,74 +1,56 @@
import buildlogic.internalVersion
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
`java-library`
}
applyPlatformAndCoreConfiguration()
applyShadowConfiguration()
repositories {
maven {
name = "paper"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
maven {
// TODO: Remove this once paper updated to adventure release
name = "adventure-snapshots"
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
}
configurations {
compileClasspath.get().extendsFrom(create("shadeOnly"))
id("buildlogic.platform")
}
dependencies {
"api"(project(":worldguard-core"))
"compileOnly"("io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT")
"runtimeOnly"("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") {
"api"(libs.worldedit.bukkit) { isTransitive = false }
"compileOnly"(libs.commandbook) { isTransitive = false }
"compileOnly"(libs.jetbrains.annotations) {
because("Resolving Spigot annotations")
}
"testCompileOnly"(libs.jetbrains.annotations) {
because("Resolving Spigot annotations")
}
"compileOnly"(libs.paperApi) {
exclude("org.slf4j", "slf4j-api")
exclude("junit", "junit")
}
"api"("com.sk89q.worldedit:worldedit-bukkit:${Versions.WORLDEDIT}") { isTransitive = false }
"implementation"("com.google.guava:guava:${Versions.GUAVA}")
"compileOnly"("com.sk89q:commandbook:2.3") { isTransitive = false }
"shadeOnly"("io.papermc:paperlib:1.0.8")
"shadeOnly"("org.bstats:bstats-bukkit:3.0.1")
"implementation"(libs.paperLib)
"implementation"(libs.bstats.bukkit)
}
tasks.named<Copy>("processResources") {
val internalVersion = project.ext["internalVersion"]
val internalVersion = project.internalVersion
inputs.property("internalVersion", internalVersion)
filesMatching("plugin.yml") {
expand("internalVersion" to internalVersion)
}
}
tasks.named<Jar>("jar") {
val projectVersion = project.version
inputs.property("projectVersion", projectVersion)
manifest {
attributes("Implementation-Version" to projectVersion)
expand("internalVersion" to internalVersion.get())
}
}
tasks.named<ShadowJar>("shadowJar") {
configurations = listOf(project.configurations["shadeOnly"], project.configurations["runtimeClasspath"])
dependencies {
include(dependency(":worldguard-core"))
relocate("org.bstats", "com.sk89q.worldguard.bukkit.bstats") {
include(dependency("org.bstats:"))
}
relocate ("io.papermc.lib", "com.sk89q.worldguard.bukkit.paperlib") {
include(dependency("io.papermc:paperlib"))
}
relocate ("co.aikar.timings.lib", "com.sk89q.worldguard.bukkit.timingslib") {
include(dependency("co.aikar:minecraft-timings"))
}
include(dependency("org.bstats:bstats-bukkit"))
include(dependency("org.bstats:bstats-base"))
include(dependency("io.papermc:paperlib"))
relocate("org.bstats", "com.sk89q.worldguard.bukkit.bstats")
relocate("io.papermc.lib", "com.sk89q.worldguard.bukkit.paperlib")
}
}
tasks.named("assemble").configure {
dependsOn("shadowJar")
}
configure<PublishingExtension> {
publications.named<MavenPublication>("maven") {
from(components["java"])
}
}
@@ -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() {
@@ -55,23 +55,6 @@ public class BukkitUtil {
return item.getDurability() & 0x3F;
}
/**
* Get a blacklist target for the given block.
*
* @param block the block
* @param effectiveMaterial The effective material, if different
* @return a target
*/
public static Target createTarget(Block block, Material effectiveMaterial) {
checkNotNull(block);
checkNotNull(block.getType());
if (block.getType() == effectiveMaterial) {
return createTarget(block.getType());
} else {
return createTarget(effectiveMaterial);
}
}
/**
* Get a blacklist target for the given block.
*
@@ -215,6 +215,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
blockEnderDragonPortalCreation = getBoolean("mobs.block-enderdragon-portal-creation", false);
blockFireballExplosions = getBoolean("mobs.block-fireball-explosions", false);
blockFireballBlockDamage = getBoolean("mobs.block-fireball-block-damage", false);
blockWindChargeExplosions = getBoolean("mobs.block-windcharge-explosions", false);
antiWolfDumbness = getBoolean("mobs.anti-wolf-dumbness", false);
allowTamedSpawns = getBoolean("mobs.allow-tamed-spawns", true);
disableEndermanGriefing = getBoolean("mobs.disable-enderman-griefing", false);
@@ -282,8 +283,10 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableSculkGrowth = getBoolean("dynamics.disable-sculk-growth", false);
disableCropGrowth = getBoolean("dynamics.disable-crop-growth", false);
disableSoilDehydration = getBoolean("dynamics.disable-soil-dehydration", false);
disableSoilMoistureChange = getBoolean("dynamics.disable-soil-moisture-change", false);
disableCoralBlockFade = getBoolean("dynamics.disable-coral-block-fade", false);
disableCopperBlockFade = getBoolean("dynamics.disable-copper-block-fade", false);
disableLavaHarden = getBoolean("dynamics.disable-lava-harden", false);
allowedSnowFallOver = new HashSet<>(convertLegacyBlocks(getStringList("dynamics.snow-fall-blocks", null)));
useRegions = getBoolean("regions.enable", true);
@@ -171,9 +171,10 @@ public class BukkitWorldGuardPlatform implements WorldGuardPlatform {
return WorldGuardPlugin.inst().getDataFolder().toPath();
}
@SuppressWarnings("removal")
@Override
public void stackPlayerInventory(LocalPlayer localPlayer) {
boolean ignoreMax = localPlayer.hasPermission("worldguard.stack.illegitimate");
boolean ignoreMax = false; // localPlayer.hasPermission("worldguard.stack.illegitimate");
Player player = ((BukkitPlayer) localPlayer).getPlayer();
@@ -191,7 +192,7 @@ public class BukkitWorldGuardPlatform implements WorldGuardPlatform {
continue;
}
int max = ignoreMax ? 64 : item.getMaxStackSize();
int max = /*ignoreMax ? 64 :*/ item.getMaxStackSize();
if (item.getAmount() < max) {
int needed = max - item.getAmount(); // Number of needed items until max
@@ -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;
@@ -74,6 +76,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 +99,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 +108,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 +142,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 +170,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,12 +220,24 @@ 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);
@@ -264,7 +292,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 +557,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();
}
}
@@ -32,8 +32,10 @@ import org.bukkit.block.Block;
import org.bukkit.entity.AnimalTamer;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Firework;
import org.bukkit.entity.LightningStrike;
import org.bukkit.entity.Player;
@@ -326,15 +328,21 @@ public final class Cause {
addAll(player.getPlayer()); // player object if online, else null
}
}
} else if (o instanceof Creature && ((Creature) o).getTarget() != null) {
} else if (o instanceof Creeper c) {
indirect = true;
addAll(((Creature) o).getTarget());
addAll(c.getTarget(), c.getIgniter());
} else if (o instanceof Creature c) {
indirect = true;
addAll(c.getTarget());
} else if (o instanceof BlockProjectileSource) {
addAll(((BlockProjectileSource) o).getBlock());
} else if (o instanceof LightningStrike && PaperLib.isPaper() &&
((LightningStrike) o).getCausingEntity() != null) {
indirect = true;
addAll(((LightningStrike) o).getCausingEntity());
} else if (o instanceof FallingBlock f && PaperLib.isPaper() && f.getOrigin() != null) {
indirect = true;
addAll(f.getOrigin().getBlock());
}
// Add manually tracked parent causes
@@ -96,7 +96,7 @@ public class BlacklistListener extends AbstractListener {
event.filter(target -> {
if (!wcfg.getBlacklist().check(
new BlockBreakBlacklistEvent(localPlayer, BukkitAdapter.asBlockVector(target),
createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false)) {
createTarget(target.getBlock())), false, false)) {
return false;
} else if (!wcfg.getBlacklist().check(
new ItemDestroyWithBlacklistEvent(localPlayer, BukkitAdapter.asBlockVector(target),
@@ -124,7 +124,7 @@ public class BlacklistListener extends AbstractListener {
final LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
event.filter(target -> wcfg.getBlacklist().check(new BlockPlaceBlacklistEvent(
localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false));
localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock())), false, false));
}
@EventHandler(ignoreCancelled = true)
@@ -143,7 +143,7 @@ public class BlacklistListener extends AbstractListener {
final LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
event.filter(target -> wcfg.getBlacklist().check(new BlockInteractBlacklistEvent(
localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false));
localPlayer, BukkitAdapter.asBlockVector(target), createTarget(target.getBlock())), false, false));
}
@EventHandler(ignoreCancelled = true)
@@ -101,12 +101,14 @@ public class BuildPermissionListener extends AbstractListener {
if (rootCause instanceof Player) {
final Player player = (Player) rootCause;
final Material material = event.getEffectiveMaterial();
if (!hasBuildPermission(player, "block." + material.name().toLowerCase() + ".interact")
&& !hasBuildPermission(player, "block.interact." + material.name().toLowerCase())) {
boolean blocked = event.filter(loc -> {
String blacklistName = loc.getBlock().getType().name().toLowerCase();
return hasBuildPermission(player, "block." + blacklistName + ".interact") ||
hasBuildPermission(player, "block.interact." + blacklistName);
}, true);
if (blocked && !event.isSilent()) {
tellErrorMessage(player, event.getWorld());
event.setCancelled(true);
}
}
}
@@ -44,12 +44,15 @@ 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;
import io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent;
import io.papermc.paper.event.player.PlayerOpenSignEvent;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.ExplosionResult;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -66,11 +69,14 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Dispenser;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.BreezeWindCharge;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Firework;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
@@ -79,6 +85,7 @@ import org.bukkit.entity.Painting;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.minecart.HopperMinecart;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
@@ -112,14 +119,18 @@ import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityInteractEvent;
import org.bukkit.event.entity.EntityKnockbackByEntityEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.EntityTameEvent;
import org.bukkit.event.entity.EntityUnleashEvent;
import org.bukkit.event.entity.ExpBottleEvent;
import org.bukkit.event.entity.LingeringPotionSplashEvent;
import org.bukkit.event.entity.PlayerLeashEntityEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
@@ -152,6 +163,8 @@ import org.bukkit.util.Vector;
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 {
@@ -176,9 +189,11 @@ public class EventAbstractionListener extends AbstractListener {
public void registerEvents() {
super.registerEvents();
PluginManager pm = getPlugin().getServer().getPluginManager();
if (PaperLib.isPaper()) {
PluginManager pm = getPlugin().getServer().getPluginManager();
pm.registerEvents(new EventAbstractionListener.PaperListener(), getPlugin());
} else {
pm.registerEvents(new EventAbstractionListener.SpigotListener(), getPlugin());
}
}
@@ -196,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(),
@@ -218,8 +246,8 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireToCancel(event, new BreakBlockEvent(event, create(event.getPlayer()), previousState.getLocation(), previousState.getType()));
}
if (!event.isCancelled()) {
ItemStack itemStack = new ItemStack(event.getBlockPlaced().getType(), 1);
ItemStack itemStack = event.getItemInHand();
if (!event.isCancelled() && itemStack.getType() != Material.AIR) {
Events.fireToCancel(event, new UseItemEvent(event, create(event.getPlayer()), event.getPlayer().getWorld(), itemStack));
}
@@ -323,10 +351,10 @@ public class EventAbstractionListener extends AbstractListener {
// Fire two events: one as BREAK and one as PLACE
if (toType != Material.AIR && fromType != Material.AIR) {
BreakBlockEvent breakDelagate = new BreakBlockEvent(event, cause, block);
setDelegateEventMaterialOptions(breakDelagate, fromType, toType);
BreakBlockEvent breakDelegate = new BreakBlockEvent(event, cause, block);
setDelegateEventMaterialOptions(breakDelegate, fromType, toType);
boolean denied;
if (!(denied = Events.fireToCancel(event, breakDelagate))) {
if (!(denied = Events.fireToCancel(event, breakDelegate))) {
PlaceBlockEvent placeDelegate = new PlaceBlockEvent(event, cause, block.getLocation(), toType);
setDelegateEventMaterialOptions(placeDelegate, fromType, toType);
denied = Events.fireToCancel(event, placeDelegate);
@@ -339,7 +367,10 @@ public class EventAbstractionListener extends AbstractListener {
} else if (toType == Material.AIR) {
// Track the source so later we can create a proper chain of causes
if (entity instanceof FallingBlock) {
Cause.trackParentCause(entity, block);
if (!PaperLib.isPaper()) {
// On paper we use FallingBlock#getOrigin to get the origin location, on spigot we store it.
Cause.trackParentCause(entity, block);
}
// Switch around the event
Events.fireToCancel(event, new SpawnEntityEvent(event, create(block), entity));
@@ -354,10 +385,29 @@ public class EventAbstractionListener extends AbstractListener {
}
private static <T extends EntityEvent & Cancellable> void handleKnockback(T event, Entity damager) {
final DamageEntityEvent eventToFire = new DamageEntityEvent(event, create(damager), event.getEntity());
if (damager instanceof BreezeWindCharge) {
eventToFire.getRelevantFlags().add(Flags.BREEZE_WIND_CHARGE);
} else if (damager instanceof WindCharge) {
eventToFire.getRelevantFlags().add(Flags.WIND_CHARGE_BURST);
}
Events.fireToCancel(event, eventToFire);
}
@SuppressWarnings("UnstableApiUsage")
@EventHandler(ignoreCancelled = true)
public void onEntityExplode(EntityExplodeEvent event) {
Entity entity = event.getEntity();
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR));
if (event.getExplosionResult() == ExplosionResult.TRIGGER_BLOCK) {
UseBlockEvent useEvent = new UseBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR);
useEvent.getRelevantFlags().add(Entities.getExplosionFlag(entity));
useEvent.setSilent(true);
Events.fireBulkEventToCancel(event, useEvent);
} else if (event.getExplosionResult() == ExplosionResult.DESTROY || event.getExplosionResult() == ExplosionResult.DESTROY_WITH_DECAY) {
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR));
}
if (entity instanceof Creeper) {
Cause.untrackParentCause(entity);
}
@@ -576,7 +626,7 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onBlockFertilize(BlockFertilizeEvent event) {
if (event.getBlocks().isEmpty()) return;
if (event.getBlocks().isEmpty()) return;
Cause cause = create(event.getPlayer(), event.getBlock());
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getWorld(), event.getBlocks()));
}
@@ -742,7 +792,7 @@ public class EventAbstractionListener extends AbstractListener {
if (event.isCancelled() && remover instanceof Player) {
playDenyEffect((Player) remover, event.getEntity().getLocation());
}
} else if (event.getCause() == HangingBreakEvent.RemoveCause.EXPLOSION){
} else if (event.getCause() == HangingBreakEvent.RemoveCause.EXPLOSION) {
DestroyEntityEvent destroyEntityEvent = new DestroyEntityEvent(event, Cause.unknown(), event.getEntity());
destroyEntityEvent.getRelevantFlags().add(Flags.OTHER_EXPLOSION);
if (event.getEntity() instanceof ItemFrame) {
@@ -772,7 +822,8 @@ public class EventAbstractionListener extends AbstractListener {
public void onPlayerFish(PlayerFishEvent event) {
if (event.getState() == PlayerFishEvent.State.FISHING) {
if (Events.fireAndTestCancel(new UseItemEvent(event, create(event.getPlayer(), event.getHook()),
event.getPlayer().getWorld(), event.getPlayer().getInventory().getItemInMainHand()))) {
event.getPlayer().getWorld(),
event.getPlayer().getInventory().getItem(Objects.requireNonNull(event.getHand()))))) {
event.setCancelled(true);
}
} else if (event.getState() == PlayerFishEvent.State.CAUGHT_FISH) {
@@ -786,12 +837,19 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireToCancel(event, new DestroyEntityEvent(event, create(event.getPlayer(), event.getHook()), caught));
} else if (Entities.isConsideredBuildingIfUsed(caught)) {
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getPlayer(), event.getHook()), caught));
} else if (Entities.isNonHostile(caught) || caught instanceof Player) {
} else if (!Entities.isHostile(caught) || caught instanceof Player) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(event.getPlayer(), event.getHook()), caught));
}
}
}
@EventHandler(ignoreCancelled = true)
public void onProjectileHit(ProjectileHitEvent event) {
if (event.getEntity() instanceof FishHook hook && event.getHitEntity() instanceof Entity target) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(hook), target));
}
}
@EventHandler(ignoreCancelled = true)
public void onExpBottle(ExpBottleEvent event) {
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getEntity()), event.getEntity().getLocation(), EntityType.EXPERIENCE_ORB))) {
@@ -837,12 +895,7 @@ public class EventAbstractionListener extends AbstractListener {
if (matchingItem != null && hasInteractBypass(world, matchingItem)) {
useEntityEvent.setAllowed(true);
}
if (!Events.fireToCancel(event, useEntityEvent)) {
// so this is a hack but CreeperIgniteEvent doesn't actually tell us who, so we need to do it here
if (item.getType() == Material.FLINT_AND_STEEL && entity.getType() == EntityType.CREEPER) {
Cause.trackParentCause(entity, player);
}
}
Events.fireToCancel(event, useEntityEvent);
}
@EventHandler(ignoreCancelled = true)
@@ -887,19 +940,34 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityCombust(EntityCombustEvent event) {
if (event instanceof EntityCombustByBlockEvent) {
if (event instanceof EntityCombustByBlockEvent combustByBlockEvent) {
// at the time of writing, spigot is throwing null for the event's combuster. this causes lots of issues downstream.
// whenever (i mean if ever) it is fixed, use getCombuster again instead of the current block
Events.fireToCancel(event, new DamageEntityEvent(event, create(event.getEntity().getLocation().getBlock()), event.getEntity()));
Block combuster = combustByBlockEvent.getCombuster();
Events.fireToCancel(event, new DamageEntityEvent(event,
create(combuster == null ? event.getEntity().getLocation().getBlock() : combuster), event.getEntity()));
} else if (event instanceof EntityCombustByEntityEvent) {
if (event.getEntity() instanceof Arrow) {
// this only happens from the Flame enchant. igniting arrows in other ways (eg with lava) doesn't even
// throw the combust event, not even the CombustByBlock event... they're also very buggy and don't even
// show as lit on the client consistently
return;
}
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityCombustByEntityEvent) event).getCombuster()), event.getEntity()));
}
}
@EventHandler(ignoreCancelled = true)
public void onEntityLeash(PlayerLeashEntityEvent event) {
UseEntityEvent useEntityEvent = new UseEntityEvent(event, create(event.getPlayer()), event.getEntity());
useEntityEvent.getRelevantFlags().add(Flags.RIDE);
useEntityEvent.getRelevantFlags().add(Flags.INTERACT);
Events.fireToCancel(event, useEntityEvent);
}
@EventHandler(ignoreCancelled = true)
public void onEntityUnleash(EntityUnleashEvent event) {
if (event instanceof PlayerUnleashEntityEvent) {
PlayerUnleashEntityEvent playerEvent = (PlayerUnleashEntityEvent) event;
if (event instanceof PlayerUnleashEntityEvent playerEvent) {
Events.fireToCancel(playerEvent, new UseEntityEvent(playerEvent, create(playerEvent.getPlayer()), event.getEntity()));
}
}
@@ -948,15 +1016,16 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onInventoryOpen(InventoryOpenEvent event) {
InventoryHolder holder = event.getInventory().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
@@ -970,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;
@@ -987,11 +1056,23 @@ public class EventAbstractionListener extends AbstractListener {
handleInventoryHolderUse(event, cause, sourceHolder);
}
handleInventoryHolderUse(event, cause, targetHolder);
if (causeHolder != null && !causeHolder.equals(targetHolder)) {
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());
}
@@ -1007,7 +1088,6 @@ public class EventAbstractionListener extends AbstractListener {
// Fire item interaction event
Events.fireToCancel(event, new UseItemEvent(event, cause, world, potion.getItem()));
// Fire entity interaction event
if (!event.isCancelled()) {
int blocked = 0;
@@ -1019,8 +1099,11 @@ public class EventAbstractionListener extends AbstractListener {
? new DamageEntityEvent(event, cause, affected) :
new UseEntityEvent(event, cause, affected);
// Consider the potion splash flag
// Consider extra relevant flags
delegate.getRelevantFlags().add(Flags.POTION_SPLASH);
if (potion.getShooter() instanceof LivingEntity shooter && !(shooter instanceof Player) && affected instanceof Player) {
delegate.getRelevantFlags().add(Flags.MOB_DAMAGE);
}
if (Events.fireAndTestCancel(delegate)) {
event.setIntensity(affected, 0);
@@ -1102,7 +1185,7 @@ public class EventAbstractionListener extends AbstractListener {
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event){
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
onPlayerInteractEntity(event);
}
@@ -1161,7 +1244,7 @@ public class EventAbstractionListener extends AbstractListener {
// Handle created boats
if (item != null && Materials.isBoat(item.getType())) {
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.BOAT));
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), Materials.getRelatedEntity(item.getType())));
return;
}
@@ -1213,9 +1296,9 @@ public class EventAbstractionListener extends AbstractListener {
useBlockEvent.setAllowed(true);
}
Events.fireToCancel(originalEvent, useBlockEvent);
} else if (holder instanceof DoubleChest) {
InventoryHolder left = ((DoubleChest) holder).getLeftSide();
InventoryHolder right = ((DoubleChest) holder).getRightSide();
} else if (holder instanceof DoubleChest doubleChest) {
InventoryHolder left = PaperLib.isPaper() ? doubleChest.getLeftSide(false) : doubleChest.getLeftSide();
InventoryHolder right = PaperLib.isPaper() ? doubleChest.getRightSide(false) : doubleChest.getRightSide();
if (left instanceof Chest) {
Events.fireToCancel(originalEvent, new UseBlockEvent(originalEvent, cause, ((Chest) left).getBlock()));
}
@@ -1261,7 +1344,7 @@ public class EventAbstractionListener extends AbstractListener {
}
}
private class PaperListener implements Listener {
private static class PaperListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onEntityTransform(EntityZapEvent event) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(event.getBolt()), event.getEntity()));
@@ -1274,5 +1357,18 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), event.getSign().getBlock()));
}
}
@EventHandler(ignoreCancelled = true)
public void onEntityKnockbackByEntity(EntityPushedByEntityAttackEvent event) {
handleKnockback(event, event.getPushedBy());
}
}
@SuppressWarnings("removal")
private static class SpigotListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onEntityKnockbackByEntity(EntityKnockbackByEntityEvent event) {
handleKnockback(event, event.getSourceEntity());
}
}
}
@@ -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();
@@ -61,6 +61,10 @@ import org.bukkit.entity.Tameable;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityMountEvent;
import org.bukkit.event.entity.PlayerLeashEntityEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerTakeLecternBookEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
@@ -244,13 +248,13 @@ public class RegionProtectionListener extends AbstractListener {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
final Material type = event.getEffectiveMaterial();
final RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
final RegionAssociable associable = createRegionAssociable(event.getCause());
event.filter((Predicate<Location>) target -> {
boolean canUse;
String what;
final Material type = target.getBlock().getType();
/* Saplings, etc. */
if (Materials.isConsideredBuildingIfUsed(type)) {
@@ -406,17 +410,19 @@ 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. */
} else if (Entities.isConsideredBuildingIfUsed(entity)) {
} else if (Entities.isConsideredBuildingIfUsed(entity)
// weird case since sneak+interact is chest access and not ride
|| event.getOriginalEvent() instanceof InventoryOpenEvent) {
if ((type == EntityType.ITEM_FRAME || type == EntityType.GLOW_ITEM_FRAME)
&& event.getCause().getFirstPlayer() != null
&& ((ItemFrame) entity).getItem().getType() != Material.AIR) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.ITEM_FRAME_ROTATE));
what = "change that";
} else if (Entities.isMinecart(type)) {
} else if (event.getOriginalEvent() instanceof InventoryOpenEvent || event.getOriginalEvent() instanceof InventoryMoveItemEvent) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.CHEST_ACCESS));
what = "open that";
} else {
@@ -425,9 +431,15 @@ public class RegionProtectionListener extends AbstractListener {
}
/* Ridden on use */
} else if (Entities.isRiddenOnUse(entity)) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.RIDE, Flags.INTERACT));
what = "ride that";
if (event.getOriginalEvent() instanceof PlayerLeashEntityEvent) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event));
what = "use that";
} else {
// this is bypassed here as it's handled by the entity mount listener below
// bukkit actually gives three events in this case - in order: PlayerInteractAtEntity, VehicleEnter, EntityMount
canUse = true;
what = "ride that";
}
/* Everything else */
} else {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.INTERACT));
@@ -463,11 +475,12 @@ public class RegionProtectionListener extends AbstractListener {
}
/* Hostile / ambient mob override */
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())
|| Entities.isVehicle(event.getEntity().getType())) {
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())) {
canDamage = event.getRelevantFlags().isEmpty() || query.queryState(target, associable, combine(event)) != State.DENY;
what = "hit that";
} else if (Entities.isVehicle(event.getEntity().getType())) {
canDamage = query.testBuild(target, associable, combine(event, Flags.DESTROY_VEHICLE));
what = "change that";
/* Paintings, item frames, etc. */
} else if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
canDamage = query.testBuild(target, associable, combine(event));
@@ -516,6 +529,27 @@ public class RegionProtectionListener extends AbstractListener {
}
}
@EventHandler
public void onEntityMount(EntityMountEvent event) {
Entity vehicle = event.getMount();
if (!isRegionSupportEnabled(vehicle.getWorld())) return; // Region support disabled
if (!(event.getEntity() instanceof Player player)) {
return;
}
Cause cause = Cause.create(player);
if (isWhitelisted(cause, vehicle.getWorld(), false)) {
return;
}
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
Location location = vehicle.getLocation();
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (!query.testBuild(BukkitAdapter.adapt(location), localPlayer, Flags.RIDE, Flags.INTERACT)) {
event.setCancelled(true);
DelegateEvent dummy = new UseEntityEvent(event, cause, vehicle);
tellErrorMessage(dummy, cause, vehicle.getLocation(), "ride that");
}
}
@EventHandler(ignoreCancelled = true)
public void onVehicleExit(VehicleExitEvent event) {
Entity vehicle = event.getVehicle();
@@ -56,6 +56,7 @@ import org.bukkit.event.block.BlockRedstoneEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.block.MoistureChangeEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
@@ -477,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) {
@@ -489,7 +491,7 @@ public class WorldGuardBlockListener extends AbstractListener {
return;
}
if (type == Material.ICE) {
if (newType == Material.ICE) {
if (wcfg.disableIceFormation) {
event.setCancelled(true);
return;
@@ -501,7 +503,7 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
if (type == Material.SNOW) {
if (newType == Material.SNOW) {
if (wcfg.disableSnowFormation) {
event.setCancelled(true);
return;
@@ -521,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;
@@ -532,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;
}
}
}
/*
@@ -726,4 +741,24 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
/**
* Called when the moisture level of a block changes
*/
@EventHandler(ignoreCancelled = true)
public void onMoistureChange(MoistureChangeEvent event) {
WorldConfiguration wcfg = getWorldConfig(event.getBlock().getWorld());
if (wcfg.disableSoilMoistureChange) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions) {
if (!StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.queryState(BukkitAdapter.adapt(event.getBlock().getLocation()), (RegionAssociable) null, Flags.MOISTURE_CHANGE))) {
event.setCancelled(true);
}
}
}
}
@@ -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,11 +40,13 @@ 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;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.AbstractWindCharge;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderCrystal;
@@ -60,12 +63,15 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.Wither;
import org.bukkit.entity.WitherSkull;
import org.bukkit.entity.Wolf;
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;
@@ -88,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;
@@ -106,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();
@@ -311,13 +330,17 @@ public class WorldGuardEntityListener extends AbstractListener {
return;
}
}
if (event.getDamager() instanceof Fireball) {
Fireball fireball = (Fireball) event.getDamager();
if (event.getDamager() instanceof Fireball fireball) {
if (fireball instanceof WitherSkull) {
if (wcfg.blockWitherSkullExplosions) {
event.setCancelled(true);
return;
}
} else if (fireball instanceof AbstractWindCharge) {
if (wcfg.blockWindChargeExplosions) {
event.setCancelled(true);
return;
}
} else {
if (wcfg.blockFireballExplosions) {
event.setCancelled(true);
@@ -326,7 +349,7 @@ public class WorldGuardEntityListener extends AbstractListener {
}
if (wcfg.useRegions) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
if (!query.testState(localPlayer.getLocation(), localPlayer, Flags.GHAST_FIREBALL) && wcfg.explosionFlagCancellation) {
if (!query.testState(localPlayer.getLocation(), localPlayer, Entities.getExplosionFlag(event.getDamager())) && wcfg.explosionFlagCancellation) {
event.setCancelled(true);
return;
}
@@ -483,6 +506,11 @@ public class WorldGuardEntityListener extends AbstractListener {
event.blockList().clear();
return;
}
} else if (ent instanceof AbstractWindCharge) {
if (wcfg.blockWindChargeExplosions) {
event.setCancelled(true);
return;
}
} else {
if (wcfg.blockFireballExplosions) {
event.setCancelled(true);
@@ -493,10 +521,10 @@ public class WorldGuardEntityListener extends AbstractListener {
return;
}
}
// allow wither skull blocking since there is no dedicated flag atm
if (wcfg.useRegions) {
if (wcfg.useRegions && !(ent instanceof WindCharge)) {
for (Block block : event.blockList()) {
if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation())).testState(null, Flags.GHAST_FIREBALL)) {
if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.testState(BukkitAdapter.adapt(block.getLocation()), null, Entities.getExplosionFlag(ent))) {
event.blockList().clear();
if (wcfg.explosionFlagCancellation) event.setCancelled(true);
return;
@@ -514,8 +542,8 @@ public class WorldGuardEntityListener extends AbstractListener {
}
if (wcfg.useRegions) {
for (Block block : event.blockList()) {
if (!StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().queryState(BukkitAdapter.adapt(block.getLocation()),
(RegionAssociable) null, Flags.WITHER_DAMAGE))) {
if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.testState(BukkitAdapter.adapt(block.getLocation()), null, Flags.WITHER_DAMAGE)) {
event.blockList().clear();
event.setCancelled(true);
return;
@@ -530,7 +558,8 @@ public class WorldGuardEntityListener extends AbstractListener {
}
if (wcfg.useRegions) {
for (Block block : event.blockList()) {
if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation())).testState(null, Flags.OTHER_EXPLOSION)) {
if (!WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.testState(BukkitAdapter.adapt(block.getLocation()), null, Flags.OTHER_EXPLOSION)) {
event.blockList().clear();
if (wcfg.explosionFlagCancellation) event.setCancelled(true);
return;
@@ -539,7 +568,6 @@ public class WorldGuardEntityListener extends AbstractListener {
}
}
if (wcfg.signChestProtection) {
for (Block block : event.blockList()) {
if (wcfg.isChestProtected(BukkitAdapter.adapt(block.getLocation()))) {
@@ -592,6 +620,11 @@ public class WorldGuardEntityListener extends AbstractListener {
event.setCancelled(true);
return;
}
} else if (event.getEntity() instanceof AbstractWindCharge) {
if (wcfg.blockWindChargeExplosions) {
event.setCancelled(true);
return;
}
}
}
@@ -725,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) {
@@ -773,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);
@@ -867,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);
}
}
}
@@ -350,6 +350,11 @@ public class WorldGuardPlayerListener extends AbstractListener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
if (event.getTo() == null) {
// The target location for PlayerTeleportEvents can be null.
// Those events will be ignored by the server, so we can ignore them too.
return;
}
Player player = event.getPlayer();
if (com.sk89q.worldguard.bukkit.util.Entities.isNPC(player)) return;
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
@@ -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();
@@ -19,35 +19,41 @@
package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import org.bukkit.entity.Allay;
import org.bukkit.entity.Ambient;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.BreezeWindCharge;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Enemy;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Flying;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.Firework;
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;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.Wither;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.projectiles.ProjectileSource;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class Entities {
@@ -113,8 +119,11 @@ public final class Entities {
* @return true if the type is a Boat type
*/
public static boolean isBoat(EntityType type) {
return switch(type) {
case BOAT, CHEST_BOAT -> true;
return switch (type) {
case OAK_BOAT, DARK_OAK_BOAT, SPRUCE_BOAT, ACACIA_BOAT, CHERRY_BOAT, JUNGLE_BOAT, MANGROVE_BOAT,
BIRCH_BOAT, PALE_OAK_BOAT, BAMBOO_RAFT, OAK_CHEST_BOAT, DARK_OAK_CHEST_BOAT, SPRUCE_CHEST_BOAT,
ACACIA_CHEST_BOAT, CHERRY_CHEST_BOAT, JUNGLE_CHEST_BOAT, MANGROVE_CHEST_BOAT, BIRCH_CHEST_BOAT,
PALE_OAK_CHEST_BOAT, BAMBOO_CHEST_RAFT -> true;
default -> false;
};
}
@@ -161,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;
}
/**
@@ -237,7 +242,7 @@ public final class Entities {
* This is true for custom creations or the summon command.
*
* @param spawnReason the reason
* @return true if considerd plugin spawning
* @return true if considered plugin spawning
*/
public static boolean isPluginSpawning(CreatureSpawnEvent.SpawnReason spawnReason) {
return switch (spawnReason) {
@@ -245,4 +250,24 @@ public final class Entities {
default -> false;
};
}
/**
* Get the explosion flag relevant for an entity type.
* @param entity the entity
* @return the relevant StateFlag or OTHER_EXPLOSION if none is matching
*/
public static @Nonnull StateFlag getExplosionFlag(Entity entity) {
return switch (entity) {
case BreezeWindCharge breezeWindCharge -> Flags.BREEZE_WIND_CHARGE;
case WindCharge windCharge -> Flags.WIND_CHARGE_BURST;
case Firework firework -> Flags.FIREWORK_DAMAGE;
case Fireball fireball -> Flags.GHAST_FIREBALL;
case Wither wither -> Flags.WITHER_DAMAGE;
case Creeper creeper -> Flags.CREEPER_EXPLOSION;
case TNTPrimed tnt -> Flags.TNT;
case ExplosiveMinecart minecart -> Flags.TNT;
case EnderDragon dragon -> Flags.ENDERDRAGON_BLOCK_DAMAGE;
case null, default -> Flags.OTHER_EXPLOSION;
};
}
}
@@ -23,6 +23,7 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.sk89q.worldguard.protection.flags.Flags;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.Tag;
import org.bukkit.entity.EntityType;
import org.bukkit.potion.PotionEffect;
@@ -69,17 +70,30 @@ public final class Materials {
ENTITY_ITEMS.put(EntityType.TNT, Material.TNT);
ENTITY_ITEMS.put(EntityType.FIREWORK_ROCKET, Material.FIREWORK_ROCKET);
ENTITY_ITEMS.put(EntityType.COMMAND_BLOCK_MINECART, Material.COMMAND_BLOCK_MINECART);
ENTITY_ITEMS.put(EntityType.BOAT, Material.OAK_BOAT);
ENTITY_ITEMS.put(EntityType.MINECART, Material.MINECART);
ENTITY_ITEMS.put(EntityType.CHEST_MINECART, Material.CHEST_MINECART);
ENTITY_ITEMS.put(EntityType.FURNACE_MINECART, Material.FURNACE_MINECART);
ENTITY_ITEMS.put(EntityType.TNT_MINECART, Material.TNT_MINECART);
ENTITY_ITEMS.put(EntityType.HOPPER_MINECART, Material.HOPPER_MINECART);
ENTITY_ITEMS.put(EntityType.POTION, Material.POTION);
ENTITY_ITEMS.put(EntityType.SPLASH_POTION, Material.SPLASH_POTION);
ENTITY_ITEMS.put(EntityType.LINGERING_POTION, Material.LINGERING_POTION);
ENTITY_ITEMS.put(EntityType.EGG, Material.EGG);
ENTITY_ITEMS.put(EntityType.ARMOR_STAND, Material.ARMOR_STAND);
ENTITY_ITEMS.put(EntityType.END_CRYSTAL, Material.END_CRYSTAL);
for (String wood : new String[]{"OAK", "SPRUCE", "BIRCH", "JUNGLE", "ACACIA", "DARK_OAK", "MANGROVE", "CHERRY", "PALE_OAK"}) {
String regular = wood + "_BOAT";
String chest = wood + "_CHEST_BOAT";
ENTITY_ITEMS.put(EntityType.valueOf(regular), Material.getMaterial(regular));
ENTITY_ITEMS.put(EntityType.valueOf(chest), Material.getMaterial(chest));
}
ENTITY_ITEMS.put(EntityType.BAMBOO_RAFT, Material.BAMBOO_RAFT);
ENTITY_ITEMS.put(EntityType.BAMBOO_CHEST_RAFT, Material.BAMBOO_CHEST_RAFT);
// preset some tags to a default value, override some of them:
putMaterialTag(Tag.DOORS, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.TRAPDOORS, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.AIR, 0);
MATERIAL_FLAGS.put(Material.STONE, 0);
MATERIAL_FLAGS.put(Material.GRASS_BLOCK, 0);
@@ -150,12 +164,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.CAKE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REPEATER, MODIFIED_ON_RIGHT);
// MATERIAL_FLAGS.put(Material.STAINED_GLASS, 0);
MATERIAL_FLAGS.put(Material.ACACIA_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BIRCH_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DARK_OAK_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.JUNGLE_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.OAK_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SPRUCE_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.INFESTED_STONE, 0);
MATERIAL_FLAGS.put(Material.INFESTED_STONE_BRICKS, 0);
MATERIAL_FLAGS.put(Material.INFESTED_MOSSY_STONE_BRICKS, 0);
@@ -168,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);
@@ -227,11 +234,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.IRON_TRAPDOOR, 0);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE, 0);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE_STAIRS, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BIRCH_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.JUNGLE_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.ACACIA_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DARK_OAK_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DIRT_PATH, 0);
MATERIAL_FLAGS.put(Material.CHORUS_PLANT, 0);
@@ -247,7 +249,7 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.PURPUR_SLAB, 0);
MATERIAL_FLAGS.put(Material.STRUCTURE_BLOCK, MODIFIED_ON_LEFT | MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REPEATING_COMMAND_BLOCK, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CHAIN_COMMAND_BLOCK , MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CHAIN_COMMAND_BLOCK, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.MAGMA_BLOCK, 0);
MATERIAL_FLAGS.put(Material.NETHER_WART_BLOCK, 0);
@@ -410,7 +412,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);
@@ -669,7 +670,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);
@@ -677,7 +677,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.CRIMSON_FUNGUS, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_NYLIUM, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_ROOTS, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CRYING_OBSIDIAN, 0);
MATERIAL_FLAGS.put(Material.GILDED_BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.LODESTONE, 0);
@@ -706,7 +705,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);
@@ -718,7 +716,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.WARPED_FUNGUS_ON_A_STICK, 0);
MATERIAL_FLAGS.put(Material.WARPED_NYLIUM, 0);
MATERIAL_FLAGS.put(Material.WARPED_ROOTS, 0);
MATERIAL_FLAGS.put(Material.WARPED_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.WARPED_WART_BLOCK, 0);
MATERIAL_FLAGS.put(Material.WEEPING_VINES, 0);
MATERIAL_FLAGS.put(Material.WEEPING_VINES_PLANT, 0);
@@ -772,7 +769,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);
@@ -838,16 +834,54 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.PITCHER_CROP, 0);
MATERIAL_FLAGS.put(Material.PINK_PETALS, 0);
MATERIAL_FLAGS.put(Material.PITCHER_POD, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_UPGRADE_SMITHING_TEMPLATE, 0);
MATERIAL_FLAGS.put(Material.ARMADILLO_SCUTE, 0);
MATERIAL_FLAGS.put(Material.WOLF_ARMOR, 0);
// Generated via tag
putMaterialTag(Tag.WOODEN_DOORS, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.WOODEN_TRAPDOORS, MODIFIED_ON_RIGHT);
// 1.21
MATERIAL_FLAGS.put(Material.CHISELED_TUFF, 0);
MATERIAL_FLAGS.put(Material.POLISHED_TUFF, 0);
MATERIAL_FLAGS.put(Material.TUFF_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_TUFF_BRICKS, 0);
MATERIAL_FLAGS.put(Material.HEAVY_CORE, 0);
MATERIAL_FLAGS.put(Material.CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.EXPOSED_CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.WEATHERED_CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.OXIDIZED_CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.WAXED_CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.WAXED_EXPOSED_CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.WAXED_WEATHERED_CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.WAXED_OXIDIZED_CHISELED_COPPER, 0);
MATERIAL_FLAGS.put(Material.CRAFTER, 0);
MATERIAL_FLAGS.put(Material.FLOW_BANNER_PATTERN, 0);
MATERIAL_FLAGS.put(Material.GUSTER_BANNER_PATTERN, 0);
MATERIAL_FLAGS.put(Material.COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.WEATHERED_COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.EXPOSED_COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.OXIDIZED_COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.WAXED_COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.WAXED_WEATHERED_COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.WAXED_EXPOSED_COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.WAXED_OXIDIZED_COPPER_GRATE, 0);
MATERIAL_FLAGS.put(Material.COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.WEATHERED_COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.EXPOSED_COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.OXIDIZED_COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.WAXED_COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.WAXED_WEATHERED_COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.WAXED_EXPOSED_COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.WAXED_OXIDIZED_COPPER_BULB, 0);
MATERIAL_FLAGS.put(Material.TRIAL_SPAWNER, 0);
MATERIAL_FLAGS.put(Material.TRIAL_KEY, 0);
MATERIAL_FLAGS.put(Material.OMINOUS_TRIAL_KEY, 0);
MATERIAL_FLAGS.put(Material.VAULT, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.OMINOUS_BOTTLE, 0);
MATERIAL_FLAGS.put(Material.BREEZE_ROD, 0);
MATERIAL_FLAGS.put(Material.WIND_CHARGE, 0);
putMaterialTag(Tag.SHULKER_BOXES, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.ITEMS_BOATS, 0);
putMaterialTag(Tag.ITEMS_CHEST_BOATS, 0);
putMaterialTag(Tag.BANNERS, 0);
putMaterialTag(Tag.SLABS, 0);
putMaterialTag(Tag.PLANKS, 0);
@@ -864,7 +898,6 @@ public final class Materials {
putMaterialTag(Tag.ALL_SIGNS, 0);
putMaterialTag(Tag.SMALL_FLOWERS, 0);
putMaterialTag(Tag.BEDS, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.ITEMS_MUSIC_DISCS, 0);
putMaterialTag(Tag.ITEMS_BANNERS, 0);
putMaterialTag(Tag.FENCE_GATES, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.FENCES, 0);
@@ -882,9 +915,74 @@ public final class Materials {
putMaterialTag(Tag.CAULDRONS, MODIFIED_ON_RIGHT);
// 1.20
putMaterialTag(Tag.ITEMS_TRIM_TEMPLATES, 0);
putMaterialTag(Tag.ITEMS_DECORATED_POT_SHERDS, 0);
// 1.21(.4)
putMaterialTag(Tag.ITEMS_BUNDLES, 0);
MATERIAL_FLAGS.put(Material.FIELD_MASONED_BANNER_PATTERN, 0);
MATERIAL_FLAGS.put(Material.BORDURE_INDENTED_BANNER_PATTERN, 0);
MATERIAL_FLAGS.put(Material.PALE_MOSS_CARPET, 0);
MATERIAL_FLAGS.put(Material.PALE_HANGING_MOSS, 0);
MATERIAL_FLAGS.put(Material.PALE_MOSS_BLOCK, 0);
MATERIAL_FLAGS.put(Material.CREAKING_HEART, 0);
MATERIAL_FLAGS.put(Material.RESIN_CLUMP, 0);
MATERIAL_FLAGS.put(Material.RESIN_BLOCK, 0);
MATERIAL_FLAGS.put(Material.RESIN_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_RESIN_BRICKS, 0);
MATERIAL_FLAGS.put(Material.MACE, 0);
MATERIAL_FLAGS.put(Material.RESIN_BRICK, 0);
// 1.21.5
MATERIAL_FLAGS.put(Material.BUSH, 0);
MATERIAL_FLAGS.put(Material.CACTUS_FLOWER, 0);
MATERIAL_FLAGS.put(Material.FIREFLY_BUSH, 0);
MATERIAL_FLAGS.put(Material.LEAF_LITTER, 0);
MATERIAL_FLAGS.put(Material.SHORT_DRY_GRASS, 0);
MATERIAL_FLAGS.put(Material.TALL_DRY_GRASS, 0);
MATERIAL_FLAGS.put(Material.WILDFLOWERS, 0);
MATERIAL_FLAGS.put(Material.TEST_BLOCK, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.TEST_INSTANCE_BLOCK, MODIFIED_ON_RIGHT);
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);
Stream.concat(Stream.concat(
Tag.CORAL_BLOCKS.getValues().stream(),
Tag.CORALS.getValues().stream()),
@@ -897,28 +995,33 @@ public final class Materials {
});
// Check for missing items/blocks
for (Material material : Material.values()) {
if (material.isLegacy()) continue;
Registry.MATERIAL.stream().forEach(material -> {
// Add spawn eggs
if (isSpawnEgg(material)) {
MATERIAL_FLAGS.put(material, 0);
}
if (material.name().startsWith("MUSIC_DISC_")) {
MATERIAL_FLAGS.put(material, 0);
}
if (material.name().endsWith("_SMITHING_TEMPLATE")) {
MATERIAL_FLAGS.put(material, 0);
}
if (!MATERIAL_FLAGS.containsKey(material)) {
logger.fine("Missing material definition for " + (material.isBlock() ? "block " : "item ") + material.name());
}
}
});
// DAMAGE_EFFECTS.add(PotionEffectType.SPEED);
DAMAGE_EFFECTS.add(PotionEffectType.SLOWNESS);
// DAMAGE_EFFECTS.add(PotionEffectType.FAST_DIGGING);
// DAMAGE_EFFECTS.add(PotionEffectType.HASTE);
DAMAGE_EFFECTS.add(PotionEffectType.MINING_FATIGUE);
// DAMAGE_EFFECTS.add(PotionEffectType.INCREASE_DAMAGE);
// DAMAGE_EFFECTS.add(PotionEffectType.HEAL);
// DAMAGE_EFFECTS.add(PotionEffectType.STRENGTH);
// DAMAGE_EFFECTS.add(PotionEffectType.INSTANT_HEALTH);
DAMAGE_EFFECTS.add(PotionEffectType.INSTANT_DAMAGE);
// DAMAGE_EFFECTS.add(PotionEffectType.JUMP);
// DAMAGE_EFFECTS.add(PotionEffectType.JUMP_BOOST);
DAMAGE_EFFECTS.add(PotionEffectType.NAUSEA);
// DAMAGE_EFFECTS.add(PotionEffectType.REGENERATION);
// DAMAGE_EFFECTS.add(PotionEffectType.DAMAGE_RESISTANCE);
// DAMAGE_EFFECTS.add(PotionEffectType.RESISTANCE);
// DAMAGE_EFFECTS.add(PotionEffectType.FIRE_RESISTANCE);
// DAMAGE_EFFECTS.add(PotionEffectType.WATER_BREATHING);
// DAMAGE_EFFECTS.add(PotionEffectType.INVISIBILITY);
@@ -941,6 +1044,11 @@ public final class Materials {
DAMAGE_EFFECTS.add(PotionEffectType.BAD_OMEN);
// DAMAGE_EFFECTS.add(PotionEffectType.HERO_OF_THE_VILLAGE);
DAMAGE_EFFECTS.add(PotionEffectType.DARKNESS);
DAMAGE_EFFECTS.add(PotionEffectType.TRIAL_OMEN);
DAMAGE_EFFECTS.add(PotionEffectType.WIND_CHARGED);
DAMAGE_EFFECTS.add(PotionEffectType.WEAVING);
DAMAGE_EFFECTS.add(PotionEffectType.OOZING);
DAMAGE_EFFECTS.add(PotionEffectType.INFESTED);
}
private Materials() {
@@ -1127,6 +1235,10 @@ public final class Materials {
|| material == Material.BLAST_FURNACE
|| material == Material.SMOKER
|| 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);
}
@@ -1140,24 +1252,28 @@ public final class Materials {
case ALLAY_SPAWN_EGG -> EntityType.ALLAY;
case ARMADILLO_SPAWN_EGG -> EntityType.ARMADILLO;
case AXOLOTL_SPAWN_EGG -> EntityType.AXOLOTL;
case SPIDER_SPAWN_EGG -> EntityType.SPIDER;
case BAT_SPAWN_EGG -> EntityType.BAT;
case BEE_SPAWN_EGG -> EntityType.BEE;
case BLAZE_SPAWN_EGG -> EntityType.BLAZE;
case CAT_SPAWN_EGG -> EntityType.CAT;
case BOGGED_SPAWN_EGG -> EntityType.BOGGED;
case BREEZE_SPAWN_EGG -> EntityType.BREEZE;
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;
case DOLPHIN_SPAWN_EGG -> EntityType.DOLPHIN;
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;
@@ -1165,6 +1281,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;
@@ -1173,12 +1290,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;
@@ -1193,6 +1313,7 @@ public final class Materials {
case SLIME_SPAWN_EGG -> EntityType.SLIME;
case SNIFFER_SPAWN_EGG -> EntityType.SNIFFER;
case SNOW_GOLEM_SPAWN_EGG -> EntityType.SNOW_GOLEM;
case SPIDER_SPAWN_EGG -> EntityType.SPIDER;
case SQUID_SPAWN_EGG -> EntityType.SQUID;
case STRAY_SPAWN_EGG -> EntityType.STRAY;
case STRIDER_SPAWN_EGG -> EntityType.STRIDER;
@@ -1206,15 +1327,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;
};
}
@@ -1244,7 +1365,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;
};
@@ -1276,15 +1397,15 @@ public final class Materials {
*/
public static boolean isUseFlagApplicable(Material material) {
if (Tag.BUTTONS.isTagged(material)
|| Tag.WOODEN_DOORS.isTagged(material)
|| Tag.WOODEN_TRAPDOORS.isTagged(material)
|| Tag.DOORS.isTagged(material)
|| Tag.TRAPDOORS.isTagged(material)
|| Tag.FENCE_GATES.isTagged(material)
|| Tag.PRESSURE_PLATES.isTagged(material)) {
return true;
}
return switch (material) {
case LEVER, LECTERN, ENCHANTING_TABLE, BELL, LOOM,
CARTOGRAPHY_TABLE, STONECUTTER, GRINDSTONE -> true;
CARTOGRAPHY_TABLE, STONECUTTER, GRINDSTONE, VAULT -> true;
default -> false;
};
}
@@ -1367,15 +1488,13 @@ public final class Materials {
* @return true if equippable armor
*/
public static boolean isArmor(Material type) {
if (Tag.ITEMS_HEAD_ARMOR.isTagged(type) || Tag.ITEMS_CHEST_ARMOR.isTagged(type) ||
Tag.ITEMS_LEG_ARMOR.isTagged(type) || Tag.ITEMS_FOOT_ARMOR.isTagged(type) ||
Tag.ITEMS_SKULLS.isTagged(type)) {
return true;
}
return switch (type) {
case LEATHER_HELMET, LEATHER_CHESTPLATE, LEATHER_LEGGINGS, LEATHER_BOOTS,
CHAINMAIL_HELMET, CHAINMAIL_CHESTPLATE, CHAINMAIL_LEGGINGS, CHAINMAIL_BOOTS,
IRON_HELMET, IRON_CHESTPLATE, IRON_LEGGINGS, IRON_BOOTS,
DIAMOND_HELMET, DIAMOND_CHESTPLATE, DIAMOND_LEGGINGS, DIAMOND_BOOTS,
GOLDEN_HELMET, GOLDEN_CHESTPLATE, GOLDEN_LEGGINGS, GOLDEN_BOOTS,
NETHERITE_HELMET, NETHERITE_CHESTPLATE, NETHERITE_LEGGINGS, NETHERITE_BOOTS,
TURTLE_HELMET, ELYTRA ->
true;
case CARVED_PUMPKIN, ELYTRA -> true;
default -> false;
};
}
@@ -1394,6 +1513,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:
@@ -1405,6 +1525,7 @@ public final class Materials {
};
case WOODEN_AXE:
case STONE_AXE:
case COPPER_AXE:
case IRON_AXE:
case GOLDEN_AXE:
case DIAMOND_AXE:
@@ -1419,6 +1540,7 @@ public final class Materials {
};
case WOODEN_SHOVEL:
case STONE_SHOVEL:
case COPPER_SHOVEL:
case IRON_SHOVEL:
case GOLDEN_SHOVEL:
case DIAMOND_SHOVEL:
@@ -1458,6 +1580,9 @@ public final class Materials {
case SUSPICIOUS_GRAVEL, SUSPICIOUS_SAND -> true;
default -> false;
};
case WRITTEN_BOOK:
case WRITABLE_BOOK:
return targetMaterial == Material.LECTERN;
default:
return false;
}
@@ -1466,27 +1591,19 @@ public final class Materials {
public static boolean isFire(Material type) {
return type == Material.FIRE || type == Material.SOUL_FIRE;
}
public static boolean isWaxedCopper(Material type) {
return switch (type) {
case WAXED_COPPER_BLOCK, WAXED_EXPOSED_COPPER, WAXED_WEATHERED_COPPER, WAXED_OXIDIZED_COPPER,
WAXED_CUT_COPPER, WAXED_EXPOSED_CUT_COPPER, WAXED_WEATHERED_CUT_COPPER,
WAXED_OXIDIZED_CUT_COPPER, WAXED_CUT_COPPER_STAIRS, WAXED_EXPOSED_CUT_COPPER_STAIRS,
WAXED_WEATHERED_CUT_COPPER_STAIRS, WAXED_OXIDIZED_CUT_COPPER_STAIRS, WAXED_CUT_COPPER_SLAB,
WAXED_EXPOSED_CUT_COPPER_SLAB, WAXED_WEATHERED_CUT_COPPER_SLAB, WAXED_OXIDIZED_CUT_COPPER_SLAB ->
true;
default -> false;
};
// copied from the MaterialTags class in Paper
return type.name().startsWith("WAXED_") && type.name().contains("COPPER");
}
public static boolean isUnwaxedCopper(Material type) {
// copied from the MaterialTags class in Paper
return switch (type) {
case COPPER_BLOCK, EXPOSED_COPPER, WEATHERED_COPPER, OXIDIZED_COPPER, CUT_COPPER,
EXPOSED_CUT_COPPER, WEATHERED_CUT_COPPER, OXIDIZED_CUT_COPPER, CUT_COPPER_STAIRS,
EXPOSED_CUT_COPPER_STAIRS, WEATHERED_CUT_COPPER_STAIRS, OXIDIZED_CUT_COPPER_STAIRS,
CUT_COPPER_SLAB, EXPOSED_CUT_COPPER_SLAB, WEATHERED_CUT_COPPER_SLAB, OXIDIZED_CUT_COPPER_SLAB ->
true;
default -> false;
case COPPER_BLOCK, CHISELED_COPPER, COPPER_DOOR, COPPER_TRAPDOOR, COPPER_GRATE, COPPER_BULB, 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,5 +2,5 @@ name: WorldGuard
main: com.sk89q.worldguard.bukkit.WorldGuardPlugin
version: "${internalVersion}"
depend: [WorldEdit]
softdepend: [CommandBook]
api-version: "1.20"
api-version: "26.1"
folia-supported: true
+34 -12
View File
@@ -1,20 +1,42 @@
plugins {
`java-library`
id("buildlogic.core-and-platform")
}
applyPlatformAndCoreConfiguration()
dependencies {
"api"(project(":worldguard-libs:core"))
"api"("com.sk89q.worldedit:worldedit-core:${Versions.WORLDEDIT}")
"implementation"("org.flywaydb:flyway-core:3.0")
"implementation"("org.yaml:snakeyaml:2.0")
"implementation"("com.google.guava:guava:${Versions.GUAVA}")
constraints {
"implementation"(libs.snakeyaml) {
because("Bukkit provides SnakeYaml")
}
}
"compileOnly"("com.google.code.findbugs:jsr305:${Versions.FINDBUGS}")
"testImplementation"("org.hamcrest:hamcrest-library:2.2")
"api"(project(":worldguard-libs:core"))
"api"(libs.worldedit.core)
"implementation"(libs.flyway.core)
"implementation"(libs.snakeyaml)
"implementation"(libs.guava)
"compileOnlyApi"(libs.jsr305)
"implementation"(libs.gson)
"compileOnly"(libs.worldedit.libs.ap)
"annotationProcessor"(libs.worldedit.libs.ap)
// ensure this is on the classpath for the AP
"annotationProcessor"(libs.guava)
"compileOnly"(libs.autoService) {
because("Needed to resolve annotations in Piston")
}
"testImplementation"(libs.hamcrest.library)
}
tasks.withType<JavaCompile>().configureEach {
tasks.compileJava {
dependsOn(":worldguard-libs:build")
}
options.compilerArgs.add("-Aarg.name.key.prefix=")
}
configure<PublishingExtension> {
publications.named<MavenPublication>("maven") {
artifactId = the<BasePluginExtension>().archivesName.get()
from(components["java"])
}
}
@@ -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());
}
}
@@ -70,7 +70,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("God enabled by " + sender.getDisplayName() + ".");
}
@@ -79,7 +79,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players now have god mode.");
}
}
@@ -113,7 +113,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("God disabled by " + sender.getDisplayName() + ".");
}
@@ -122,7 +122,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players no longer have god mode.");
}
}
@@ -158,7 +158,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("Healed by " + sender.getDisplayName() + ".");
}
@@ -166,7 +166,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players healed.");
}
}
@@ -199,7 +199,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("Slain by " + sender.getDisplayName() + ".");
}
@@ -207,7 +207,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players slain.");
}
}
@@ -229,6 +229,7 @@ public class GeneralCommands {
}
}
@SuppressWarnings("removal")
@Command(aliases = {"stack", ";"}, usage = "", desc = "Stack items", max = 0)
@CommandPermissions({"worldguard.stack"})
public void stack(CommandContext args, Actor sender) throws CommandException {
@@ -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;
@@ -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);
}
@@ -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;
@@ -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).");
@@ -101,6 +101,7 @@ public abstract class WorldConfiguration {
public boolean blockEnderDragonPortalCreation;
public boolean blockFireballExplosions;
public boolean blockFireballBlockDamage;
public boolean blockWindChargeExplosions;
public boolean blockOtherExplosions;
public boolean blockEntityPaintingDestroy;
public boolean blockEntityItemFrameDestroy;
@@ -166,8 +167,10 @@ public abstract class WorldConfiguration {
public boolean disableEndermanGriefing;
public boolean disableSnowmanTrails;
public boolean disableSoilDehydration;
public boolean disableSoilMoistureChange;
public boolean disableCoralBlockFade;
public boolean disableCopperBlockFade;
public boolean disableLavaHarden;
public Set<String> allowedSnowFallOver;
public boolean regionInvinciblityRemovesMobs;
public boolean regionCancelEmptyChatEvents;
@@ -145,6 +145,7 @@ public interface WorldGuardPlatform {
*
* @param localPlayer The player
*/
@Deprecated(forRemoval = true)
void stackPlayerInventory(LocalPlayer localPlayer);
/**
@@ -74,6 +74,7 @@ public final class Flags {
public static final StateFlag FIREWORK_DAMAGE = register(new StateFlag("firework-damage", false));
public static final StateFlag USE_ANVIL = register(new StateFlag("use-anvil", false));
public static final StateFlag USE_DRIPLEAF = register(new StateFlag("use-dripleaf", false));
public static final StateFlag WIND_CHARGE_BURST = register(new StateFlag("wind-charge-burst", false));
// These flags are similar to the ones above (used in tandem with BUILD),
// but their defaults are set to TRUE because it is more user friendly.
@@ -93,6 +94,7 @@ public final class Flags {
public static final StateFlag ENDERDRAGON_BLOCK_DAMAGE = register(new StateFlag("enderdragon-block-damage", true));
public static final StateFlag GHAST_FIREBALL = register(new StateFlag("ghast-fireball", true));
public static final StateFlag OTHER_EXPLOSION = register(new StateFlag("other-explosion", true));
public static final StateFlag BREEZE_WIND_CHARGE = register(new StateFlag("breeze-charge-explosion", true));
public static final StateFlag WITHER_DAMAGE = register(new StateFlag("wither-damage", true));
public static final StateFlag ENDER_BUILD = register(new StateFlag("enderman-grief", true));
public static final StateFlag SNOWMAN_TRAILS = register(new StateFlag("snowman-trails", true));
@@ -128,6 +130,8 @@ public final class Flags {
public static final StateFlag COPPER_FADE = register(new StateFlag("copper-fade", true));
public static final StateFlag WATER_FLOW = register(new StateFlag("water-flow", true));
public static final StateFlag LAVA_FLOW = register(new StateFlag("lava-flow", true));
public static final StateFlag MOISTURE_CHANGE = register(new StateFlag("moisture-change", true));
public static final 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"));
@@ -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>
*
@@ -50,6 +50,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 +119,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 +194,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
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.session;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@@ -67,10 +68,9 @@ public abstract class AbstractSessionManager implements SessionManager {
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(CacheLoader.from(tuple -> BYPASS_PERMISSION_TEST.test(tuple.getWorld(), tuple.getPlayer())));
private final LoadingCache<CacheKey, Session> sessions = CacheBuilder.newBuilder()
private final Cache<CacheKey, Session> sessions = CacheBuilder.newBuilder()
.expireAfterAccess(SESSION_LIFETIME, TimeUnit.MINUTES)
.build(CacheLoader.from(key ->
createSession(key.playerRef.get())));
.build();
private boolean hasCustom = false;
private List<Handler.Factory<? extends Handler>> handlers = new LinkedList<>();
@@ -152,7 +152,7 @@ public abstract class AbstractSessionManager implements SessionManager {
@Override
public void resetState(LocalPlayer player) {
checkNotNull(player, "player");
@Nullable Session session = sessions.getIfPresent(new CacheKey(player));
@Nullable Session session = getIfPresentInternal(new CacheKey(player));
if (session != null) {
session.resetState(player);
}
@@ -161,22 +161,35 @@ public abstract class AbstractSessionManager implements SessionManager {
@Override
@Nullable
public Session getIfPresent(LocalPlayer player) {
return sessions.getIfPresent(new CacheKey(player));
return getIfPresentInternal(new CacheKey(player));
}
private Session getIfPresentInternal(CacheKey cacheKey) {
@Nullable Session session = sessions.getIfPresent(cacheKey);
if (session != null) {
session.ensureInitialized(cacheKey.playerRef.get(), this::initializeSession);
return session;
}
return null;
}
@Override
public Session get(LocalPlayer player) {
return sessions.getUnchecked(new CacheKey(player));
Session session = sessions.asMap().computeIfAbsent(new CacheKey(player), (k) -> new Session(this));
session.ensureInitialized(player, this::initializeSession);
return session;
}
@Override
public Session createSession(LocalPlayer player) {
Session session = new Session(this);
return get(player);
}
private void initializeSession(Session session, LocalPlayer player) {
for (Handler.Factory<? extends Handler> factory : handlers) {
session.register(factory.create(session));
}
session.initialize(player);
return session;
}
protected static final class CacheKey {
@@ -38,6 +38,7 @@ import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -52,6 +53,7 @@ public class Session {
private Location lastValid;
private Set<ProtectedRegion> lastRegionSet;
private final AtomicBoolean needRefresh = new AtomicBoolean(false);
private boolean initialized;
/**
* Create a new session.
@@ -110,7 +112,7 @@ public class Session {
disableBypass = cfg.disableDefaultBypass;
if (cfg.announceBypassStatus && player.hasPermission("worldguard.region.toggle-bypass")) {
player.printInfo(TextComponent.of(
"You are " + (disableBypass ? "not" : "") + " bypassing region protection. " +
"You are " + (disableBypass ? "not " : "") + "bypassing region protection. " +
"You can toggle this with /rg bypass", TextColor.DARK_PURPLE));
}
@@ -120,6 +122,14 @@ public class Session {
}
}
synchronized void ensureInitialized(LocalPlayer player, BiConsumer<Session, LocalPlayer> initializer) {
if (initialized) {
return;
}
initialized = true;
initializer.accept(this, player);
}
/**
* Uninitialize the session.
*
@@ -95,7 +95,9 @@ public interface SessionManager {
*
* @param player The player
* @return The new session
* @deprecated Use {@link SessionManager#get} instead
*/
@Deprecated
Session createSession(LocalPlayer player);
/**
@@ -59,7 +59,9 @@ public class GameModeFlag extends FlagValueChangeHandler<GameMode> {
private void updateGameMode(LocalPlayer player, @Nullable GameMode newValue, World world) {
if (!getSession().getManager().hasBypass(player, world) && newValue != null) {
if (player.getGameMode() != newValue) {
originalGameMode = player.getGameMode();
if (originalGameMode == null) {
originalGameMode = player.getGameMode();
}
player.setGameMode(newValue);
} else if (originalGameMode == null) {
originalGameMode = WorldGuard.getInstance().getPlatform().getDefaultGameMode();
@@ -50,10 +50,15 @@ public class NotifyEntryFlag extends FlagValueChangeHandler<Boolean> {
@Override
protected boolean onSetValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, Boolean currentValue, Boolean lastValue, MoveType moveType) {
if (!currentValue) {
// If the current value is false, we do not notify
return true;
}
StringBuilder regionList = new StringBuilder();
for (ProtectedRegion region : toSet) {
if (regionList.length() != 0) {
if (!regionList.isEmpty()) {
regionList.append(", ");
}
@@ -56,6 +56,10 @@ public class NotifyExitFlag extends FlagValueChangeHandler<Boolean> {
@Override
protected boolean onAbsentValue(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, Boolean lastValue, MoveType moveType) {
if (!lastValue) {
// If the lastValue was false, we don't notify
return true;
}
WorldGuard.getInstance().getPlatform().broadcastNotification(new Notify(player.getName(), " left NOTIFY region").create());
return true;
}
@@ -19,14 +19,18 @@
package com.sk89q.worldguard.util.formatting.component;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
public class BlacklistNotify extends Notify {
public BlacklistNotify(BlacklistEvent event, String comment) {
super(event.getCauseName(), " (" + event.getDescription() + ") ");
append(TextComponent.of(event.getTarget().getFriendlyName() + (comment != null ? " (" + comment + ")" : "") + ".", TextColor.WHITE));
Component base = event.getTarget().getFriendlyNameComponent();
if (comment != null) {
base = base.append(TextComponent.of(" (" + comment + ")"));
}
append(base);
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
tasks.register("build") {
dependsOn(subprojects.map { it.tasks.named("build") })
}
}
-1
View File
@@ -1 +0,0 @@
applyLibrariesConfiguration()
+6 -14
View File
@@ -1,18 +1,10 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
applyLibrariesConfiguration()
plugins {
id("buildlogic.libs")
}
dependencies {
"shade"("org.enginehub:squirrelid:${Versions.SQUIRRELID}")
"shade"("org.khelekore:prtree:1.5.0")
}
tasks.named<ShadowJar>("jar") {
dependencies {
relocate("org.enginehub.squirrelid", "com.sk89q.worldguard.util.profile") {
include(dependency("org.enginehub:squirrelid"))
}
include(dependency("org.khelekore:prtree"))
"shade"(libs.squirrelid) {
isTransitive = false
}
"shade"(libs.prtree)
}