Compare commits

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

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

* Synchronize on the class instead of the instance

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

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

* Add lava-harden flag

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

* missed java 21 refs

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

* add some comments

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

* Teleport async only with Folia server

* restore

* Extract the location for teleportation and add the {}

* Extract the location for teleportation

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

* Remove commented-out materials
2025-10-30 17:48:18 +10:00
Maddy Miller 8191e5dfef Improve region file loading compatibility with NIO Java APIs 2025-10-27 22:12:41 +10:00
Joo200 86a1fa6ee9 Merge branch 'version/7.0.x'
# Conflicts:
#	gradle.properties
2025-08-24 21:20:09 +02:00
Maddy Miller f8415edfcd Skip handling notify flags on false values 2025-07-27 16:13:58 +10:00
Maddy Miller c4c17a2e4f Remove weird files 2025-06-12 23:17:17 +10:00
Maddy Miller e2f21b66ed Back to SNAPSHOT for continued development 2025-06-12 23:10:23 +10:00
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
Joo200 ab48a66237 Merge branch 'refs/heads/version/7.0.x'
# Conflicts:
#	buildSrc/src/main/kotlin/GradleExtras.kt
#	buildSrc/src/main/kotlin/LibsConfig.kt
#	buildSrc/src/main/kotlin/PlatformConfig.kt
#	gradle.properties
#	worldguard-libs/bukkit/build.gradle.kts
2024-09-16 20:08:34 +02:00
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
wizjany d9424b1c71 Release 7.0.10. 2024-05-14 18:11:53 -04:00
aurora 65431c7df8 Fix fire placement by blocks when fire-spread is set to deny
Fixes #2070
2024-05-13 20:27:34 +02:00
Joo200 aa254c80e0 Merge branch 'refs/heads/version/7.0.x'
# Conflicts:
#	buildSrc/build.gradle.kts
2024-05-03 19:57:42 +02:00
Joo200 2f93b26be0 Update dependencies to 1.20.6 2024-05-03 19:57:10 +02:00
wizjany 6bbf49314d Merge pull request #2075 from EngineHub/feature/1.20.5
Update WorldGuard to 1.20.5
2024-05-02 12:12:15 -04:00
Madeline Miller f6a0a0b415 Add outline to logo SVG akin to WorldEdit and CraftBook 2024-05-01 23:08:16 +10:00
Joo200 4ad11151fe Fix compilation for 1.20.5 2024-04-28 15:39:15 +02:00
Joo200 c29edf7467 Fix Deprecations from WorldEdit 7.3.0 2024-04-28 15:36:52 +02:00
Joo200 da3c81a88d Update dependencies to 1.20.5 and jdk 21 2024-04-28 15:32:32 +02:00
Joo200 c65dd83a7e Don't show particles for denied interact events with dripleaf and redstone ores 2024-04-07 22:04:00 +02:00
Joo200 694195435d Bump Versions 2024-04-07 22:02:57 +02:00
Madeline Miller 0d824d375b Add a Paper fast-path for DoubleChest#getLeftSide when possible 2024-03-31 12:28:53 -04:00
aromaa c7319f10dc Bump up respawn event priority to monitor 2023-09-11 21:25:47 -04:00
Joo200 c2b95f59a8 Paper only: Protect sign modifications as building 2023-08-22 14:34:52 +02:00
Joo200 5fa6f2a858 Update paper-api and spigot-api dependencies to 1.20.1 2023-08-22 14:34:26 +02:00
Joo200 0a9eb447d6 store custom domains thread safe, improve api usability 2023-08-20 11:06:36 +02:00
Joo200 02a8fd4c17 Merge remote-tracking branch 'origin/version/7.0.x'
# Conflicts:
#	gradle.properties
2023-08-14 14:21:50 +02:00
wizjany 3201cee1b7 Bump to snapshot. 2023-07-31 20:12:56 -04:00
Joo200 8cbce96a2c Merge branch 'version/7.0.x' 2023-06-18 18:47:29 +02:00
Joo200 bb3fdcc880 Renamed InvalidFlagFormat to InvalidFlagFormatException 2023-06-04 18:55:01 +02:00
JOO200 8d5953a550 apidomains: Added custom domains to WorldGuard
This change allows third party plugins to dynamically add custom domains to WorldGuard.
2023-06-04 18:55:01 +02:00
wizjany 129ae6c971 Merge branch 'version/7.0.x'
# Conflicts:
#	gradle.properties
2023-05-27 13:49:05 -04:00
Joo200 b67fd01ebd Merge branch 'version/7.0.x'
# Conflicts:
#	buildSrc/src/main/kotlin/Versions.kt
#	gradle/wrapper/gradle-wrapper.jar
#	gradle/wrapper/gradle-wrapper.properties
#	gradlew.bat
#	worldguard-core/build.gradle.kts
2023-03-26 15:17:06 +02:00
Joo200 62be386626 Merge branch 'version/7.0.x' 2022-11-27 10:52:54 +01:00
Joo200 741f9e231b Merge branch 'version/7.0.x'
# Conflicts:
#	buildSrc/build.gradle.kts
#	buildSrc/src/main/kotlin/PlatformConfig.kt
#	buildSrc/src/main/kotlin/Versions.kt
2022-09-19 11:56:50 +02:00
wizjany bc63119373 Fix publish. 2022-03-12 17:32:40 -05:00
wizjany 3549f04a33 Build script updates.
Bump gradle. Copy a bunch from WE. Hopefully nothing breaks.
2022-03-12 17:21:50 -05:00
143 changed files with 3299 additions and 1362 deletions

No files matched your search

+33 -1
View File
@@ -1,2 +1,34 @@
*.java diff=java
* text=auto eol=lf
# Force Batch files to CRLF
*.bat eol=crlf -text
# Java sources
*.java text diff=java
*.kt text diff=java
*.gradle text diff=java
*.gradle.kts text diff=java
# These files are text and should be normalized (Convert crlf => lf)
*.css text diff=css
*.df text
*.htm text diff=html
*.html text diff=html
*.js text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.tld text
*.tag text
*.tagx text
*.xml text
# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.jar binary
*.so binary
*.war binary
*.jks binary
+48
View File
@@ -0,0 +1,48 @@
name: Gradle Build
on:
push:
branches:
- 'master'
- 'version/*'
pull_request:
merge_group:
jobs:
build:
name: Build WorldGuard on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v6
- name: Set up JDK
uses: actions/setup-java@v5
with:
java-version: 25
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
with:
cache-read-only: ${{ !(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/version/')) }}
- name: Execute Gradle build
run: ./gradlew build -s
- uses: actions/upload-artifact@v6
name: Archive Reports
if: always()
with:
name: reports for ${{ matrix.os }}
path: '**/build/reports/**'
- uses: actions/upload-artifact@v6
name: Archive Logs
if: always()
with:
name: logs for ${{ matrix.os }}
path: '**/*.log'
-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
+66
View File
@@ -1,5 +1,71 @@
# 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
## 7.0.9
* Add support for MC 1.20, drop support for MC 1.19
* Made entities spawned via the `/summon` command get treated as plugin-spawned entities
+2 -5
View File
@@ -1,11 +1,8 @@
Compiling
=========
You can compile WorldGuard as long as you have some version of Java greater than or equal to 17 installed. Gradle will download JDK 17 specifically if needed,
but it needs some version of Java to bootstrap from.
Note that if you have JRE 17 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 16 and
replace it with JDK 17.
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")
}
-17
View File
@@ -1,17 +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:4.1.1")
implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2")
implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.27.1")
}
@@ -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(17))
}
}
apply(plugin = "org.cadixdev.licenser")
configure<LicenseExtension> {
header(rootProject.file("HEADER.txt"))
include("**/*.java")
include("**/*.kt")
}
}
@@ -0,0 +1,86 @@
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.withType
fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, javaRelease: Int = 8, banSlf4j: Boolean = true) {
applyCommonConfiguration()
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "checkstyle")
tasks
.withType<JavaCompile>()
.matching { it.name == "compileJava" || it.name == "compileTestJava" }
.configureEach {
val disabledLint = listOf(
"processing", "path", "fallthrough", "serial"
)
options.release.set(javaRelease)
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
options.isDeprecation = true
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
}
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "9.1"
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
"compileOnly"("com.google.code.findbugs:jsr305:${Versions.FINDBUGS}")
"testImplementation"("org.junit.jupiter:junit-jupiter-api:${Versions.JUNIT}")
"testImplementation"("org.junit.jupiter:junit-jupiter-params:${Versions.JUNIT}")
"testImplementation"("org.mockito:mockito-core:${Versions.MOCKITO}")
"testImplementation"("org.mockito:mockito-junit-jupiter:${Versions.MOCKITO}")
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:${Versions.JUNIT}")
}
// Java 8 turns on doclint which we fail
tasks.withType<Javadoc>().configureEach {
options.encoding = "UTF-8"
(options as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:none", "-quiet")
tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
}
}
configure<JavaPluginExtension> {
disableAutoTargetJvm()
withJavadocJar()
if (sourcesJar) {
withSourcesJar()
}
}
if (banSlf4j) {
configurations["compileClasspath"].apply {
resolutionStrategy.componentSelection {
withModule("org.slf4j:slf4j-api") {
reject("No SLF4J allowed on compile classpath")
}
}
}
}
tasks.named("check").configure {
dependsOn("checkstyleMain", "checkstyleTest")
}
}
-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.2.14"
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.9
version=7.1.0-SNAPSHOT
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.4"
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.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.6.0-jre"
log4j-bom = "org.apache.logging.log4j:log4j-bom:2.25.2"
gson = "com.google.code.gson:gson:2.14.0"
fastutil = "it.unimi.dsi:fastutil:8.5.18"
# Bukkit-provided libraries, CHECK AGAINST SPIGOT for versions
# Note that we need to balance support for older MC versus working at all on newer ones, so the exact versions here
# 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"
Binary file not shown.
+4 -1
View File
@@ -1,6 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-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
+14 -10
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/.
@@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -130,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
@@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -198,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Vendored
+10 -10
View File
@@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
+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 -43
View File
@@ -1,69 +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/")
}
}
configurations {
compileClasspath.get().extendsFrom(create("shadeOnly"))
id("buildlogic.platform")
}
dependencies {
"api"(project(":worldguard-core"))
"compileOnly"("io.papermc.paper:paper-api:1.20-R0.1-SNAPSHOT")
"runtimeOnly"("org.spigotmc:spigot-api:1.20-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
@@ -266,7 +267,7 @@ public class BukkitWorldGuardPlatform implements WorldGuardPlatform {
if (radius > 0) {
BlockVector3 spawnLoc = BukkitAdapter.asBlockVector(bWorld.getSpawnLocation());
return new ProtectedCuboidRegion("__spawn_protection__",
spawnLoc.subtract(radius, 0, radius).withY(world.getMinimumPoint().getY()),
spawnLoc.subtract(radius, 0, radius).withY(world.getMinimumPoint().y()),
spawnLoc.add(radius, 0, radius).withY(world.getMaxY()));
}
}
@@ -33,6 +33,8 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitCommandSender;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.blacklist.Blacklist;
@@ -65,6 +67,7 @@ import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.commands.GeneralCommands;
import com.sk89q.worldguard.commands.ProtectionCommands;
import com.sk89q.worldguard.commands.ToggleCommands;
import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry;
@@ -74,6 +77,8 @@ import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver
import com.sk89q.worldguard.protection.managers.storage.sql.SQLDriver;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
import io.papermc.lib.PaperLib;
import io.papermc.paper.ServerBuildInfo;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.DrilldownPie;
import org.bstats.charts.SimplePie;
@@ -95,6 +100,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -103,6 +109,7 @@ import java.util.logging.Logger;
*/
public class WorldGuardPlugin extends JavaPlugin {
private static final org.apache.logging.log4j.Logger LOGGER = LogManagerCompat.getLogger();
private static WorldGuardPlugin inst;
private static BukkitWorldGuardPlatform platform;
private final CommandsManager<Actor> commands;
@@ -136,6 +143,7 @@ public class WorldGuardPlugin extends JavaPlugin {
* Called on plugin enable.
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void onEnable() {
// Catch bad things being done by naughty plugins that include WorldGuard's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
@@ -163,7 +171,16 @@ public class WorldGuardPlugin extends JavaPlugin {
reg.register(GeneralCommands.class);
}
getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
if (this.isFolia()) {
getServer().getGlobalRegionScheduler().runAtFixedRate(this, new Consumer() {
@Override
public void accept(Object ignored) {
sessionManager.run();
}
}, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
} else {
getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, BukkitSessionManager.RUN_DELAY, BukkitSessionManager.RUN_DELAY);
}
// Register events
getServer().getPluginManager().registerEvents(sessionManager, this);
@@ -204,14 +221,27 @@ public class WorldGuardPlugin extends JavaPlugin {
}
worldListener.registerEvents();
Bukkit.getScheduler().runTask(this, () -> {
if (this.isFolia()) {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
player.getScheduler().run(this, new Consumer() {
@Override
public void accept(Object ignored) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
}
}, null);
}
});
} else {
Bukkit.getScheduler().runTask(this, () -> {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
}
});
}
((SimpleFlagRegistry) WorldGuard.getInstance().getFlagRegistry()).setInitialized(true);
((SimpleDomainRegistry) WorldGuard.getInstance().getDomainRegistry()).setInitialized(true);
// Enable metrics
final Metrics metrics = new Metrics(this, BSTATS_PLUGIN_ID); // bStats plugin id
@@ -264,7 +294,12 @@ public class WorldGuardPlugin extends JavaPlugin {
@Override
public void onDisable() {
WorldGuard.getInstance().disable();
this.getServer().getScheduler().cancelTasks(this);
if (this.isFolia()) {
this.getServer().getGlobalRegionScheduler().cancelTasks(this);
this.getServer().getAsyncScheduler().cancelTasks(this);
} else {
this.getServer().getScheduler().cancelTasks(this);
}
}
@Override
@@ -524,4 +559,22 @@ public class WorldGuardPlugin extends JavaPlugin {
return playerMoveListener;
}
private final LazyReference<Boolean> folia = LazyReference.from(() -> {
try {
// Folia is Paper-based, so this is a good first check.
if (PaperLib.isPaper()) {
return ServerBuildInfo.buildInfo().isBrandCompatible(net.kyori.adventure.key.Key.key("papermc", "folia"));
}
} catch (Throwable t) {
// Ignore, this likely means an outdated version.
LOGGER.warn("Failed to check if server is running Folia", t);
}
return false;
});
public boolean isFolia() {
return folia.getValue();
}
}
@@ -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)
@@ -35,6 +35,10 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import java.util.ArrayList;
import java.util.List;
/**
* Handles blocked potions.
@@ -50,43 +54,50 @@ public class BlockedPotionsListener extends AbstractListener {
super(plugin);
}
private PotionEffectType getBlockedEffectByArrow(Arrow arrow, BukkitWorldConfiguration wcfg) {
List<PotionEffect> effects = new ArrayList<>();
PotionType potionType = arrow.getBasePotionType();
if (potionType != null) {
effects.addAll(potionType.getPotionEffects());
}
effects.addAll(arrow.getCustomEffects());
for (PotionEffect potionEffect : effects) {
if (wcfg.blockPotions.contains(potionEffect.getType())) {
return potionEffect.getType();
}
}
return null;
}
@EventHandler
public void onProjectile(DamageEntityEvent event) {
if (event.getOriginalEvent() instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent originalEvent = (EntityDamageByEntityEvent) event.getOriginalEvent();
if (Entities.isPotionArrow(originalEvent.getDamager())) { // should take care of backcompat
BukkitWorldConfiguration wcfg = getWorldConfig(event.getWorld());
PotionEffectType blockedEffect = null;
if (originalEvent.getDamager() instanceof SpectralArrow) {
if (wcfg.blockPotions.contains(PotionEffectType.GLOWING)) {
blockedEffect = PotionEffectType.GLOWING;
}
} else if (originalEvent.getDamager() instanceof Arrow) {
Arrow tippedArrow = (Arrow) originalEvent.getDamager();
PotionEffectType baseEffect = tippedArrow.getBasePotionData().getType().getEffectType();
if (wcfg.blockPotions.contains(baseEffect)) {
blockedEffect = baseEffect;
} else {
for (PotionEffect potionEffect : tippedArrow.getCustomEffects()) {
if (wcfg.blockPotions.contains(potionEffect.getType())) {
blockedEffect = potionEffect.getType();
break;
}
}
}
}
if (blockedEffect != null) {
Player player = event.getCause().getFirstPlayer();
if (player != null) {
if (getPlugin().hasPermission(player, "worldguard.override.potions")) {
return;
}
player.sendMessage(ChatColor.RED + "Sorry, arrows with "
+ blockedEffect.getName() + " are presently disabled.");
}
event.setCancelled(true);
}
if (!(event.getOriginalEvent() instanceof EntityDamageByEntityEvent originalEvent)) {
return;
}
if (!Entities.isPotionArrow(originalEvent.getDamager())) {
return;
}
BukkitWorldConfiguration wcfg = getWorldConfig(event.getWorld());
PotionEffectType blockedEffect = null;
if (originalEvent.getDamager() instanceof SpectralArrow) {
if (wcfg.blockPotions.contains(PotionEffectType.GLOWING)) {
blockedEffect = PotionEffectType.GLOWING;
}
} else if (originalEvent.getDamager() instanceof Arrow arrow) {
blockedEffect = getBlockedEffectByArrow(arrow, wcfg);
}
if (blockedEffect != null) {
Player player = event.getCause().getFirstPlayer();
if (player != null) {
if (getPlugin().hasPermission(player, "worldguard.override.potions")) {
return;
}
player.sendMessage(ChatColor.RED + "Sorry, arrows with "
+ blockedEffect.getName() + " are presently disabled.");
}
event.setCancelled(true);
}
}
@@ -104,25 +115,20 @@ public class BlockedPotionsListener extends AbstractListener {
if (!wcfg.blockPotions.isEmpty()) {
PotionEffectType blockedEffect = null;
PotionMeta meta;
if (item.getItemMeta() instanceof PotionMeta) {
meta = ((PotionMeta) item.getItemMeta());
} else {
return; // ok...?
if (!(item.getItemMeta() instanceof PotionMeta meta)) {
return;
}
// Find the first blocked effect
PotionEffectType baseEffect = meta.getBasePotionData().getType().getEffectType();
if (wcfg.blockPotions.contains(baseEffect)) {
blockedEffect = baseEffect;
List<PotionEffect> effects = new ArrayList<>();
if (meta.getBasePotionType() != null) {
effects.addAll(meta.getBasePotionType().getPotionEffects());
}
if (blockedEffect == null && meta.hasCustomEffects()) {
for (PotionEffect effect : meta.getCustomEffects()) {
if (wcfg.blockPotions.contains(effect.getType())) {
blockedEffect = effect.getType();
break;
}
effects.addAll(meta.getCustomEffects());
for (PotionEffect potionEffect : effects) {
if (wcfg.blockPotions.contains(potionEffect.getType())) {
blockedEffect = potionEffect.getType();
break;
}
}
@@ -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,11 +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;
@@ -65,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;
@@ -78,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;
@@ -111,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;
@@ -145,13 +157,14 @@ import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;
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);
}
@@ -482,7 +532,7 @@ public class EventAbstractionListener extends AbstractListener {
firedEvent.setSilent(true);
}
interactDebounce.debounce(clicked, event.getPlayer(), event, firedEvent);
if (event.useInteractedBlock() == Result.DENY) {
if (event.useInteractedBlock() == Result.DENY && !firedEvent.isSilent()) {
playDenyEffect(player, clicked.getLocation().add(0, 1, 0));
}
}
@@ -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);
@@ -1086,9 +1169,9 @@ public class EventAbstractionListener extends AbstractListener {
public void onLingeringApply(AreaEffectCloudApplyEvent event) {
AreaEffectCloud entity = event.getEntity();
List<PotionEffect> effects = new ArrayList<>();
PotionEffectType baseEffectType = entity.getBasePotionData().getType().getEffectType();
if (baseEffectType != null) {
effects.add(new PotionEffect(baseEffectType, 0, 0));
List<PotionEffect> baseEffectTypes = entity.getBasePotionType() == null ? null : entity.getBasePotionType().getPotionEffects();
if (baseEffectTypes != null) {
effects.addAll(baseEffectTypes);
}
if (entity.hasCustomEffects()) {
effects.addAll(entity.getCustomEffects());
@@ -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;
}
@@ -1173,7 +1256,7 @@ public class EventAbstractionListener extends AbstractListener {
if (item != null && item.getType() == Material.END_CRYSTAL) { /*&& placed.getType() == Material.BEDROCK) {*/ // in vanilla you can only place them on bedrock but who knows what plugins will add
// may be overprotective as a result, but better than being underprotective
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ENDER_CRYSTAL));
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.END_CRYSTAL));
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,10 +1344,31 @@ 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()));
}
@EventHandler(ignoreCancelled = true)
public void onSignOpen(PlayerOpenSignEvent event) {
if (event.getCause() == PlayerOpenSignEvent.Cause.INTERACT) {
// other cases are handled by other events
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,6 +23,7 @@ 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;
@@ -34,14 +35,15 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityMountEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector;
import org.spigotmc.event.entity.EntityMountEvent;
import java.util.function.Consumer;
public class PlayerMoveListener extends AbstractListener {
@@ -54,13 +56,10 @@ public class PlayerMoveListener extends AbstractListener {
if (WorldGuard.getInstance().getPlatform().getGlobalStateManager().usePlayerMove) {
PluginManager pm = getPlugin().getServer().getPluginManager();
pm.registerEvents(this, getPlugin());
if (PaperLib.isSpigot()) {
pm.registerEvents(new EntityMountListener(), getPlugin());
}
}
}
@EventHandler
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerRespawn(PlayerRespawnEvent event) {
LocalPlayer player = getPlugin().wrapPlayer(event.getPlayer());
@@ -81,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();
@@ -123,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);
}
}
}
}
@@ -146,22 +161,40 @@ 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);
}
private class EntityMountListener implements Listener {
@EventHandler
public void onEntityMount(EntityMountEvent event) {
Entity entity = event.getEntity();
if (entity instanceof Player) {
LocalPlayer player = getPlugin().wrapPlayer((Player) entity);
Session session = WorldGuard.getInstance().getPlatform().getSessionManager().get(player);
if (null != session.testMoveTo(player, BukkitAdapter.adapt(event.getMount().getLocation()), MoveType.EMBARK, true)) {
event.setCancelled(true);
}
/**
* 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();
if (entity instanceof Player) {
LocalPlayer player = getPlugin().wrapPlayer((Player) entity);
Session session = WorldGuard.getInstance().getPlatform().getSessionManager().get(player);
if (null != session.testMoveTo(player, BukkitAdapter.adapt(event.getMount().getLocation()), MoveType.EMBARK, true)) {
event.setCancelled(true);
}
}
}
@@ -69,7 +69,7 @@ public class RegionFlagsListener extends AbstractListener {
}
}
if (event.getCause().find(EntityType.SNOWMAN) != null) {
if (event.getCause().find(EntityType.SNOW_GOLEM) != null) {
event.filter(testState(query, Flags.SNOWMAN_TRAILS), false);
}
@@ -100,7 +100,7 @@ public class RegionFlagsListener extends AbstractListener {
event.filter(testState(query, Flags.ENDERDRAGON_BLOCK_DAMAGE), config.explosionFlagCancellation);
}
if (event.getCause().find(EntityType.ENDER_CRYSTAL) != null) { // EnderCrystal
if (event.getCause().find(EntityType.END_CRYSTAL) != null) { // EnderCrystal
event.filter(testState(query, Flags.OTHER_EXPLOSION), config.explosionFlagCancellation);
}
@@ -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;
@@ -173,7 +177,7 @@ public class RegionProtectionListener extends AbstractListener {
/* Flint and steel, fire charge, etc. */
if (Materials.isFire(type)) {
Block block = event.getCause().getFirstBlock();
boolean fire = block != null && Materials.isFire(type);
boolean fire = block != null && Materials.isFire(block.getType());
boolean lava = block != null && Materials.isLava(block.getType());
List<StateFlag> flags = new ArrayList<>();
flags.add(Flags.BLOCK_PLACE);
@@ -218,7 +222,7 @@ public class RegionProtectionListener extends AbstractListener {
String what;
/* TNT */
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.MINECART_TNT) != null) {
if (event.getCause().find(EntityType.TNT, EntityType.TNT_MINECART) != null) {
canBreak = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.BLOCK_BREAK, Flags.TNT));
what = "use dynamite";
@@ -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()))) {
@@ -586,12 +614,17 @@ public class WorldGuardEntityListener extends AbstractListener {
event.setCancelled(true);
return;
}
} else if (event.getEntityType() == EntityType.PRIMED_TNT
|| event.getEntityType() == EntityType.MINECART_TNT) {
} else if (event.getEntityType() == EntityType.TNT
|| event.getEntityType() == EntityType.TNT_MINECART) {
if (wcfg.blockTNTExplosions) {
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,16 +46,16 @@ 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) {
if (holder instanceof BlockState blockState) {
return new BlockMaterialKey(blockState);
} else if (holder instanceof DoubleChest doubleChest) {
InventoryHolder left = doubleChest.getLeftSide();
InventoryHolder left = PaperLib.isPaper() ? doubleChest.getLeftSide(false) : doubleChest.getLeftSide();
if (left instanceof Chest chest) {
return new BlockMaterialKey(chest);
} else {
@@ -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;
};
}
@@ -127,8 +136,8 @@ public final class Entities {
*/
public static boolean isMinecart(EntityType type) {
return switch(type) {
case MINECART, MINECART_CHEST, MINECART_COMMAND, MINECART_FURNACE,
MINECART_HOPPER, MINECART_MOB_SPAWNER, MINECART_TNT -> true;
case MINECART, CHEST_MINECART, COMMAND_BLOCK_MINECART, FURNACE_MINECART,
HOPPER_MINECART, SPAWNER_MINECART, TNT_MINECART -> 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;
@@ -56,7 +57,6 @@ public final class Materials {
if (tag == null) return;
tag.getValues().forEach(mat -> MATERIAL_FLAGS.put(mat, value));
}
private static Tag<Material> SIGNS_TAG = Tag.SIGNS;
static {
ENTITY_ITEMS.put(EntityType.PAINTING, Material.PAINTING);
@@ -64,22 +64,35 @@ public final class Materials {
ENTITY_ITEMS.put(EntityType.SNOWBALL, Material.SNOWBALL);
ENTITY_ITEMS.put(EntityType.FIREBALL, Material.FIRE_CHARGE);
ENTITY_ITEMS.put(EntityType.ENDER_PEARL, Material.ENDER_PEARL);
ENTITY_ITEMS.put(EntityType.THROWN_EXP_BOTTLE, Material.EXPERIENCE_BOTTLE);
ENTITY_ITEMS.put(EntityType.EXPERIENCE_BOTTLE, Material.EXPERIENCE_BOTTLE);
ENTITY_ITEMS.put(EntityType.ITEM_FRAME, Material.ITEM_FRAME);
ENTITY_ITEMS.put(EntityType.GLOW_ITEM_FRAME, Material.GLOW_ITEM_FRAME);
ENTITY_ITEMS.put(EntityType.PRIMED_TNT, Material.TNT);
ENTITY_ITEMS.put(EntityType.FIREWORK, Material.FIREWORK_ROCKET);
ENTITY_ITEMS.put(EntityType.MINECART_COMMAND, Material.COMMAND_BLOCK_MINECART);
ENTITY_ITEMS.put(EntityType.BOAT, Material.OAK_BOAT);
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.MINECART, Material.MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_CHEST, Material.CHEST_MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_FURNACE, Material.FURNACE_MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_TNT, Material.TNT_MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_HOPPER, Material.HOPPER_MINECART);
ENTITY_ITEMS.put(EntityType.SPLASH_POTION, Material.POTION);
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.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.ENDER_CRYSTAL, Material.END_CRYSTAL);
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);
@@ -101,7 +114,7 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.DETECTOR_RAIL, 0);
MATERIAL_FLAGS.put(Material.STICKY_PISTON, 0);
MATERIAL_FLAGS.put(Material.COBWEB, 0);
MATERIAL_FLAGS.put(Material.GRASS, 0);
MATERIAL_FLAGS.put(Material.SHORT_GRASS, 0);
MATERIAL_FLAGS.put(Material.DEAD_BUSH, 0);
MATERIAL_FLAGS.put(Material.PISTON, 0);
MATERIAL_FLAGS.put(Material.PISTON_HEAD, 0);
@@ -151,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);
@@ -169,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);
@@ -228,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);
@@ -248,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);
@@ -257,55 +258,9 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.BARRIER, 0);
MATERIAL_FLAGS.put(Material.STRUCTURE_VOID, 0);
// 1.12
MATERIAL_FLAGS.put(Material.BLACK_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.BLUE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.BROWN_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.CYAN_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.GRAY_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.GREEN_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.YELLOW_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.LIME_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.MAGENTA_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.ORANGE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.PINK_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.PURPLE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.RED_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.WHITE_CONCRETE, 0);
MATERIAL_FLAGS.put(Material.BLACK_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.BLUE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.BROWN_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.CYAN_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.GRAY_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.GREEN_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.YELLOW_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.LIME_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.MAGENTA_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.ORANGE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.PINK_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.PURPLE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.RED_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.WHITE_CONCRETE_POWDER, 0);
MATERIAL_FLAGS.put(Material.WHITE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.ORANGE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.MAGENTA_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.YELLOW_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.LIME_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.PINK_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.GRAY_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.CYAN_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.PURPLE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.BLUE_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.BROWN_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.GREEN_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.RED_GLAZED_TERRACOTTA, 0);
MATERIAL_FLAGS.put(Material.BLACK_GLAZED_TERRACOTTA, 0);
putMaterialTag(Tag.CONCRETE, 0);
putMaterialTag(Tag.CONCRETE_POWDERS, 0);
putMaterialTag(Tag.GLAZED_TERRACOTTA, 0);
// 1.13
MATERIAL_FLAGS.put(Material.ANDESITE, 0);
@@ -411,7 +366,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.FLETCHING_TABLE, 0);
MATERIAL_FLAGS.put(Material.GRINDSTONE, 0);
MATERIAL_FLAGS.put(Material.JIGSAW, MODIFIED_ON_RIGHT | MODIFIED_ON_LEFT);
MATERIAL_FLAGS.put(Material.LANTERN, 0);
MATERIAL_FLAGS.put(Material.LECTERN, 0);
MATERIAL_FLAGS.put(Material.LOOM, 0);
MATERIAL_FLAGS.put(Material.SCAFFOLDING, 0);
@@ -642,7 +596,7 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.PUFFERFISH_BUCKET, 0);
MATERIAL_FLAGS.put(Material.SALMON, 0);
MATERIAL_FLAGS.put(Material.SALMON_BUCKET, 0);
MATERIAL_FLAGS.put(Material.SCUTE, 0);
MATERIAL_FLAGS.put(Material.TURTLE_SCUTE, 0);
MATERIAL_FLAGS.put(Material.SPLASH_POTION, 0);
MATERIAL_FLAGS.put(Material.TURTLE_HELMET, 0);
MATERIAL_FLAGS.put(Material.TRIDENT, 0);
@@ -670,7 +624,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.ANCIENT_DEBRIS, 0);
MATERIAL_FLAGS.put(Material.BASALT, 0);
MATERIAL_FLAGS.put(Material.BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.CHAIN, 0);
MATERIAL_FLAGS.put(Material.CHISELED_NETHER_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_POLISHED_BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.CRACKED_NETHER_BRICKS, 0);
@@ -678,7 +631,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);
@@ -707,7 +659,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.SHROOMLIGHT, 0);
MATERIAL_FLAGS.put(Material.SOUL_CAMPFIRE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SOUL_FIRE, 0);
MATERIAL_FLAGS.put(Material.SOUL_LANTERN, 0);
MATERIAL_FLAGS.put(Material.SOUL_SOIL, 0);
MATERIAL_FLAGS.put(Material.SOUL_TORCH, 0);
MATERIAL_FLAGS.put(Material.SOUL_WALL_TORCH, 0);
@@ -719,7 +670,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);
@@ -730,7 +680,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.POLISHED_DEEPSLATE, 0);
MATERIAL_FLAGS.put(Material.CALCITE, 0);
MATERIAL_FLAGS.put(Material.TUFF, 0);
MATERIAL_FLAGS.put(Material.DRIPSTONE_BLOCK, 0);
MATERIAL_FLAGS.put(Material.ROOTED_DIRT, 0);
MATERIAL_FLAGS.put(Material.RAW_IRON_BLOCK, 0);
@@ -773,7 +722,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.CHISELED_DEEPSLATE, 0);
MATERIAL_FLAGS.put(Material.GLOW_LICHEN, 0);
MATERIAL_FLAGS.put(Material.LIGHT, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.LIGHTNING_ROD, 0);
MATERIAL_FLAGS.put(Material.SCULK_SENSOR, 0);
MATERIAL_FLAGS.put(Material.AMETHYST_SHARD, 0);
MATERIAL_FLAGS.put(Material.RAW_IRON, 0);
@@ -821,37 +769,72 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.ECHO_SHARD, 0);
MATERIAL_FLAGS.put(Material.REINFORCED_DEEPSLATE, 0);
// 1.20
try {
SIGNS_TAG = Tag.ALL_SIGNS;
MATERIAL_FLAGS.put(Material.BAMBOO_MOSAIC, 0);
MATERIAL_FLAGS.put(Material.BAMBOO_BLOCK, 0);
MATERIAL_FLAGS.put(Material.STRIPPED_BAMBOO_BLOCK, 0);
MATERIAL_FLAGS.put(Material.SUSPICIOUS_SAND, 0);
MATERIAL_FLAGS.put(Material.SUSPICIOUS_GRAVEL, 0);
MATERIAL_FLAGS.put(Material.PITCHER_PLANT, 0);
MATERIAL_FLAGS.put(Material.CHISELED_BOOKSHELF, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DECORATED_POT, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BRUSH, 0);
MATERIAL_FLAGS.put(Material.SNIFFER_EGG, 0);
MATERIAL_FLAGS.put(Material.CALIBRATED_SCULK_SENSOR, 0);
MATERIAL_FLAGS.put(Material.PIGLIN_HEAD, 0);
MATERIAL_FLAGS.put(Material.PIGLIN_WALL_HEAD, 0);
MATERIAL_FLAGS.put(Material.TORCHFLOWER_SEEDS, 0);
MATERIAL_FLAGS.put(Material.TORCHFLOWER_CROP, 0);
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.BAMBOO_MOSAIC, 0);
MATERIAL_FLAGS.put(Material.BAMBOO_BLOCK, 0);
MATERIAL_FLAGS.put(Material.STRIPPED_BAMBOO_BLOCK, 0);
MATERIAL_FLAGS.put(Material.SUSPICIOUS_SAND, 0);
MATERIAL_FLAGS.put(Material.SUSPICIOUS_GRAVEL, 0);
MATERIAL_FLAGS.put(Material.PITCHER_PLANT, 0);
MATERIAL_FLAGS.put(Material.CHISELED_BOOKSHELF, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DECORATED_POT, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BRUSH, 0);
MATERIAL_FLAGS.put(Material.SNIFFER_EGG, 0);
MATERIAL_FLAGS.put(Material.CALIBRATED_SCULK_SENSOR, 0);
MATERIAL_FLAGS.put(Material.PIGLIN_HEAD, 0);
MATERIAL_FLAGS.put(Material.PIGLIN_WALL_HEAD, 0);
MATERIAL_FLAGS.put(Material.TORCHFLOWER_SEEDS, 0);
MATERIAL_FLAGS.put(Material.TORCHFLOWER_CROP, 0);
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);
} catch (NoSuchFieldError ignored) {
}
MATERIAL_FLAGS.put(Material.ARMADILLO_SCUTE, 0);
MATERIAL_FLAGS.put(Material.WOLF_ARMOR, 0);
// 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);
// Generated via tag
putMaterialTag(Tag.WOODEN_DOORS, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.WOODEN_TRAPDOORS, MODIFIED_ON_RIGHT);
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);
@@ -865,10 +848,9 @@ public final class Materials {
putMaterialTag(Tag.BUTTONS, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.FLOWER_POTS, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.WALLS, 0);
putMaterialTag(SIGNS_TAG, 0);
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);
@@ -884,12 +866,87 @@ public final class Materials {
putMaterialTag(Tag.CANDLES, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.CANDLE_CAKES, MODIFIED_ON_RIGHT);
putMaterialTag(Tag.CAULDRONS, MODIFIED_ON_RIGHT);
try {
// 1.20
putMaterialTag(Tag.ITEMS_TRIM_TEMPLATES, 0);
putMaterialTag(Tag.ITEMS_DECORATED_POT_SHERDS, 0);
} catch (NoSuchFieldError ignored) {
}
// 1.20
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);
// 26.2
MATERIAL_FLAGS.put(Material.CINNABAR, 0);
MATERIAL_FLAGS.put(Material.POLISHED_CINNABAR, 0);
MATERIAL_FLAGS.put(Material.CINNABAR_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_CINNABAR, 0);
MATERIAL_FLAGS.put(Material.POTENT_SULFUR, 0);
MATERIAL_FLAGS.put(Material.SULFUR, 0);
MATERIAL_FLAGS.put(Material.POLISHED_SULFUR, 0);
MATERIAL_FLAGS.put(Material.SULFUR_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_SULFUR, 0);
putMaterialTag(Tag.SPELEOTHEMS, 0);
Stream.concat(Stream.concat(
Tag.CORAL_BLOCKS.getValues().stream(),
@@ -903,28 +960,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.SLOW);
// DAMAGE_EFFECTS.add(PotionEffectType.FAST_DIGGING);
DAMAGE_EFFECTS.add(PotionEffectType.SLOW_DIGGING);
// DAMAGE_EFFECTS.add(PotionEffectType.INCREASE_DAMAGE);
// DAMAGE_EFFECTS.add(PotionEffectType.HEAL);
DAMAGE_EFFECTS.add(PotionEffectType.HARM);
// DAMAGE_EFFECTS.add(PotionEffectType.JUMP);
DAMAGE_EFFECTS.add(PotionEffectType.CONFUSION);
DAMAGE_EFFECTS.add(PotionEffectType.SLOWNESS);
// DAMAGE_EFFECTS.add(PotionEffectType.HASTE);
DAMAGE_EFFECTS.add(PotionEffectType.MINING_FATIGUE);
// DAMAGE_EFFECTS.add(PotionEffectType.STRENGTH);
// DAMAGE_EFFECTS.add(PotionEffectType.INSTANT_HEALTH);
DAMAGE_EFFECTS.add(PotionEffectType.INSTANT_DAMAGE);
// 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);
@@ -947,6 +1009,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() {
@@ -988,13 +1055,11 @@ public final class Materials {
* @return the block material
*/
public static Material getBucketBlockMaterial(Material type) {
switch (type) {
case LAVA_BUCKET:
return Material.LAVA;
case WATER_BUCKET:
default:
return Material.WATER;
}
return switch (type) {
case LAVA_BUCKET -> Material.LAVA;
case WATER_BUCKET -> Material.WATER;
default -> Material.WATER;
};
}
/**
@@ -1135,6 +1200,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);
}
@@ -1146,25 +1215,30 @@ public final class Materials {
public static EntityType getEntitySpawnEgg(Material material) {
return switch (material) {
case ALLAY_SPAWN_EGG -> EntityType.ALLAY;
case ARMADILLO_SPAWN_EGG -> EntityType.ARMADILLO;
case AXOLOTL_SPAWN_EGG -> EntityType.AXOLOTL;
case SPIDER_SPAWN_EGG -> EntityType.SPIDER;
case BAT_SPAWN_EGG -> EntityType.BAT;
case BEE_SPAWN_EGG -> EntityType.BEE;
case BLAZE_SPAWN_EGG -> EntityType.BLAZE;
case 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;
@@ -1172,20 +1246,24 @@ 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;
case IRON_GOLEM_SPAWN_EGG -> EntityType.IRON_GOLEM;
case LLAMA_SPAWN_EGG -> EntityType.LLAMA;
case MAGMA_CUBE_SPAWN_EGG -> EntityType.MAGMA_CUBE;
case MOOSHROOM_SPAWN_EGG -> EntityType.MUSHROOM_COW;
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;
@@ -1199,10 +1277,12 @@ public final class Materials {
case SKELETON_SPAWN_EGG -> EntityType.SKELETON;
case SLIME_SPAWN_EGG -> EntityType.SLIME;
case SNIFFER_SPAWN_EGG -> EntityType.SNIFFER;
case SNOW_GOLEM_SPAWN_EGG -> EntityType.SNOWMAN;
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;
case SULFUR_CUBE_SPAWN_EGG -> EntityType.SULFUR_CUBE;
case TADPOLE_SPAWN_EGG -> EntityType.TADPOLE;
case TRADER_LLAMA_SPAWN_EGG -> EntityType.TRADER_LLAMA;
case TROPICAL_FISH_SPAWN_EGG -> EntityType.TROPICAL_FISH;
@@ -1213,15 +1293,15 @@ public final class Materials {
case WANDERING_TRADER_SPAWN_EGG -> EntityType.WANDERING_TRADER;
case WARDEN_SPAWN_EGG -> EntityType.WARDEN;
case WITCH_SPAWN_EGG -> EntityType.WITCH;
case WITHER_SPAWN_EGG -> EntityType.WITHER;
case WITHER_SKELETON_SPAWN_EGG -> EntityType.WITHER_SKELETON;
case WITHER_SPAWN_EGG -> EntityType.WITHER;
case WOLF_SPAWN_EGG -> EntityType.WOLF;
case ZOGLIN_SPAWN_EGG -> EntityType.ZOGLIN;
case ZOMBIE_HORSE_SPAWN_EGG -> EntityType.ZOMBIE_HORSE;
case ZOMBIFIED_PIGLIN_SPAWN_EGG -> EntityType.ZOMBIFIED_PIGLIN;
case ZOMBIE_NAUTILUS_SPAWN_EGG -> EntityType.ZOMBIE_NAUTILUS;
case ZOMBIE_SPAWN_EGG -> EntityType.ZOMBIE;
case ZOMBIE_VILLAGER_SPAWN_EGG -> EntityType.ZOMBIE_VILLAGER;
case PIG_SPAWN_EGG -> EntityType.PIG;
case ZOMBIFIED_PIGLIN_SPAWN_EGG -> EntityType.ZOMBIFIED_PIGLIN;
default -> null;
};
}
@@ -1251,7 +1331,7 @@ public final class Materials {
// yea, that's not all, there are some more
return switch (type) {
case PUMPKIN, MELON, CACTUS, SUGAR_CANE, BAMBOO, BAMBOO_SAPLING,
SWEET_BERRY_BUSH, NETHER_WART, CAVE_VINES, CAVE_VINES_PLANT ->
SWEET_BERRY_BUSH, NETHER_WART, CAVE_VINES, CAVE_VINES_PLANT, COCOA ->
true;
default -> false;
};
@@ -1283,15 +1363,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;
};
}
@@ -1343,7 +1423,8 @@ public final class Materials {
|| type == Material.DRAGON_EGG
|| Tag.FLOWER_POTS.isTagged(type)
|| Tag.CANDLES.isTagged(type)
|| Tag.CANDLE_CAKES.isTagged(type);
|| Tag.CANDLE_CAKES.isTagged(type)
|| Tag.ALL_SIGNS.isTagged(type);
}
/**
@@ -1373,15 +1454,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;
};
}
@@ -1400,6 +1479,7 @@ public final class Materials {
switch (toolMaterial) {
case WOODEN_HOE:
case STONE_HOE:
case COPPER_HOE:
case IRON_HOE:
case GOLDEN_HOE:
case DIAMOND_HOE:
@@ -1411,6 +1491,7 @@ public final class Materials {
};
case WOODEN_AXE:
case STONE_AXE:
case COPPER_AXE:
case IRON_AXE:
case GOLDEN_AXE:
case DIAMOND_AXE:
@@ -1425,6 +1506,7 @@ public final class Materials {
};
case WOODEN_SHOVEL:
case STONE_SHOVEL:
case COPPER_SHOVEL:
case IRON_SHOVEL:
case GOLDEN_SHOVEL:
case DIAMOND_SHOVEL:
@@ -1456,14 +1538,17 @@ public final class Materials {
case YELLOW_DYE:
case GLOW_INK_SAC:
case INK_SAC:
return SIGNS_TAG.isTagged(targetMaterial);
return Tag.ALL_SIGNS.isTagged(targetMaterial);
case HONEYCOMB:
return isUnwaxedCopper(targetMaterial) || SIGNS_TAG.isTagged(targetMaterial);
return isUnwaxedCopper(targetMaterial) || Tag.ALL_SIGNS.isTagged(targetMaterial);
case BRUSH:
return switch (targetMaterial) {
case SUSPICIOUS_GRAVEL, SUSPICIOUS_SAND -> true;
default -> false;
};
case WRITTEN_BOOK:
case WRITABLE_BOOK:
return targetMaterial == Material.LECTERN;
default:
return false;
}
@@ -1472,27 +1557,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.2"
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"])
}
}
@@ -24,6 +24,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldguard.domains.registry.DomainRegistry;
import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry;
import com.sk89q.worldguard.util.profile.cache.HashMapCache;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import com.sk89q.worldguard.util.profile.cache.SQLiteCache;
@@ -55,6 +57,7 @@ public final class WorldGuard {
private WorldGuardPlatform platform;
private final SimpleFlagRegistry flagRegistry = new SimpleFlagRegistry();
private final SimpleDomainRegistry domainRegistry = new SimpleDomainRegistry();
private final Supervisor supervisor = new SimpleSupervisor();
private ProfileCache profileCache;
private ProfileService profileService;
@@ -116,6 +119,16 @@ public final class WorldGuard {
return this.flagRegistry;
}
/**
* Get the domain registry.
*
* @return the domain registry
*/
public DomainRegistry getDomainRegistry() {
return this.domainRegistry;
}
/**
* Get the supervisor.
*
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -42,10 +43,12 @@ public class BanAction implements Action {
if (event.getPlayer() != null) {
String message = entry.getMessage();
String friendlyName = PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent());
if (message != null) {
event.getPlayer().ban("Banned: " + String.format(message, event.getTarget().getFriendlyName()));
event.getPlayer().ban("Banned: " + String.format(message, friendlyName));
} else {
event.getPlayer().ban("Banned: You can't " + event.getDescription() + " " + event.getTarget().getFriendlyName());
event.getPlayer().ban("Banned: You can't " + event.getDescription() + " " + friendlyName);
}
}
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -42,10 +43,12 @@ public class KickAction implements Action {
if (event.getPlayer() != null) {
String message = entry.getMessage();
String friendlyName = PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent());
if (message != null) {
event.getPlayer().kick(String.format(message, event.getTarget().getFriendlyName()));
event.getPlayer().kick(String.format(message, friendlyName));
} else {
event.getPlayer().kick("You can't " + event.getDescription() + " " + event.getTarget().getFriendlyName());
event.getPlayer().kick("You can't " + event.getDescription() + " " + friendlyName);
}
}
@@ -19,6 +19,8 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -44,9 +46,10 @@ public class TellAction extends RepeatGuardedAction {
if (event.getPlayer() != null) {
if (message != null) {
message = message.replaceAll("(?!<\\\\)\\\\n", "\n").replaceAll("\\\\\\\\n", "\\n");
event.getPlayer().print(String.format(message, event.getTarget().getFriendlyName()));
// TODO Find a better way to do this String.format call that doesn't require a string.
event.getPlayer().print(TextComponent.of(String.format(message, PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent()))));
} else {
event.getPlayer().printError("You're not allowed to " + event.getDescription() + " " + event.getTarget().getFriendlyName() + ".");
event.getPlayer().printError(TextComponent.of("You're not allowed to " + event.getDescription() + " ").append(event.getTarget().getFriendlyNameComponent()).append(TextComponent.of(".")));
}
}
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -40,7 +41,7 @@ abstract class BlockBlacklistEvent extends AbstractBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPlayerName() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPlayerName() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -45,7 +46,7 @@ public final class BlockDispenseBlacklistEvent extends BlockBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPosition() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPosition() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -40,7 +41,7 @@ abstract class ItemBlacklistEvent extends AbstractBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPlayerName() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPlayerName() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -95,9 +95,9 @@ public class DatabaseHandler implements LoggerHandler {
stmt.setString(1, eventType.name());
stmt.setString(2, worldName);
stmt.setString(3, player != null ? player.getName() : "");
stmt.setInt(4, pos.getBlockX());
stmt.setInt(5, pos.getBlockY());
stmt.setInt(6, pos.getBlockZ());
stmt.setInt(4, pos.x());
stmt.setInt(5, pos.y());
stmt.setInt(6, pos.z());
stmt.setString(7, item);
stmt.setInt(8, (int)(System.currentTimeMillis() / 1000));
stmt.setString(9, comment);
@@ -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;
@@ -221,11 +222,11 @@ public class FileHandler implements LoggerHandler {
* @return The position's coordinates in human-readable form
*/
private String getCoordinates(BlockVector3 pos) {
return "@" + pos.getBlockX() + "," + pos.getBlockY() + "," + pos.getBlockZ();
return "@" + pos.x() + "," + pos.y() + "," + pos.z();
}
private void logEvent(BlacklistEvent event, String text, Target target, BlockVector3 pos, String comment) {
log(event.getPlayer(), "Tried to " + text + " " + target.getFriendlyName() + " " + getCoordinates(pos), comment);
log(event.getPlayer(), "Tried to " + text + " " + PlainComponentSerializer.INSTANCE.serialize(target.getFriendlyNameComponent()) + " " + getCoordinates(pos), comment);
}
@Override
@@ -19,11 +19,12 @@
package com.sk89q.worldguard.blacklist.target;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.block.BlockType;
public class BlockTarget implements Target {
private BlockType type;
private final BlockType type;
public BlockTarget(BlockType type) {
this.type = type;
@@ -31,11 +32,16 @@ public class BlockTarget implements Target {
@Override
public String getTypeId() {
return type.getId();
return type.id();
}
@Override
public String getFriendlyName() {
return type.getName();
}
@Override
public Component getFriendlyNameComponent() {
return type.getRichName();
}
}
@@ -19,11 +19,12 @@
package com.sk89q.worldguard.blacklist.target;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.item.ItemType;
public class ItemTarget implements Target {
private ItemType type;
private final ItemType type;
public ItemTarget(ItemType type) {
this.type = type;
@@ -31,7 +32,7 @@ public class ItemTarget implements Target {
@Override
public String getTypeId() {
return type.getId();
return type.id();
}
@Override
@@ -39,4 +40,8 @@ public class ItemTarget implements Target {
return type.getName();
}
@Override
public Component getFriendlyNameComponent() {
return type.getRichName();
}
}
@@ -19,6 +19,9 @@
package com.sk89q.worldguard.blacklist.target;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
/**
* A target is something that can have events attached to it.
*/
@@ -35,7 +38,18 @@ public interface Target {
* Get a friendly name to be printed.
*
* @return a friendly name
* @deprecated Use {@link #getFriendlyNameComponent()} instead, which supports more complex formatting.
*/
@Deprecated
String getFriendlyName();
/**
* Get a friendly name to be printed.
*
* @return a friendly name
*/
default Component getFriendlyNameComponent() {
return TextComponent.of(getFriendlyName());
}
}
@@ -0,0 +1,111 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.commands;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.LocalPlayer;
import javax.annotation.Nullable;
import java.util.Map;
public abstract class CommandInputContext<T extends Exception> {
protected final Actor sender;
protected final String input;
protected Map<String, Object> context;
protected CommandInputContext(Actor sender, String input, Map<String, Object> values) {
this.sender = sender;
this.input = input;
this.context = values;
}
public void put(String name, Object value) {
context.put(name, value);
}
public Actor getSender() {
return sender;
}
public String getUserInput() {
return input;
}
/**
* Gets the CommandSender as a player.
*
* @return Player
* @throws T if the sender is not a player
*/
public LocalPlayer getPlayerSender() throws T {
if (sender.isPlayer() && sender instanceof LocalPlayer) {
return (LocalPlayer) sender;
} else {
throw createException("Not a player");
}
}
public Integer getUserInputAsInt() throws T {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw createException("Not a number: " + input);
}
}
public Double getUserInputAsDouble() throws T {
try {
return Double.parseDouble(input);
} catch (NumberFormatException e) {
throw createException("Not a number: " + input);
}
}
protected abstract T createException(String str);
/**
* Get an object from the context by key name.
* May return null if the object does not exist in the context.
*
* @param name key name of the object
* @return the object matching the key, or null
*/
@Nullable
public Object get(String name) {
return get(name, null);
}
/**
* Get an object from the context by key name.
* Will only return null if
* a) you provide null as the default
* b) the key has explicity been set to null
*
* @param name key name of the object
* @return the object matching the key
*/
@Nullable
public Object get(String name, Object defaultValue) {
Object obj;
return (((obj = context.get(name)) != null) || context.containsKey(name)
? obj : defaultValue);
}
}
@@ -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 {
@@ -378,7 +378,7 @@ class FlagHelperBox extends PaginationBox {
if (currVal == null) {
currVal = getInheritedValue(region, flag);
}
String display = currVal == null ? regName : currVal.getId();
String display = currVal == null ? regName : currVal.id();
appendValueText(builder, flag, display, null);
}
@@ -25,16 +25,27 @@ import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.worldedit.command.util.AsyncCommandBuilder;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.domains.registry.DomainFactory;
import com.sk89q.worldguard.domains.registry.DomainRegistry;
import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.util.DomainInputResolver;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
public class MemberCommands extends RegionCommandsBase {
@@ -67,6 +78,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
resolver.setActor(sender);
resolver.setRegion(region);
final String description = String.format("Adding members to the region '%s' on '%s'", region.getId(), world.getName());
@@ -101,7 +114,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
resolver.setActor(sender);
resolver.setRegion(region);
final String description = String.format("Adding owners to the region '%s' on '%s'", region.getId(), world.getName());
AsyncCommandBuilder.wrap(checkedAddOwners(sender, manager, region, world, resolver), sender)
@@ -174,6 +188,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
resolver.setActor(sender);
resolver.setRegion(region);
callable = resolver;
}
@@ -217,6 +233,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
resolver.setActor(sender);
resolver.setRegion(region);
callable = resolver;
}
@@ -59,7 +59,7 @@ import com.sk89q.worldguard.protection.FlagValueCalculator;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormatException;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.RegionGroupFlag;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
@@ -76,7 +76,6 @@ import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import com.sk89q.worldguard.protection.util.WorldEditRegionConverter;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.util.Enums;
@@ -160,7 +159,7 @@ public final class RegionCommands extends RegionCommandsBase {
region = checkRegionFromSelection(sender, id);
}
RegionAdder task = new RegionAdder(manager, region);
RegionAdder task = new RegionAdder(manager, region, sender);
task.addOwnersFromCommand(args, 2);
final String description = String.format("Adding region '%s'", region.getId());
@@ -214,7 +213,7 @@ public final class RegionCommands extends RegionCommandsBase {
region.copyFrom(existing);
RegionAdder task = new RegionAdder(manager, region);
RegionAdder task = new RegionAdder(manager, region, sender);
final String description = String.format("Updating region '%s'", region.getId());
AsyncCommandBuilder.wrap(task, sender)
@@ -351,6 +350,7 @@ public final class RegionCommands extends RegionCommandsBase {
World world = checkWorld(args, sender, 'w');
RegionManager manager = checkRegionManager(world);
ProtectedRegion existing;
RegionPermissionModel permissionModel = getPermissionModel(sender);
// If no arguments were given, get the region that the player is inside
if (args.argsLength() == 0) {
@@ -359,13 +359,13 @@ public final class RegionCommands extends RegionCommandsBase {
throw new CommandException("Please specify a region name."); // just don't allow that
}
world = player.getWorld();
existing = checkRegionStandingIn(manager, player, "/rg select -w \"" + world.getName() + "\" %id%");
existing = checkRegionStandingIn(manager, player, "/rg select -w \"" + world.getName() + "\" %id%", permissionModel::maySelect);
} else {
existing = checkExistingRegion(manager, args.getString(0), false);
}
// Check permissions
if (!getPermissionModel(sender).maySelect(existing)) {
if (!permissionModel.maySelect(existing)) {
throw new CommandPermissionsException();
}
@@ -401,7 +401,7 @@ public final class RegionCommands extends RegionCommandsBase {
}
existing = checkRegionStandingIn(manager, (LocalPlayer) sender, true,
"/rg info -w \"" + world.getName() + "\" %id%" + (args.hasFlag('u') ? " -u" : "") + (args.hasFlag('s') ? " -s" : ""));
"/rg info -w \"" + world.getName() + "\" %id%" + (args.hasFlag('u') ? " -u" : "") + (args.hasFlag('s') ? " -s" : ""), permModel::mayLookup);
} else { // Get region from the ID
existing = checkExistingRegion(manager, args.getString(0), true);
}
@@ -587,7 +587,7 @@ public final class RegionCommands extends RegionCommandsBase {
// the [value] part throws an error.
try {
groupValue = groupFlag.parseInput(FlagContext.create().setSender(sender).setInput(group).setObject("region", existing).build());
} catch (InvalidFlagFormat e) {
} catch (InvalidFlagFormatException e) {
throw new CommandException(e.getMessage());
}
@@ -598,7 +598,7 @@ public final class RegionCommands extends RegionCommandsBase {
// Set the flag if [value] was given even if [-g group] was given as well
try {
value = setFlag(existing, foundFlag, sender, value).toString();
} catch (InvalidFlagFormat e) {
} catch (InvalidFlagFormatException e) {
throw new CommandException(e.getMessage());
}
@@ -661,18 +661,19 @@ public final class RegionCommands extends RegionCommandsBase {
// Lookup the existing region
RegionManager manager = checkRegionManager(world);
ProtectedRegion region;
final RegionPermissionModel perms = getPermissionModel(sender);
if (args.argsLength() == 0) { // Get region from where the player is
if (!(sender instanceof LocalPlayer)) {
throw new CommandException("Please specify the region with /region flags -w world_name region_name.");
}
region = checkRegionStandingIn(manager, (LocalPlayer) sender, true,
"/rg flags -w \"" + world.getName() + "\" %id%");
"/rg flags -w \"" + world.getName() + "\" %id%", perms::mayLookup);
} else { // Get region from the ID
region = checkExistingRegion(manager, args.getString(0), true);
}
final RegionPermissionModel perms = getPermissionModel(sender);
if (!perms.mayLookup(region)) {
throw new CommandPermissionsException();
}
@@ -32,15 +32,12 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.util.formatting.text.format.TextDecoration;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
@@ -48,7 +45,7 @@ import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormatException;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
@@ -59,6 +56,7 @@ import com.sk89q.worldguard.protection.regions.RegionQuery.QueryOption;
import com.sk89q.worldguard.protection.util.WorldEditRegionConverter;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
class RegionCommandsBase {
@@ -178,11 +176,13 @@ class RegionCommandsBase {
*
* @param regionManager the region manager
* @param player the player
* @param rgCmd the command to construct when clicking one of multiple items
* @param permissionPredicate a predicate to filter regions based on permission access
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, String rgCmd) throws CommandException {
return checkRegionStandingIn(regionManager, player, false, rgCmd);
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, String rgCmd, Predicate<ProtectedRegion> permissionPredicate) throws CommandException {
return checkRegionStandingIn(regionManager, player, false, rgCmd, permissionPredicate);
}
/**
@@ -197,10 +197,12 @@ class RegionCommandsBase {
* @param regionManager the region manager
* @param player the player
* @param allowGlobal whether to search for a global region if no others are found
* @param rgCmd the command to construct when clicking one of multiple items
* @param permissionPredicate a predicate to filter regions based on permission access
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, boolean allowGlobal, String rgCmd) throws CommandException {
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, boolean allowGlobal, String rgCmd, Predicate<ProtectedRegion> permissionPredicate) throws CommandException {
ApplicableRegionSet set = regionManager.getApplicableRegions(player.getLocation().toVector().toBlockPoint(), QueryOption.SORT);
if (set.size() == 0) {
@@ -215,20 +217,30 @@ class RegionCommandsBase {
"Specify an ID if you want to select a specific region.");
} else if (set.size() > 1) {
boolean first = true;
Set<ProtectedRegion> filteredRegions = set.getRegions().stream().filter(permissionPredicate).collect(Collectors.toSet());
int hiddenRegions = set.size() - filteredRegions.size();
final TextComponent.Builder builder = TextComponent.builder("");
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
for (ProtectedRegion region : set) {
if (!first) {
builder.append(TextComponent.of(", "));
if (!filteredRegions.isEmpty()) {
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
for (ProtectedRegion region : filteredRegions) {
if (!first) {
builder.append(TextComponent.of(", "));
}
first = false;
TextComponent regionComp = TextComponent.of(region.getId(), TextColor.AQUA);
if (rgCmd != null && rgCmd.contains("%id%")) {
regionComp = regionComp.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to pick this region")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, rgCmd.replace("%id%", region.getId())));
}
builder.append(regionComp);
}
first = false;
TextComponent regionComp = TextComponent.of(region.getId(), TextColor.AQUA);
if (rgCmd != null && rgCmd.contains("%id%")) {
regionComp = regionComp.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to pick this region")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, rgCmd.replace("%id%", region.getId())));
if (hiddenRegions > 0) {
builder.append(TextComponent.of(", and " + hiddenRegions + " hidden regions", TextColor.GRAY));
}
builder.append(regionComp);
} else {
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
builder.append(TextComponent.of(hiddenRegions + " hidden regions", TextColor.GRAY));
}
player.print(builder.build());
throw new CommandException("You're standing in several regions (please pick one).");
@@ -308,8 +320,8 @@ class RegionCommandsBase {
// Detect the type of region from WorldEdit
if (selection instanceof Polygonal2DRegion) {
Polygonal2DRegion polySel = (Polygonal2DRegion) selection;
int minY = polySel.getMinimumPoint().getBlockY();
int maxY = polySel.getMaximumPoint().getBlockY();
int minY = polySel.getMinimumPoint().y();
int maxY = polySel.getMaximumPoint().y();
return new ProtectedPolygonalRegion(id, polySel.getPoints(), minY, maxY);
} else if (selection instanceof CuboidRegion) {
BlockVector3 min = selection.getMinimumPoint();
@@ -348,7 +360,7 @@ class RegionCommandsBase {
if (region instanceof GlobalProtectedRegion) {
return;
}
int height = region.getMaximumPoint().getBlockY() - region.getMinimumPoint().getBlockY();
int height = region.getMaximumPoint().y() - region.getMinimumPoint().y();
if (height <= 2) {
sender.printDebug("(Warning: The height of the region was " + (height + 1) + " block(s).)");
}
@@ -418,9 +430,9 @@ class RegionCommandsBase {
* @param flag the flag
* @param sender the sender
* @param value the value
* @throws InvalidFlagFormat thrown if the value is invalid
* @throws InvalidFlagFormatException thrown if the value is invalid
*/
protected static <V> V setFlag(ProtectedRegion region, Flag<V> flag, Actor sender, String value) throws InvalidFlagFormat {
protected static <V> V setFlag(ProtectedRegion region, Flag<V> flag, Actor sender, String value) throws InvalidFlagFormatException {
V val = flag.parseInput(FlagContext.create().setSender(sender).setInput(value).setObject("region", region).build());
region.setFlag(flag, val);
return val;
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.commands.task;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.managers.RegionManager;
@@ -39,6 +40,7 @@ public class RegionAdder implements Callable<ProtectedRegion> {
private final RegionManager manager;
private final ProtectedRegion region;
private final Actor actor;
@Nullable
private String[] ownersInput;
private UserLocatorPolicy locatorPolicy = UserLocatorPolicy.UUID_ONLY;
@@ -46,15 +48,26 @@ public class RegionAdder implements Callable<ProtectedRegion> {
/**
* Create a new instance.
*
* @param manager the manage
* @param manager the manager
* @param region the region
*/
public RegionAdder(RegionManager manager, ProtectedRegion region) {
this(manager, region, null);
}
/**
* Create a new instance.
* @param manager the manager
* @param region the region
* @param actor the actor
*/
public RegionAdder(RegionManager manager, ProtectedRegion region, Actor actor) {
checkNotNull(manager);
checkNotNull(region);
this.manager = manager;
this.region = region;
this.actor = actor;
}
/**
@@ -75,6 +88,9 @@ public class RegionAdder implements Callable<ProtectedRegion> {
if (ownersInput != null) {
DomainInputResolver resolver = new DomainInputResolver(WorldGuard.getInstance().getProfileService(), ownersInput);
resolver.setLocatorPolicy(locatorPolicy);
resolver.setActor(actor);
resolver.setRegion(region);
DefaultDomain domain = resolver.call();
region.getOwners().addAll(domain);
}
@@ -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;
@@ -0,0 +1,108 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.domains.registry.CustomDomainContext;
import com.sk89q.worldguard.domains.registry.InvalidDomainFormatException;
import com.sk89q.worldguard.util.ChangeTracked;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class CustomDomain implements Domain, ChangeTracked {
private static final Pattern VALID_NAME = Pattern.compile("^[a-z0-9\\-]{1,40}$");
private final String name;
private boolean dirty;
public CustomDomain(String name) {
if (name == null ||!isValidName(name)) {
throw new IllegalArgumentException("Invalid Domain name used.");
}
this.name = name;
}
/**
* Get the name of the domain resolver.
*
* @return The name of the domain
*/
public String getName() {
return name;
}
/**
* Parse a given input to fill the context of the CustomDomain.
*
* @param context the {@link CustomDomainContext}
* @throws InvalidDomainFormatException Raised if the input is invalid
*/
public abstract void parseInput(CustomDomainContext context) throws InvalidDomainFormatException;
/**
* Convert a raw type that was loaded (from a YAML file, for example)
* into the custom domain.
*
* @param o The object
*/
public abstract void unmarshal(Object o);
/**
* Convert the current Domain to a storable foramt
*
* @return The marshalled type
*/
public abstract Object marshal();
/**
* Test whether a flag name is valid.
*
* @param name The flag name
* @return Whether the name is valid
*/
public static boolean isValidName(String name) {
checkNotNull(name, "name");
// g is already reserved by the group domain
return VALID_NAME.matcher(name).matches() && !name.equalsIgnoreCase("g");
}
@Override
public boolean contains(LocalPlayer player) {
return contains(player.getUniqueId());
}
@Override
public int size() {
return 1;
}
@Override
public boolean isDirty() {
return dirty;
}
@Override
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
}
@@ -22,8 +22,6 @@ package com.sk89q.worldguard.domains;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sk89q.worldguard.util.profile.Profile;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
@@ -31,14 +29,19 @@ import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.util.ChangeTracked;
import com.sk89q.worldguard.util.profile.Profile;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -50,6 +53,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
private PlayerDomain playerDomain = new PlayerDomain();
private GroupDomain groupDomain = new GroupDomain();
private final Map<String, CustomDomain> customDomains = new ConcurrentHashMap<>();
private boolean customDomainsChanged = false;
/**
* Create a new domain.
*/
@@ -64,6 +70,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
public DefaultDomain(DefaultDomain existing) {
setPlayerDomain(existing.getPlayerDomain());
setGroupDomain(existing.getGroupDomain());
setCustomDomains(existing.customDomains);
}
/**
@@ -104,6 +111,72 @@ public class DefaultDomain implements Domain, ChangeTracked {
this.groupDomain = new GroupDomain(groupDomain);
}
/**
* Add new custom domains
*
* @param customDomain a domain
*/
public void addCustomDomain(CustomDomain customDomain) {
checkNotNull(customDomain);
this.customDomains.put(customDomain.getName(), customDomain);
this.customDomainsChanged = true;
}
/**
* Remove a custom domain matched by the name
*
* @param name the name
*/
public void removeCustomDomain(String name) {
checkNotNull(name);
if (this.customDomains.remove(name) != null) {
this.customDomainsChanged = true;
}
}
/**
* Remove a custom domain
*
* @param customDomain a domain
*/
public void removeCustomDomain(CustomDomain customDomain) {
checkNotNull(customDomain);
if (this.customDomains.remove(customDomain.getName()) != null) {
this.customDomainsChanged = true;
}
}
/**
* Set the api domains to a specified value
*
* @param customDomains the domains
*/
public void setCustomDomains(Map<String, CustomDomain> customDomains) {
checkNotNull(customDomains);
this.customDomains.clear();
this.customDomains.putAll(customDomains);
this.customDomainsChanged = true;
}
/**
* Get all api domains
*
* @return a unmodifiable copy of the domains
*/
public Collection<CustomDomain> getCustomDomains() {
return Collections.unmodifiableCollection(this.customDomains.values());
}
/**
* Get the api domain specified by its name
*
* @param name the name of the domain
* @return the custom domain
*/
public @Nullable CustomDomain getCustomDomain(String name) {
return this.customDomains.get(name);
}
/**
* Add the given player to the domain, identified by the player's name.
*
@@ -175,6 +248,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
for (String group : other.getGroups()) {
addGroup(group);
}
for (CustomDomain domain : other.getCustomDomains()) {
addCustomDomain(domain);
}
}
/**
@@ -193,6 +269,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
for (String group : other.getGroups()) {
removeGroup(group);
}
for (CustomDomain domain : other.getCustomDomains()) {
removeCustomDomain(domain.getName());
}
}
/**
@@ -242,12 +321,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
@Override
public boolean contains(LocalPlayer player) {
return playerDomain.contains(player) || groupDomain.contains(player);
return playerDomain.contains(player) || groupDomain.contains(player) || customDomains.values().stream().anyMatch(d -> d.contains(player));
}
@Override
public boolean contains(UUID uniqueId) {
return playerDomain.contains(uniqueId);
return playerDomain.contains(uniqueId) || customDomains.values().stream().anyMatch(d -> d.contains(uniqueId));
}
@Override
@@ -257,7 +336,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
@Override
public int size() {
return groupDomain.size() + playerDomain.size();
return groupDomain.size() + playerDomain.size() + customDomains.size();
}
@Override
@@ -275,7 +354,6 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
public String toPlayersString(@Nullable ProfileCache cache) {
StringBuilder str = new StringBuilder();
List<String> output = new ArrayList<>();
for (String name : playerDomain.getPlayers()) {
@@ -299,13 +377,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
output.sort(String.CASE_INSENSITIVE_ORDER);
for (Iterator<String> it = output.iterator(); it.hasNext();) {
str.append(it.next());
if (it.hasNext()) {
str.append(", ");
}
}
return str.toString();
return String.join(", ", output);
}
public String toGroupsString() {
@@ -320,25 +392,20 @@ public class DefaultDomain implements Domain, ChangeTracked {
return str.toString();
}
public String toUserFriendlyString() {
StringBuilder str = new StringBuilder();
if (playerDomain.size() > 0) {
str.append(toPlayersString());
public String toCustomDomainsString() {
List<String> output = new ArrayList<>();
for (CustomDomain customDomain : customDomains.values()) {
output.add(customDomain.getName() + ":" + customDomain.toString());
}
if (groupDomain.size() > 0) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toGroupsString());
}
return str.toString();
output.sort(String.CASE_INSENSITIVE_ORDER);
return String.join(", ", output);
}
public String toUserFriendlyString(ProfileCache cache) {
public String toUserFriendlyString() {
return toUserFriendlyString(null);
}
public String toUserFriendlyString(@Nullable ProfileCache cache) {
StringBuilder str = new StringBuilder();
if (playerDomain.size() > 0) {
@@ -352,6 +419,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
str.append(toGroupsString());
}
if (!customDomains.isEmpty()) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toCustomDomainsString());
}
return str.toString();
}
@@ -367,6 +440,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
builder.append(toGroupsComponent());
}
if (!customDomains.isEmpty()) {
if (playerDomain.size() > 0 || groupDomain.size() > 0) {
builder.append(TextComponent.of("; "));
}
builder.append(toCustomDomainsComponent());
}
return builder.build();
}
@@ -442,21 +521,39 @@ public class DefaultDomain implements Domain, ChangeTracked {
return builder.build();
}
private Component toCustomDomainsComponent() {
final TextComponent.Builder builder = TextComponent.builder("");
for (Iterator<CustomDomain> it = customDomains.values().iterator(); it.hasNext(); ) {
CustomDomain domain = it.next();
builder.append(TextComponent.of(domain.getName() + ":", TextColor.LIGHT_PURPLE))
.append(TextComponent.of(domain.toString(), TextColor.GOLD));
if (it.hasNext()) {
builder.append(TextComponent.of(", "));
}
}
return builder.build().hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("CustomDomain")));
}
@Override
public boolean isDirty() {
return playerDomain.isDirty() || groupDomain.isDirty();
return playerDomain.isDirty() || groupDomain.isDirty() ||
customDomainsChanged || customDomains.values().stream().anyMatch(ChangeTracked::isDirty);
}
@Override
public void setDirty(boolean dirty) {
playerDomain.setDirty(dirty);
groupDomain.setDirty(dirty);
customDomainsChanged = dirty;
customDomains.values().forEach(d -> d.setDirty(dirty));
}
@Override
public String toString() {
return "{players=" + playerDomain +
", groups=" + groupDomain +
", custom=" + customDomains +
'}';
}
@@ -0,0 +1,98 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.commands.CommandInputContext;
import javax.annotation.Nullable;
import java.util.Map;
public final class CustomDomainContext extends CommandInputContext<InvalidDomainFormatException> {
private CustomDomainContext(Actor sender, String input, Map<String, Object> values) {
super(sender, input, values);
}
public static CustomDomainContext.CustomDomainContextBuilder create() {
return new CustomDomainContext.CustomDomainContextBuilder();
}
/**
* Create a copy of this CustomDomainContext, with optional substitutions for values
*
* <p>If any supplied variable is null, it will be ignored.
* If a map is supplied, it will override this CustomDomainContext's values of the same key,
* but unprovided keys will not be overriden and will be returned as shallow copies.</p>
*
* @param commandSender CommandSender for the new CustomDomainContext to run under
* @param s String of the user input for the new CustomDomainContext
* @param values map of values to override from the current CustomDomainContext
* @return a copy of this CustomDomainContext
*/
public CustomDomainContext copyWith(@Nullable Actor commandSender, @Nullable String s, @Nullable Map<String, Object> values) {
Map<String, Object> map = Maps.newHashMap();
map.putAll(context);
if (values != null) {
map.putAll(values);
}
return new CustomDomainContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map);
}
@Override
protected InvalidDomainFormatException createException(String str) {
return new InvalidDomainFormatException(str);
}
public static class CustomDomainContextBuilder {
private Actor sender;
private String input;
private Map<String, Object> map = Maps.newHashMap();
public CustomDomainContextBuilder setSender(Actor sender) {
this.sender = sender;
return this;
}
public CustomDomainContextBuilder setInput(String input) {
this.input = input;
return this;
}
public CustomDomainContextBuilder setObject(String key, Object value) {
this.map.put(key, value);
return this;
}
public boolean tryAddToMap(String key, Object value) {
if (map.containsKey(key)) return false;
this.map.put(key, value);
return true;
}
public CustomDomainContext build() {
return new CustomDomainContext(sender, input, map);
}
}
}
@@ -0,0 +1,26 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
public class DomainConflictException extends RuntimeException {
public DomainConflictException(String message) {
super(message);
}
}
@@ -0,0 +1,28 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
@FunctionalInterface
public interface DomainFactory<T extends CustomDomain> {
T create(String name);
}
@@ -0,0 +1,94 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
public interface DomainRegistry extends Iterable<DomainFactory<?>> {
/**
* Register a new Domain
*
* <p>There may be an appropiate time to register domains. if domains are
* registered outside this time, then an exception may be thrown.</p>
*
* @param domain The domain
* @throws DomainConflictException Thrown when already an existing domain exists with the same name
* @throws IllegalStateException If it is not the right time to register new domains
*/
void register(String name, DomainFactory<?> domain) throws DomainConflictException;
/**
* Register a collection of domains.
*
* <p>There may be an appropriate time to register domains. If domains are
* registered outside this time, then an exception may be thrown.</p>
*
* <p>If there is a domain conflict, then an error will be logged but
* no exception will be thrown.</p>
*
* @param domains a collection of domain factories
* @throws IllegalStateException If it is not the right time to register new domains
*/
void registerAll(Map<String, DomainFactory<?>> domains);
/**
* Get the domain by its name.
*
* @param name The name
* @return The domain, if it has been registered
*/
@Nullable
DomainFactory<?> get(String name);
/**
* Try to get a domain by its name
*/
@Nullable
CustomDomain createDomain(String name);
/**
* Get all domains keyed by the registered name
*
* @return All domains
*/
Map<String, DomainFactory<?>> getAll();
/**
* Unmarshal a raw map of values into a list of domains with their
* unmarshalled values.
*
* @param rawValues The raw values map
* @param createUnknown Whether "just in time" domains should be created for unknown domains
* @return The unmarshalled domain list
*/
Map<String, CustomDomain> unmarshal(Map<String, Object> rawValues, boolean createUnknown);
/**
* Get the number of registered domains.
*
* @return The number of registered domains
*/
int size();
}
@@ -0,0 +1,28 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
public class InvalidDomainFormatException extends Exception {
private static final long serialVersionUID = 8101615074524004172L;
public InvalidDomainFormatException(String msg) {
super(msg);
}
}
@@ -0,0 +1,166 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.sk89q.worldguard.domains.CustomDomain;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
public class SimpleDomainRegistry implements DomainRegistry {
private static final Logger log = Logger.getLogger(SimpleDomainRegistry.class.getCanonicalName());
private final Object lock = new Object();
private final ConcurrentMap<String, DomainFactory<?>> domains = Maps.newConcurrentMap();
private boolean initialized = false;
public boolean isInitialized() {
return initialized;
}
public void setInitialized(boolean initialized) {
this.initialized = initialized;
}
@Override
public void register(String name, DomainFactory<?> domain) throws DomainConflictException {
synchronized (lock) {
if (initialized) {
throw new IllegalStateException("New domains cannot be registered at this time");
}
forceRegister(name, domain);
}
}
@Override
public void registerAll(Map<String, DomainFactory<?>> domains) {
synchronized (lock) {
for (Map.Entry<String, DomainFactory<?>> entry : domains.entrySet()) {
try {
register(entry.getKey(), entry.getValue());
} catch (DomainConflictException e) {
log.log(Level.WARNING, e.getMessage());
}
}
}
}
private <T extends DomainFactory<?>> T forceRegister(String name, T domain) throws DomainConflictException {
checkNotNull(domain, "domain");
checkNotNull(name, "name");
if (!CustomDomain.isValidName(name)) {
throw new IllegalArgumentException("Invalid Domain name used.");
}
synchronized (lock) {
if (domains.containsKey(name)) {
throw new DomainConflictException("A domain already exists by the name " + name);
}
domains.put(name, domain);
}
return domain;
}
@Nullable
@Override
public DomainFactory<?> get(String name) {
checkNotNull(name, "name");
return domains.get(name.toLowerCase());
}
@Nullable
@Override
public CustomDomain createDomain(String name) {
DomainFactory<?> factory = get(name);
if (factory == null) return null;
return factory.create(name);
}
@Override
public Map<String, DomainFactory<?>> getAll() {
return ImmutableMap.copyOf(domains);
}
private CustomDomain getOrCreate(String name, Object value, boolean createUnknown) {
CustomDomain customDomain = createDomain(name);
if (customDomain != null) {
customDomain.unmarshal(value);
return customDomain;
}
synchronized (lock) {
customDomain = createDomain(name); // Load again because the previous load was not synchronized
if (customDomain != null) {
customDomain.unmarshal(value);
return customDomain;
}
if (createUnknown) {
DomainFactory<UnknownDomain> unknownFactory = forceRegister(name, UnknownDomain.FACTORY);
if (unknownFactory != null) {
customDomain = unknownFactory.create(name);
if (customDomain != null) customDomain.unmarshal(value);
return customDomain;
}
}
}
return null;
}
public Map<String, CustomDomain> unmarshal(Map<String, Object> rawValues, boolean createUnknown) {
checkNotNull(rawValues, "rawValues");
Map<String, CustomDomain> domains = new HashMap<>();
for (Map.Entry<String, Object> entry : rawValues.entrySet()) {
try {
CustomDomain domain = getOrCreate(entry.getKey(), entry.getValue(), createUnknown);
domains.put(domain.getName(), domain);
} catch (Throwable e) {
log.log(Level.WARNING, "Failed to unmarshal domain for " + entry.getKey(), e);
}
}
return domains;
}
@Override
public int size() {
return domains.size();
}
@Override
public Iterator<DomainFactory<?>> iterator() {
return Iterators.unmodifiableIterator(domains.values().iterator());
}
}
@@ -0,0 +1,88 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
import java.util.UUID;
public class UnknownDomain extends CustomDomain {
public static DomainFactory<UnknownDomain> FACTORY = UnknownDomain::new;
private boolean isDirty = false;
private Object o;
public UnknownDomain(String name) {
super(name);
}
@Override
public void parseInput(CustomDomainContext context) throws InvalidDomainFormatException {
throw new InvalidDomainFormatException("The plugin that registered this domain is not currently installed");
}
@Override
public void unmarshal(Object o) {
this.o = o;
}
@Override
public Object marshal() {
return o;
}
@Override
public boolean contains(UUID uniqueId) {
return false;
}
@Override
public boolean contains(String playerName) {
return false;
}
@Override
public int size() {
return 0;
}
@Override
public void clear() {
isDirty = true;
o = null;
}
@Override
public void setDirty(boolean dirty) {
isDirty = dirty;
}
@Override
public boolean isDirty() {
return isDirty;
}
@Override
public String toString() {
return "UnknownDomain{" +
"o=" + o +
'}';
}
}
@@ -176,13 +176,14 @@ public class RegionPermissionModel extends AbstractPermissionModel {
public boolean mayRemoveOwners(ProtectedRegion region) {
return hasPatternPermission("removeowner", region);
}
/**
* Checks to see if the given sender has permission to modify the given region
* using the region permission pattern.
*
* @param perm the name of the node
* @param region the region
* @return whether the actor has the permission
*/
private boolean hasPatternPermission(String perm, ProtectedRegion region) {
if (!(getSender() instanceof Player)) {
@@ -145,6 +145,7 @@ public interface WorldGuardPlatform {
*
* @param localPlayer The player
*/
@Deprecated(forRemoval = true)
void stackPlayerInventory(LocalPlayer localPlayer);
/**
@@ -33,7 +33,7 @@ public class BooleanFlag extends Flag<Boolean> {
}
@Override
public Boolean parseInput(FlagContext context) throws InvalidFlagFormat {
public Boolean parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if (input.equalsIgnoreCase("true") || input.equalsIgnoreCase("yes")
@@ -45,7 +45,7 @@ public class BooleanFlag extends Flag<Boolean> {
|| input.equalsIgnoreCase("0")) {
return false;
} else {
throw new InvalidFlagFormat("Not a yes/no value: " + input);
throw new InvalidFlagFormatException("Not a yes/no value: " + input);
}
}
@@ -33,7 +33,7 @@ public class CommandStringFlag extends Flag<String> {
}
@Override
public String parseInput(FlagContext context) throws InvalidFlagFormat {
public String parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
if (!input.startsWith("/")) {
@@ -33,7 +33,7 @@ public class DoubleFlag extends NumberFlag<Double> {
}
@Override
public Double parseInput(FlagContext context) throws InvalidFlagFormat {
public Double parseInput(FlagContext context) throws InvalidFlagFormatException {
return context.getUserInputAsDouble();
}
@@ -40,12 +40,12 @@ public class EntityTypeFlag extends Flag<EntityType> {
}
@Override
public EntityType parseInput(FlagContext context) throws InvalidFlagFormat {
public EntityType parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
EntityType entityType = unmarshal(input);
if (entityType == null) {
throw new InvalidFlagFormat("Unknown entity type: " + input);
throw new InvalidFlagFormatException("Unknown entity type: " + input);
}
return entityType;
}
@@ -57,6 +57,6 @@ public class EntityTypeFlag extends Flag<EntityType> {
@Override
public Object marshal(EntityType o) {
return o.getId();
return o.id();
}
}
@@ -74,12 +74,12 @@ public class EnumFlag<T extends Enum<T>> extends Flag<T> {
}
@Override
public T parseInput(FlagContext context) throws InvalidFlagFormat {
public T parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
try {
return findValue(input);
} catch (IllegalArgumentException e) {
throw new InvalidFlagFormat("Unknown value '" + input + "' in "
throw new InvalidFlagFormatException("Unknown value '" + input + "' in "
+ enumClass.getName());
}
}
@@ -181,9 +181,9 @@ public abstract class Flag<T> {
*
* @param context the {@link FlagContext}
* @return The coerced type
* @throws InvalidFlagFormat Raised if the input is invalid
* @throws InvalidFlagFormatException Raised if the input is invalid
*/
public abstract T parseInput(FlagContext context) throws InvalidFlagFormat;
public abstract T parseInput(FlagContext context) throws InvalidFlagFormatException;
/**
* Convert a raw type that was loaded (from a YAML file, for example)
@@ -21,106 +21,28 @@ package com.sk89q.worldguard.protection.flags;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import java.util.Map;
import com.sk89q.worldguard.commands.CommandInputContext;
import javax.annotation.Nullable;
import java.util.Map;
public final class FlagContext {
private final Actor sender;
private final String input;
private Map<String, Object> context;
public final class FlagContext extends CommandInputContext<InvalidFlagFormatException> {
private FlagContext(Actor sender, String input, Map<String, Object> values) {
this.sender = sender;
this.input = input;
this.context = values;
super(sender, input, values);
}
public static FlagContextBuilder create() {
public static FlagContext.FlagContextBuilder create() {
return new FlagContextBuilder();
}
public void put(String name, Object value) {
context.put(name, value);
}
public Actor getSender() {
return sender;
}
public String getUserInput() {
return input;
}
/**
* Gets the CommandSender as a player.
*
* @return Player
* @throws InvalidFlagFormat if the sender is not a player
*/
public LocalPlayer getPlayerSender() throws InvalidFlagFormat {
if (sender.isPlayer() && sender instanceof LocalPlayer) {
return (LocalPlayer) sender;
} else {
throw new InvalidFlagFormat("Not a player");
}
}
public Integer getUserInputAsInt() throws InvalidFlagFormat {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw new InvalidFlagFormat("Not a number: " + input);
}
}
public Double getUserInputAsDouble() throws InvalidFlagFormat {
try {
return Double.parseDouble(input);
} catch (NumberFormatException e) {
throw new InvalidFlagFormat("Not a number: " + input);
}
}
/**
* Get an object from the context by key name.
* May return null if the object does not exist in the context.
*
* @param name key name of the object
* @return the object matching the key, or null
*/
@Nullable
public Object get(String name) {
return get(name, null);
}
/**
* Get an object from the context by key name.
* Will only return null if
* a) you provide null as the default
* b) the key has explicity been set to null
*
* @param name key name of the object
* @return the object matching the key
*/
@Nullable
public Object get(String name, Object defaultValue) {
Object obj;
return (((obj = context.get(name)) != null) || context.containsKey(name)
? obj : defaultValue);
}
/**
* Create a copy of this FlagContext, with optional substitutions for values
*
* If any supplied variable is null, it will be ignored.
* <p>If any supplied variable is null, it will be ignored.
* If a map is supplied, it will override this FlagContext's values of the same key,
* but unprovided keys will not be overriden and will be returned as shallow copies.
* but unprovided keys will not be overriden and will be returned as shallow copies.</p>
*
* @param commandSender CommandSender for the new FlagContext to run under
* @param s String of the user input for the new FlagContext
@@ -136,6 +58,11 @@ public final class FlagContext {
return new FlagContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map);
}
@Override
protected InvalidFlagFormatException createException(String str) {
return new InvalidFlagFormatException(str);
}
public static class FlagContextBuilder {
private Actor sender;
private String input;
Loaded 100 of 143 files, more files were not shown because too many files have changed in this diff. Show more