Compare commits

...
192 Commits
Author SHA1 Message Date
Maddy Miller 0b6c3f1045 Release 7.0.20 2026-10-17 16:41:25 +10:00
Maddy Miller 3f9b7cf4e0 Add cushions to ENTITY_ITEMS 2026-10-17 16:13:38 +10:00
HPnetwork fdbdb91816 Avoid NPE when clearing a region flag (#2307)
* Fix region flag clear feedback

* Use unset feedback when state flag parsing returns null
2026-10-16 21:33:07 +10:00
BaiChuan a670fc70f9 Guard Folia creature cause expansion by region ownership (#2312) 2026-10-16 20:52:49 +10:00
Maddy Miller 408845ad09 Add materials map for 26.3 blocks/items 2026-10-16 20:44:07 +10:00
CatTeaA 96d18c4efc Fix PlayerBucketEmptyEvent to use correct position check (#2313)
* Fix PlayerBucketEmptyEvent to use correct position check

* Considering that cauldrons trigger PlayerBucketEmptyEvent
2026-10-16 09:55:21 +10:00
nivcoo a468153cd8 feat. add entity break event handling and update Paper API version to 26.3 (#2315)
* feat. add entity break event handling and update Paper API version to 26.3

* improv. add braces to handle Hanging entities
2026-10-15 20:27:30 +10:00
Maddy Miller 4181ebfe36 Fixed Poplar boats causing an error, and harden against future issues (#2309) 2026-09-23 19:29:35 +10:00
Maddy Miller a6d64dcc79 Back to SNAPSHOT for continued development 2026-09-18 22:09:41 +10:00
Maddy Miller f395a1675b Release 7.0.19 2026-09-18 22:09:17 +10:00
Brokkonaut 0aeb9d8d54 Fix lock flag restoration after session reinitialization (#2304) 2026-09-18 21:18:27 +10:00
Rasmus Kjær Damgaard 7c280a1348 Cancel blocked natural spawns before the entity is created (#2300)
* Cancel blocked natural spawns before the entity is created

The mob-spawning and deny-spawn checks in WorldGuardEntityListener fire
on CreatureSpawnEvent, at the very end of the spawn pipeline. By that
point the server has picked a spawn position, run the placement checks,
constructed the mob and run finalizeSpawn, and the cancelled mob is
thrown away. Since a cancelled spawn never counts toward the mob cap,
the natural spawner keeps retrying the same area at full rate, so
regions that deny mob spawning become permanent spawn attempt hotspots
that pay entity construction over and over for nothing.

On Paper servers the same checks can run in PreCreatureSpawnEvent,
before the entity exists. Cancelling there also ends the remaining
attempts for the chunk in that spawn cycle, so the wasted work is gone
almost entirely. Measured on a flat test world with a region denying
mob-spawning over the whole spawn range and the mob cap kept empty, the
attempt rate around a single player collapsed from roughly 75000
attempts per second to roughly 60 per second, with no entities
constructed at all.

The new listener mirrors the natural spawn conditions from
onCreatureSpawn exactly: activity halt, block-creature-spawn,
mob-spawning and deny-spawn region flags, and block-ground-slimes. All
other spawn reasons keep going through the existing CreatureSpawnEvent
checks unchanged, and the listener is only registered when the Paper
event class is present.

* Move the pre spawn handler into the existing Paper inner listener

Review feedback: platform specific code lives in the Paper inner
classes of the main listeners, and WorldGuardEntityListener already has
one for EntityZapEvent, so the handler moves in there and the separate
listener class is gone.

* Match the HIGH priority of the other protection handlers

* Extract the shared spawn checks into a method used by both handlers

The pre spawn handler duplicated the tail of onCreatureSpawn. Both now
call handleCreatureSpawn, which takes the event as a Cancellable and
the location, entity type and spawn reason as parameters, following
the same shape as handlePigZap. The entity specific checks (plugin
spawning, armor stands, tamed animals) stay in onCreatureSpawn since
no entity exists yet at pre spawn time, and the activity halt check
stays in each handler so its ordering relative to those checks is
unchanged.

* Pass cfg and wcfg into the shared spawn checks

Both handlers already have them, so the shared method no longer does a
second lookup.

* Correct the rationale on the pre spawn handler

The comment claimed that cancelling ends the chunk's remaining spawn
attempts. It does not. Only setShouldAbortSpawn(true) makes the spawner
return early; a plain cancel falls through to the next candidate position
exactly like a failed placement check.

What the handler does buy is stated accurately instead: the placement
checks, the entity construction and finalizeSpawn are skipped for a spawn
that was going to be refused.

Two consequences a server operator should know are now named. The region
query runs for every candidate position rather than every constructed mob,
because Paper fires the event before the vanilla suitability checks. And on
Paper with per-player-mob-spawns enabled, every cancelled pre spawn is
charged to a per player mob backoff counter, so a large denied region can
suppress spawning in neighbouring chunks that allow mobs.

* Add a config option for the pre spawn handler

regions.use-pre-creature-spawn-event, default true, matching how
regions.use-creature-spawn-event already gates the CreatureSpawnEvent
path. Turning it off leaves the existing handler doing all the work, so
a server that sees a regression can revert without downgrading.
2026-08-11 21:21:44 +10:00
Vladimir Turov c90c483862 Add Cause tracking for SulfurCube (#2295) 2026-08-02 18:20:44 +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
Maddy Miller f8415edfcd Skip handling notify flags on false values 2025-07-27 16:13:58 +10:00
Maddy Miller c4c17a2e4f Remove weird files 2025-06-12 23:17:17 +10:00
Maddy Miller e2f21b66ed Back to SNAPSHOT for continued development 2025-06-12 23:10:23 +10:00
Maddy Miller 43997ecfdc Release 7.0.14 2025-06-12 23:09:40 +10:00
wizjany b0a98d4c38 Add material defs for 1.21.5. (#2204) 2025-05-17 16:08:40 -04:00
Wertík 98b52206a0 Listen to EntityPushedByEntityAttackEvent for knockback/push (#2193)
Listening to the push event instead of EntityKnockbackByEntity includes other sources of knockback/push in the internal DamageEntityEvent.

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

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

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

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

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

Compiles, launches, nothing tested yet.

* Boat tag includes chest boat tag.

* Avoid Material.values call.

* Split ride checks to separate event handler.

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

* Fix cause detection, use always on paper

* Fix fat fingers

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

* Fix imports

* Add comment

* Actually read the value from config.

Closes #1879 

---------

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

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

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

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

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

* Update Materials.java with 1.21 tags and materials

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

* Fix ItemStack conversion on block place

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

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

* Use ItemStack as-is.

Closes #2092.

* Fix ItemStack conversion for spigot compatibility

* Special handling for WindCharges

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

* WindCharge -> AbstractWindCharge

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

* Cleanup code

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

---------

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

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

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

* Use ItemStack as-is.

Closes #2092.

---------

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

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

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

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

* codestyle
2024-05-23 13:05:29 -04:00
Joo200 d6ef5e9398 Remove adventure snapshot repository 2024-05-17 18:05:37 +02:00
wizjany 6f5501f7be Bump to snapshot. 2024-05-14 18:14:06 -04:00
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 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
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
wizjany 3201cee1b7 Bump to snapshot. 2023-07-31 20:12:56 -04:00
wizjany 16a3c85005 Release 7.0.9. 2023-07-31 20:11:06 -04:00
Joo200 5934e49489 Fix changed event for copper-fade flag 2023-07-30 18:34:12 +02:00
Joo200 58fbb6f008 Remove Support for 1.19 2023-07-30 18:20:02 +02:00
Joo200 fba8333de3 Fix backwards compatibility with 1.19.4 2023-06-21 22:20:42 +02:00
Madeline Miller fffb0c1f98 Bump to snapshot 2023-06-16 21:01:49 +10:00
Madeline Miller 223b80c590 Release 7.0.9-beta1 2023-06-16 20:59:43 +10:00
Joo200 853631139d Update Protections to 1.20
* add new materials
* add protections for sniffer eggs
* add protection for signs
2023-06-16 09:50:37 +02:00
Joo200 c61e9f1fe0 Update Readme to use https and Java 17 2023-06-16 09:50:37 +02:00
Joo200 64ccda4615 deps: Update WorldEdit to 7.2.14 2023-06-16 09:50:37 +02:00
Joo200 16887c8540 deps: Update Paper to 1.20, snakeyml to 2.0 2023-06-16 09:50:37 +02:00
Joo200 2c448f1ba2 deps: Update gradle to 8.1.1 2023-06-16 09:50:37 +02:00
wizjany c0cbe27efc yaml ctors 2023-06-08 15:08:05 -04:00
Joo200 4a26e306b6 Consider the summon command as plugin spawning 2023-05-31 13:26:05 +02:00
wizjany 44d0735412 Bump to snapshot. 2023-05-27 13:41:49 -04:00
wizjany 33cdb4a6a8 Release 7.0.8 2023-05-27 13:39:01 -04:00
wizjany feb548aa84 Check movement on AbstractHorse instead of Horse.
Not tested cuz I don't know how to enable camels, but in theory this should work for that.
2023-05-16 17:04:28 -04:00
wizjany 961461c23c Protect against allay pickups and modification.
Closes #1923.
2023-05-16 17:02:19 -04:00
wizjany ad6d5af592 Treat tameables with offline owners as unknown causes.
Paper-only.

Closes #1900.
2023-05-16 16:15:57 -04:00
wizjany 7ae7a04721 Make region wand act more like /rg info.
Addresses the part that #1534 and #1817 missed.
2023-05-16 15:25:52 -04:00
wizjany 40adfe9cef Add dragon egg teleporting to build protection.
Closes #1977.
2023-05-16 14:22:47 -04:00
Joo200 78498491dd Remove timings for third-party session handlers
Reverted MR #1717
2023-04-09 21:27:13 -04:00
stonar96 ca636d20af Fix NPE when non-player entities create new nether portals (#1995)
* Fix NPE when non-player entities create new nether portals

* Fix flag checking for portal create event

* Use failed load region set

* Clean up
2023-04-09 21:25:44 -04:00
Joo200 bddfbdd353 gradle: updated wrapper to gradle 8.0.2 2023-03-26 15:14:10 +02:00
JOO200 ece376a69e Improve NPC handling in WorldGuard's listeners (#1988)
* fix: added more npc checks in listeners
* Do not listen to events from NPCs such as Citizens. Don't handle NPCs as players.
* replaced hasMetaData calls by Entities utilities class
2023-03-23 18:58:48 +01:00
wizjany 1e81a91d4d Bump squirrelid, remove workaround. 2023-03-23 11:47:02 -04:00
JOO200 216f95f87c Merge pull request #1989 from EngineHub/feature/copper-fade-flag
Add copper-fade flag to WorldGuard
2023-03-23 15:05:53 +01:00
JOO200 ca6e228f61 Merge pull request #1973 from EngineHub/feat/datapackreport
Add DataPack Report to track active DataPacks
2023-03-23 14:53:06 +01:00
Joo200 fd1cb1e4bd flags: added copper-fade flag to prevent oxidizing copper 2023-03-19 16:56:46 +01:00
Joo200 8c8a8092b5 deps: updated Paper repository to new url, updated bstats to 3.0.1 2023-03-12 16:50:21 +01:00
Maddy Miller 1729e5e3d6 Add additional holder snapshot bypasses for performance (#1978)
* Add additional holder snapshot bypasses for performance

* Extra optimisation - cuts lookups of block data in the world by half
2023-01-19 20:28:54 +10:00
Madeline Miller 46dfb69fb1 Use updated PaperLib for InventoryHolder optimisation 2023-01-05 21:28:13 +10:00
Joo200 9ceecf5d3a Add DataPack Report to track active DataPacks 2022-12-27 13:39:35 +01:00
Maddy Miller 20044a72d3 fix: re-enable no snapshot inventories (#1972) 2022-12-26 10:29:26 +10:00
JOO200 8bc7ff49ab Merge pull request #1971 from EngineHub/version/1.19.3
Update to Minecraft 1.19.3
2022-12-19 11:01:20 +01:00
Joo200 6f749b058b Restore 1.19.2 compatibility 2022-12-09 16:37:04 +01:00
Joo200 91380a8316 Updated wrapper 2022-12-09 13:26:02 +01:00
Joo200 ba55cc79c2 Update to Minecraft 1.19.3 2022-12-09 13:23:57 +01:00
aromaa cb100bb797 Improve compatibility with the new onClearValue 2022-09-20 09:07:27 -04:00
Joni Aromaa bd1d772faa Introduce uninitialize for sessions (#1940)
* Introduce uninitialize for sessions

* Add FlagValueChangeHandler#onClearValue
2022-09-18 11:18:08 -04:00
wizjany f1f1e8aa7d Remove command reg delay for CommandBook compat.
This may break said compat but I doubt anyone is using it anyway.

Fixes #1943.
2022-08-28 10:15:49 -04:00
wizjany 598c441718 Back to snapshot.
Also update changelog
2022-07-27 21:28:09 -04:00
wizjany cbb2ba7216 Release 7.0.8 beta 1. 2022-07-27 21:15:21 -04:00
dordsor21 e756d127c5 Account for possible world nullability for Entity#getOrigin Location 2022-07-27 21:15:31 -04:00
Joo200 0d2ed8205f Properly protect chest_boats as vehicles 2022-07-07 21:04:44 +02:00
JOO200 6efdb1089e Fix Report for Spigot based servers
Bukkit.spigot().getSpigotConfig() is the paper implementation, it's not available on Non-Paper servers
2022-06-21 20:44:30 +02:00
wizjany 4a21bf43e7 Check if InventoryHolder BlockState is placed.
Closes #1903.
2022-06-14 11:31:24 -04:00
JOO200 3a181a230f Tidy up Materials.java, added missing effect type, removed todo for paper only 2022-06-14 11:25:06 -04:00
JOO200 857f7468d8 Add Sculk Growth Flag and options to disable sculk growths 2022-06-14 11:25:06 -04:00
JOO200 f8e8d0f01e Plugin Version to 1.19, cleanup from Materials, added 1.19 Materials 2022-06-14 11:25:06 -04:00
JOO200 23521858fd Bumped versions: Minecraft to 1.19 and JDK 17 2022-06-14 11:25:06 -04:00
JOO200 0fddd2a573 Fixed Typo in CommandException 2022-04-26 18:26:07 +02:00
JOO200 85dd012b85 Improvement and Cleanup Domain view for /region info
* Don't suggest the uuids to the command line, copy them to the clipboard instead
* Tidy up the hover events and added hints to copy uuids
2022-04-09 11:46:54 +02:00
wizjany dc23af7947 Skip lookups on claim.
Claim hasn't allowed user-input for ages, so no need to resolve anything.
2022-04-05 12:23:32 -04:00
JOO200 b698941378 Append OnlineMode server information to ServerReport (#1891) 2022-04-03 16:35:34 -04:00
wizjany 271b32aa1d Default chest-protection.disable-off-check to true.
Fixes #1890.
2022-03-24 10:01:17 -04:00
wizjany 938f0c3b66 Handle all the amethyst growth.
Fixes #1889.
2022-03-20 08:26:41 -04:00
wizjany 216b061172 Fix class source validator on spigot. 2022-03-06 08:59:44 -05:00
wizjany 27dca2b506 Bump to snapshot. 2022-03-03 15:05:52 -05:00
119 changed files with 2811 additions and 1958 deletions

No files matched your search

+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
+102
View File
@@ -1,5 +1,107 @@
# Changelog
## 7.0.20
* Require 26.3+.
* Fixed poplar boats causing errors in some situations.
* Support Paper's new EntityBreakEvent (used for cushion destruction) in protection.
* Improved handling of buckets on waterlogged blocks when sneaking.
* Fixed a Folia error caused by entity actions occuring across Folia region boundaries.
* Improved command feedback when setting a state flag to "none".
## 7.0.19
* Require 26.2+.
* Improved handling for TNT inside of sulfur cubes.
* Improve performance of mob spawn prevention on Paper servers in some situations.
* Improved handling of certain flags when `/wg flushstates` is run, or in certain login situations.
## 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
* Add sniffer egg trample protection options
## 7.0.8
* Add support for MC 1.19
* Add skulk-growth flag and config option
* Add copper-fade flag
* Add data packs to report output
* Add protection for allay inventory slot
* Categorize allay item pickups under item-pickup flag
* Categorize dragon egg interaction (teleporting) as building
* Ignore most NPC-based actions for Player events
* Optimize handling of tamed animals where the owner was offline (Paper only)
* Optimize additional InventoryHolder accesses (Paper only)
* Fix an exception that occurred when plugins created portals with non-player entities
* Fix possible error when using Paper's entity origin API
* Update bstats and squirrelid libs
## 7.0.7
* Add rock-growth flag for budding amethyst and pointed dripstone.
* Add /rg migrateheights command. See https://worldguard.enginehub.org/en/latest/regions/commands/#migrate-region-heights
+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 16 installed. Gradle will download JDK 16 specifically if needed,
but it needs some version of Java to bootstrap from.
Note that if you have JRE 16 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 16.
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:
+3 -6
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 16 and our build process makes use of
[Gradle](http://gradle.org).
Dependencies are automatically handled by Gradle.
See [COMPILING.md](COMPILING.md).
Contributing
------------
@@ -40,8 +37,8 @@ Submissions must be licensed under the GNU Lesser General Public License v3.
Links
-----
* [Homepage](http://enginehub.org/worldguard)
* [Homepage](https://enginehub.org/worldguard)
* [Discord](https://discord.gg/enginehub)
* [Issue tracker](https://github.com/EngineHub/WorldGuard/issues)
* [Continuous integration](http://builds.enginehub.org) [![Build Status](https://ci.enginehub.org/app/rest/builds/buildType:bt11,branch:master/statusIcon.svg)](http://ci.enginehub.org/viewType.html?buildTypeId=bt11&guest=1)
* [Continuous integration](https://builds.enginehub.org) [![Build Status](https://ci.enginehub.org/app/rest/builds/buildType:bt11,branch:master/statusIcon.svg)](http://ci.enginehub.org/viewType.html?buildTypeId=bt11&guest=1)
* [End-user documentation](https://worldguard.enginehub.org/en/latest/)
+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.0")
implementation("com.github.jengelman.gradle.plugins:shadow:6.1.0")
implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.21.0")
}
@@ -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(16))
}
}
apply(plugin = "org.cadixdev.licenser")
configure<LicenseExtension> {
header(rootProject.file("HEADER.txt"))
include("**/*.java")
include("**/*.kt")
}
}
-12
View File
@@ -1,12 +0,0 @@
import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the
val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
val Project.sourceSets: SourceSetContainer
get() = the<JavaPluginConvention>().sourceSets
-171
View File
@@ -1,171 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.DocsType
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.attributes.Usage
import org.gradle.api.attributes.java.TargetJvmVersion
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
import javax.inject.Inject
fun Project.applyLibrariesConfiguration() {
applyCommonConfiguration()
apply(plugin = "java-base")
apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "com.jfrog.artifactory")
configurations {
create("shade")
}
group = "${rootProject.group}.worldguard-libs"
val relocations = mapOf(
"org.enginehub.squirrelid" to "com.sk89q.worldguard.util.profile"
)
tasks.register<ShadowJar>("jar") {
configurations = listOf(project.configurations["shade"])
archiveClassifier.set("")
dependencies {
exclude(dependency("com.google.code.findbugs:jsr305"))
}
relocations.forEach { (from, to) ->
relocate(from, to)
}
}
val altConfigFiles = { artifactType: String ->
val deps = configurations["shade"].incoming.dependencies
.filterIsInstance<ModuleDependency>()
.map { it.copy() }
.map { dependency ->
dependency.artifact {
name = dependency.name
type = artifactType
extension = "jar"
classifier = artifactType
}
dependency
}
files(configurations.detachedConfiguration(*deps.toTypedArray())
.resolvedConfiguration.lenientConfiguration.artifacts
.filter { it.classifier == artifactType }
.map { zipTree(it.file) })
}
tasks.register<Jar>("sourcesJar") {
from({
altConfigFiles("sources")
})
relocations.forEach { (from, to) ->
val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)")
val textPattern = Regex.fromLiteral(from)
eachFile {
filter {
it.replaceFirst(textPattern, to)
}
path = path.replaceFirst(filePattern, "$1${to.replace('.', '/')}$2")
}
}
archiveClassifier.set("sources")
}
tasks.named("assemble").configure {
dependsOn("jar", "sourcesJar")
}
project.apply<LibsConfigPluginHack>()
val libsComponent = project.components["libs"] as AdhocComponentWithVariants
val apiElements = project.configurations.register("apiElements") {
isVisible = false
description = "API elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
}
outgoing.artifact(tasks.named("jar"))
}
val runtimeElements = project.configurations.register("runtimeElements") {
isVisible = false
description = "Runtime elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
}
outgoing.artifact(tasks.named("jar"))
}
val sourcesElements = project.configurations.register("sourcesElements") {
isVisible = false
description = "Source elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES))
}
outgoing.artifact(tasks.named("sourcesJar"))
}
libsComponent.addVariantsFromConfiguration(apiElements.get()) {
mapToMavenScope("compile")
}
libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
mapToMavenScope("runtime")
}
libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
mapToMavenScope("runtime")
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("maven") {
from(libsComponent)
}
}
}
applyCommonArtifactoryConfig()
}
internal open class LibsConfigPluginHack @Inject constructor(
private val softwareComponentFactory: SoftwareComponentFactory
) : Plugin<Project> {
override fun apply(project: Project) {
val libsComponents = softwareComponentFactory.adhoc("libs")
project.components.add(libsComponents)
}
}
-113
View File
@@ -1,113 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.withType
import org.gradle.kotlin.dsl.the
fun Project.applyPlatformAndCoreConfiguration() {
applyCommonConfiguration()
apply(plugin = "java")
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "maven-publish")
apply(plugin = "checkstyle")
apply(plugin = "com.jfrog.artifactory")
ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "8.34"
}
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()
}
}
-9
View File
@@ -1,9 +0,0 @@
object Versions {
// const val PISTON = "0.4.3"
// const val AUTO_VALUE = "1.6.5"
const val WORLDEDIT = "7.2.7"
const val JUNIT = "5.7.0"
const val SQUIRRELID = "0.3.0"
const val GUAVA = "31.0.1-jre"
const val MOCKITO = "3.7.7"
}
+1 -2
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"/>
@@ -30,7 +29,7 @@
<allow pkg="org.bstats.charts"/>
<allow pkg="io.papermc.lib"/>
<allow pkg="com.destroystokyo.paper"/>
<allow pkg="co.aikar.timings.lib" />
<allow pkg="io.papermc.paper"/>
<allow pkg="org.spigotmc" />
</subpackage>
+3 -1
View File
@@ -1,2 +1,4 @@
group=com.sk89q.worldguard
version=7.0.7
version=7.0.20
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.3.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.
+5 -1
View File
@@ -1,5 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-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
+28 -13
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/master/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/.
@@ -80,13 +80,11 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# 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"'
# 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
@@ -133,22 +131,29 @@ 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.
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=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
done
fi
# 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.
# 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, 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" \
@@ -205,6 +214,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
Vendored
+19 -16
View File
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
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
@@ -56,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
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
+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 -52
View File
@@ -1,78 +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://papermc.io/repo/repository/maven-public/")
}
maven {
name = "bstats"
url = uri("https://repo.codemc.org/repository/maven-public")
}
maven {
name = "aikar-timings"
url = uri("https://repo.aikar.co/nexus/content/groups/aikar/")
}
}
configurations {
compileClasspath.get().extendsFrom(create("shadeOnly"))
id("buildlogic.platform")
}
dependencies {
"api"(project(":worldguard-core"))
"compileOnly"("io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT")
"runtimeOnly"("org.spigotmc:spigot-api:1.17.1-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.7")
"shadeOnly"("org.bstats:bstats-bukkit:2.1.0")
"shadeOnly"("co.aikar:minecraft-timings:1.0.4")
"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"])
}
}
@@ -37,7 +37,6 @@ public class BukkitConfigurationManager extends YamlConfigurationManager {
private boolean hasCommandBookGodMode;
boolean extraStats;
boolean timedSessionHandlers;
/**
* Construct the object.
@@ -57,7 +56,6 @@ public class BukkitConfigurationManager extends YamlConfigurationManager {
public void load() {
super.load();
this.extraStats = getConfig().getBoolean("custom-metrics-charts", true);
this.timedSessionHandlers = getConfig().getBoolean("extra-timings.session-handlers", true);
}
@Override
@@ -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);
@@ -244,7 +245,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableDeathMessages = getBoolean("player-damage.disable-death-messages", false);
signChestProtection = getBoolean("chest-protection.enable", false);
disableSignChestProtectionCheck = getBoolean("chest-protection.disable-off-check", false);
disableSignChestProtectionCheck = getBoolean("chest-protection.disable-off-check", true);
if (signChestProtection) {
log.warning("Sign-based chest protection is deprecated for removal in a future version. See https://worldguard.enginehub.org/en/latest/chest-protection/ for details.");
} else {
@@ -256,6 +257,8 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableCreatureTurtleEggTrampling = getBoolean("turtle-egg.disable-creature-trampling", false);
disablePlayerTurtleEggTrampling = getBoolean("turtle-egg.disable-player-trampling", false);
disableCreatureSnifferEggTrampling = getBoolean("sniffer-egg.disable-creature-trampling", false);
disablePlayerSnifferEggTrampling = getBoolean("sniffer-egg.disable-player-trampling", false);
disallowedLightningBlocks = new HashSet<>(convertLegacyBlocks(getStringList("weather.prevent-lightning-strike-blocks", null)));
preventLightningFire = getBoolean("weather.disable-lightning-strike-fire", false);
@@ -277,9 +280,13 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableMyceliumSpread = getBoolean("dynamics.disable-mycelium-spread", false);
disableVineGrowth = getBoolean("dynamics.disable-vine-growth", false);
disableRockGrowth = getBoolean("dynamics.disable-rock-growth", false);
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);
@@ -34,6 +34,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.profile.resolver.PaperPlayerService;
import com.sk89q.worldguard.bukkit.protection.events.flags.FlagContextCreateEvent;
import com.sk89q.worldguard.bukkit.session.BukkitSessionManager;
import com.sk89q.worldguard.bukkit.util.report.DatapackReport;
import com.sk89q.worldguard.bukkit.util.report.PerformanceReport;
import com.sk89q.worldguard.bukkit.util.report.PluginReport;
import com.sk89q.worldguard.bukkit.util.report.SchedulerReport;
@@ -138,7 +139,6 @@ public class BukkitWorldGuardPlatform implements WorldGuardPlatform {
sessionManager = new BukkitSessionManager();
configuration = new BukkitConfigurationManager(WorldGuardPlugin.inst());
configuration.load();
sessionManager.setUsingTimings(configuration.timedSessionHandlers);
regionContainer = new BukkitRegionContainer(WorldGuardPlugin.inst());
regionContainer.initialize();
debugHandler = new BukkitDebugHandler(WorldGuardPlugin.inst());
@@ -146,6 +146,7 @@ public class BukkitWorldGuardPlatform implements WorldGuardPlatform {
@Override
public void unload() {
sessionManager.shutdown();
configuration.unload();
regionContainer.shutdown();
}
@@ -170,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();
@@ -190,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
@@ -238,6 +240,7 @@ public class BukkitWorldGuardPlatform implements WorldGuardPlatform {
report.add(new ServicesReport());
report.add(new WorldReport());
report.add(new PerformanceReport());
if (PaperLib.isPaper()) report.add(new DatapackReport());
}
@Override
@@ -264,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;
@@ -60,6 +62,7 @@ import com.sk89q.worldguard.bukkit.listener.WorldGuardWorldListener;
import com.sk89q.worldguard.bukkit.listener.WorldRulesListener;
import com.sk89q.worldguard.bukkit.session.BukkitSessionManager;
import com.sk89q.worldguard.bukkit.util.ClassSourceValidator;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.commands.GeneralCommands;
import com.sk89q.worldguard.commands.ProtectionCommands;
@@ -73,6 +76,8 @@ import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver
import com.sk89q.worldguard.protection.managers.storage.sql.SQLDriver;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
import io.papermc.lib.PaperLib;
import io.papermc.paper.ServerBuildInfo;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.DrilldownPie;
import org.bstats.charts.SimplePie;
@@ -94,6 +99,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -102,6 +108,7 @@ import java.util.logging.Logger;
*/
public class WorldGuardPlugin extends JavaPlugin {
private static final org.apache.logging.log4j.Logger LOGGER = LogManagerCompat.getLogger();
private static WorldGuardPlugin inst;
private static BukkitWorldGuardPlatform platform;
private final CommandsManager<Actor> commands;
@@ -135,6 +142,7 @@ public class WorldGuardPlugin extends JavaPlugin {
* Called on plugin enable.
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void onEnable() {
// Catch bad things being done by naughty plugins that include WorldGuard's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
@@ -158,13 +166,20 @@ public class WorldGuardPlugin extends JavaPlugin {
reg.register(ToggleCommands.class);
reg.register(ProtectionCommands.class);
getServer().getScheduler().scheduleSyncDelayedTask(this, () -> {
if (!platform.getGlobalStateManager().hasCommandBookGodMode()) {
reg.register(GeneralCommands.class);
}
}, 0L);
if (!platform.getGlobalStateManager().hasCommandBookGodMode()) {
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);
@@ -205,12 +220,24 @@ public class WorldGuardPlugin extends JavaPlugin {
}
worldListener.registerEvents();
Bukkit.getScheduler().runTask(this, () -> {
if (this.isFolia()) {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
player.getScheduler().run(this, new Consumer() {
@Override
public void accept(Object ignored) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
}
}, null);
}
});
} else {
Bukkit.getScheduler().runTask(this, () -> {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
}
});
}
((SimpleFlagRegistry) WorldGuard.getInstance().getFlagRegistry()).setInitialized(true);
@@ -265,7 +292,12 @@ public class WorldGuardPlugin extends JavaPlugin {
@Override
public void onDisable() {
WorldGuard.getInstance().disable();
this.getServer().getScheduler().cancelTasks(this);
if (this.isFolia()) {
this.getServer().getGlobalRegionScheduler().cancelTasks(this);
this.getServer().getAsyncScheduler().cancelTasks(this);
} else {
this.getServer().getScheduler().cancelTasks(this);
}
}
@Override
@@ -421,8 +453,9 @@ public class WorldGuardPlugin extends JavaPlugin {
}
public Actor wrapCommandSender(CommandSender sender) {
if (sender instanceof Player) {
return wrapPlayer((Player) sender);
if (sender instanceof Player player) {
if (Entities.isNPC(player)) return null;
return wrapPlayer(player);
}
try {
@@ -524,4 +557,22 @@ public class WorldGuardPlugin extends JavaPlugin {
return playerMoveListener;
}
private final LazyReference<Boolean> folia = LazyReference.from(() -> {
try {
// Folia is Paper-based, so this is a good first check.
if (PaperLib.isPaper()) {
return ServerBuildInfo.buildInfo().isBrandCompatible(net.kyori.adventure.key.Key.key("papermc", "folia"));
}
} catch (Throwable t) {
// Ignore, this likely means an outdated version.
LOGGER.warn("Failed to check if server is running Folia", t);
}
return false;
});
public boolean isFolia() {
return folia.getValue();
}
}
@@ -24,17 +24,23 @@ import com.google.common.collect.Sets;
import com.sk89q.worldguard.bukkit.BukkitWorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.internal.WGMetadata;
import com.sk89q.worldguard.bukkit.util.Entities;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
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;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.SulfurCube;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Vehicle;
@@ -106,7 +112,13 @@ public final class Cause {
return false;
}
if (object instanceof TNTPrimed || object instanceof Vehicle) {
if (object instanceof Tameable tameable && tameable.isTamed()) {
// if they're tamed but also the root cause, the owner is offline
// otherwise the owner will be the root cause (and known)
return false;
}
if (object instanceof TNTPrimed || object instanceof Vehicle || object instanceof SulfurCube) {
if (!PaperLib.isPaper()) {
return false;
}
@@ -134,8 +146,8 @@ public final class Cause {
@Nullable
public Player getFirstPlayer() {
for (Object object : causes) {
if (object instanceof Player) {
return (Player) object;
if (object instanceof Player p && !Entities.isNPC(p)) {
return p;
}
}
@@ -145,8 +157,8 @@ public final class Cause {
@Nullable
public Entity getFirstEntity() {
for (Object object : causes) {
if (object instanceof Entity) {
return (Entity) object;
if (object instanceof Entity e) {
return e;
}
}
@@ -156,8 +168,8 @@ public final class Cause {
@Nullable
public Entity getFirstNonPlayerEntity() {
for (Object object : causes) {
if (object instanceof Entity && !(object instanceof Player)) {
return (Entity) object;
if (object instanceof Entity e && (!(object instanceof Player) || Entities.isNPC(e))) {
return e;
}
}
@@ -167,8 +179,8 @@ public final class Cause {
@Nullable
public Block getFirstBlock() {
for (Object object : causes) {
if (object instanceof Block) {
return (Block) object;
if (object instanceof Block b) {
return b;
}
}
@@ -299,18 +311,45 @@ public final class Cause {
} else if (o instanceof AreaEffectCloud) {
indirect = true;
addAll(((AreaEffectCloud) o).getSource());
} else if (o instanceof Tameable) {
} else if (o instanceof Tameable tameable) {
indirect = true;
addAll(((Tameable) o).getOwner());
} else if (o instanceof Creature && ((Creature) o).getTarget() != null) {
if (PaperLib.isPaper()) {
UUID ownerId = tameable.getOwnerUniqueId();
if (ownerId != null) {
Player owner = Bukkit.getPlayer(ownerId);
if (owner != null) {
addAll(owner);
}
}
} else {
// this will cause offline player loads if the player is offline
// too bad for spigot users
AnimalTamer owner = tameable.getOwner();
if (owner instanceof OfflinePlayer player) {
addAll(player.getPlayer()); // player object if online, else null
}
}
} else if (o instanceof Creeper c) {
indirect = true;
addAll(((Creature) o).getTarget());
if (!WorldGuardPlugin.inst().isFolia()
|| Bukkit.isOwnedByCurrentRegion(c)) {
addAll(c.getTarget(), c.getIgniter());
}
} else if (o instanceof Creature c) {
indirect = true;
if (!WorldGuardPlugin.inst().isFolia()
|| Bukkit.isOwnedByCurrentRegion(c)) {
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
@@ -29,6 +29,7 @@ import com.sk89q.worldguard.bukkit.BukkitPlayer;
import com.sk89q.worldguard.bukkit.BukkitWorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.association.DelayedRegionOverlapAssociation;
@@ -124,18 +125,18 @@ class AbstractListener implements Listener {
if (!cause.isKnown()) {
return Associables.constant(Association.NON_MEMBER);
} else if (rootCause instanceof Player) {
return getPlugin().wrapPlayer((Player) rootCause);
} else if (rootCause instanceof OfflinePlayer) {
return getPlugin().wrapOfflinePlayer((OfflinePlayer) rootCause);
} else if (rootCause instanceof Entity) {
} else if (rootCause instanceof Player player && !Entities.isNPC(player)) {
return getPlugin().wrapPlayer(player);
} else if (rootCause instanceof OfflinePlayer offlinePlayer) {
return getPlugin().wrapOfflinePlayer(offlinePlayer);
} else if (rootCause instanceof Entity entity) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
final Entity entity = (Entity) rootCause;
BukkitWorldConfiguration config = getWorldConfig(entity.getWorld());
Location loc;
if (PaperLib.isPaper() && config.usePaperEntityOrigin) {
loc = entity.getOrigin();
if (loc == null) {
// Origin world may be null, and thus a Location with a null world created, which cannot be adapted to a WorldEdit location
if (loc == null || loc.getWorld() == null) {
loc = entity.getLocation();
}
} else {
@@ -143,9 +144,9 @@ class AbstractListener implements Listener {
}
return new DelayedRegionOverlapAssociation(query, BukkitAdapter.adapt(loc),
config.useMaxPriorityAssociation);
} else if (rootCause instanceof Block) {
} else if (rootCause instanceof Block block) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
Location loc = ((Block) rootCause).getLocation();
Location loc = block.getLocation();
return new DelayedRegionOverlapAssociation(query, BukkitAdapter.adapt(loc),
getWorldConfig(loc.getWorld()).useMaxPriorityAssociation);
} else {
@@ -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);
}
}
}
@@ -22,8 +22,6 @@ package com.sk89q.worldguard.bukkit.listener;
import static com.sk89q.worldguard.bukkit.cause.Cause.create;
import com.destroystokyo.paper.event.entity.EntityZapEvent;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.bukkit.BukkitWorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.DelegateEvent;
@@ -46,11 +44,17 @@ 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.EntityBreakByEntityEvent;
import io.papermc.paper.event.entity.EntityBreakEvent;
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;
@@ -67,19 +71,25 @@ 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.Hanging;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Player;
import org.bukkit.entity.SulfurCube;
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;
@@ -113,13 +123,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;
@@ -142,18 +157,18 @@ import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory;
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 {
@@ -165,17 +180,6 @@ public class EventAbstractionListener extends AbstractListener {
private final EventDebounce<BlockPistonRetractKey> pistonRetractDebounce = EventDebounce.create(5000);
private final EventDebounce<BlockPistonExtendKey> pistonExtendDebounce = EventDebounce.create(5000);
private static final boolean HAS_SNAPSHOT_INVHOLDER;
static {
boolean temp;
try {
Inventory.class.getMethod("getHolder", boolean.class);
temp = true;
} catch (NoSuchMethodException e) {
temp = false;
}
HAS_SNAPSHOT_INVHOLDER = temp;
}
/**
* Construct the listener.
*
@@ -189,9 +193,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());
}
}
@@ -209,8 +215,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(),
@@ -231,8 +250,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));
}
@@ -336,10 +355,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);
@@ -352,7 +371,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));
@@ -367,10 +389,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);
}
@@ -467,7 +508,9 @@ public class EventAbstractionListener extends AbstractListener {
switch (event.getAction()) {
case PHYSICAL:
if (event.useInteractedBlock() != Result.DENY) {
if (clicked.getType() == Material.FARMLAND || clicked.getType() == Material.TURTLE_EGG) {
if (clicked.getType() == Material.FARMLAND ||
clicked.getType() == Material.TURTLE_EGG ||
clicked.getType() == Material.SNIFFER_EGG) {
BreakBlockEvent breakDelagate = new BreakBlockEvent(event, cause, clicked);
breakDelagate.setSilent(true);
breakDelagate.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
@@ -493,7 +536,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));
}
}
@@ -587,7 +630,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()));
}
@@ -613,9 +656,7 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) {
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), event.getBlock()));
if (event.isCancelled()) {
if (Events.fireToCancel(event, new PlaceBlockEvent(event, create(event.getPlayer()), event.getBlock()))) {
playDenyEffect(event.getPlayer(), event.getBlock().getLocation().add(0.5, 0.5, 0.5));
}
}
@@ -630,8 +671,13 @@ public class EventAbstractionListener extends AbstractListener {
Player player = event.getPlayer();
Block blockClicked = event.getBlockClicked();
Block blockAffected;
if (blockClicked.getBlockData() instanceof Waterlogged) {
boolean canPlaceInside = false;
// Can be placed inside blocks only when not sneaking
if (!player.isSneaking()) {
canPlaceInside = (event.getBucket() != Material.LAVA_BUCKET && blockClicked.getBlockData() instanceof Waterlogged)
|| (Materials.isCauldron(blockClicked.getType()) && Materials.isCauldronBucketType(event.getBucket()));
}
if (canPlaceInside) {
blockAffected = blockClicked;
} else {
blockAffected = blockClicked.getRelative(event.getBlockFace());
@@ -755,7 +801,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) {
@@ -785,7 +831,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) {
@@ -799,12 +846,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))) {
@@ -851,9 +905,15 @@ public class EventAbstractionListener extends AbstractListener {
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);
/* Sulfur cube doesn't have API for interaction/ignition source tracking */
if(entity instanceof SulfurCube) {
/* Remove player in case of using shears */
if(item.getType() == Material.SHEARS) {
Cause.untrackParentCause(entity);
/* Save player overwise */
} else {
Cause.trackParentCause(entity, player);
}
}
}
}
@@ -877,6 +937,8 @@ public class EventAbstractionListener extends AbstractListener {
eventToFire.getRelevantFlags().add(Flags.FIREWORK_DAMAGE);
} else if (damager instanceof Creeper) {
eventToFire.getRelevantFlags().add(Flags.CREEPER_EXPLOSION);
} else if (damager instanceof SulfurCube) {
eventToFire.getRelevantFlags().add(Flags.TNT);
}
if (Events.fireToCancel(event, eventToFire)) {
if (damager instanceof Tameable && damager instanceof Mob) {
@@ -900,19 +962,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()));
}
}
@@ -933,6 +1010,12 @@ public class EventAbstractionListener extends AbstractListener {
pickupDebounce.debounce(event.getPlayer(), item, event, new DestroyEntityEvent(event, create(event.getPlayer()), event.getItem()));
}
@EventHandler(ignoreCancelled = true)
public void onEntityPickupItem(EntityPickupItemEvent event) {
Item item = event.getItem();
pickupDebounce.debounce(event.getEntity(), item, event, new DestroyEntityEvent(event, create(event.getEntity()), event.getItem()));
}
@EventHandler(ignoreCancelled = true)
public void onPlayerDropItem(PlayerDropItemEvent event) {
Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getItemDrop()));
@@ -955,20 +1038,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;
if (HAS_SNAPSHOT_INVHOLDER) {
causeHolder = event.getInitiator().getHolder(false);
} else {
causeHolder = event.getInitiator().getHolder();
}
InventoryHolder causeHolder = PaperInterop.getHolder(event.getInitiator(), false);
WorldConfiguration wcfg = null;
if (causeHolder instanceof Hopper
@@ -982,15 +1061,8 @@ public class EventAbstractionListener extends AbstractListener {
Entry entry;
if ((entry = moveItemDebounce.tryDebounce(event)) != null) {
InventoryHolder sourceHolder;
InventoryHolder targetHolder;
/*if (HAS_SNAPSHOT_INVHOLDER) {
sourceHolder = event.getSource().getHolder(false);
targetHolder = event.getDestination().getHolder(false);
} else {*/
sourceHolder = event.getSource().getHolder();
targetHolder = event.getDestination().getHolder();
//}
InventoryHolder sourceHolder = PaperInterop.getHolder(event.getSource(), false);
InventoryHolder targetHolder = PaperInterop.getHolder(event.getDestination(), false);
Cause cause;
@@ -1006,11 +1078,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());
}
@@ -1026,7 +1110,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;
@@ -1038,8 +1121,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);
@@ -1105,9 +1191,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());
@@ -1121,7 +1207,7 @@ public class EventAbstractionListener extends AbstractListener {
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event){
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
onPlayerInteractEntity(event);
}
@@ -1180,7 +1266,11 @@ 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));
EntityType entityType = Materials.getRelatedEntity(item.getType());
if (entityType == null) {
entityType = EntityType.OAK_BOAT;
}
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), entityType));
return;
}
@@ -1192,14 +1282,17 @@ 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;
}
// Handle created spawn eggs
if (item != null && Materials.isSpawnEgg(item.getType())) {
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), Materials.getEntitySpawnEgg(item.getType())));
return;
if (item != null) {
EntityType possibleEntityType = Materials.getEntitySpawnEgg(item.getType());
if (possibleEntityType != null) {
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), possibleEntityType));
return;
}
}
// handle water/lava placement
@@ -1215,8 +1308,7 @@ public class EventAbstractionListener extends AbstractListener {
return;
}
if (holder instanceof Entity) {
Entity entity = (Entity) holder;
if (holder instanceof Entity entity) {
Material mat = Materials.getRelatedMaterial((entity).getType());
UseEntityEvent useEntityEvent = new UseEntityEvent(originalEvent, cause, entity);
if (mat != null && hasInteractBypass((entity).getWorld(), mat)) {
@@ -1224,16 +1316,15 @@ public class EventAbstractionListener extends AbstractListener {
}
Events.fireToCancel(originalEvent, useEntityEvent);
} else {
if (holder instanceof BlockState) {
final BlockState block = (BlockState) holder;
if (holder instanceof BlockState block && block.isPlaced()) {
final UseBlockEvent useBlockEvent = new UseBlockEvent(originalEvent, cause, block.getBlock());
if (hasInteractBypass(block.getWorld(), block.getType())) {
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()));
}
@@ -1279,10 +1370,51 @@ 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());
}
@EventHandler(ignoreCancelled = true)
public void onEntityBreak(EntityBreakEvent event) {
if (event.getEntity() instanceof Hanging) {
return;
}
if (event instanceof EntityBreakByEntityEvent entityEvent) {
Entity remover = entityEvent.getRemover();
Events.fireToCancel(event, new DestroyEntityEvent(event, create(remover), event.getEntity()));
if (event.isCancelled() && remover instanceof Player player) {
playDenyEffect(player, event.getEntity().getLocation());
}
} else if (event.getCause() == EntityBreakEvent.RemoveCause.EXPLOSION) {
DestroyEntityEvent destroyEntityEvent = new DestroyEntityEvent(event, Cause.unknown(), event.getEntity());
destroyEntityEvent.getRelevantFlags().add(Flags.OTHER_EXPLOSION);
Events.fireToCancel(event, destroyEntityEvent);
}
}
}
@SuppressWarnings("removal")
private static class SpigotListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onEntityKnockbackByEntity(EntityKnockbackByEntityEvent event) {
handleKnockback(event, event.getSourceEntity());
}
}
}
@@ -22,6 +22,7 @@ package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.Entities;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@@ -57,28 +58,27 @@ public class InvincibilityListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
Entity victim = event.getEntity();
if (!(victim instanceof Player player)) return;
if (Entities.isNPC(player)) return;
if (victim instanceof Player) {
Player player = (Player) victim;
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();
}
}
}
@@ -87,26 +87,25 @@ public class InvincibilityListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityCombust(EntityCombustEvent event) {
Entity entity = event.getEntity();
if (!(entity instanceof Player player)) return;
if (Entities.isNPC(player)) return;
if (entity instanceof Player) {
Player player = (Player) entity;
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 (event.getEntity() instanceof Player) {
Player player = (Player) event.getEntity();
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (!(event.getEntity() instanceof Player player)) return;
if (Entities.isNPC(player)) return;
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(localPlayer)) {
event.setCancelled(true);
}
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(localPlayer)) {
event.setCancelled(true);
}
}
@@ -23,25 +23,27 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.PaperInterop;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Horse;
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();
@@ -99,7 +99,7 @@ public class PlayerMoveListener extends AbstractListener {
moveType = MoveType.GLIDE;
} else if (event.getPlayer().isSwimming()) {
moveType = MoveType.SWIM;
} else if (event.getPlayer().getVehicle() != null && event.getPlayer().getVehicle() instanceof Horse) {
} else if (event.getPlayer().getVehicle() != null && event.getPlayer().getVehicle() instanceof AbstractHorse) {
moveType = MoveType.RIDE;
}
com.sk89q.worldedit.util.Location weLocation = session.testMoveTo(localPlayer, BukkitAdapter.adapt(to), moveType);
@@ -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,20 +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);
}
/**
* 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);
}
}
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);
}
@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);
}
}
}
@@ -25,6 +25,7 @@ import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.protection.association.RegionAssociable;
@@ -68,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);
}
@@ -99,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);
}
@@ -118,24 +119,24 @@ public class RegionFlagsListener extends AbstractListener {
World world = entity.getWorld();
if (!isRegionSupportEnabled(world)) return; // Region support disabled
if (!(entity instanceof Player player)) return;
if (Entities.isNPC(player)) return;
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
if (entity instanceof Player && event.getCause() == DamageCause.FALL) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer((Player) entity);
if (event.getCause() == DamageCause.FALL) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (!query.testState(BukkitAdapter.adapt(entity.getLocation()), localPlayer, Flags.FALL_DAMAGE)) {
event.setCancelled(true);
return;
}
} else {
if (entity instanceof Player && event.getCause() == DamageCause.FLY_INTO_WALL) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer((Player) entity);
if (!query.testState(BukkitAdapter.adapt(entity.getLocation()), localPlayer, Flags.FALL_DAMAGE)) {
event.setCancelled(true);
return;
}
} else if (event.getCause() == DamageCause.FLY_INTO_WALL) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (!query.testState(BukkitAdapter.adapt(entity.getLocation()), localPlayer, Flags.FALL_DAMAGE)) {
event.setCancelled(true);
return;
}
}
}
/**
@@ -57,10 +57,15 @@ import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.entity.SulfurCube;
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 +178,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 +223,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, EntityType.SULFUR_CUBE) != null) {
canBreak = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.BLOCK_BREAK, Flags.TNT));
what = "use dynamite";
@@ -244,13 +249,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 +411,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 +432,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 +476,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,14 +530,34 @@ 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();
if (!isRegionSupportEnabled(vehicle.getWorld())) return; // Region support disabled
Entity exited = event.getExited();
if (vehicle instanceof Tameable && exited instanceof Player) {
Player player = (Player) exited;
if (vehicle instanceof Tameable && exited instanceof Player player && !Entities.isNPC(player)) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (!isWhitelisted(Cause.create(player), vehicle.getWorld(), false)) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
@@ -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;
@@ -470,7 +471,6 @@ public class WorldGuardBlockListener extends AbstractListener {
public void onBlockForm(BlockFormEvent event) {
ConfigurationManager cfg = getConfig();
if (cfg.activityHaltToggle) {
event.setCancelled(true);
return;
@@ -478,7 +478,8 @@ public class WorldGuardBlockListener extends AbstractListener {
WorldConfiguration wcfg = getWorldConfig(event.getBlock().getWorld());
Material type = event.getNewState().getType();
Material oldType = event.getBlock().getType();
Material newType = event.getNewState().getType();
if (event instanceof EntityBlockFormEvent) {
if (((EntityBlockFormEvent) event).getEntity() instanceof Snowman) {
@@ -490,7 +491,7 @@ public class WorldGuardBlockListener extends AbstractListener {
return;
}
if (type == Material.ICE) {
if (newType == Material.ICE) {
if (wcfg.disableIceFormation) {
event.setCancelled(true);
return;
@@ -502,7 +503,7 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
if (type == Material.SNOW) {
if (newType == Material.SNOW) {
if (wcfg.disableSnowFormation) {
event.setCancelled(true);
return;
@@ -521,6 +522,31 @@ public class WorldGuardBlockListener extends AbstractListener {
return;
}
}
if (Materials.isUnwaxedCopper(oldType)) {
if (wcfg.disableCopperBlockFade) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && !StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.queryState(BukkitAdapter.adapt(event.getBlock().getLocation()), (RegionAssociable) null, Flags.COPPER_FADE))) {
event.setCancelled(true);
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;
}
}
}
/*
@@ -588,7 +614,7 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
if (newType == Material.BUDDING_AMETHYST || newType == Material.POINTED_DRIPSTONE) {
if (Materials.isAmethystGrowth(newType) || newType == Material.POINTED_DRIPSTONE) {
if (wcfg.disableRockGrowth) {
event.setCancelled(true);
return;
@@ -601,6 +627,19 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
if (Materials.isSculkGrowth(newType)) {
if (wcfg.disableSculkGrowth) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && !StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.queryState(BukkitAdapter.adapt(event.getBlock().getLocation()), (RegionAssociable) null, Flags.SCULK_GROWTH))) {
event.setCancelled(true);
return;
}
}
handleGrow(event, event.getBlock().getLocation(), newType);
}
@@ -702,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,27 +19,35 @@
package com.sk89q.worldguard.bukkit.listener;
import com.destroystokyo.paper.event.entity.EntityZapEvent;
import com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.BukkitWorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.InteropUtils;
import com.sk89q.worldguard.config.ConfigurationManager;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.FailedLoadRegionSet;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
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;
@@ -54,14 +62,18 @@ import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.SulfurCube;
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;
@@ -84,6 +96,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;
@@ -102,6 +115,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();
@@ -116,6 +141,10 @@ public class WorldGuardEntityListener extends AbstractListener {
event.setCancelled(true);
return;
}
if (block.getType() == Material.SNIFFER_EGG && wcfg.disableCreatureSnifferEggTrampling) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH)
@@ -138,8 +167,7 @@ public class WorldGuardEntityListener extends AbstractListener {
event.setCancelled(true);
return;
}
} else if (defender instanceof Player) {
Player player = (Player) defender;
} else if (defender instanceof Player player && !Entities.isNPC(defender)) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (wcfg.disableLavaDamage && type == DamageCause.LAVA) {
@@ -227,8 +255,7 @@ public class WorldGuardEntityListener extends AbstractListener {
}
}
if (defender instanceof Player) {
Player player = (Player) defender;
if (defender instanceof Player player && !Entities.isNPC(defender)) {
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
if (wcfg.disableLightningDamage && event.getCause() == DamageCause.LIGHTNING) {
@@ -289,8 +316,7 @@ public class WorldGuardEntityListener extends AbstractListener {
}
WorldConfiguration wcfg = getWorldConfig(defender.getWorld());
if (defender instanceof Player) {
Player player = (Player) defender;
if (defender instanceof Player player && !Entities.isNPC(defender)) {
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
@@ -306,13 +332,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);
@@ -321,7 +351,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;
}
@@ -363,8 +393,7 @@ public class WorldGuardEntityListener extends AbstractListener {
event.setCancelled(true);
return;
}
} else if (defender instanceof Player) {
Player player = (Player) defender;
} else if (defender instanceof Player player && !Entities.isNPC(defender)) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (type == DamageCause.WITHER) {
@@ -460,7 +489,7 @@ public class WorldGuardEntityListener extends AbstractListener {
event.blockList().clear();
return;
}
} else if (ent instanceof TNTPrimed || ent instanceof ExplosiveMinecart) {
} else if (ent instanceof TNTPrimed || ent instanceof ExplosiveMinecart || ent instanceof SulfurCube) {
if (wcfg.blockTNTExplosions) {
event.setCancelled(true);
return;
@@ -479,6 +508,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);
@@ -489,10 +523,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;
@@ -510,8 +544,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;
@@ -526,7 +560,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;
@@ -535,7 +570,6 @@ public class WorldGuardEntityListener extends AbstractListener {
}
}
if (wcfg.signChestProtection) {
for (Block block : event.blockList()) {
if (wcfg.isChestProtected(BukkitAdapter.adapt(block.getLocation()))) {
@@ -582,12 +616,18 @@ 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
|| event.getEntityType() == EntityType.SULFUR_CUBE) {
if (wcfg.blockTNTExplosions) {
event.setCancelled(true);
return;
}
} else if (event.getEntity() instanceof AbstractWindCharge) {
if (wcfg.blockWindChargeExplosions) {
event.setCancelled(true);
return;
}
}
}
@@ -603,7 +643,7 @@ public class WorldGuardEntityListener extends AbstractListener {
WorldConfiguration wcfg = getWorldConfig(event.getEntity().getWorld());
// allow spawning of creatures from plugins
if (!wcfg.blockPluginSpawning && event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.CUSTOM) {
if (!wcfg.blockPluginSpawning && Entities.isPluginSpawning(event.getSpawnReason())) {
return;
}
@@ -618,8 +658,11 @@ public class WorldGuardEntityListener extends AbstractListener {
return;
}
EntityType entityType = event.getEntityType();
handleCreatureSpawn(event, event.getLocation(), event.getEntityType(), event.getSpawnReason(), cfg, wcfg);
}
private static void handleCreatureSpawn(Cancellable event, Location location, EntityType entityType, SpawnReason spawnReason,
ConfigurationManager cfg, WorldConfiguration wcfg) {
com.sk89q.worldedit.world.entity.EntityType weEntityType = BukkitAdapter.adapt(entityType);
if (weEntityType != null && wcfg.blockCreatureSpawn.contains(weEntityType)) {
@@ -627,11 +670,9 @@ public class WorldGuardEntityListener extends AbstractListener {
return;
}
Location eventLoc = event.getLocation();
if (wcfg.useRegions && cfg.useRegionsCreatureSpawnEvent) {
ApplicableRegionSet set =
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(eventLoc));
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(location));
if (!set.testState(null, Flags.MOB_SPAWNING)) {
event.setCancelled(true);
@@ -646,8 +687,8 @@ public class WorldGuardEntityListener extends AbstractListener {
}
if (wcfg.blockGroundSlimes && entityType == EntityType.SLIME
&& eventLoc.getY() >= 60
&& event.getSpawnReason() == SpawnReason.NATURAL) {
&& location.getY() >= 60
&& spawnReason == SpawnReason.NATURAL) {
event.setCancelled(true);
return;
}
@@ -657,35 +698,46 @@ public class WorldGuardEntityListener extends AbstractListener {
public void onCreatePortal(PortalCreateEvent event) {
WorldConfiguration wcfg = getWorldConfig(event.getWorld());
if (wcfg.regionNetherPortalProtection
if (wcfg.useRegions && wcfg.regionNetherPortalProtection
&& event.getReason() == PortalCreateEvent.CreateReason.NETHER_PAIR
&& !event.getBlocks().isEmpty()) {
final com.sk89q.worldedit.world.World world = BukkitAdapter.adapt(event.getWorld());
final RegionManager regionManager = WorldGuard.getInstance().getPlatform().getRegionContainer()
.get(world);
if (regionManager == null) return;
LocalPlayer associable = null;
if (event.getEntity() instanceof Player) {
associable = getPlugin().wrapPlayer(((Player) event.getEntity()));
if (WorldGuard.getInstance().getPlatform().getSessionManager().hasBypass(associable, world)) {
final Cause cause = Cause.create(event.getEntity());
LocalPlayer localPlayer = null;
if (cause.getRootCause() instanceof Player player) {
if (wcfg.fakePlayerBuildOverride && InteropUtils.isFakePlayer(player)) {
return;
}
localPlayer = getPlugin().wrapPlayer(player);
if (WorldGuard.getInstance().getPlatform().getSessionManager().hasBypass(localPlayer, world)) {
return;
}
}
BlockVector3 min = null;
BlockVector3 max = null;
for (BlockState block : event.getBlocks()) {
BlockVector3 loc = BlockVector3.at(block.getX(), block.getY(), block.getZ());
min = min == null ? loc : loc.getMinimum(min);
max = max == null ? loc : loc.getMaximum(max);
final RegionManager regionManager = WorldGuard.getInstance().getPlatform().getRegionContainer()
.get(world);
ApplicableRegionSet regions;
if (regionManager == null) {
regions = FailedLoadRegionSet.getInstance();
} else {
BlockVector3 min = null;
BlockVector3 max = null;
for (BlockState block : event.getBlocks()) {
BlockVector3 loc = BlockVector3.at(block.getX(), block.getY(), block.getZ());
min = min == null ? loc : loc.getMinimum(min);
max = max == null ? loc : loc.getMaximum(max);
}
ProtectedCuboidRegion target = new ProtectedCuboidRegion("__portal_check", true, min, max);
regions = regionManager.getApplicableRegions(target);
}
ProtectedCuboidRegion target = new ProtectedCuboidRegion("__portal_check", true, min, max);
final ApplicableRegionSet regions = regionManager.getApplicableRegions(target);
if (!regions.testState(associable, Flags.BUILD, Flags.BLOCK_PLACE)) {
if (associable != null) {
final RegionAssociable associable = createRegionAssociable(cause);
final State buildState = StateFlag.denyToNone(regions.queryState(associable, Flags.BUILD));
if (!StateFlag.test(buildState, regions.queryState(associable, Flags.BLOCK_BREAK))
|| !StateFlag.test(buildState, regions.queryState(associable, Flags.BLOCK_PLACE))) {
if (localPlayer != null && !cause.isIndirect()) {
// NB there is no way to cancel the teleport without PTA (since PlayerPortal doesn't have block info)
// removing PTA was a mistake
String message = regions.queryValue(associable, Flags.DENY_MESSAGE);
RegionProtectionListener.formatAndSendDenyMessage("create portals", associable, message);
String message = regions.queryValue(localPlayer, Flags.DENY_MESSAGE);
RegionProtectionListener.formatAndSendDenyMessage("create portals", localPlayer, message);
}
event.setCancelled(true);
}
@@ -710,9 +762,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) {
@@ -745,10 +795,10 @@ public class WorldGuardEntityListener extends AbstractListener {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && ent instanceof Player
if (wcfg.useRegions && ent instanceof Player player && !Entities.isNPC(ent)
&& !WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().testState(
BukkitAdapter.adapt(ent.getLocation()),
WorldGuardPlugin.inst().wrapPlayer((Player) ent),
WorldGuardPlugin.inst().wrapPlayer(player),
Flags.HEALTH_REGEN)) {
event.setCancelled(true);
}
@@ -758,10 +808,11 @@ public class WorldGuardEntityListener extends AbstractListener {
public void onFoodChange(FoodLevelChangeEvent event) {
if (event.getItem() != null) return;
HumanEntity ent = event.getEntity();
if (!(ent instanceof Player)) return;
if (!(ent instanceof Player bukkitPlayer)) return;
if (Entities.isNPC(bukkitPlayer)) return;
if (event.getFoodLevel() > ent.getFoodLevel()) return;
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer((Player) ent);
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer(bukkitPlayer);
WorldConfiguration wcfg = getWorldConfig(ent.getWorld());
if (wcfg.useRegions
@@ -851,4 +902,67 @@ 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);
}
}
/**
* Applies the natural spawn checks from {@link WorldGuardEntityListener#onCreatureSpawn} before the
* server constructs the entity. The CreatureSpawnEvent checks fire at the very
* end of the spawn pipeline, after the position was picked, the placement
* checks ran and the mob was constructed and finalized, so a region that denies
* mob spawning pays for a mob to be built and thrown away on every attempt.
* Cancelling here skips the placement checks, the construction and
* finalizeSpawn for a spawn that was going to be refused anyway.
*
* Cancelling does not end the chunk's remaining attempts. Only
* setShouldAbortSpawn(true) makes the spawner return early; a plain cancel
* falls through to the next candidate position exactly like a failed
* placement check.
*
* Note that Paper fires this event for every candidate position, before the
* light, block and collision checks, so the region query below runs
* considerably more often than the CreatureSpawnEvent one did. On Paper with
* per-player-mob-spawns enabled, which is the default, every cancelled pre
* spawn is also charged to a per player mob backoff counter that is added to
* the mob cap of every player within tick view distance and bleeds off one per
* spawn cycle, so a large denied region can suppress spawning in neighbouring
* chunks that allow mobs.
*
* Only NATURAL spawns are handled here; every other spawn reason keeps going
* through the CreatureSpawnEvent checks unchanged.
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPreCreatureSpawn(PreCreatureSpawnEvent event) {
if (event.getReason() != SpawnReason.NATURAL) {
return;
}
ConfigurationManager cfg = getConfig();
if (!cfg.useRegionsPreCreatureSpawnEvent) {
return;
}
if (cfg.activityHaltToggle) {
event.setCancelled(true);
return;
}
Location spawnLoc = event.getSpawnLocation();
handleCreatureSpawn(event, spawnLoc, event.getType(), event.getReason(), cfg, getWorldConfig(spawnLoc.getWorld()));
}
}
private static class SpigotListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPigZap(PigZapEvent event) {
handlePigZap(event.getEntity(), event);
}
}
}
@@ -258,13 +258,11 @@ public class WorldGuardPlayerListener extends AbstractListener {
}
if (wcfg.useRegions) {
//Block placedIn = block.getRelative(event.getBlockFace());
ApplicableRegionSet set =
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation()));
//ApplicableRegionSet placedInSet = plugin.getRegionContainer().createQuery().getApplicableRegions(placedIn.getLocation());
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
if (item != null && item.getType().getKey().toString().equals(wcfg.regionWand) && getPlugin().hasPermission(player, "worldguard.region.wand")) {
ApplicableRegionSet set = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.getApplicableRegions(BukkitAdapter.adapt(block.getLocation()), RegionQuery.QueryOption.SORT);
if (set.size() > 0) {
player.sendMessage(ChatColor.YELLOW + "Can you build? " + (set.testState(localPlayer, Flags.BUILD) ? "Yes" : "No"));
@@ -309,11 +307,16 @@ public class WorldGuardPlayerListener extends AbstractListener {
event.setCancelled(true);
return;
}
if (type == Material.SNIFFER_EGG && wcfg.disablePlayerSnifferEggTrampling) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
if (com.sk89q.worldguard.bukkit.util.Entities.isNPC(player)) return;
WorldConfiguration wcfg = getWorldConfig(player.getWorld());
if (wcfg.useRegions) {
@@ -347,7 +350,13 @@ 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);
ConfigurationManager cfg = getConfig();
WorldConfiguration wcfg = getWorldConfig(player.getWorld());
@@ -24,6 +24,8 @@ import com.sk89q.worldedit.util.Location;
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;
@@ -54,20 +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,8 @@
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;
import org.bukkit.block.BlockState;
@@ -44,18 +46,18 @@ public class InventoryMoveItemEventDebounce extends AbstractEventDebounce<Key> {
private final Object target;
public Key(InventoryMoveItemEvent event) {
cause = transform(event.getInitiator().getHolder());
source = transform(event.getSource().getHolder());
target = transform(event.getDestination().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) {
return new BlockMaterialKey(((BlockState) holder).getBlock());
} else if (holder instanceof DoubleChest) {
InventoryHolder left = ((DoubleChest) holder).getLeftSide();
if (left instanceof Chest) {
return new BlockMaterialKey(((Chest) left).getBlock());
if (holder instanceof BlockState blockState) {
return new BlockMaterialKey(blockState);
} else if (holder instanceof DoubleChest doubleChest) {
InventoryHolder left = PaperLib.isPaper() ? doubleChest.getLeftSide(false) : doubleChest.getLeftSide();
if (left instanceof Chest chest) {
return new BlockMaterialKey(chest);
} else {
return holder;
}
@@ -94,8 +96,8 @@ public class InventoryMoveItemEventDebounce extends AbstractEventDebounce<Key> {
private final Block block;
private final Material material;
private BlockMaterialKey(Block block) {
this.block = block;
private BlockMaterialKey(BlockState block) {
this.block = block.getBlock();
material = block.getType();
}
@@ -25,15 +25,16 @@ import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.BukkitPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.session.AbstractSessionManager;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.Handler;
import org.bukkit.Bukkit;
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
@@ -41,63 +42,85 @@ import java.util.Collection;
*/
public class BukkitSessionManager extends AbstractSessionManager implements Runnable, Listener {
private boolean useTimings;
@Override
protected Handler.Factory<? extends Handler> wrapForRegistration(Handler.Factory<? extends Handler> factory) {
return useTimings ? new TimedHandlerFactory(factory) : factory;
}
/**
* Re-initialize handlers and clear "last position," "last state," etc.
* information for all players.
* Restore handler-managed state, re-initialize handlers, and clear
* "last position," "last state," etc. 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();
}
}
}
@EventHandler
public void onPlayerProcess(ProcessPlayerEvent event) {
// Pre-load a session
// Create a new session or re-initialize a cached one.
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer(event.getPlayer());
get(player).initialize(player);
Session session = getIfPresent(player);
if (session == null) {
get(player); // this also initializes the new session
} else {
session.resetState(player); // old sessions need explicit re-initialization
}
}
@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();
}
}
}
@Override
public boolean hasBypass(LocalPlayer player, World world) {
if (player instanceof BukkitPlayer) {
if (((BukkitPlayer) player).getPlayer().hasMetadata("NPC")
&& WorldGuard.getInstance().getPlatform().getGlobalStateManager().get(world).fakePlayerBuildOverride) {
if (player instanceof BukkitPlayer bukkitPlayer) {
if (Entities.isNPC(bukkitPlayer.getPlayer())
&& WorldGuard.getInstance().getPlatform().getGlobalStateManager().get(world).fakePlayerBuildOverride) {
return true;
}
if (!((BukkitPlayer) player).getPlayer().isOnline()) {
if (!bukkitPlayer.getPlayer().isOnline()) {
return false;
}
}
return super.hasBypass(player, world);
}
public boolean isUsingTimings() {
return useTimings;
}
public void setUsingTimings(boolean useTimings) {
this.useTimings = useTimings;
public void shutdown() {
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
get(localPlayer).uninitialize(localPlayer);
}
}
}
@@ -1,132 +0,0 @@
/*
* 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.session;
import co.aikar.timings.lib.MCTiming;
import co.aikar.timings.lib.TimingManager;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.Handler;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import javax.annotation.Nullable;
import java.security.CodeSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
class TimedHandlerFactory extends Handler.Factory<Handler> {
private static final TimingManager TIMINGS = TimingManager.of(WorldGuardPlugin.inst());
private static final MCTiming UNKNOWN_SOURCE = TIMINGS.of("Third-Party Session Handlers");
private static final Map<CodeSource, TimingManager> PLUGIN_SOURCES = new HashMap<>();
private final Handler.Factory<?> factory;
private final MCTiming timing;
TimedHandlerFactory(Handler.Factory<?> factory) {
this.factory = factory;
this.timing = makeTiming();
}
private MCTiming makeTiming() {
CodeSource codeSource = factory.getClass().getProtectionDomain().getCodeSource();
TimingManager owner = PLUGIN_SOURCES.computeIfAbsent(codeSource, source -> {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
CodeSource pluginSource = plugin.getClass().getProtectionDomain().getCodeSource();
if (Objects.equals(pluginSource, source)) {
return TimingManager.of(plugin);
}
}
return null;
});
String handlerName = factory.getClass().getEnclosingClass().getSimpleName();
return owner == null
? TIMINGS.of(handlerName, UNKNOWN_SOURCE)
: owner.of(handlerName, owner.of("Session Handlers"));
}
@Override
public Handler create(Session session) {
return new TimedHandler(factory.create(session), session, timing);
}
static class TimedHandler extends Handler {
private final Handler handler;
private final MCTiming timing;
TimedHandler(Handler innerHandler, Session session, MCTiming timing) {
super(session);
this.handler = innerHandler;
this.timing = timing;
}
@Override
public void initialize(LocalPlayer player, Location current, ApplicableRegionSet set) {
try (MCTiming ignored = timing.startTiming()) {
handler.initialize(player, current, set);
}
}
@Override
public boolean testMoveTo(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, MoveType moveType) {
try (MCTiming ignored = timing.startTiming()) {
return handler.testMoveTo(player, from, to, toSet, moveType);
}
}
@Override
public boolean onCrossBoundary(LocalPlayer player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) {
try (MCTiming ignored = timing.startTiming()) {
return handler.onCrossBoundary(player, from, to, toSet, entered, exited, moveType);
}
}
@Override
public void tick(LocalPlayer player, ApplicableRegionSet set) {
try (MCTiming ignored = timing.startTiming()) {
handler.tick(player, set);
}
}
@Nullable
@Override
public StateFlag.State getInvincibility(LocalPlayer player) {
try (MCTiming ignored = timing.startTiming()) {
return handler.getInvincibility(player);
}
}
@Override
public Handler getWrappedHandler() {
return handler;
}
}
}
@@ -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();
@@ -47,14 +47,17 @@ public class ClassSourceValidator {
private static final String SEPARATOR_LINE = Strings.repeat("*", 46);
private static final Method loadClass;
private static Class<?> pluginClassLoaderClass;
static {
Method tmp;
try {
tmp = PluginClassLoader.class.getDeclaredMethod("loadClass0",
pluginClassLoaderClass = Class.forName("org.bukkit.plugin.java.PluginClassLoader", false,
Bukkit.class.getClassLoader());
tmp = pluginClassLoaderClass.getDeclaredMethod("loadClass0",
String.class, boolean.class, boolean.class, boolean.class);
tmp.setAccessible(true);
} catch (NoSuchMethodException e) {
} catch (NoSuchMethodException | ClassNotFoundException e) {
tmp = null;
}
loadClass = tmp;
@@ -95,7 +98,7 @@ public class ClassSourceValidator {
continue;
}
ClassLoader targetLoader = target.getClass().getClassLoader();
if (!(targetLoader instanceof PluginClassLoader)) {
if (!(pluginClassLoaderClass.isAssignableFrom(targetLoader.getClass()))) {
continue;
}
for (Class<?> testClass : classes) {
@@ -19,33 +19,42 @@
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.SulfurCube;
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 {
@@ -70,7 +79,9 @@ public final class Entities {
* @return true if TNT based
*/
public static boolean isTNTBased(Entity entity) {
return entity instanceof TNTPrimed || entity instanceof ExplosiveMinecart;
return entity instanceof TNTPrimed
|| entity instanceof ExplosiveMinecart
|| entity instanceof SulfurCube sulfurCube && sulfurCube.canExplode();
}
/**
@@ -101,8 +112,23 @@ public final class Entities {
* @return true if the type is a vehicle type
*/
public static boolean isVehicle(EntityType type) {
return type == EntityType.BOAT
|| isMinecart(type);
return isBoat(type) || isMinecart(type);
}
/**
* Test whether the given entity type is a Boat type.
*
* @param type the type
* @return true if the type is a Boat type
*/
public static boolean isBoat(EntityType type) {
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;
};
}
/**
@@ -112,13 +138,11 @@ public final class Entities {
* @return true if the type is a Minecart type
*/
public static boolean isMinecart(EntityType type) {
return type == EntityType.MINECART
|| type == EntityType.MINECART_CHEST
|| type == EntityType.MINECART_COMMAND
|| type == EntityType.MINECART_FURNACE
|| type == EntityType.MINECART_HOPPER
|| type == EntityType.MINECART_MOB_SPAWNER
|| type == EntityType.MINECART_TNT;
return switch(type) {
case MINECART, CHEST_MINECART, COMMAND_BLOCK_MINECART, FURNACE_MINECART,
HOPPER_MINECART, SPAWNER_MINECART, TNT_MINECART -> true;
default -> false;
};
}
/**
@@ -149,11 +173,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;
}
/**
@@ -208,6 +228,7 @@ public final class Entities {
return entity instanceof Hanging
|| entity instanceof ArmorStand
|| entity instanceof EnderCrystal
|| entity instanceof Allay
|| entity instanceof Minecart && entity instanceof InventoryHolder;
}
@@ -218,4 +239,39 @@ public final class Entities {
public static boolean isAoECloud(EntityType type) {
return type == EntityType.AREA_EFFECT_CLOUD;
}
/**
* Check whether the spawn reason should be considered as a "plugin spawning".
* This is true for custom creations or the summon command.
*
* @param spawnReason the reason
* @return true if considered plugin spawning
*/
public static boolean isPluginSpawning(CreatureSpawnEvent.SpawnReason spawnReason) {
return switch (spawnReason) {
case CUSTOM, COMMAND -> true;
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 SulfurCube sulfurCube -> Flags.TNT;
case ExplosiveMinecart minecart -> Flags.TNT;
case EnderDragon dragon -> Flags.ENDERDRAGON_BLOCK_DAMAGE;
case null, default -> Flags.OTHER_EXPLOSION;
};
}
}
@@ -70,7 +70,7 @@ public final class InteropUtils {
UUID uuid = player.getUniqueId();
String name = player.getName();
if (player.hasMetadata("NPC")) {
if (Entities.isNPC(player)) {
return true;
}
File diff suppressed because it is too large. Load diff
@@ -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));
}
}
@@ -0,0 +1,48 @@
/*
* 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.report;
import com.sk89q.worldedit.util.report.DataReport;
import io.papermc.paper.datapack.Datapack;
import org.bukkit.Bukkit;
import java.util.Collection;
/**
* A report for current datapacks with some information. Only available on Paper
*/
public class DatapackReport extends DataReport {
public DatapackReport() {
super("DataPacks");
Collection<Datapack> packs = Bukkit.getDatapackManager().getPacks();
append("Datapack Count", packs.size());
append("Datapack Enabled Count", Bukkit.getDatapackManager().getEnabledPacks().size());
for (Datapack pack : packs) {
DataReport report = new DataReport("DataPack: " + pack.getName());
report.append("Enabled?", pack.isEnabled());
report.append("Name", pack.getName());
report.append("Compatibility", pack.getCompatibility().name());
append(report.getTitle(), report);
}
}
}
@@ -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();
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.bukkit.util.report;
import com.sk89q.worldedit.util.report.DataReport;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit;
import org.bukkit.Server;
@@ -33,9 +34,18 @@ public class ServerReport extends DataReport {
append("Bukkit Version", server.getBukkitVersion());
append("Implementation", server.getName() + " " + server.getVersion());
append("Player Count", "%d/%d", Bukkit.getOnlinePlayers().size(), server.getMaxPlayers());
append("Server Class Source", server.getClass().getProtectionDomain().getCodeSource().getLocation());
DataReport onlineMode = new DataReport("Online Mode");
onlineMode.append("enabled?", server.getOnlineMode());
if (PaperLib.isSpigot()) {
onlineMode.append("BungeeCord support?", Bukkit.spigot().getConfig().getBoolean("settings.bungeecord", false));
}
if (PaperLib.isPaper()) {
onlineMode.append("Velocity support?", Bukkit.spigot().getPaperConfig().getBoolean("proxies.velocity.enabled", false));
}
append(onlineMode.getTitle(), onlineMode);
DataReport spawning = new DataReport("Spawning");
spawning.append("Ambient Spawn Limit", server.getAmbientSpawnLimit());
spawning.append("Animal Spawn Limit", server.getAnimalSpawnLimit());
@@ -2,5 +2,5 @@ name: WorldGuard
main: com.sk89q.worldguard.bukkit.WorldGuardPlugin
version: "${internalVersion}"
depend: [WorldEdit]
softdepend: [CommandBook]
api-version: 1.17
api-version: "26.3"
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:1.29")
"implementation"("com.google.guava:guava:${Versions.GUAVA}")
constraints {
"implementation"(libs.snakeyaml) {
because("Bukkit provides SnakeYaml")
}
}
"compileOnly"("com.google.code.findbugs:jsr305:1.3.9")
"testImplementation"("org.hamcrest:hamcrest-library:1.2.1")
"api"(project(":worldguard-libs:core"))
"api"(libs.worldedit.core)
"implementation"(libs.flyway.core)
"implementation"(libs.snakeyaml)
"implementation"(libs.guava)
"compileOnlyApi"(libs.jsr305)
"implementation"(libs.gson)
"compileOnly"(libs.worldedit.libs.ap)
"annotationProcessor"(libs.worldedit.libs.ap)
// ensure this is on the classpath for the AP
"annotationProcessor"(libs.guava)
"compileOnly"(libs.autoService) {
because("Needed to resolve annotations in Piston")
}
"testImplementation"(libs.hamcrest.library)
}
tasks.withType<JavaCompile>().configureEach {
tasks.compileJava {
dependsOn(":worldguard-libs:build")
}
options.compilerArgs.add("-Aarg.name.key.prefix=")
}
configure<PublishingExtension> {
publications.named<MavenPublication>("maven") {
artifactId = the<BasePluginExtension>().archivesName.get()
from(components["java"])
}
}
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -42,10 +43,12 @@ public class BanAction implements Action {
if (event.getPlayer() != null) {
String message = entry.getMessage();
String friendlyName = PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent());
if (message != null) {
event.getPlayer().ban("Banned: " + String.format(message, event.getTarget().getFriendlyName()));
event.getPlayer().ban("Banned: " + String.format(message, friendlyName));
} else {
event.getPlayer().ban("Banned: You can't " + event.getDescription() + " " + event.getTarget().getFriendlyName());
event.getPlayer().ban("Banned: You can't " + event.getDescription() + " " + friendlyName);
}
}
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -42,10 +43,12 @@ public class KickAction implements Action {
if (event.getPlayer() != null) {
String message = entry.getMessage();
String friendlyName = PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent());
if (message != null) {
event.getPlayer().kick(String.format(message, event.getTarget().getFriendlyName()));
event.getPlayer().kick(String.format(message, friendlyName));
} else {
event.getPlayer().kick("You can't " + event.getDescription() + " " + event.getTarget().getFriendlyName());
event.getPlayer().kick("You can't " + event.getDescription() + " " + friendlyName);
}
}
@@ -19,6 +19,8 @@
package com.sk89q.worldguard.blacklist.action;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.blacklist.BlacklistEntry;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -44,9 +46,10 @@ public class TellAction extends RepeatGuardedAction {
if (event.getPlayer() != null) {
if (message != null) {
message = message.replaceAll("(?!<\\\\)\\\\n", "\n").replaceAll("\\\\\\\\n", "\\n");
event.getPlayer().print(String.format(message, event.getTarget().getFriendlyName()));
// TODO Find a better way to do this String.format call that doesn't require a string.
event.getPlayer().print(TextComponent.of(String.format(message, PlainComponentSerializer.INSTANCE.serialize(event.getTarget().getFriendlyNameComponent()))));
} else {
event.getPlayer().printError("You're not allowed to " + event.getDescription() + " " + event.getTarget().getFriendlyName() + ".");
event.getPlayer().printError(TextComponent.of("You're not allowed to " + event.getDescription() + " ").append(event.getTarget().getFriendlyNameComponent()).append(TextComponent.of(".")));
}
}
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -40,7 +41,7 @@ abstract class BlockBlacklistEvent extends AbstractBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPlayerName() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPlayerName() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -45,7 +46,7 @@ public final class BlockDispenseBlacklistEvent extends BlockBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPosition() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPosition() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.blacklist.event;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.target.Target;
@@ -40,7 +41,7 @@ abstract class ItemBlacklistEvent extends AbstractBlacklistEvent {
@Override
public String getLoggerMessage() {
return getPlayerName() + " tried to " + getDescription() + " " + getTarget().getFriendlyName();
return getPlayerName() + " tried to " + getDescription() + " " + PlainComponentSerializer.INSTANCE.serialize(getTarget().getFriendlyNameComponent());
}
@Override
@@ -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());
}
}
@@ -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);
}
@@ -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;
@@ -330,17 +329,9 @@ public final class RegionCommands extends RegionCommandsBase {
}
}
RegionAdder task = new RegionAdder(manager, region);
task.setLocatorPolicy(UserLocatorPolicy.UUID_ONLY);
task.setOwnersInput(new String[]{player.getName()});
final String description = String.format("Claiming region '%s'", id);
AsyncCommandBuilder.wrap(task, sender)
.registerWithSupervisor(WorldGuard.getInstance().getSupervisor(), description)
.sendMessageAfterDelay("(Please wait... " + description + ")")
.onSuccess(TextComponent.of(String.format("A new region has been claimed named '%s'.", id)), null)
.onFailure("Failed to claim region", WorldGuard.getInstance().getExceptionConverter())
.buildAndExec(WorldGuard.getInstance().getExecutorService());
region.getOwners().addPlayer(player);
manager.addRegion(region);
player.print(TextComponent.of(String.format("A new region has been claimed named '%s'.", id)));
}
/**
@@ -359,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) {
@@ -367,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();
}
@@ -409,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);
}
@@ -605,11 +597,14 @@ public final class RegionCommands extends RegionCommandsBase {
if (value != null) {
// Set the flag if [value] was given even if [-g group] was given as well
try {
value = setFlag(existing, foundFlag, sender, value).toString();
Object parsedValue = setFlag(existing, foundFlag, sender, value);
value = parsedValue == null ? null : parsedValue.toString();
} catch (InvalidFlagFormat e) {
throw new CommandException(e.getMessage());
}
}
if (value != null) {
if (!args.hasFlag('h')) {
sender.print("Region flag " + foundFlag.getName() + " set on '" + regionId + "' to '" + value + "'.");
}
@@ -669,18 +664,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();
}
@@ -1200,7 +1196,7 @@ public final class RegionCommands extends RegionCommandsBase {
// TODO: Add some method to create a safe teleport location.
// The method AbstractPlayerActor$findFreePoisition(Location loc) is no good way for this.
// It doesn't return the found location and it can't be checked if the location is inside the region.
throw new CommandException("Center teleport is only availible in Spectator gamemode.");
throw new CommandException("Center teleport is only available in Spectator gamemode.");
}
} else {
teleportLocation = FlagValueCalculator.getEffectiveFlagOf(existing, Flags.TELE_LOC, player);
@@ -32,15 +32,12 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.util.formatting.text.format.TextDecoration;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
@@ -59,6 +56,7 @@ import com.sk89q.worldguard.protection.regions.RegionQuery.QueryOption;
import com.sk89q.worldguard.protection.util.WorldEditRegionConverter;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
class RegionCommandsBase {
@@ -178,11 +176,13 @@ class RegionCommandsBase {
*
* @param regionManager the region manager
* @param player the player
* @param rgCmd the command to construct when clicking one of multiple items
* @param permissionPredicate a predicate to filter regions based on permission access
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, String rgCmd) throws CommandException {
return checkRegionStandingIn(regionManager, player, false, rgCmd);
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, String rgCmd, Predicate<ProtectedRegion> permissionPredicate) throws CommandException {
return checkRegionStandingIn(regionManager, player, false, rgCmd, permissionPredicate);
}
/**
@@ -197,10 +197,12 @@ class RegionCommandsBase {
* @param regionManager the region manager
* @param player the player
* @param allowGlobal whether to search for a global region if no others are found
* @param rgCmd the command to construct when clicking one of multiple items
* @param permissionPredicate a predicate to filter regions based on permission access
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, boolean allowGlobal, String rgCmd) throws CommandException {
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, LocalPlayer player, boolean allowGlobal, String rgCmd, Predicate<ProtectedRegion> permissionPredicate) throws CommandException {
ApplicableRegionSet set = regionManager.getApplicableRegions(player.getLocation().toVector().toBlockPoint(), QueryOption.SORT);
if (set.size() == 0) {
@@ -215,20 +217,30 @@ class RegionCommandsBase {
"Specify an ID if you want to select a specific region.");
} else if (set.size() > 1) {
boolean first = true;
Set<ProtectedRegion> filteredRegions = set.getRegions().stream().filter(permissionPredicate).collect(Collectors.toSet());
int hiddenRegions = set.size() - filteredRegions.size();
final TextComponent.Builder builder = TextComponent.builder("");
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
for (ProtectedRegion region : set) {
if (!first) {
builder.append(TextComponent.of(", "));
if (!filteredRegions.isEmpty()) {
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
for (ProtectedRegion region : filteredRegions) {
if (!first) {
builder.append(TextComponent.of(", "));
}
first = false;
TextComponent regionComp = TextComponent.of(region.getId(), TextColor.AQUA);
if (rgCmd != null && rgCmd.contains("%id%")) {
regionComp = regionComp.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to pick this region")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, rgCmd.replace("%id%", region.getId())));
}
builder.append(regionComp);
}
first = false;
TextComponent regionComp = TextComponent.of(region.getId(), TextColor.AQUA);
if (rgCmd != null && rgCmd.contains("%id%")) {
regionComp = regionComp.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to pick this region")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, rgCmd.replace("%id%", region.getId())));
if (hiddenRegions > 0) {
builder.append(TextComponent.of(", and " + hiddenRegions + " hidden regions", TextColor.GRAY));
}
builder.append(regionComp);
} else {
builder.append(TextComponent.of("Current regions: ", TextColor.GOLD));
builder.append(TextComponent.of(hiddenRegions + " hidden regions", TextColor.GRAY));
}
player.print(builder.build());
throw new CommandException("You're standing in several regions (please pick one).");
@@ -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).)");
}
@@ -65,6 +65,7 @@ public abstract class ConfigurationManager {
"#\r\n";
public boolean useRegionsCreatureSpawnEvent;
public boolean useRegionsPreCreatureSpawnEvent;
public boolean activityHaltToggle = false;
public boolean useGodPermission;
public boolean useGodGroup;
@@ -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;
@@ -139,6 +140,8 @@ public abstract class WorldConfiguration {
public boolean disablePlayerCropTrampling;
public boolean disableCreatureTurtleEggTrampling;
public boolean disablePlayerTurtleEggTrampling;
public boolean disableCreatureSnifferEggTrampling;
public boolean disablePlayerSnifferEggTrampling;
public boolean preventLightningFire;
public Set<String> disallowedLightningBlocks;
public boolean disableThunder;
@@ -159,11 +162,15 @@ public abstract class WorldConfiguration {
public boolean disableMyceliumSpread;
public boolean disableVineGrowth;
public boolean disableRockGrowth;
public boolean disableSculkGrowth;
public boolean disableCropGrowth;
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;
@@ -56,6 +56,7 @@ public abstract class YamlConfigurationManager extends ConfigurationManager {
migrateRegionsToUuid = config.getBoolean("regions.uuid-migration.perform-on-next-start", true);
keepUnresolvedNames = config.getBoolean("regions.uuid-migration.keep-names-that-lack-uuids", true);
useRegionsCreatureSpawnEvent = config.getBoolean("regions.use-creature-spawn-event", true);
useRegionsPreCreatureSpawnEvent = config.getBoolean("regions.use-pre-creature-spawn-event", false);
disableDefaultBypass = config.getBoolean("regions.disable-bypass-by-default", false);
announceBypassStatus = config.getBoolean("regions.announce-bypass-status", false);
@@ -409,15 +409,18 @@ public class DefaultDomain implements Domain, ChangeTracked {
final TextComponent.Builder builder = TextComponent.builder("");
final Iterator<TextComponent> profiles = profileMap.keySet().stream().sorted().map(name -> {
final UUID uuid = profileMap.get(name);
final TextComponent component = TextComponent.of(name, TextColor.YELLOW)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, uuid == null
? TextComponent.of("Name only", TextColor.GRAY)
: TextComponent.of("Last known name of uuid: ", TextColor.GRAY)
.append(TextComponent.of(uuid.toString(), TextColor.WHITE))));
if (uuid == null) {
return component;
return TextComponent.of(name, TextColor.YELLOW)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Name only", TextColor.GRAY)
.append(TextComponent.newline()).append(TextComponent.of("Click to copy"))))
.clickEvent(ClickEvent.of(ClickEvent.Action.COPY_TO_CLIPBOARD, name));
} else {
return TextComponent.of(name, TextColor.YELLOW)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Last known name of uuid: ", TextColor.GRAY)
.append(TextComponent.of(uuid.toString(), TextColor.WHITE))
.append(TextComponent.newline()).append(TextComponent.of("Click to copy"))))
.clickEvent(ClickEvent.of(ClickEvent.Action.COPY_TO_CLIPBOARD, uuid.toString()));
}
return component.clickEvent(ClickEvent.of(ClickEvent.Action.SUGGEST_COMMAND, uuid.toString()));
}).iterator();
while (profiles.hasNext()) {
builder.append(profiles.next());
@@ -428,9 +431,11 @@ public class DefaultDomain implements Domain, ChangeTracked {
if (!uuids.isEmpty()) {
builder.append(TextComponent.of(uuids.size() + " unknown uuid" + (uuids.size() == 1 ? "" : "s"), TextColor.GRAY)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of(String.join("\n", uuids))
.append(TextComponent.newline().append(TextComponent.of("Click to select")))))
.clickEvent(ClickEvent.of(ClickEvent.Action.SUGGEST_COMMAND, String.join(",", uuids))));
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Unable to resolve the name for:", TextColor.GRAY)
.append(TextComponent.newline())
.append(TextComponent.of(String.join("\n", uuids), TextColor.WHITE))
.append(TextComponent.newline().append(TextComponent.of("Click to copy")))))
.clickEvent(ClickEvent.of(ClickEvent.Action.COPY_TO_CLIPBOARD, String.join(",", uuids))));
}
@@ -145,6 +145,7 @@ public interface WorldGuardPlatform {
*
* @param localPlayer The player
*/
@Deprecated(forRemoval = true)
void stackPlayerInventory(LocalPlayer localPlayer);
/**
@@ -57,6 +57,6 @@ public class EntityTypeFlag extends Flag<EntityType> {
@Override
public Object marshal(EntityType o) {
return o.getId();
return o.id();
}
}
@@ -74,6 +74,7 @@ public final class Flags {
public static final StateFlag FIREWORK_DAMAGE = register(new StateFlag("firework-damage", false));
public static final StateFlag USE_ANVIL = register(new StateFlag("use-anvil", false));
public static final StateFlag USE_DRIPLEAF = register(new StateFlag("use-dripleaf", false));
public static final StateFlag WIND_CHARGE_BURST = register(new StateFlag("wind-charge-burst", false));
// These flags are similar to the ones above (used in tandem with BUILD),
// but their defaults are set to TRUE because it is more user friendly.
@@ -93,6 +94,7 @@ public final class Flags {
public static final StateFlag ENDERDRAGON_BLOCK_DAMAGE = register(new StateFlag("enderdragon-block-damage", true));
public static final StateFlag GHAST_FIREBALL = register(new StateFlag("ghast-fireball", true));
public static final StateFlag OTHER_EXPLOSION = register(new StateFlag("other-explosion", true));
public static final StateFlag BREEZE_WIND_CHARGE = register(new StateFlag("breeze-charge-explosion", true));
public static final StateFlag WITHER_DAMAGE = register(new StateFlag("wither-damage", true));
public static final StateFlag ENDER_BUILD = register(new StateFlag("enderman-grief", true));
public static final StateFlag SNOWMAN_TRAILS = register(new StateFlag("snowman-trails", true));
@@ -121,11 +123,15 @@ public final class Flags {
public static final StateFlag MYCELIUM_SPREAD = register(new StateFlag("mycelium-spread", true));
public static final StateFlag VINE_GROWTH = register(new StateFlag("vine-growth", true));
public static final StateFlag ROCK_GROWTH = register(new StateFlag("rock-growth", true));
public static final StateFlag SCULK_GROWTH = register (new StateFlag("sculk-growth", true));
public static final StateFlag CROP_GROWTH = register(new StateFlag("crop-growth", true));
public static final StateFlag SOIL_DRY = register(new StateFlag("soil-dry", true));
public static final StateFlag CORAL_FADE = register(new StateFlag("coral-fade", true));
public static final StateFlag COPPER_FADE = register(new StateFlag("copper-fade", true));
public static final StateFlag WATER_FLOW = register(new StateFlag("water-flow", true));
public static final StateFlag LAVA_FLOW = register(new StateFlag("lava-flow", true));
public static final StateFlag MOISTURE_CHANGE = register(new StateFlag("moisture-change", true));
public static final StateFlag LAVA_HARDEN = register(new StateFlag("lava-harden", true));
public static final RegistryFlag<WeatherType> WEATHER_LOCK = register(new RegistryFlag<>("weather-lock", WeatherType.REGISTRY));
public static final StringFlag TIME_LOCK = register(new StringFlag("time-lock"));
@@ -57,6 +57,6 @@ public class GameModeTypeFlag extends Flag<GameMode> {
@Override
public Object marshal(GameMode o) {
return o.getId();
return o.id();
}
}
@@ -137,9 +137,9 @@ public class LocationFlag extends Flag<Location> {
return null;
}
}
vec.put("x", position.getX());
vec.put("y", position.getY());
vec.put("z", position.getZ());
vec.put("x", position.x());
vec.put("y", position.y());
vec.put("z", position.z());
vec.put("yaw", o.getYaw());
vec.put("pitch", o.getPitch());
return vec;
@@ -61,6 +61,6 @@ public class RegistryFlag<T extends Keyed> extends Flag<T> {
@Override
public Object marshal(T o) {
return o.getId();
return o.id();
}
}
@@ -82,9 +82,9 @@ public class VectorFlag extends Flag<Vector3> {
@Override
public Object marshal(Vector3 o) {
Map<String, Object> vec = new HashMap<>();
vec.put("x", o.getX());
vec.put("y", o.getY());
vec.put("z", o.getZ());
vec.put("x", o.x());
vec.put("y", o.y());
vec.put("z", o.z());
return vec;
}
@@ -57,6 +57,6 @@ public class WeatherTypeFlag extends Flag<WeatherType> {
@Override
public Object marshal(WeatherType o) {
return o.getId();
return o.id();
}
}
@@ -224,7 +224,7 @@ public final class RegionManager {
}
/**
* Aad a region to the manager.
* Add a region to the manager.
*
* <p>The parents of the region will also be added to the index.</p>
*
@@ -93,10 +93,10 @@ public class ChunkHashTable implements ConcurrentRegionIndex {
private ChunkState get(BlockVector2 position, boolean create) {
ChunkState state;
synchronized (lock) {
state = states.get(position.getBlockX(), position.getBlockZ());
state = states.get(position.x(), position.z());
if (state == null && create) {
state = new ChunkState(position);
states.put(position.getBlockX(), position.getBlockZ(), state);
states.put(position.x(), position.z(), state);
executor.submit(new EnumerateRegions(position));
}
}
@@ -130,7 +130,7 @@ public class ChunkHashTable implements ConcurrentRegionIndex {
for (ChunkState state : previousStates.values()) {
BlockVector2 position = state.getPosition();
positions.add(position);
states.put(position.getBlockX(), position.getBlockZ(), new ChunkState(position));
states.put(position.x(), position.z(), new ChunkState(position));
}
if (!positions.isEmpty()) {
@@ -179,9 +179,9 @@ public class ChunkHashTable implements ConcurrentRegionIndex {
public void forget(BlockVector2 chunkPosition) {
checkNotNull(chunkPosition);
synchronized (lock) {
states.remove(chunkPosition.getBlockX(), chunkPosition.getBlockZ());
states.remove(chunkPosition.x(), chunkPosition.z());
ChunkState state = lastState;
if (state != null && state.getPosition().getBlockX() == chunkPosition.getBlockX() && state.getPosition().getBlockZ() == chunkPosition.getBlockZ()) {
if (state != null && state.getPosition().x() == chunkPosition.x() && state.getPosition().z() == chunkPosition.z()) {
lastState = null;
}
}
@@ -238,10 +238,10 @@ public class ChunkHashTable implements ConcurrentRegionIndex {
checkNotNull(consumer);
ChunkState state = lastState;
int chunkX = position.getBlockX() >> 4;
int chunkZ = position.getBlockZ() >> 4;
int chunkX = position.x() >> 4;
int chunkZ = position.z() >> 4;
if (state == null || state.getPosition().getBlockX() != chunkX || state.getPosition().getBlockZ() != chunkZ) {
if (state == null || state.getPosition().x() != chunkX || state.getPosition().z() != chunkZ) {
state = get(BlockVector2.at(chunkX, chunkZ), false);
}
@@ -69,7 +69,7 @@ public class PriorityRTreeIndex extends HashMapIndex {
@Override
public void applyContaining(BlockVector3 position, Predicate<ProtectedRegion> consumer) {
Set<ProtectedRegion> seen = new HashSet<>();
MBR pointMBR = new SimpleMBR(position.getX(), position.getX(), position.getY(), position.getY(), position.getZ(), position.getZ());
MBR pointMBR = new SimpleMBR(position.x(), position.x(), position.y(), position.y(), position.z(), position.z());
for (ProtectedRegion region : tree.find(pointMBR)) {
if (region.contains(position) && !seen.contains(region)) {
@@ -87,7 +87,7 @@ public class PriorityRTreeIndex extends HashMapIndex {
BlockVector3 max = region.getMaximumPoint().ceil();
Set<ProtectedRegion> candidates = new HashSet<>();
MBR pointMBR = new SimpleMBR(min.getX(), max.getX(), min.getY(), max.getY(), min.getZ(), max.getZ());
MBR pointMBR = new SimpleMBR(min.x(), max.x(), min.y(), max.y(), min.z(), max.z());
for (ProtectedRegion found : tree.find(pointMBR)) {
candidates.add(found);
@@ -84,8 +84,8 @@ public class WorldHeightMigration extends AbstractMigration {
if (min == 0 && max == 255) return;
}
for (ProtectedRegion region : regions) {
if (region.getMinimumPoint().getBlockY() <= 0
&& region.getMaximumPoint().getBlockY() >= 255) {
if (region.getMinimumPoint().y() <= 0
&& region.getMaximumPoint().y() >= 255) {
expand(region, min, max);
changed++;
}
@@ -41,6 +41,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.parser.ParserException;
@@ -49,6 +50,7 @@ import org.yaml.snakeyaml.representer.Representer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -89,7 +91,7 @@ public class YamlRegionFile implements RegionDatabase {
options.setIndent(4);
options.setDefaultFlowStyle(FlowStyle.AUTO);
ERROR_DUMP_YAML = new Yaml(new SafeConstructor(), new Representer(), options);
ERROR_DUMP_YAML = new Yaml(new SafeConstructor(new LoaderOptions()), new Representer(new DumperOptions()), options);
}
/**
@@ -117,7 +119,7 @@ public class YamlRegionFile implements RegionDatabase {
YAMLProcessor config = createYamlProcessor(file);
try {
config.load();
} catch (FileNotFoundException e) {
} catch (FileNotFoundException | NoSuchFileException e) {
return new HashSet<>(loaded.values());
} catch (IOException | ParserException e) {
throw new StorageException("Failed to load region data from '" + file + "'", e);
@@ -192,64 +194,66 @@ public class YamlRegionFile implements RegionDatabase {
public void saveAll(Set<ProtectedRegion> regions) throws StorageException {
checkNotNull(regions);
File tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
YAMLProcessor config = createYamlProcessor(tempFile);
synchronized (YamlRegionFile.class) {
File tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
YAMLProcessor config = createYamlProcessor(tempFile);
config.clear();
config.clear();
YAMLNode regionsNode = config.addNode("regions");
Map<String, Object> map = regionsNode.getMap();
YAMLNode regionsNode = config.addNode("regions");
Map<String, Object> map = regionsNode.getMap();
for (ProtectedRegion region : regions) {
Map<String, Object> nodeMap = new HashMap<>();
map.put(region.getId(), nodeMap);
YAMLNode node = new YAMLNode(nodeMap, false);
for (ProtectedRegion region : regions) {
Map<String, Object> nodeMap = new HashMap<>();
map.put(region.getId(), nodeMap);
YAMLNode node = new YAMLNode(nodeMap, false);
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
node.setProperty("type", "cuboid");
node.setProperty("min", cuboid.getMinimumPoint());
node.setProperty("max", cuboid.getMaximumPoint());
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly = (ProtectedPolygonalRegion) region;
node.setProperty("type", "poly2d");
node.setProperty("min-y", poly.getMinimumPoint().getBlockY());
node.setProperty("max-y", poly.getMaximumPoint().getBlockY());
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
node.setProperty("type", "cuboid");
node.setProperty("min", cuboid.getMinimumPoint());
node.setProperty("max", cuboid.getMaximumPoint());
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly = (ProtectedPolygonalRegion) region;
node.setProperty("type", "poly2d");
node.setProperty("min-y", poly.getMinimumPoint().y());
node.setProperty("max-y", poly.getMaximumPoint().y());
List<Map<String, Object>> points = new ArrayList<>();
for (BlockVector2 point : poly.getPoints()) {
Map<String, Object> data = new HashMap<>();
data.put("x", point.getBlockX());
data.put("z", point.getBlockZ());
points.add(data);
List<Map<String, Object>> points = new ArrayList<>();
for (BlockVector2 point : poly.getPoints()) {
Map<String, Object> data = new HashMap<>();
data.put("x", point.x());
data.put("z", point.z());
points.add(data);
}
node.setProperty("points", points);
} else if (region instanceof GlobalProtectedRegion) {
node.setProperty("type", "global");
} else {
node.setProperty("type", region.getClass().getCanonicalName());
}
node.setProperty("points", points);
} else if (region instanceof GlobalProtectedRegion) {
node.setProperty("type", "global");
} else {
node.setProperty("type", region.getClass().getCanonicalName());
node.setProperty("priority", region.getPriority());
node.setProperty("flags", getFlagData(region));
node.setProperty("owners", getDomainData(region.getOwners()));
node.setProperty("members", getDomainData(region.getMembers()));
ProtectedRegion parent = region.getParent();
if (parent != null) {
node.setProperty("parent", parent.getId());
}
}
node.setProperty("priority", region.getPriority());
node.setProperty("flags", getFlagData(region));
node.setProperty("owners", getDomainData(region.getOwners()));
node.setProperty("members", getDomainData(region.getMembers()));
config.setHeader(FILE_HEADER);
config.save();
ProtectedRegion parent = region.getParent();
if (parent != null) {
node.setProperty("parent", parent.getId());
//noinspection ResultOfMethodCallIgnored
file.delete();
if (!tempFile.renameTo(file)) {
throw new StorageException("Failed to rename temporary regions file to " + file.getAbsolutePath());
}
}
config.setHeader(FILE_HEADER);
config.save();
//noinspection ResultOfMethodCallIgnored
file.delete();
if (!tempFile.renameTo(file)) {
throw new StorageException("Failed to rename temporary regions file to " + file.getAbsolutePath());
}
}
@Override
@@ -322,7 +326,7 @@ public class YamlRegionFile implements RegionDatabase {
}
/**
* Create a YAML processer instance.
* Create a YAML processor instance.
*
* @param file the file
* @return a processor instance
@@ -336,7 +340,7 @@ public class YamlRegionFile implements RegionDatabase {
* Dump the given object as YAML for debugging purposes.
*
* @param object the object
* @return the YAML string or an error string if dumping fals
* @return the YAML string or an error string if dumping fails
*/
private static String toYamlOutput(Object object) {
try {
@@ -113,12 +113,12 @@ class RegionInserter {
BlockVector3 max = region.getMaximumPoint();
stmt.setString(1, region.getId());
stmt.setInt(2, min.getBlockZ());
stmt.setInt(3, min.getBlockY());
stmt.setInt(4, min.getBlockX());
stmt.setInt(5, max.getBlockZ());
stmt.setInt(6, max.getBlockY());
stmt.setInt(7, max.getBlockX());
stmt.setInt(2, min.z());
stmt.setInt(3, min.y());
stmt.setInt(4, min.x());
stmt.setInt(5, max.z());
stmt.setInt(6, max.y());
stmt.setInt(7, max.x());
stmt.addBatch();
}
@@ -141,8 +141,8 @@ class RegionInserter {
for (List<ProtectedPolygonalRegion> partition : Lists.partition(polygons, StatementBatch.MAX_BATCH_SIZE)) {
for (ProtectedPolygonalRegion region : partition) {
stmt.setString(1, region.getId());
stmt.setInt(2, region.getMaximumPoint().getBlockY());
stmt.setInt(3, region.getMinimumPoint().getBlockY());
stmt.setInt(2, region.getMaximumPoint().y());
stmt.setInt(3, region.getMinimumPoint().y());
stmt.addBatch();
}
@@ -167,8 +167,8 @@ class RegionInserter {
for (ProtectedPolygonalRegion region : polygons) {
for (BlockVector2 point : region.getPoints()) {
stmt.setString(1, region.getId());
stmt.setInt(2, point.getBlockZ());
stmt.setInt(3, point.getBlockX());
stmt.setInt(2, point.z());
stmt.setInt(3, point.x());
batch.addBatch();
}
}
Loaded 100 of 119 files, more files were not shown because too many files have changed in this diff. Show more