Compare commits

...
155 Commits
Author SHA1 Message Date
Joo200 ab48a66237 Merge branch 'refs/heads/version/7.0.x'
# Conflicts:
#	buildSrc/src/main/kotlin/GradleExtras.kt
#	buildSrc/src/main/kotlin/LibsConfig.kt
#	buildSrc/src/main/kotlin/PlatformConfig.kt
#	gradle.properties
#	worldguard-libs/bukkit/build.gradle.kts
2024-09-16 20:08:34 +02:00
wizjany d9716a5bd8 Ignore arrow combustion.
Closes #2144.
2024-09-13 14:29:18 -04:00
wizjany a0e397e57f Use more snapshot-less holders on Paper.
This is already past the debounce so in theory it's not getting hit *often*, but I guess if it's really slow it'll still show up.
2024-09-13 14:15:32 -04:00
wizjany 02dc89b224 Bump to snapshot. 2024-09-13 11:58:55 -04:00
wizjany 829a4a42df Release 7.0.12. 2024-09-13 11:58:22 -04:00
wizjany 830472d36e Revert previous changes to explosion event handling.
Event abstraction sucks and everything needs rewriting.
2024-09-13 11:46:06 -04:00
wizjany 03aac83f4c Match explosion flag coverage with EntityListener. 2024-09-13 10:00:48 -04:00
wizjany fb88d56646 Bump to SNAPSHOT for dev.
Also update the changelog.
2024-09-09 16:56:05 -04:00
wizjany 068ad680fc Release 7.0.11. 2024-09-09 16:24:43 -04:00
ploppypersonandwizjany cb011a88cf Add moisture-change flag (#1879) (#2096)
* Create and implement moisture-change flag

* Fix imports

* Add comment

* Actually read the value from config.

Closes #1879 

---------

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

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

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

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

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

* Update Materials.java with 1.21 tags and materials

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

* Fix ItemStack conversion on block place

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

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

* Use ItemStack as-is.

Closes #2092.

* Fix ItemStack conversion for spigot compatibility

* Special handling for WindCharges

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

* WindCharge -> AbstractWindCharge

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

* Cleanup code

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

---------

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

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

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

* Use ItemStack as-is.

Closes #2092.

---------

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

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

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

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

* codestyle
2024-05-23 13:05:29 -04:00
Joo200 d6ef5e9398 Remove adventure snapshot repository 2024-05-17 18:05:37 +02:00
wizjany 6f5501f7be Bump to snapshot. 2024-05-14 18:14:06 -04:00
wizjany d9424b1c71 Release 7.0.10. 2024-05-14 18:11:53 -04:00
aurora 65431c7df8 Fix fire placement by blocks when fire-spread is set to deny
Fixes #2070
2024-05-13 20:27:34 +02:00
Joo200 aa254c80e0 Merge branch 'refs/heads/version/7.0.x'
# Conflicts:
#	buildSrc/build.gradle.kts
2024-05-03 19:57:42 +02:00
Joo200 2f93b26be0 Update dependencies to 1.20.6 2024-05-03 19:57:10 +02:00
wizjany 6bbf49314d Merge pull request #2075 from EngineHub/feature/1.20.5
Update WorldGuard to 1.20.5
2024-05-02 12:12:15 -04:00
Madeline Miller f6a0a0b415 Add outline to logo SVG akin to WorldEdit and CraftBook 2024-05-01 23:08:16 +10:00
Joo200 4ad11151fe Fix compilation for 1.20.5 2024-04-28 15:39:15 +02:00
Joo200 c29edf7467 Fix Deprecations from WorldEdit 7.3.0 2024-04-28 15:36:52 +02:00
Joo200 da3c81a88d Update dependencies to 1.20.5 and jdk 21 2024-04-28 15:32:32 +02:00
Joo200 c65dd83a7e Don't show particles for denied interact events with dripleaf and redstone ores 2024-04-07 22:04:00 +02:00
Joo200 694195435d Bump Versions 2024-04-07 22:02:57 +02:00
Madeline Miller 0d824d375b Add a Paper fast-path for DoubleChest#getLeftSide when possible 2024-03-31 12:28:53 -04:00
aromaa c7319f10dc Bump up respawn event priority to monitor 2023-09-11 21:25:47 -04:00
Joo200 c2b95f59a8 Paper only: Protect sign modifications as building 2023-08-22 14:34:52 +02:00
Joo200 5fa6f2a858 Update paper-api and spigot-api dependencies to 1.20.1 2023-08-22 14:34:26 +02:00
Joo200 0a9eb447d6 store custom domains thread safe, improve api usability 2023-08-20 11:06:36 +02:00
Joo200 02a8fd4c17 Merge remote-tracking branch 'origin/version/7.0.x'
# Conflicts:
#	gradle.properties
2023-08-14 14:21:50 +02:00
wizjany 3201cee1b7 Bump to snapshot. 2023-07-31 20:12:56 -04:00
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
Joo200 8cbce96a2c Merge branch 'version/7.0.x' 2023-06-18 18:47:29 +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 bb3fdcc880 Renamed InvalidFlagFormat to InvalidFlagFormatException 2023-06-04 18:55:01 +02:00
JOO200 8d5953a550 apidomains: Added custom domains to WorldGuard
This change allows third party plugins to dynamically add custom domains to WorldGuard.
2023-06-04 18:55:01 +02:00
Joo200 4a26e306b6 Consider the summon command as plugin spawning 2023-05-31 13:26:05 +02:00
wizjany 129ae6c971 Merge branch 'version/7.0.x'
# Conflicts:
#	gradle.properties
2023-05-27 13:49:05 -04: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 b67fd01ebd Merge branch 'version/7.0.x'
# Conflicts:
#	buildSrc/src/main/kotlin/Versions.kt
#	gradle/wrapper/gradle-wrapper.jar
#	gradle/wrapper/gradle-wrapper.properties
#	gradlew.bat
#	worldguard-core/build.gradle.kts
2023-03-26 15:17:06 +02:00
Joo200 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
Joo200 62be386626 Merge branch 'version/7.0.x' 2022-11-27 10:52:54 +01:00
aromaa cb100bb797 Improve compatibility with the new onClearValue 2022-09-20 09:07:27 -04:00
Joo200 741f9e231b Merge branch 'version/7.0.x'
# Conflicts:
#	buildSrc/build.gradle.kts
#	buildSrc/src/main/kotlin/PlatformConfig.kt
#	buildSrc/src/main/kotlin/Versions.kt
2022-09-19 11:56:50 +02:00
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 bc63119373 Fix publish. 2022-03-12 17:32:40 -05:00
wizjany 3549f04a33 Build script updates.
Bump gradle. Copy a bunch from WE. Hopefully nothing breaks.
2022-03-12 17:21:50 -05:00
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
wizjany 79a3b70d8d Release 7.0.7. 2022-03-03 14:21:45 -05:00
wizjany cf69425153 Don't cancel potion splashes with no targets. 2022-03-03 07:59:00 -05:00
wizjany e2fe770e6f Disregard that, definitely need to duplicate. 2022-03-01 18:27:45 -05:00
wizjany 7e06088c1a Switch to WE's ClassSourceValidator.
Since it's (being) fixed there and no need to duplicate any more.
2022-02-27 19:25:58 -05:00
wizjany f9d1c2d4e0 Fix some errors in config loading.
Technically removing a nonexistant property should be fixed in WE's yaml utils but eh.
2022-02-27 17:51:52 -05:00
wizjany f883899cfe Add deprecation warnings.
Also remove the nodes from config if unused.
2022-02-27 16:34:27 -05:00
wizjany de386fb4d8 Provisional changelog for 7.0.7. 2022-02-26 19:04:13 -05:00
wizjany 660f9ffa0d Use deny-message for nether portal protection.
Closes #1882.
2022-02-26 18:49:35 -05:00
wizjany e05d42371f Protect modification of candles and cake as building.
Closes #1880.
2022-02-26 18:43:04 -05:00
JOO200 dca0515104 Optimize Region List and Region Teleport commands (#1868)
* Optimized command usage for /rg list and /rg teleport:
* added a flag to the teleport command to teleport the actor to the center of the region
* added a flag to the list command to filter the regions for special ids
* added a flag to the list command to get regions intersecting your selection

* Fixed wrong pagination in RegionLister
2022-01-23 13:03:40 -05:00
wizjany 4abf971cf6 Add red sand to sand physics.
This option is still at the mercy of bukkit api and might still not work ¯\_(ツ)_/¯
2022-01-16 11:13:18 -05:00
wizjany 875a6fc827 Add space in an error message. 2022-01-16 11:13:15 -05:00
JOO200 3cb4abdbf7 Updated amount of modules, Windows command prompt and outdated hints 2022-01-08 21:23:11 +01:00
JOO200 4caf0afb38 Add COMPILING.md and set Java Version to 16 2022-01-08 21:03:11 +01:00
JOO200 054a73416b Update Java-Version in README.md to Java 17 2022-01-07 13:17:54 +01:00
Cristobal Lopez b59da5992f Allows claimed regions to inherit from a template region (#1864)
* Allows claimed regions to inherit from a template region

* Replace template-when-claiming with set-parent-on-claim

* Make the set-parent-on-claim option check secure
2022-01-02 10:07:00 -05:00
wizjany 46251f5ffa Don't check bypass for offline players.
This is someone else's problem now (╯°□°)╯︵ ┻━┻
2022-01-01 20:08:16 -05:00
wizjany 98bef4e0ab Remove extra import. 2021-12-31 10:55:51 -05:00
JOO200 f1c8649f9a Improve Checks for LightningStrikes (fixes #1845) 2021-12-31 10:55:51 -05:00
JOO200 aad698af84 Update Paper and Spigot to 1.17.1 2021-12-31 10:55:51 -05:00
JOO200 ad7ecbaefe Exclude paper-api from squirrelid dependency (Compilefix for removed maven mirrors) 2021-12-30 20:41:57 +01:00
wizjany 81750e191d Add /rg migrateheights. (#1857)
Closes #1856.
2021-12-02 15:44:25 -05:00
wizjany 703146bc18 Update guava to match MC 1.18 guava. 2021-11-30 20:42:54 -05:00
JOO200 2541483ebc Fixed invalid label 2021-11-25 22:00:40 +01:00
JOO200 0a601dbc28 Improved Bug Report and Feature Request Template 2021-11-25 21:59:46 +01:00
stonar96 f55802c176 Make cause known if origin can be used (#1838) 2021-11-25 12:33:43 -05:00
wizjany a0922cb467 Add rock-growth flag.
Handles amethyst and dripstone.

Closes #1855.
2021-11-25 12:32:24 -05:00
wizjany fb9705e4f0 Update gradle.
Getting ready for java 17.
2021-11-25 11:27:00 -05:00
JOO200 9b665136d0 Fix Blacklist log entry not by player results in NPE (#1837) 2021-09-25 13:22:33 +02:00
wizjany efac79fd38 Bump to 7.0.7-SNAPSHOT. 2021-09-16 18:51:54 -04:00
145 changed files with 4106 additions and 2215 deletions

No files matched your search

+33 -1
View File
@@ -1,2 +1,34 @@
*.java diff=java
* text=auto eol=lf
# Force Batch files to CRLF
*.bat eol=crlf -text
# Java sources
*.java text diff=java
*.kt text diff=java
*.gradle text diff=java
*.gradle.kts text diff=java
# These files are text and should be normalized (Convert crlf => lf)
*.css text diff=css
*.df text
*.htm text diff=html
*.html text diff=html
*.js text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.tld text
*.tag text
*.tagx text
*.xml text
# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.jar binary
*.so binary
*.war binary
*.jks binary
-34
View File
@@ -1,34 +0,0 @@
---
name: Bug report
about: Report a way in which WorldGuard is not working as intended
title: ''
labels: type:bug, status:pending
assignees: ''
---
**Versions**
<!-- Please include the full version of WorldEdit, WorldGuard and the platform (Bukkit/Spigot/Paper) you are running, e.g. output from `/we version`, `/wg version` `/version` commands. Please ensure you are running up to date software before making a bug report. Old versions will receive little to no support. -->
WorldEdit version:
WorldGuard version:
Platform version:
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
**To Reproduce**
<!-- Steps to reproduce the behavior: -->
1. ...
2. ...
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Screenshots**
<!-- If applicable, add screenshots to help explain your problem. Screenshots of `/rg info` for any applicable regions (or simply the link from `/wg report -p`) are good to include. -->
**Additional context**
<!-- Add any other context about the problem here. -->
+93
View File
@@ -0,0 +1,93 @@
name: Bug report
description: Report a way in which WorldGuard is not working as intended
labels: ['type:bug', 'status:pending']
body:
- type: markdown
attributes:
value: |
Please note that this is only for bugs, help with installation or other types of support should
be taken to the Discord Guild instead.
- type: input
attributes:
label: WorldEdit Version
description: The full version of WorldEdit, can be found by using `/we version`.
placeholder: e.g. 7.2.3 or 7.3.0-SNAPSHOT
validations:
required: true
- type: input
attributes:
label: WorldGuard Version
description: The full version of WorldGuard, can be found by using `/wg version`.
placeholder: e.g. 7.0.5 or 7.0.6-SNAPSHOT
validations:
required: true
- type: input
attributes:
label: Platform Version
description: |
The version of the platform you are on, i.e. Spigot or Paper.
Please ensure you are running up-to-date software before making a bug report.
Old versions, paper forks or hybrids will receive little to no support.
placeholder: e.g. git-Spigot-21fe707-e1ebe52, git-Paper-463
validations:
required: true
- type: checkboxes
id: confirmations
attributes:
label: Confirmations
description: Please confirm the following before submitting the bug. Your report will be closed if you are running hybrids or old software.
options:
- label: I am using the most recent Minecraft release.
required: true
- label: I am using a version of WorldEdit compatible with my Minecraft version.
required: true
- label: I am using a version of WorldGuard compatible with my Minecraft version.
required: true
- label: I am using the latest or recommended version of my platform software.
required: true
- label: I am NOT using a hybrid server, e.g. a server that combines Bukkit and Forge. Examples include Arclight, Mohist, and Cardboard.
required: true
- label: I am NOT using a fork of WorldEdit, such as FastAsyncWorldEdit (FAWE) or AsyncWorldEdit (AWE)
required: true
- type: textarea
attributes:
label: Bug Description
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: The behavior that you expected, instead of the bugged behavior that occurs.
validations:
required: true
- type: textarea
attributes:
label: Reproduction Steps
description: Steps to reproduce the behavior.
value: |
1. ...
2. ...
validations:
required: true
- type: input
attributes:
label: Optional WorldGuard-Report
description: Link to WorldGuard Region report for bugs with regions, received with `/wg report -p`
validations:
required: false
- type: textarea
attributes:
label: Anything Else?
description: Add any additional context you can provide below.
-20
View File
@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for WorldGuard
title: ''
labels: type:feature-request, status:pending
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->
**Describe alternatives you've considered**
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->
@@ -0,0 +1,35 @@
name: Feature request
description: Suggest an idea for WorldGuard
labels: ['type:feature-request', 'status:pending']
body:
- type: textarea
attributes:
label: The Problem
description: >
What is making your WorldGuard experience sub-optimal? This should be something that
cannot be easily solved by existing WorldGuard features.
placeholder: It's hard to ... ; I'm unable to ...
validations:
required: true
- type: textarea
attributes:
label: A Solution
description: What is your proposed solution to the above problem?
validations:
required: true
- type: textarea
attributes:
label: Alternatives
description: |
Alternative solutions or workarounds to the problem.
You should also describe why these are not preferable to the given solution.
validations:
required: false
- type: textarea
attributes:
label: Anything Else?
description: Add any additional context you can provide below.
-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
+52
View File
@@ -1,5 +1,57 @@
# Changelog
## 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
* Add regions.set-parent-on-claim config (set to a region id for /rg claim to automatically assign the parent region).
* Add `-i search` and `-s` flags to /rg list, -c to /rg teleport.
* Fix an error in blacklist logging caused by non-player actions (eg on-dispense)
* Treat unknown causes as known if using paper-entity-origin config option.
* Improve lightning strike handling from channeling tridents (PaperMC only).
* Ignore an error caused by lingering player references of offline players.
* Add red sand to no-physics-sand.
* Fix potion splash events being cancelled if no entities were affected.
## 7.0.6
* Add support for 1.17 blocks/items, drop support for 1.16.
+39
View File
@@ -0,0 +1,39 @@
Compiling
=========
You can compile WorldGuard as long as you have some version of Java greater than or equal to 21 installed.
Gradle will download JDK 21 specifically if needed, but it needs some version of Java to bootstrap from.
The build process uses Gradle, which you do *not* need to download. WorldGuard is a multi-module project with three modules:
* `worldguard-core` contains the WorldGuard API
* `worldguard-bukkit` is the Bukkit plugin
* `worldguard-libs` contains library relocations
## To compile...
### On Windows
1. **Shift** + **right click** the folder with WorldGuard's files and click "Open PowerShell window here".
2. `gradlew build`
### On Linux, BSD, or Mac OS X
1. In your terminal, navigate to the folder with WorldGuard's files (`cd /folder/of/worldguard/files`)
2. `./gradlew build`
## Then you will find...
You will find:
* The core WorldGuard API in **worldguard-core/build/libs**
* WorldGuard for Bukkit in **worldguard-bukkit/build/libs**
If you want to use WorldGuard, use the `-dist` version.
(The -dist version includes WorldGuard + necessary libraries.)
## Other commands
* `gradlew idea` will generate an [IntelliJ IDEA](http://www.jetbrains.com/idea/) module for each folder.
* `gradlew eclipse` will generate an [Eclipse](https://www.eclipse.org/downloads/) project for each folder.
+1 -3
View File
@@ -7,9 +7,7 @@ ask that you make note of the following guidelines.
* **Follow the [Oracle coding conventions](https://www.oracle.com/technetwork/java/javase/documentation/codeconvtoc-136057.html).**
We can't stress this enough; if your code has notable issues, it may delay
the process significantly.
* **Target Java 8 for source and compilation.** Make sure to mark methods with
` @Override` that override methods of parent classes, or that implement
methods of interfaces.
* **Target Java 16 for source and compilation.**
* **Use only spaces for indentation.** Our indents are 4-spaces long, and tabs
are unacceptable.
* **Wrap code to a 89 column limit.** We do this to make side by side diffs
+3 -3
View File
@@ -23,7 +23,7 @@ A Bukkit server implementation (such as [Paper](https://papermc.io)) and the [Wo
Compiling
---------
The project is written for Java 8 and our build process makes use of
The project is written for Java 17 and our build process makes use of
[Gradle](http://gradle.org).
Dependencies are automatically handled by Gradle.
@@ -40,8 +40,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/)
+29
View File
@@ -0,0 +1,29 @@
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
}
dependencies {
implementation(gradleApi())
implementation(libs.licenser)
implementation(libs.grgit)
implementation(libs.shadow)
implementation(libs.jfrog.buildinfo)
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,32 @@
import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention
import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask
plugins {
id("com.jfrog.artifactory")
}
val ARTIFACTORY_CONTEXT_URL = "artifactory_contextUrl"
val ARTIFACTORY_USER = "artifactory_user"
val ARTIFACTORY_PASSWORD = "artifactory_password"
if (!project.hasProperty(ARTIFACTORY_CONTEXT_URL)) ext[ARTIFACTORY_CONTEXT_URL] = "http://localhost"
if (!project.hasProperty(ARTIFACTORY_USER)) ext[ARTIFACTORY_USER] = "guest"
if (!project.hasProperty(ARTIFACTORY_PASSWORD)) ext[ARTIFACTORY_PASSWORD] = ""
configure<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
}
@@ -0,0 +1,10 @@
plugins {
id("com.jfrog.artifactory")
}
// Artifactory eagerly evaluates publications, so this must run after all changes to artifacts are done
afterEvaluate {
tasks.named<org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask>("artifactoryPublish") {
publications("maven")
}
}
@@ -0,0 +1,65 @@
import buildlogic.getLibrary
import buildlogic.stringyLibs
plugins {
id("eclipse")
id("idea")
id("checkstyle")
id("buildlogic.common")
}
tasks
.withType<JavaCompile>()
.matching { it.name == "compileJava" || it.name == "compileTestJava" }
.configureEach {
val disabledLint = listOf(
"processing", "path", "fallthrough", "serial", "overloads",
)
options.release.set(21)
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
options.isDeprecation = true
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
//options.compilerArgs.add("-Werror")
}
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "10.16.0"
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
"compileOnly"(stringyLibs.getLibrary("jsr305"))
"testImplementation"(platform(stringyLibs.getLibrary("junit-bom")))
"testImplementation"(stringyLibs.getLibrary("junit-jupiter-api"))
"testImplementation"(stringyLibs.getLibrary("junit-jupiter-params"))
"testRuntimeOnly"(stringyLibs.getLibrary("junit-jupiter-engine"))
}
// Java 8 turns on doclint which we fail
tasks.withType<Javadoc>().configureEach {
options.encoding = "UTF-8"
(options as StandardJavadocDocletOptions).apply {
//addBooleanOption("Werror", true)
addBooleanOption("Xdoclint:all", true)
addBooleanOption("Xdoclint:-missing", true)
tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
}
}
configure<JavaPluginExtension> {
withJavadocJar()
withSourcesJar()
}
tasks.named("check").configure {
dependsOn("checkstyleMain", "checkstyleTest")
}
@@ -0,0 +1,69 @@
import buildlogic.getLibrary
import buildlogic.stringyLibs
import org.gradle.plugins.ide.idea.model.IdeaModel
plugins {
id("org.cadixdev.licenser")
}
group = rootProject.group
version = rootProject.version
repositories {
mavenCentral()
maven {
name = "EngineHub"
url = uri("https://maven.enginehub.org/repo/")
}
}
configurations.all {
resolutionStrategy {
cacheChangingModulesFor(1, TimeUnit.DAYS)
}
}
plugins.withId("java") {
the<JavaPluginExtension>().toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
dependencies {
for (conf in listOf("implementation", "api")) {
if (!configurations.names.contains(conf)) {
continue
}
add(conf, platform(stringyLibs.getLibrary("log4j-bom")).map {
val dep = create(it)
dep.because("Mojang provides Log4j")
dep
})
constraints {
add(conf, stringyLibs.getLibrary("guava")) {
because("Mojang provides Guava")
}
add(conf, stringyLibs.getLibrary("gson")) {
because("Mojang provides Gson")
}
add(conf, stringyLibs.getLibrary("fastutil")) {
because("Mojang provides FastUtil")
}
}
}
}
license {
header(rootProject.file("HEADER.txt"))
include("**/*.java")
include("**/*.kt")
}
plugins.withId("idea") {
configure<IdeaModel> {
module {
isDownloadSources = true
isDownloadJavadoc = true
}
}
}
@@ -0,0 +1,23 @@
plugins {
id("java")
id("maven-publish")
id("buildlogic.common-java")
id("buildlogic.artifactory-sub")
}
ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
publishing {
publications {
register<MavenPublication>("maven") {
versionMapping {
usage("java-api") {
fromResolutionOf("runtimeClasspath")
}
usage("java-runtime") {
fromResolutionResult()
}
}
}
}
}
@@ -0,0 +1,179 @@
plugins {
id("java-base")
id("maven-publish")
id("com.github.johnrengelman.shadow")
id("com.jfrog.artifactory")
id("buildlogic.common")
id("buildlogic.artifactory-sub")
}
// A horrible hack because `softwareComponentFactory` has to be gotten via plugin
// gradle why
internal open class LibsConfigPluginHack @Inject constructor(
private val softwareComponentFactory: SoftwareComponentFactory
) : Plugin<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, 21)
}
outgoing.artifact(tasks.named("jar"))
}
val runtimeElements = project.configurations.register("runtimeElements") {
isVisible = false
description = "Runtime elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
}
outgoing.artifact(tasks.named("jar"))
}
val sourcesElements = project.configurations.register("sourcesElements") {
isVisible = false
description = "Source elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES))
}
outgoing.artifact(tasks.named("sourcesJar"))
}
libsComponent.addVariantsFromConfiguration(apiElements.get()) {
mapToMavenScope("compile")
}
libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
mapToMavenScope("runtime")
}
libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
mapToMavenScope("runtime")
}
configure<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,39 @@
plugins {
id("com.github.johnrengelman.shadow")
id("buildlogic.core-and-platform")
}
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()
}
val javaComponent = components["java"] as AdhocComponentWithVariants
// I don't think we want this published (it's the shadow jar)
javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
skip()
}
afterEvaluate {
tasks.named<Jar>("jar") {
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,24 @@
package buildlogic
import org.gradle.api.Project
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.artifacts.VersionCatalog
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.api.artifacts.VersionConstraint
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.provider.Provider
import org.gradle.kotlin.dsl.getByType
val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
val Project.stringyLibs: VersionCatalog
get() = extensions.getByType<VersionCatalogsExtension>().named("libs")
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")
}
+6 -15
View File
@@ -1,26 +1,17 @@
import org.ajoberstar.grgit.Grgit
logger.lifecycle("""
*******************************************
You are building WorldGuard!
If you encounter trouble:
1) Try running 'build' in a separate Gradle run
2) Use gradlew and not gradle
3) If you still need help, ask on Discord! https://discord.gg/enginehub
Output files will be in [subproject]/build/libs
*******************************************
""")
applyRootArtifactoryConfig()
plugins {
id("buildlogic.common")
id("buildlogic.artifactory-root")
}
if (!project.hasProperty("gitCommitHash")) {
apply(plugin = "org.ajoberstar.grgit")
ext["gitCommitHash"] = try {
Grgit.open(mapOf("currentDir" to project.rootDir))?.head()?.abbreviatedId
extensions.getByName<Grgit>("grgit").head()?.abbreviatedId
} catch (e: Exception) {
logger.warn("Error getting commit hash", e)
"no.git.id"
}
}
}
-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.0")
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")
}
}
@@ -0,0 +1,86 @@
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.withType
fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, javaRelease: Int = 8, banSlf4j: Boolean = true) {
applyCommonConfiguration()
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "checkstyle")
tasks
.withType<JavaCompile>()
.matching { it.name == "compileJava" || it.name == "compileTestJava" }
.configureEach {
val disabledLint = listOf(
"processing", "path", "fallthrough", "serial"
)
options.release.set(javaRelease)
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
options.isDeprecation = true
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
}
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "9.1"
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
"compileOnly"("com.google.code.findbugs:jsr305:${Versions.FINDBUGS}")
"testImplementation"("org.junit.jupiter:junit-jupiter-api:${Versions.JUNIT}")
"testImplementation"("org.junit.jupiter:junit-jupiter-params:${Versions.JUNIT}")
"testImplementation"("org.mockito:mockito-core:${Versions.MOCKITO}")
"testImplementation"("org.mockito:mockito-junit-jupiter:${Versions.MOCKITO}")
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:${Versions.JUNIT}")
}
// Java 8 turns on doclint which we fail
tasks.withType<Javadoc>().configureEach {
options.encoding = "UTF-8"
(options as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:none", "-quiet")
tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
}
}
configure<JavaPluginExtension> {
disableAutoTargetJvm()
withJavadocJar()
if (sourcesJar) {
withSourcesJar()
}
}
if (banSlf4j) {
configurations["compileClasspath"].apply {
resolutionStrategy.componentSelection {
withModule("org.slf4j:slf4j-api") {
reject("No SLF4J allowed on compile classpath")
}
}
}
}
tasks.named("check").configure {
dependsOn("checkstyleMain", "checkstyleTest")
}
}
-12
View File
@@ -1,12 +0,0 @@
import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the
val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
val Project.sourceSets: SourceSetContainer
get() = the<JavaPluginConvention>().sourceSets
-171
View File
@@ -1,171 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.DocsType
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.attributes.Usage
import org.gradle.api.attributes.java.TargetJvmVersion
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
import javax.inject.Inject
fun Project.applyLibrariesConfiguration() {
applyCommonConfiguration()
apply(plugin = "java-base")
apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "com.jfrog.artifactory")
configurations {
create("shade")
}
group = "${rootProject.group}.worldguard-libs"
val relocations = mapOf(
"org.enginehub.squirrelid" to "com.sk89q.worldguard.util.profile"
)
tasks.register<ShadowJar>("jar") {
configurations = listOf(project.configurations["shade"])
archiveClassifier.set("")
dependencies {
exclude(dependency("com.google.code.findbugs:jsr305"))
}
relocations.forEach { (from, to) ->
relocate(from, to)
}
}
val altConfigFiles = { artifactType: String ->
val deps = configurations["shade"].incoming.dependencies
.filterIsInstance<ModuleDependency>()
.map { it.copy() }
.map { dependency ->
dependency.artifact {
name = dependency.name
type = artifactType
extension = "jar"
classifier = artifactType
}
dependency
}
files(configurations.detachedConfiguration(*deps.toTypedArray())
.resolvedConfiguration.lenientConfiguration.artifacts
.filter { it.classifier == artifactType }
.map { zipTree(it.file) })
}
tasks.register<Jar>("sourcesJar") {
from({
altConfigFiles("sources")
})
relocations.forEach { (from, to) ->
val filePattern = Regex("(.*)${from.replace('.', '/')}((?:/|$).*)")
val textPattern = Regex.fromLiteral(from)
eachFile {
filter {
it.replaceFirst(textPattern, to)
}
path = path.replaceFirst(filePattern, "$1${to.replace('.', '/')}$2")
}
}
archiveClassifier.set("sources")
}
tasks.named("assemble").configure {
dependsOn("jar", "sourcesJar")
}
project.apply<LibsConfigPluginHack>()
val libsComponent = project.components["libs"] as AdhocComponentWithVariants
val apiElements = project.configurations.register("apiElements") {
isVisible = false
description = "API elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
}
outgoing.artifact(tasks.named("jar"))
}
val runtimeElements = project.configurations.register("runtimeElements") {
isVisible = false
description = "Runtime elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
}
outgoing.artifact(tasks.named("jar"))
}
val sourcesElements = project.configurations.register("sourcesElements") {
isVisible = false
description = "Source elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES))
}
outgoing.artifact(tasks.named("sourcesJar"))
}
libsComponent.addVariantsFromConfiguration(apiElements.get()) {
mapToMavenScope("compile")
}
libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
mapToMavenScope("runtime")
}
libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
mapToMavenScope("runtime")
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("maven") {
from(libsComponent)
}
}
}
applyCommonArtifactoryConfig()
}
internal open class LibsConfigPluginHack @Inject constructor(
private val softwareComponentFactory: SoftwareComponentFactory
) : Plugin<Project> {
override fun apply(project: Project) {
val libsComponents = softwareComponentFactory.adhoc("libs")
project.components.add(libsComponents)
}
}
-113
View File
@@ -1,113 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.withType
import org.gradle.kotlin.dsl.the
fun Project.applyPlatformAndCoreConfiguration() {
applyCommonConfiguration()
apply(plugin = "java")
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "maven-publish")
apply(plugin = "checkstyle")
apply(plugin = "com.jfrog.artifactory")
ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "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.6-SNAPSHOT"
const val JUNIT = "5.7.0"
const val SQUIRRELID = "0.3.0"
const val GUAVA = "21.0"
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.6
version=7.1.0-SNAPSHOT
org.gradle.parallel=true
+2
View File
@@ -0,0 +1,2 @@
#This file is generated by updateDaemonJvm
toolchainVersion=21
+66
View File
@@ -0,0 +1,66 @@
[versions]
worldedit = "7.3.0"
# Minimum versions we apply to make dependencies support newer Java
minimumAsm = "9.7"
minimumJdependency = "2.10"
minimumTinyRemapper = "0.8.11"
# lang-version = ""
[libraries]
licenser = "gradle.plugin.org.cadixdev.gradle:licenser:0.6.1"
grgit = "org.ajoberstar.grgit:grgit-gradle:5.2.2"
shadow = "com.github.johnrengelman:shadow:8.1.1"
jfrog-buildinfo = "org.jfrog.buildinfo:build-info-extractor-gradle:5.2.0"
squirrelid = "org.enginehub:squirrelid:0.3.2"
autoService = "com.google.auto.service:auto-service:1.1.1"
jsr305 = "com.google.code.findbugs:jsr305:3.0.2"
jetbrains-annotations = "org.jetbrains:annotations:24.1.0"
junit-bom = "org.junit:junit-bom:5.10.2"
junit-jupiter-api.module = "org.junit.jupiter:junit-jupiter-api"
junit-jupiter-params.module = "org.junit.jupiter:junit-jupiter-params"
junit-jupiter-engine.module = "org.junit.jupiter:junit-jupiter-engine"
spigot = "org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT"
paperApi = "io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT"
paperLib = "io.papermc:paperlib:1.0.8"
dummypermscompat = "com.sk89q:dummypermscompat:1.10"
bstats-bukkit = "org.bstats:bstats-bukkit:2.2.1"
prtree = "org.khelekore:prtree:1.5.0"
flyway-core = "org.flywaydb:flyway-core:3.0"
commandbook = "com.sk89q:commandbook:2.3"
hamcrest-library = "org.hamcrest:hamcrest-library:2.2"
# Mojang-provided libraries, CHECK AGAINST MINECRAFT for versions
guava = "com.google.guava:guava:32.1.3-jre!!"
log4j-bom = "org.apache.logging.log4j:log4j-bom:2.22.1!!"
gson = "com.google.code.gson:gson:2.10.1!!"
fastutil = "it.unimi.dsi:fastutil:8.5.12!!"
# Bukkit-provided libraries, CHECK AGAINST SPIGOT for versions
# Note that we need to balance support for older MC versus working at all on newer ones, so the exact versions here
# may not be the same as the ones in the latest Bukkit API.
snakeyaml = "org.yaml:snakeyaml:2.0"
[libraries.worldedit-core]
module = "com.sk89q.worldedit:worldedit-core"
version.ref = "worldedit"
[libraries.worldedit-bukkit]
module = "com.sk89q.worldedit:worldedit-bukkit"
version.ref = "worldedit"
[libraries.worldedit-libs-ap]
module = "com.sk89q.worldedit.worldedit-libs:ap"
version.ref = "worldedit"
Binary file not shown.
+3 -1
View File
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+178 -117
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,78 +17,111 @@
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$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"'
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# 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"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -97,92 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the
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.
JAVACMD=java
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" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
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
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, 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" \
-classpath "$CLASSPATH" \
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.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+25 -33
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,10 +25,14 @@
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%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@@ -37,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
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
@@ -51,48 +55,36 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
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
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
: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
+29 -3
View File
@@ -1,7 +1,33 @@
pluginManagement {
repositories {
gradlePluginPortal()
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
logger.lifecycle("""
*******************************************
You are building WorldGuard!
If you encounter trouble:
1) Read COMPILING.md if you haven't yet
2) Try running 'build' in a separate Gradle run
3) Use gradlew and not gradle
4) If you still need help, ask on Discord! https://discord.gg/enginehub
Output files will be in [subproject]/build/libs
*******************************************
""")
rootProject.name = "worldguard"
includeBuild("build-logic")
include("worldguard-libs")
include("worldguard-libs:core")
include("worldguard-core")
//include("worldguard-libs:bukkit")
include("worldguard-bukkit")
listOf("bukkit", "core").forEach {
include("worldguard-$it")
}
+37 -47
View File
@@ -2,42 +2,40 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
`java-library`
id("buildlogic.platform")
}
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"))
val localImplementation = configurations.create("localImplementation") {
description = "Dependencies used locally, but provided by the runtime Bukkit implementation"
isCanBeConsumed = false
isCanBeResolved = false
}
configurations["compileOnly"].extendsFrom(localImplementation)
configurations["testImplementation"].extendsFrom(localImplementation)
dependencies {
"api"(project(":worldguard-core"))
"compileOnly"("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT")
"runtimeOnly"("org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT") {
"api"(libs.worldedit.bukkit) { isTransitive = false }
"compileOnly"(libs.commandbook) { isTransitive = false }
// Technically this is api, but everyone should already have some form of the bukkit API
// Avoid pulling in another one, especially one so outdated.
"localImplementation"(libs.spigot) {
exclude("junit", "junit")
}
"api"("com.sk89q.worldedit:worldedit-bukkit:${Versions.WORLDEDIT}") { isTransitive = false }
"implementation"("com.google.guava:guava:${Versions.GUAVA}")
"compileOnly"("com.sk89q:commandbook:2.3") { isTransitive = false }
"shadeOnly"("io.papermc:paperlib:1.0.6")
"shadeOnly"("org.bstats:bstats-bukkit:2.1.0")
"shadeOnly"("co.aikar:minecraft-timings:1.0.4")
"compileOnly"(libs.jetbrains.annotations) {
because("Resolving Spigot annotations")
}
"testCompileOnly"(libs.jetbrains.annotations) {
because("Resolving Spigot annotations")
}
"compileOnly"(libs.paperApi) {
exclude("org.slf4j", "slf4j-api")
exclude("junit", "junit")
}
"implementation"(libs.paperLib)
"implementation"(libs.bstats.bukkit)
}
tasks.named<Copy>("processResources") {
@@ -48,31 +46,23 @@ tasks.named<Copy>("processResources") {
}
}
tasks.named<Jar>("jar") {
val projectVersion = project.version
inputs.property("projectVersion", projectVersion)
manifest {
attributes("Implementation-Version" to projectVersion)
}
}
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:"))
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
@@ -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.
*
@@ -140,6 +140,8 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
throw e;
}
boolean needParentSave = false;
summaryOnStart = getBoolean("summary-on-start", true);
opPermissions = getBoolean("op-permissions", true);
@@ -158,7 +160,8 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
itemDurability = getBoolean("protection.item-durability", true);
removeInfiniteStacks = getBoolean("protection.remove-infinite-stacks", false);
disableExpDrops = getBoolean("protection.disable-xp-orb-drops", false);
disableObsidianGenerators = getBoolean("protection.disable-obsidian-generators", false);
needParentSave |= removeProperty("protection.disable-obsidian-generators");
useMaxPriorityAssociation = getBoolean("protection.use-max-priority-association", false);
@@ -178,6 +181,11 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
simulateSponge = getBoolean("simulation.sponge.enable", false);
spongeRadius = Math.max(1, getInt("simulation.sponge.radius", 3)) - 1;
redstoneSponges = getBoolean("simulation.sponge.redstone", false);
if (simulateSponge) {
log.warning("Sponge simulation is deprecated for removal in a future version. We recommend using CraftBook's sponge simulation instead.");
} else {
needParentSave |= removeProperty("simulation");
}
pumpkinScuba = getBoolean("default.pumpkin-scuba", false);
disableHealthRegain = getBoolean("default.disable-health-regain", false);
@@ -207,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);
@@ -236,13 +245,20 @@ 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 {
needParentSave |= removeProperty("chest-protection");
}
disableCreatureCropTrampling = getBoolean("crops.disable-creature-trampling", false);
disablePlayerCropTrampling = getBoolean("crops.disable-player-trampling", false);
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);
@@ -263,9 +279,13 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableGrassGrowth = getBoolean("dynamics.disable-grass-growth", false);
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);
allowedSnowFallOver = new HashSet<>(convertLegacyBlocks(getStringList("dynamics.snow-fall-blocks", null)));
useRegions = getBoolean("regions.enable", true);
@@ -280,6 +300,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
regionWand = convertLegacyItem(getString("regions.wand", ItemTypes.LEATHER.getId()));
maxClaimVolume = getInt("regions.max-claim-volume", 30000);
claimOnlyInsideExistingRegions = getBoolean("regions.claim-only-inside-existing-regions", false);
setParentOnClaim = getString("regions.set-parent-on-claim", "");
boundedLocationFlags = getBoolean("regions.location-flags-only-inside-regions", false);
maxRegionCountPerPlayer = getInt("regions.max-region-count-per-player.default", 7);
@@ -401,6 +422,20 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
config.setHeader(CONFIG_HEADER);
config.save();
if (needParentSave) {
parentConfig.save();
}
}
private boolean removeProperty(String prop) {
if (config.getProperty(prop) != null) {
config.removeProperty(prop);
}
if (parentConfig.getProperty(prop) != null) {
parentConfig.removeProperty(prop);
return true;
}
return false;
}
public boolean isChestProtected(Location block, LocalPlayer player) {
@@ -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();
}
@@ -238,6 +239,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 +266,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()));
}
}
@@ -59,11 +59,13 @@ import com.sk89q.worldguard.bukkit.listener.WorldGuardWeatherListener;
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.bukkit.util.logging.ClassSourceValidator;
import com.sk89q.worldguard.commands.GeneralCommands;
import com.sk89q.worldguard.commands.ProtectionCommands;
import com.sk89q.worldguard.commands.ToggleCommands;
import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry;
@@ -71,7 +73,6 @@ import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.storage.RegionDriver;
import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver;
import com.sk89q.worldguard.protection.managers.storage.sql.SQLDriver;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
import org.bstats.bukkit.Metrics;
@@ -137,6 +138,10 @@ public class WorldGuardPlugin extends JavaPlugin {
*/
@Override
public void onEnable() {
// Catch bad things being done by naughty plugins that include WorldGuard's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
verifier.reportMismatches(ImmutableList.of(WorldGuard.class, ProtectedRegion.class, Flag.class));
configureLogger();
getDataFolder().mkdirs(); // Need to create the plugins/WorldGuard folder
@@ -150,21 +155,14 @@ public class WorldGuardPlugin extends JavaPlugin {
// Set the proper command injector
commands.setInjector(new SimpleInjector(WorldGuard.getInstance()));
// Catch bad things being done by naughty plugins that include
// WorldGuard's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
verifier.reportMismatches(ImmutableList.of(ProtectedRegion.class, ProtectedCuboidRegion.class, Flag.class));
// Register command classes
final CommandsManagerRegistration reg = new CommandsManagerRegistration(this, commands);
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);
@@ -215,6 +213,7 @@ public class WorldGuardPlugin extends JavaPlugin {
});
((SimpleFlagRegistry) WorldGuard.getInstance().getFlagRegistry()).setInitialized(true);
((SimpleDomainRegistry) WorldGuard.getInstance().getDomainRegistry()).setInitialized(true);
// Enable metrics
final Metrics metrics = new Metrics(this, BSTATS_PLUGIN_ID); // bStats plugin id
@@ -423,8 +422,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 {
@@ -21,15 +21,21 @@ package com.sk89q.worldguard.bukkit.cause;
import com.google.common.base.Joiner;
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.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
import org.bukkit.entity.LightningStrike;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
@@ -98,7 +104,31 @@ public final class Cause {
*/
public boolean isKnown() {
Object object = getRootCause();
return !(object == null || object instanceof TNTPrimed || object instanceof Vehicle);
if (object == null) {
return false;
}
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) {
if (!PaperLib.isPaper()) {
return false;
}
Entity entity = (Entity) object;
BukkitWorldConfiguration config = WorldGuardPlugin.inst().getConfigManager().get(entity.getWorld().getName());
if (!config.usePaperEntityOrigin || entity.getOrigin() == null) {
return false;
}
}
return true;
}
@Nullable
@@ -113,8 +143,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;
}
}
@@ -124,8 +154,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;
}
}
@@ -135,8 +165,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;
}
}
@@ -146,8 +176,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;
}
}
@@ -249,56 +279,76 @@ public final class Cause {
}
private void addAll(@Nullable Object... element) {
if (element != null) {
for (Object o : element) {
if (o == null || seen.contains(o)) {
continue;
}
if (element == null) {
return;
}
for (Object o : element) {
if (o == null || seen.contains(o)) {
continue;
}
seen.add(o);
seen.add(o);
if (o instanceof TNTPrimed) {
addAll(((TNTPrimed) o).getSource());
} else if (o instanceof Projectile) {
ProjectileSource shooter = ((Projectile) o).getShooter();
addAll(shooter);
if (shooter == null && o instanceof Firework && PaperLib.isPaper()) {
UUID spawningUUID = ((Firework) o).getSpawningEntity();
if (spawningUUID != null) {
Entity spawningEntity = Bukkit.getEntity(spawningUUID);
if (spawningEntity != null) {
addAll(spawningEntity);
}
if (o instanceof TNTPrimed) {
addAll(((TNTPrimed) o).getSource());
} else if (o instanceof Projectile) {
ProjectileSource shooter = ((Projectile) o).getShooter();
addAll(shooter);
if (shooter == null && o instanceof Firework && PaperLib.isPaper()) {
UUID spawningUUID = ((Firework) o).getSpawningEntity();
if (spawningUUID != null) {
Entity spawningEntity = Bukkit.getEntity(spawningUUID);
if (spawningEntity != null) {
addAll(spawningEntity);
}
}
} else if (o instanceof Vehicle) {
((Vehicle) o).getPassengers().forEach(this::addAll);
} else if (o instanceof AreaEffectCloud) {
indirect = true;
addAll(((AreaEffectCloud) o).getSource());
} else if (o instanceof Tameable) {
indirect = true;
addAll(((Tameable) o).getOwner());
} else if (o instanceof Creature && ((Creature) o).getTarget() != null) {
indirect = true;
addAll(((Creature) o).getTarget());
} else if (o instanceof BlockProjectileSource) {
addAll(((BlockProjectileSource) o).getBlock());
}
// Add manually tracked parent causes
Object source = o;
int index = causes.size();
while (source instanceof Metadatable && !(source instanceof Block)) {
source = WGMetadata.getIfPresent((Metadatable) source, CAUSE_KEY, Object.class);
if (source != null) {
causes.add(index, source);
seen.add(source);
} else if (o instanceof Vehicle) {
((Vehicle) o).getPassengers().forEach(this::addAll);
} else if (o instanceof AreaEffectCloud) {
indirect = true;
addAll(((AreaEffectCloud) o).getSource());
} else if (o instanceof Tameable tameable) {
indirect = true;
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
}
}
causes.add(o);
} else if (o instanceof Creature && ((Creature) o).getTarget() != null) {
indirect = true;
addAll(((Creature) o).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());
}
// Add manually tracked parent causes
Object source = o;
int index = causes.size();
while (source instanceof Metadatable && !(source instanceof Block)) {
source = WGMetadata.getIfPresent((Metadatable) source, CAUSE_KEY, Object.class);
if (source != null) {
causes.add(index, source);
seen.add(source);
}
}
causes.add(o);
}
}
@@ -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);
}
}
}
@@ -21,8 +21,7 @@ package com.sk89q.worldguard.bukkit.listener;
import static com.sk89q.worldguard.bukkit.cause.Cause.create;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.bukkit.BukkitWorldConfiguration;
import com.destroystokyo.paper.event.entity.EntityZapEvent;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.DelegateEvent;
@@ -47,8 +46,11 @@ import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.protection.flags.Flags;
import io.papermc.lib.PaperLib;
import io.papermc.paper.event.player.PlayerOpenSignEvent;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.ExplosionResult;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -65,6 +67,8 @@ 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;
@@ -78,11 +82,13 @@ import org.bukkit.entity.Painting;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.minecart.HopperMinecart;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
@@ -110,8 +116,11 @@ 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;
@@ -139,11 +148,10 @@ 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;
@@ -161,17 +169,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.
*
@@ -181,6 +178,19 @@ public class EventAbstractionListener extends AbstractListener {
super(plugin);
}
@Override
public void registerEvents() {
super.registerEvents();
PluginManager pm = getPlugin().getServer().getPluginManager();
if (PaperLib.isPaper()) {
pm.registerEvents(new EventAbstractionListener.PaperListener(), getPlugin());
} else {
pm.registerEvents(new EventAbstractionListener.SpigotListener(), getPlugin());
}
}
//-------------------------------------------------------------------------
// Block break / place
//-------------------------------------------------------------------------
@@ -216,8 +226,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));
}
@@ -321,10 +331,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,10 +362,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);
}
@@ -452,7 +481,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);
@@ -478,7 +509,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));
}
}
@@ -572,7 +603,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()));
}
@@ -598,9 +629,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));
}
}
@@ -740,7 +769,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) {
@@ -885,11 +914,19 @@ 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()));
}
}
@@ -918,6 +955,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()));
@@ -948,12 +991,7 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onInventoryMoveItem(InventoryMoveItemEvent event) {
InventoryHolder causeHolder;
if (HAS_SNAPSHOT_INVHOLDER) {
causeHolder = event.getInitiator().getHolder(false);
} else {
causeHolder = event.getInitiator().getHolder();
}
InventoryHolder causeHolder = PaperLib.getHolder(event.getInitiator(), false).getHolder();
WorldConfiguration wcfg = null;
if (causeHolder instanceof Hopper
@@ -967,15 +1005,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 = PaperLib.getHolder(event.getSource(), false).getHolder();
InventoryHolder targetHolder = PaperLib.getHolder(event.getDestination(), false).getHolder();
Cause cause;
@@ -1011,7 +1042,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;
@@ -1023,8 +1053,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);
@@ -1032,7 +1065,7 @@ public class EventAbstractionListener extends AbstractListener {
}
}
if (blocked == affectedSize) { // server does weird things with this if the event is modified, so use cached number
if (affectedSize > 0 && blocked == affectedSize) { // server does weird things with this if the event is modified, so use cached number
event.setCancelled(true);
}
}
@@ -1090,9 +1123,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());
@@ -1106,7 +1139,7 @@ public class EventAbstractionListener extends AbstractListener {
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event){
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
onPlayerInteractEntity(event);
}
@@ -1177,14 +1210,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
@@ -1200,8 +1236,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)) {
@@ -1209,16 +1244,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()));
}
@@ -1264,4 +1298,31 @@ public class EventAbstractionListener extends AbstractListener {
}
}
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(com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent event) {
handleKnockback(event, event.getHitBy());
}
}
@SuppressWarnings("removal")
private static class SpigotListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onEntityKnockbackByEntity(EntityKnockbackByEntityEvent event) {
handleKnockback(event, event.getSourceEntity());
}
}
}
@@ -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,9 +58,9 @@ public class InvincibilityListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
Entity victim = event.getEntity();
if (Entities.isNPC(victim)) return;
if (victim instanceof Player) {
Player player = (Player) victim;
if (victim instanceof Player player) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (isInvincible(localPlayer)) {
@@ -87,9 +88,9 @@ public class InvincibilityListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityCombust(EntityCombustEvent event) {
Entity entity = event.getEntity();
if (Entities.isNPC(entity)) return;
if (entity instanceof Player) {
Player player = (Player) entity;
if (entity instanceof Player player) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (isInvincible(localPlayer)) {
@@ -100,8 +101,9 @@ public class InvincibilityListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onFoodLevelChange(FoodLevelChangeEvent event) {
if (event.getEntity() instanceof Player) {
Player player = (Player) event.getEntity();
if (Entities.isNPC(event.getEntity())) return;
if (event.getEntity() instanceof Player player) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(localPlayer)) {
@@ -25,23 +25,21 @@ import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
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;
public class PlayerMoveListener extends AbstractListener {
@@ -54,13 +52,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());
@@ -99,7 +94,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);
@@ -148,18 +143,18 @@ public class PlayerMoveListener extends AbstractListener {
if (loc != null) {
player.teleport(BukkitAdapter.adapt(loc));
}
session.uninitialize(localPlayer);
}
private class EntityMountListener implements Listener {
@EventHandler
public void onEntityMount(EntityMountEvent event) {
Entity entity = event.getEntity();
if (entity instanceof Player) {
LocalPlayer player = getPlugin().wrapPlayer((Player) entity);
Session session = WorldGuard.getInstance().getPlatform().getSessionManager().get(player);
if (null != session.testMoveTo(player, BukkitAdapter.adapt(event.getMount().getLocation()), MoveType.EMBARK, true)) {
event.setCancelled(true);
}
@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 (Entities.isNPC(entity)) return;
if (!(entity instanceof Player 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;
}
}
}
/**
@@ -61,6 +61,7 @@ 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.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerTakeLecternBookEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
@@ -173,7 +174,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 +219,7 @@ public class RegionProtectionListener extends AbstractListener {
String what;
/* TNT */
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.MINECART_TNT) != null) {
if (event.getCause().find(EntityType.TNT, EntityType.TNT_MINECART) != null) {
canBreak = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.BLOCK_BREAK, Flags.TNT));
what = "use dynamite";
@@ -244,13 +245,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)) {
@@ -410,13 +411,15 @@ public class RegionProtectionListener extends AbstractListener {
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
|| type == EntityType.CHEST_BOAT && 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 (Entities.isMinecart(type) || type == EntityType.CHEST_BOAT) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.CHEST_ACCESS));
what = "open that";
} else {
@@ -522,8 +525,7 @@ public class RegionProtectionListener extends AbstractListener {
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;
@@ -365,7 +366,7 @@ public class WorldGuardBlockListener extends AbstractListener {
return;
}
if (id == Material.SAND && wcfg.noPhysicsSand) {
if ((id == Material.SAND || id == Material.RED_SAND) && wcfg.noPhysicsSand) {
event.setCancelled(true);
return;
}
@@ -470,7 +471,6 @@ public class WorldGuardBlockListener extends AbstractListener {
public void onBlockForm(BlockFormEvent event) {
ConfigurationManager cfg = getConfig();
if (cfg.activityHaltToggle) {
event.setCancelled(true);
return;
@@ -521,6 +521,18 @@ public class WorldGuardBlockListener extends AbstractListener {
return;
}
}
if (Materials.isUnwaxedCopper(event.getBlock().getType())) {
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;
}
}
}
/*
@@ -588,6 +600,32 @@ public class WorldGuardBlockListener extends AbstractListener {
}
}
if (Materials.isAmethystGrowth(newType) || newType == Material.POINTED_DRIPSTONE) {
if (wcfg.disableRockGrowth) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && !StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.queryState(BukkitAdapter.adapt(event.getBlock().getLocation()), (RegionAssociable) null, Flags.ROCK_GROWTH))) {
event.setCancelled(true);
return;
}
}
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);
}
@@ -689,4 +727,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);
}
}
}
}
@@ -25,13 +25,17 @@ 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;
@@ -40,6 +44,7 @@ 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;
@@ -56,6 +61,7 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.Wither;
import org.bukkit.entity.WitherSkull;
import org.bukkit.entity.Wolf;
@@ -116,6 +122,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 +148,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 +236,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 +297,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 +313,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 +332,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 +374,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) {
@@ -479,6 +489,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 +504,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 +525,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 +541,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 +551,6 @@ public class WorldGuardEntityListener extends AbstractListener {
}
}
if (wcfg.signChestProtection) {
for (Block block : event.blockList()) {
if (wcfg.isChestProtected(BukkitAdapter.adapt(block.getLocation()))) {
@@ -582,12 +597,17 @@ public class WorldGuardEntityListener extends AbstractListener {
event.setCancelled(true);
return;
}
} else if (event.getEntityType() == EntityType.PRIMED_TNT
|| event.getEntityType() == EntityType.MINECART_TNT) {
} else if (event.getEntityType() == EntityType.TNT
|| event.getEntityType() == EntityType.TNT_MINECART) {
if (wcfg.blockTNTExplosions) {
event.setCancelled(true);
return;
}
} else if (event instanceof AbstractWindCharge) {
if (wcfg.blockWindChargeExplosions) {
event.setCancelled(true);
return;
}
}
}
@@ -603,7 +623,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;
}
@@ -657,34 +677,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
associable.print("Destination is an a protected area.");
String message = regions.queryValue(localPlayer, Flags.DENY_MESSAGE);
RegionProtectionListener.formatAndSendDenyMessage("create portals", localPlayer, message);
}
event.setCancelled(true);
}
@@ -744,10 +776,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);
}
@@ -757,10 +789,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 (Entities.isNPC(ent)) return;
if (!(ent instanceof Player 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
@@ -788,7 +821,7 @@ public class WorldGuardEntityListener extends AbstractListener {
return;
}
if (id == Material.SAND && wcfg.noPhysicsSand) {
if ((id == Material.SAND || id == Material.RED_SAND) && wcfg.noPhysicsSand) {
event.setCancelled(true);
return;
}
@@ -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,7 @@ 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.config.WorldConfiguration;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.util.Locations;
@@ -59,6 +60,7 @@ public class WorldGuardVehicleListener extends AbstractListener {
// Did we move a block?
if (Locations.isDifferentBlock(BukkitAdapter.adapt(event.getFrom()), BukkitAdapter.adapt(event.getTo()))) {
for (Player player : playerPassengers) {
if (Entities.isNPC(player)) continue;
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
Location lastValid;
if ((lastValid = WorldGuard.getInstance().getPlatform().getSessionManager().get(localPlayer)
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.bukkit.listener.debounce.legacy;
import com.sk89q.worldguard.bukkit.listener.debounce.legacy.InventoryMoveItemEventDebounce.Key;
import io.papermc.lib.PaperLib;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
@@ -44,18 +45,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(PaperLib.getHolder(event.getInitiator(), false).getHolder());
source = transform(PaperLib.getHolder(event.getSource(), false).getHolder());
target = transform(PaperLib.getHolder(event.getDestination(), false).getHolder());
}
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 +95,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,9 +25,9 @@ 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;
@@ -41,13 +41,6 @@ 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.
@@ -81,19 +74,22 @@ public class BukkitSessionManager extends AbstractSessionManager implements Runn
@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()) {
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;
}
}
}
@@ -0,0 +1,167 @@
/*
* 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 com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.PluginClassLoader;
import javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Validates that certain specified classes came from the same source as
* a plugin.
* This is copied from the same class in WorldEdit because unfortunately
* trying to use WorldEdit's means we're susceptible to getting a bad version
* of this class if another plugin shades it....which is exactly what we're
* trying to detect and report.
*/
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 {
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 | ClassNotFoundException e) {
tmp = null;
}
loadClass = tmp;
}
private final Plugin plugin;
@Nullable
private final ClassLoader expectedClassLoader;
/**
* Create a new instance.
*
* @param plugin The plugin
*/
public ClassSourceValidator(Plugin plugin) {
checkNotNull(plugin, "plugin");
this.plugin = plugin;
this.expectedClassLoader = plugin.getClass().getClassLoader();
}
/**
* Return a map of classes that been loaded from a different source.
*
* @param classes A list of classes to check
* @return The results
*/
public Map<Class<?>, Plugin> findMismatches(List<Class<?>> classes) {
checkNotNull(classes, "classes");
if (expectedClassLoader == null || loadClass == null) {
return ImmutableMap.of();
}
Map<Class<?>, Plugin> mismatches = new HashMap<>();
for (Plugin target : Bukkit.getPluginManager().getPlugins()) {
if (target == plugin) {
continue;
}
ClassLoader targetLoader = target.getClass().getClassLoader();
if (!(pluginClassLoaderClass.isAssignableFrom(targetLoader.getClass()))) {
continue;
}
for (Class<?> testClass : classes) {
Class<?> targetClass;
try {
targetClass = (Class<?>) loadClass.invoke(targetLoader, testClass.getName(), false, false, false);
} catch (IllegalAccessException | InvocationTargetException ignored) {
continue;
}
if (targetClass.getClassLoader() != expectedClassLoader) {
mismatches.putIfAbsent(testClass, targetClass.getClassLoader() == targetLoader ? target : null);
}
}
}
return mismatches;
}
/**
* Reports classes that have come from a different source.
*
* <p>The warning is emitted to the log.</p>
*
* @param classes The list of classes to check
*/
public void reportMismatches(List<Class<?>> classes) {
if (Boolean.getBoolean("enginehub.disable.class.source.validation")) {
return;
}
Map<Class<?>, Plugin> mismatches = findMismatches(classes);
if (mismatches.isEmpty()) {
return;
}
StringBuilder builder = new StringBuilder("\n");
builder.append(SEPARATOR_LINE).append("\n");
builder.append("** /!\\ SEVERE WARNING /!\\\n");
builder.append("** \n");
builder.append("** A plugin developer has included a portion of \n");
builder.append("** ").append(plugin.getName()).append(" into their own plugin, so rather than using\n");
builder.append("** the version of ").append(plugin.getName()).append(" that you downloaded, you\n");
builder.append("** will be using a broken mix of old ").append(plugin.getName()).append(" (that came\n");
builder.append("** with the plugin) and your downloaded version. THIS MAY\n");
builder.append("** SEVERELY BREAK ").append(plugin.getName().toUpperCase(Locale.ROOT)).append(" AND ALL OF ITS FEATURES.\n");
builder.append("**\n");
builder.append("** This may have happened because the developer is using\n");
builder.append("** the ").append(plugin.getName()).append(" API and thinks that including\n");
builder.append("** ").append(plugin.getName()).append(" is necessary. However, it is not!\n");
builder.append("**\n");
builder.append("** Here are some files that have been overridden:\n");
builder.append("** \n");
for (Map.Entry<Class<?>, Plugin> entry : mismatches.entrySet()) {
Plugin badPlugin = entry.getValue();
String url = badPlugin == null
? "(unknown)"
: badPlugin.getName() + " (" + badPlugin.getClass().getProtectionDomain().getCodeSource().getLocation() + ")";
builder.append("** '").append(entry.getKey().getSimpleName()).append("' came from '").append(url).append("'\n");
}
builder.append("**\n");
builder.append("** Please report this to the plugins' developers.\n");
builder.append(SEPARATOR_LINE).append("\n");
plugin.getLogger().severe(builder.toString());
}
}
@@ -19,14 +19,21 @@
package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import org.bukkit.entity.Allay;
import org.bukkit.entity.Ambient;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.BreezeWindCharge;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Flying;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.LivingEntity;
@@ -42,10 +49,14 @@ import org.bukkit.entity.Steerable;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.WindCharge;
import org.bukkit.entity.Wither;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.projectiles.ProjectileSource;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class Entities {
@@ -101,8 +112,20 @@ 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 BOAT, CHEST_BOAT -> true;
default -> false;
};
}
/**
@@ -112,13 +135,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;
};
}
/**
@@ -208,6 +229,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 +240,38 @@ 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 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
@@ -1,127 +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.util.logging;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.bukkit.plugin.Plugin;
import javax.annotation.Nullable;
import java.security.CodeSource;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Validates that certain specified classes came from the same source as
* a plugin.
*/
public class ClassSourceValidator {
private static final Logger log = Logger.getLogger(ClassSourceValidator.class.getCanonicalName());
private static final String separatorLine = Strings.repeat("*", 46);
private final Plugin plugin;
@Nullable
private final CodeSource expectedCodeSource;
/**
* Create a new instance.
*
* @param plugin The plugin
*/
public ClassSourceValidator(Plugin plugin) {
checkNotNull(plugin, "plugin");
this.plugin = plugin;
this.expectedCodeSource = plugin.getClass().getProtectionDomain().getCodeSource();
}
/**
* Return a map of classes that been loaded from a different source.
*
* @param classes A list of classes to check
* @return The results
*/
public Map<Class<?>, CodeSource> findMismatches(List<Class<?>> classes) {
checkNotNull(classes, "classes");
Map<Class<?>, CodeSource> mismatches = Maps.newHashMap();
if (expectedCodeSource != null) {
for (Class<?> testClass : classes) {
CodeSource testSource = testClass.getProtectionDomain().getCodeSource();
if (!expectedCodeSource.equals(testSource)) {
mismatches.put(testClass, testSource);
}
}
}
return mismatches;
}
/**
* Reports classes that have come from a different source.
*
* <p>The warning is emitted to the log.</p>
*
* @param classes The list of classes to check
*/
public void reportMismatches(List<Class<?>> classes) {
if (Boolean.getBoolean("worldguard.disable.class.validation")) {
return;
}
Map<Class<?>, CodeSource> mismatches = findMismatches(classes);
if (!mismatches.isEmpty()) {
StringBuilder builder = new StringBuilder("\n");
builder.append(separatorLine).append("\n");
builder.append("** /!\\ SEVERE WARNING /!\\\n");
builder.append("** \n");
builder.append("** A plugin developer has copied and pasted a portion of \n");
builder.append("** ").append(plugin.getName()).append(" into their own plugin, so rather than using\n");
builder.append("** the version of ").append(plugin.getName()).append(" that you downloaded, you\n");
builder.append("** will be using a broken mix of old ").append(plugin.getName()).append(" (that came\n");
builder.append("** with the plugin) and your downloaded version. THIS MAY\n");
builder.append("** SEVERELY BREAK ").append(plugin.getName().toUpperCase()).append(" AND ALL OF ITS FEATURES.\n");
builder.append("**\n");
builder.append("** This may have happened because the developer is using\n");
builder.append("** the ").append(plugin.getName()).append(" API and thinks that including\n");
builder.append("** ").append(plugin.getName()).append(" is necessary. However, it is not!\n");
builder.append("**\n");
builder.append("** Here are some files that have been overridden:\n");
builder.append("** \n");
for (Map.Entry<Class<?>, CodeSource> entry : mismatches.entrySet()) {
CodeSource codeSource = entry.getValue();
String url = codeSource != null ? codeSource.getLocation().toExternalForm() : "(unknown)";
builder.append("** '").append(entry.getKey().getSimpleName()).append("' came from '").append(url).append("'\n");
}
builder.append("**\n");
builder.append("** Please report this to the plugins' developers.\n");
builder.append(separatorLine).append("\n");
log.log(Level.SEVERE, builder.toString());
}
}
}
@@ -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);
}
}
}
@@ -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());
@@ -3,4 +3,4 @@ main: com.sk89q.worldguard.bukkit.WorldGuardPlugin
version: "${internalVersion}"
depend: [WorldEdit]
softdepend: [CommandBook]
api-version: 1.17
api-version: "1.21"
+42 -11
View File
@@ -1,20 +1,51 @@
import org.cadixdev.gradle.licenser.LicenseExtension
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<LicenseExtension> {
exclude {
it.file.startsWith(project.layout.buildDirectory.get().asFile)
}
}
configure<PublishingExtension> {
publications.named<MavenPublication>("maven") {
artifactId = the<BasePluginExtension>().archivesName.get()
from(components["java"])
}
}
@@ -24,6 +24,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldguard.domains.registry.DomainRegistry;
import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry;
import com.sk89q.worldguard.util.profile.cache.HashMapCache;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import com.sk89q.worldguard.util.profile.cache.SQLiteCache;
@@ -55,6 +57,7 @@ public final class WorldGuard {
private WorldGuardPlatform platform;
private final SimpleFlagRegistry flagRegistry = new SimpleFlagRegistry();
private final SimpleDomainRegistry domainRegistry = new SimpleDomainRegistry();
private final Supervisor supervisor = new SimpleSupervisor();
private ProfileCache profileCache;
private ProfileService profileService;
@@ -116,6 +119,16 @@ public final class WorldGuard {
return this.flagRegistry;
}
/**
* Get the domain registry.
*
* @return the domain registry
*/
public DomainRegistry getDomainRegistry() {
return this.domainRegistry;
}
/**
* Get the supervisor.
*
@@ -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);
@@ -24,6 +24,7 @@ import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
import com.sk89q.worldguard.blacklist.target.Target;
import javax.annotation.Nullable;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@@ -87,13 +88,13 @@ public class FileHandler implements LoggerHandler {
* Build the path.
*
* @param playerName The name of the player
* @return The path for the logfile
* @return The path for the logfile, null when no applicable path could be found
*/
private String buildPath(String playerName) {
private @Nullable String buildPath(@Nullable String playerName) {
GregorianCalendar calendar = new GregorianCalendar();
Matcher m = pattern.matcher(pathPattern);
StringBuffer buffer = new StringBuffer();
StringBuilder buffer = new StringBuilder();
// Pattern replacements
while (m.find()) {
@@ -103,12 +104,13 @@ public class FileHandler implements LoggerHandler {
if (group.matches("%%")) {
rep = "%";
} else if (group.matches("%u")) {
if (playerName == null) return null; // Unable to create a path for non player logging events
rep = playerName.toLowerCase().replaceAll("[^A-Za-z0-9_]", "_");
if (rep.length() > 32) { // Actual max length is 16
rep = rep.substring(0, 32);
}
}else if (group.matches("%w")) {
} else if (group.matches("%w")) {
rep = worldName.toLowerCase().replaceAll("[^A-Za-z0-9_]", "_");
if (rep.length() > 32) { // Actual max length is 16
rep = rep.substring(0, 32);
@@ -148,11 +150,12 @@ public class FileHandler implements LoggerHandler {
* @param message The message to log
* @param comment The comment associated with the logged event
*/
private void log(LocalPlayer player, String message, String comment) {
String path = buildPath(player.getName());
private void log(@Nullable LocalPlayer player, String message, String comment) {
String path = buildPath(player != null ? player.getName() : null);
if (path == null) return;
try {
String date = dateFormat.format(new Date());
String line = "[" + date + "] " + player.getName() + ": " + message
String line = "[" + date + "] " + (player != null ? player.getName() : "Unknown Source") + ": " + message
+ (comment != null ? " (" + comment + ")" : "") + "\r\n";
LogFileWriter writer = writers.get(path);
@@ -190,7 +193,7 @@ public class FileHandler implements LoggerHandler {
writers.entrySet().iterator();
// Remove some entries
for (; it.hasNext(); ) {
while (it.hasNext()) {
Map.Entry<String,LogFileWriter> entry = it.next();
try {
entry.getValue().getWriter().close();
@@ -218,7 +221,7 @@ 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) {
@@ -0,0 +1,111 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.commands;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.LocalPlayer;
import javax.annotation.Nullable;
import java.util.Map;
public abstract class CommandInputContext<T extends Exception> {
protected final Actor sender;
protected final String input;
protected Map<String, Object> context;
protected CommandInputContext(Actor sender, String input, Map<String, Object> values) {
this.sender = sender;
this.input = input;
this.context = values;
}
public void put(String name, Object value) {
context.put(name, value);
}
public Actor getSender() {
return sender;
}
public String getUserInput() {
return input;
}
/**
* Gets the CommandSender as a player.
*
* @return Player
* @throws T if the sender is not a player
*/
public LocalPlayer getPlayerSender() throws T {
if (sender.isPlayer() && sender instanceof LocalPlayer) {
return (LocalPlayer) sender;
} else {
throw createException("Not a player");
}
}
public Integer getUserInputAsInt() throws T {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw createException("Not a number: " + input);
}
}
public Double getUserInputAsDouble() throws T {
try {
return Double.parseDouble(input);
} catch (NumberFormatException e) {
throw createException("Not a number: " + input);
}
}
protected abstract T createException(String str);
/**
* Get an object from the context by key name.
* May return null if the object does not exist in the context.
*
* @param name key name of the object
* @return the object matching the key, or null
*/
@Nullable
public Object get(String name) {
return get(name, null);
}
/**
* Get an object from the context by key name.
* Will only return null if
* a) you provide null as the default
* b) the key has explicity been set to null
*
* @param name key name of the object
* @return the object matching the key
*/
@Nullable
public Object get(String name, Object defaultValue) {
Object obj;
return (((obj = context.get(name)) != null) || context.containsKey(name)
? obj : defaultValue);
}
}
@@ -70,7 +70,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("God enabled by " + sender.getDisplayName() + ".");
}
@@ -79,7 +79,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players now have god mode.");
}
}
@@ -113,7 +113,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("God disabled by " + sender.getDisplayName() + ".");
}
@@ -122,7 +122,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players no longer have god mode.");
}
}
@@ -158,7 +158,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("Healed by " + sender.getDisplayName() + ".");
}
@@ -166,7 +166,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players healed.");
}
}
@@ -199,7 +199,7 @@ public class GeneralCommands {
// Keep track of this
included = true;
} else {
} else if (!args.hasFlag('s')) {
player.print("Slain by " + sender.getDisplayName() + ".");
}
@@ -207,7 +207,7 @@ public class GeneralCommands {
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
if (!included) {
sender.print("Players slain.");
}
}
@@ -226,7 +226,7 @@ public class WorldGuardCommands {
}
}, MoreExecutors.directExecutor());
Futures.addCallback(sampler.getFuture(), new FutureCallback<Sampler>() {
Futures.addCallback(sampler.getFuture(), new FutureCallback<>() {
@Override
public void onSuccess(Sampler result) {
String output = result.toString();
@@ -247,7 +247,7 @@ public class WorldGuardCommands {
@Override
public void onFailure(Throwable throwable) {
}
});
}, MoreExecutors.directExecutor());
}
@Command(aliases = {"stopprofile"}, usage = "",desc = "Stop a running profile", min = 0, max = 0)
@@ -378,7 +378,7 @@ class FlagHelperBox extends PaginationBox {
if (currVal == null) {
currVal = getInheritedValue(region, flag);
}
String display = currVal == null ? regName : currVal.getId();
String display = currVal == null ? regName : currVal.id();
appendValueText(builder, flag, display, null);
}
@@ -25,16 +25,27 @@ import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.worldedit.command.util.AsyncCommandBuilder;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.domains.registry.DomainFactory;
import com.sk89q.worldguard.domains.registry.DomainRegistry;
import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.util.DomainInputResolver;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
public class MemberCommands extends RegionCommandsBase {
@@ -67,6 +78,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
resolver.setActor(sender);
resolver.setRegion(region);
final String description = String.format("Adding members to the region '%s' on '%s'", region.getId(), world.getName());
@@ -101,7 +114,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
resolver.setActor(sender);
resolver.setRegion(region);
final String description = String.format("Adding owners to the region '%s' on '%s'", region.getId(), world.getName());
AsyncCommandBuilder.wrap(checkedAddOwners(sender, manager, region, world, resolver), sender)
@@ -174,6 +188,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
resolver.setActor(sender);
resolver.setRegion(region);
callable = resolver;
}
@@ -217,6 +233,8 @@ public class MemberCommands extends RegionCommandsBase {
DomainInputResolver resolver = new DomainInputResolver(
WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
resolver.setActor(sender);
resolver.setRegion(region);
callable = resolver;
}
@@ -21,6 +21,7 @@ package com.sk89q.worldguard.commands.region;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
@@ -30,6 +31,7 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.AsyncCommandBuilder;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.component.LabelFormat;
@@ -41,6 +43,7 @@ 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.worldedit.world.gamemode.GameModes;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.commands.task.RegionAdder;
@@ -56,7 +59,7 @@ import com.sk89q.worldguard.protection.FlagValueCalculator;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormatException;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.RegionGroupFlag;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
@@ -65,6 +68,7 @@ import com.sk89q.worldguard.protection.managers.RemovalStrategy;
import com.sk89q.worldguard.protection.managers.migration.DriverMigration;
import com.sk89q.worldguard.protection.managers.migration.MigrationException;
import com.sk89q.worldguard.protection.managers.migration.UUIDMigration;
import com.sk89q.worldguard.protection.managers.migration.WorldHeightMigration;
import com.sk89q.worldguard.protection.managers.storage.DriverType;
import com.sk89q.worldguard.protection.managers.storage.RegionDriver;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
@@ -73,6 +77,7 @@ 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;
import com.sk89q.worldguard.util.logging.LoggerToChatHandler;
@@ -155,7 +160,7 @@ public final class RegionCommands extends RegionCommandsBase {
region = checkRegionFromSelection(sender, id);
}
RegionAdder task = new RegionAdder(manager, region);
RegionAdder task = new RegionAdder(manager, region, sender);
task.addOwnersFromCommand(args, 2);
final String description = String.format("Adding region '%s'", region.getId());
@@ -209,7 +214,7 @@ public final class RegionCommands extends RegionCommandsBase {
region.copyFrom(existing);
RegionAdder task = new RegionAdder(manager, region);
RegionAdder task = new RegionAdder(manager, region, sender);
final String description = String.format("Updating region '%s'", region.getId());
AsyncCommandBuilder.wrap(task, sender)
@@ -280,7 +285,7 @@ public final class RegionCommands extends RegionCommandsBase {
}
}
// We have to check whether this region violates the space of any other reion
// We have to check whether this region violates the space of any other region
ApplicableRegionSet regions = manager.getApplicableRegions(region);
// Check if this region overlaps any other region
@@ -313,17 +318,21 @@ public final class RegionCommands extends RegionCommandsBase {
}
}
RegionAdder task = new RegionAdder(manager, region);
task.setLocatorPolicy(UserLocatorPolicy.UUID_ONLY);
task.setOwnersInput(new String[]{player.getName()});
// Inherit from a template region
if (!Strings.isNullOrEmpty(wcfg.setParentOnClaim)) {
ProtectedRegion templateRegion = manager.getRegion(wcfg.setParentOnClaim);
if (templateRegion != null) {
try {
region.setParent(templateRegion);
} catch (CircularInheritanceException e) {
throw new CommandException(e.getMessage());
}
}
}
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)));
}
/**
@@ -435,9 +444,9 @@ public final class RegionCommands extends RegionCommandsBase {
* @throws CommandException any error
*/
@Command(aliases = {"list"},
usage = "[page]",
usage = "[-w world] [-p owner [-n]] [-s] [-i filter] [page]",
desc = "Get a list of regions",
flags = "np:w:",
flags = "np:w:i:s",
max = 1)
public void list(CommandContext args, Actor sender) throws CommandException {
warnAboutSaveFailures(sender);
@@ -474,6 +483,16 @@ public final class RegionCommands extends RegionCommandsBase {
task.filterOwnedByName(ownedBy, args.hasFlag('n'));
}
if (args.hasFlag('s')) {
ProtectedRegion existing = checkRegionFromSelection(sender, "tmp");
task.filterByIntersecting(existing);
}
// -i string is in region id
if (args.hasFlag('i')) {
task.filterIdByMatch(args.getFlag('i'));
}
AsyncCommandBuilder.wrap(task, sender)
.registerWithSupervisor(WorldGuard.getInstance().getSupervisor(), "Getting region list")
.sendMessageAfterDelay("(Please wait... fetching region list...)")
@@ -568,7 +587,7 @@ public final class RegionCommands extends RegionCommandsBase {
// the [value] part throws an error.
try {
groupValue = groupFlag.parseInput(FlagContext.create().setSender(sender).setInput(group).setObject("region", existing).build());
} catch (InvalidFlagFormat e) {
} catch (InvalidFlagFormatException e) {
throw new CommandException(e.getMessage());
}
@@ -579,7 +598,7 @@ public final class RegionCommands extends RegionCommandsBase {
// Set the flag if [value] was given even if [-g group] was given as well
try {
value = setFlag(existing, foundFlag, sender, value).toString();
} catch (InvalidFlagFormat e) {
} catch (InvalidFlagFormatException e) {
throw new CommandException(e.getMessage());
}
@@ -1068,6 +1087,62 @@ public final class RegionCommands extends RegionCommandsBase {
}
}
/**
* Migrate regions that went from 0-255 to new world heights.
*
* @param args the arguments
* @param sender the sender
* @throws CommandException any error
*/
@Command(aliases = {"migrateheights"},
usage = "[world]", max = 1,
flags = "yw:",
desc = "Migrate regions from old height limits to new height limits")
public void migrateHeights(CommandContext args, Actor sender) throws CommandException {
// Check permissions
if (!getPermissionModel(sender).mayMigrateRegionHeights()) {
throw new CommandPermissionsException();
}
if (!args.hasFlag('y')) {
throw new CommandException("This command is potentially dangerous.\n" +
"Please ensure you have made a backup of your data, and then re-enter the command with -y tacked on at the end to proceed.");
}
World world = null;
try {
world = checkWorld(args, sender, 'w');
} catch (CommandException ignored) {
}
LoggerToChatHandler handler = null;
Logger minecraftLogger = null;
if (sender instanceof LocalPlayer) {
handler = new LoggerToChatHandler(sender);
handler.setLevel(Level.ALL);
minecraftLogger = Logger.getLogger("com.sk89q.worldguard");
minecraftLogger.addHandler(handler);
}
try {
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionDriver driver = container.getDriver();
WorldHeightMigration migration = new WorldHeightMigration(driver, WorldGuard.getInstance().getFlagRegistry(), world);
container.migrate(migration);
sender.print("Migration complete!");
} catch (MigrationException e) {
log.log(Level.WARNING, "Failed to migrate", e);
throw new CommandException("Error encountered while migrating: " + e.getMessage());
} finally {
if (minecraftLogger != null) {
minecraftLogger.removeHandler(handler);
}
}
}
/**
* Teleport to a region
*
@@ -1076,8 +1151,8 @@ public final class RegionCommands extends RegionCommandsBase {
* @throws CommandException any error
*/
@Command(aliases = {"teleport", "tp"},
usage = "<id>",
flags = "sw:",
usage = "[-w world] [-c|s] <id>",
flags = "csw:",
desc = "Teleports you to the location associated with the region.",
min = 1, max = 1)
public void teleport(CommandContext args, Actor sender) throws CommandException {
@@ -1102,6 +1177,23 @@ public final class RegionCommands extends RegionCommandsBase {
throw new CommandException(
"The region has no spawn point associated.");
}
} else if (args.hasFlag('c')) {
// Check permissions
if (!getPermissionModel(player).mayTeleportToCenter(existing)) {
throw new CommandPermissionsException();
}
Region region = WorldEditRegionConverter.convertToRegion(existing);
if (region == null || region.getCenter() == null) {
throw new CommandException("The region has no center point.");
}
if (player.getGameMode() == GameModes.SPECTATOR) {
teleportLocation = new Location(world, region.getCenter(), 0, 0);
} else {
// 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 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;
@@ -48,7 +45,7 @@ import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormatException;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
@@ -211,7 +208,7 @@ class RegionCommandsBase {
return global;
}
throw new CommandException(
"You're not standing in a region." +
"You're not standing in a region. " +
"Specify an ID if you want to select a specific region.");
} else if (set.size() > 1) {
boolean first = true;
@@ -308,8 +305,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 +345,7 @@ class RegionCommandsBase {
if (region instanceof GlobalProtectedRegion) {
return;
}
int height = region.getMaximumPoint().getBlockY() - region.getMinimumPoint().getBlockY();
int height = region.getMaximumPoint().y() - region.getMinimumPoint().y();
if (height <= 2) {
sender.printDebug("(Warning: The height of the region was " + (height + 1) + " block(s).)");
}
@@ -418,9 +415,9 @@ class RegionCommandsBase {
* @param flag the flag
* @param sender the sender
* @param value the value
* @throws InvalidFlagFormat thrown if the value is invalid
* @throws InvalidFlagFormatException thrown if the value is invalid
*/
protected static <V> V setFlag(ProtectedRegion region, Flag<V> flag, Actor sender, String value) throws InvalidFlagFormat {
protected static <V> V setFlag(ProtectedRegion region, Flag<V> flag, Actor sender, String value) throws InvalidFlagFormatException {
V val = flag.parseInput(FlagContext.create().setSender(sender).setInput(value).setObject("region", region).build());
region.setFlag(flag, val);
return val;
@@ -327,6 +327,12 @@ public class RegionPrintoutBuilder implements Callable<TextComponent> {
+ teleFlag.getBlockZ()))))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND,
"/rg tp -w \"" + world + "\" " + region.getId()))));
} else if (perms != null && perms.mayTeleportToCenter(region) && region.isPhysicalArea()) {
builder.append(TextComponent.space().append(TextComponent.of("[Center Teleport]", TextColor.GRAY)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT,
TextComponent.of("Click to teleport to the center of the region")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND,
"/rg tp -c -w \"" + world + "\" " + region.getId()))));
}
newline();
@@ -20,6 +20,7 @@
package com.sk89q.worldguard.commands.task;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.managers.RegionManager;
@@ -39,6 +40,7 @@ public class RegionAdder implements Callable<ProtectedRegion> {
private final RegionManager manager;
private final ProtectedRegion region;
private final Actor actor;
@Nullable
private String[] ownersInput;
private UserLocatorPolicy locatorPolicy = UserLocatorPolicy.UUID_ONLY;
@@ -46,15 +48,26 @@ public class RegionAdder implements Callable<ProtectedRegion> {
/**
* Create a new instance.
*
* @param manager the manage
* @param manager the manager
* @param region the region
*/
public RegionAdder(RegionManager manager, ProtectedRegion region) {
this(manager, region, null);
}
/**
* Create a new instance.
* @param manager the manager
* @param region the region
* @param actor the actor
*/
public RegionAdder(RegionManager manager, ProtectedRegion region, Actor actor) {
checkNotNull(manager);
checkNotNull(region);
this.manager = manager;
this.region = region;
this.actor = actor;
}
/**
@@ -75,6 +88,9 @@ public class RegionAdder implements Callable<ProtectedRegion> {
if (ownersInput != null) {
DomainInputResolver resolver = new DomainInputResolver(WorldGuard.getInstance().getProfileService(), ownersInput);
resolver.setLocatorPolicy(locatorPolicy);
resolver.setActor(actor);
resolver.setRegion(region);
DefaultDomain domain = resolver.call();
region.getOwners().addAll(domain);
}
@@ -42,6 +42,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -58,6 +59,8 @@ public class RegionLister implements Callable<Integer> {
private final RegionManager manager;
private final String world;
private OwnerMatcher ownerMatcher;
private String idFilter;
private ProtectedRegion filterByIntersecting;
private int page;
private String playerName;
private boolean nameOnly;
@@ -80,6 +83,10 @@ public class RegionLister implements Callable<Integer> {
this.page = page;
}
public void filterByIntersecting(ProtectedRegion region) {
this.filterByIntersecting = region;
}
public void filterOwnedByName(String name, boolean nameOnly) {
this.playerName = name;
this.nameOnly = nameOnly;
@@ -144,20 +151,29 @@ public class RegionLister implements Callable<Integer> {
};
}
public void filterIdByMatch(String idFilter) {
this.idFilter = idFilter;
}
@Override
public Integer call() throws Exception {
Map<String, ProtectedRegion> regions = manager.getRegions();
Collection<ProtectedRegion> iterableRegions = regions.values();
if (filterByIntersecting != null) {
iterableRegions = filterByIntersecting.getIntersectingRegions(iterableRegions);
}
// Build a list of regions to show
List<RegionListEntry> entries = new ArrayList<>();
for (Map.Entry<String, ProtectedRegion> rg : regions.entrySet()) {
if (rg.getKey().equals("__global__")) {
for (ProtectedRegion rg : iterableRegions) {
if (rg.getId().equals("__global__")) {
continue;
}
final ProtectedRegion region = rg.getValue();
final RegionListEntry entry = new RegionListEntry(region);
if (entry.matches(ownerMatcher)) {
final RegionListEntry entry = new RegionListEntry(rg);
if (entry.matches(idFilter) && entry.matches(ownerMatcher)) {
entries.add(entry);
}
}
@@ -168,7 +184,7 @@ public class RegionLister implements Callable<Integer> {
// insert global on top
if (regions.containsKey("__global__")) {
final RegionListEntry entry = new RegionListEntry(regions.get("__global__"));
if (entry.matches(ownerMatcher)) {
if (entry.matches(idFilter) && entry.matches(ownerMatcher)) {
entries.add(0, entry);
}
}
@@ -182,6 +198,8 @@ public class RegionLister implements Callable<Integer> {
String cmd = "/rg list -w \"" + world + "\""
+ (playerName != null ? " -p " + playerName : "")
+ (nameOnly ? " -n" : "")
+ (filterByIntersecting != null ? " -s" : "")
+ (idFilter != null ? " -i " + idFilter : "")
+ " %page%";
PaginationBox box = new RegionListBox(title, cmd, perms, entries, world);
sender.print(box.create(page));
@@ -210,6 +228,10 @@ public class RegionLister implements Callable<Integer> {
|| (isMember = matcher.isContainedWithin(region.getMembers()));
}
public boolean matches(String idMatcher) {
return idMatcher == null || region.getId().contains(idMatcher);
}
public ProtectedRegion getRegion() {
return region;
}
@@ -270,6 +292,12 @@ public class RegionLister implements Callable<Integer> {
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to teleport")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND,
"/rg tp -w \"" + world + "\" " + entry.region.getId()))));
} else if (perms != null && perms.mayTeleportToCenter(entry.getRegion()) && entry.getRegion().isPhysicalArea()) {
builder.append(TextComponent.space().append(TextComponent.of("[TP-Center]", TextColor.GRAY)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT,
TextComponent.of("Click to teleport to the center")))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND,
"/rg tp -c -w \"" + world + "\" " + entry.region.getId()))));
}
return builder.build();
}
@@ -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;
@@ -129,6 +130,7 @@ public abstract class WorldConfiguration {
public boolean allowTamedSpawns;
public int maxClaimVolume;
public boolean claimOnlyInsideExistingRegions;
public String setParentOnClaim;
public int maxRegionCountPerPlayer;
public boolean antiWolfDumbness;
public boolean signChestProtection;
@@ -138,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;
@@ -157,11 +161,15 @@ public abstract class WorldConfiguration {
public boolean disableGrassGrowth;
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 Set<String> allowedSnowFallOver;
public boolean regionInvinciblityRemovesMobs;
public boolean regionCancelEmptyChatEvents;
@@ -170,7 +178,6 @@ public abstract class WorldConfiguration {
public boolean fakePlayerBuildOverride;
public boolean explosionFlagCancellation;
public boolean disableDeathMessages;
public boolean disableObsidianGenerators;
public boolean strictEntitySpawn;
public boolean ignoreHopperMoveEvents;
public boolean breakDeniedHoppers;
@@ -93,6 +93,12 @@ public abstract class YamlConfigurationManager extends ConfigurationManager {
String sqlUsername = config.getString("regions.sql.username", "worldguard");
String sqlPassword = config.getString("regions.sql.password", "worldguard");
String sqlTablePrefix = config.getString("regions.sql.table-prefix", "");
if (!useSqlDatabase) {
config.removeProperty("regions.sql");
} else {
log.warning("SQL support for WorldGuard region storage is deprecated for removal in a future version. Please migrate to YAML storage.");
log.warning("For details, see https://worldguard.enginehub.org/en/latest/regions/storage/");
}
DataSourceConfig dataSourceConfig = new DataSourceConfig(sqlDsn, sqlUsername, sqlPassword, sqlTablePrefix);
SQLDriver sqlDriver = new SQLDriver(dataSourceConfig);
@@ -0,0 +1,108 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.domains.registry.CustomDomainContext;
import com.sk89q.worldguard.domains.registry.InvalidDomainFormatException;
import com.sk89q.worldguard.util.ChangeTracked;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class CustomDomain implements Domain, ChangeTracked {
private static final Pattern VALID_NAME = Pattern.compile("^[a-z0-9\\-]{1,40}$");
private final String name;
private boolean dirty;
public CustomDomain(String name) {
if (name == null ||!isValidName(name)) {
throw new IllegalArgumentException("Invalid Domain name used.");
}
this.name = name;
}
/**
* Get the name of the domain resolver.
*
* @return The name of the domain
*/
public String getName() {
return name;
}
/**
* Parse a given input to fill the context of the CustomDomain.
*
* @param context the {@link CustomDomainContext}
* @throws InvalidDomainFormatException Raised if the input is invalid
*/
public abstract void parseInput(CustomDomainContext context) throws InvalidDomainFormatException;
/**
* Convert a raw type that was loaded (from a YAML file, for example)
* into the custom domain.
*
* @param o The object
*/
public abstract void unmarshal(Object o);
/**
* Convert the current Domain to a storable foramt
*
* @return The marshalled type
*/
public abstract Object marshal();
/**
* Test whether a flag name is valid.
*
* @param name The flag name
* @return Whether the name is valid
*/
public static boolean isValidName(String name) {
checkNotNull(name, "name");
// g is already reserved by the group domain
return VALID_NAME.matcher(name).matches() && !name.equalsIgnoreCase("g");
}
@Override
public boolean contains(LocalPlayer player) {
return contains(player.getUniqueId());
}
@Override
public int size() {
return 1;
}
@Override
public boolean isDirty() {
return dirty;
}
@Override
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
}
@@ -22,8 +22,6 @@ package com.sk89q.worldguard.domains;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sk89q.worldguard.util.profile.Profile;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
@@ -31,14 +29,19 @@ import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.util.ChangeTracked;
import com.sk89q.worldguard.util.profile.Profile;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -50,6 +53,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
private PlayerDomain playerDomain = new PlayerDomain();
private GroupDomain groupDomain = new GroupDomain();
private final Map<String, CustomDomain> customDomains = new ConcurrentHashMap<>();
private boolean customDomainsChanged = false;
/**
* Create a new domain.
*/
@@ -64,6 +70,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
public DefaultDomain(DefaultDomain existing) {
setPlayerDomain(existing.getPlayerDomain());
setGroupDomain(existing.getGroupDomain());
setCustomDomains(existing.customDomains);
}
/**
@@ -104,6 +111,72 @@ public class DefaultDomain implements Domain, ChangeTracked {
this.groupDomain = new GroupDomain(groupDomain);
}
/**
* Add new custom domains
*
* @param customDomain a domain
*/
public void addCustomDomain(CustomDomain customDomain) {
checkNotNull(customDomain);
this.customDomains.put(customDomain.getName(), customDomain);
this.customDomainsChanged = true;
}
/**
* Remove a custom domain matched by the name
*
* @param name the name
*/
public void removeCustomDomain(String name) {
checkNotNull(name);
if (this.customDomains.remove(name) != null) {
this.customDomainsChanged = true;
}
}
/**
* Remove a custom domain
*
* @param customDomain a domain
*/
public void removeCustomDomain(CustomDomain customDomain) {
checkNotNull(customDomain);
if (this.customDomains.remove(customDomain.getName()) != null) {
this.customDomainsChanged = true;
}
}
/**
* Set the api domains to a specified value
*
* @param customDomains the domains
*/
public void setCustomDomains(Map<String, CustomDomain> customDomains) {
checkNotNull(customDomains);
this.customDomains.clear();
this.customDomains.putAll(customDomains);
this.customDomainsChanged = true;
}
/**
* Get all api domains
*
* @return a unmodifiable copy of the domains
*/
public Collection<CustomDomain> getCustomDomains() {
return Collections.unmodifiableCollection(this.customDomains.values());
}
/**
* Get the api domain specified by its name
*
* @param name the name of the domain
* @return the custom domain
*/
public @Nullable CustomDomain getCustomDomain(String name) {
return this.customDomains.get(name);
}
/**
* Add the given player to the domain, identified by the player's name.
*
@@ -175,6 +248,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
for (String group : other.getGroups()) {
addGroup(group);
}
for (CustomDomain domain : other.getCustomDomains()) {
addCustomDomain(domain);
}
}
/**
@@ -193,6 +269,9 @@ public class DefaultDomain implements Domain, ChangeTracked {
for (String group : other.getGroups()) {
removeGroup(group);
}
for (CustomDomain domain : other.getCustomDomains()) {
removeCustomDomain(domain.getName());
}
}
/**
@@ -242,12 +321,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
@Override
public boolean contains(LocalPlayer player) {
return playerDomain.contains(player) || groupDomain.contains(player);
return playerDomain.contains(player) || groupDomain.contains(player) || customDomains.values().stream().anyMatch(d -> d.contains(player));
}
@Override
public boolean contains(UUID uniqueId) {
return playerDomain.contains(uniqueId);
return playerDomain.contains(uniqueId) || customDomains.values().stream().anyMatch(d -> d.contains(uniqueId));
}
@Override
@@ -257,7 +336,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
@Override
public int size() {
return groupDomain.size() + playerDomain.size();
return groupDomain.size() + playerDomain.size() + customDomains.size();
}
@Override
@@ -275,7 +354,6 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
public String toPlayersString(@Nullable ProfileCache cache) {
StringBuilder str = new StringBuilder();
List<String> output = new ArrayList<>();
for (String name : playerDomain.getPlayers()) {
@@ -299,13 +377,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
output.sort(String.CASE_INSENSITIVE_ORDER);
for (Iterator<String> it = output.iterator(); it.hasNext();) {
str.append(it.next());
if (it.hasNext()) {
str.append(", ");
}
}
return str.toString();
return String.join(", ", output);
}
public String toGroupsString() {
@@ -320,25 +392,20 @@ public class DefaultDomain implements Domain, ChangeTracked {
return str.toString();
}
public String toUserFriendlyString() {
StringBuilder str = new StringBuilder();
if (playerDomain.size() > 0) {
str.append(toPlayersString());
public String toCustomDomainsString() {
List<String> output = new ArrayList<>();
for (CustomDomain customDomain : customDomains.values()) {
output.add(customDomain.getName() + ":" + customDomain.toString());
}
if (groupDomain.size() > 0) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toGroupsString());
}
return str.toString();
output.sort(String.CASE_INSENSITIVE_ORDER);
return String.join(", ", output);
}
public String toUserFriendlyString(ProfileCache cache) {
public String toUserFriendlyString() {
return toUserFriendlyString(null);
}
public String toUserFriendlyString(@Nullable ProfileCache cache) {
StringBuilder str = new StringBuilder();
if (playerDomain.size() > 0) {
@@ -352,6 +419,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
str.append(toGroupsString());
}
if (!customDomains.isEmpty()) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toCustomDomainsString());
}
return str.toString();
}
@@ -367,6 +440,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
}
builder.append(toGroupsComponent());
}
if (!customDomains.isEmpty()) {
if (playerDomain.size() > 0 || groupDomain.size() > 0) {
builder.append(TextComponent.of("; "));
}
builder.append(toCustomDomainsComponent());
}
return builder.build();
}
@@ -409,15 +488,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,30 +510,50 @@ 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))));
}
return builder.build();
}
private Component toCustomDomainsComponent() {
final TextComponent.Builder builder = TextComponent.builder("");
for (Iterator<CustomDomain> it = customDomains.values().iterator(); it.hasNext(); ) {
CustomDomain domain = it.next();
builder.append(TextComponent.of(domain.getName() + ":", TextColor.LIGHT_PURPLE))
.append(TextComponent.of(domain.toString(), TextColor.GOLD));
if (it.hasNext()) {
builder.append(TextComponent.of(", "));
}
}
return builder.build().hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("CustomDomain")));
}
@Override
public boolean isDirty() {
return playerDomain.isDirty() || groupDomain.isDirty();
return playerDomain.isDirty() || groupDomain.isDirty() ||
customDomainsChanged || customDomains.values().stream().anyMatch(ChangeTracked::isDirty);
}
@Override
public void setDirty(boolean dirty) {
playerDomain.setDirty(dirty);
groupDomain.setDirty(dirty);
customDomainsChanged = dirty;
customDomains.values().forEach(d -> d.setDirty(dirty));
}
@Override
public String toString() {
return "{players=" + playerDomain +
", groups=" + groupDomain +
", custom=" + customDomains +
'}';
}
@@ -0,0 +1,98 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.commands.CommandInputContext;
import javax.annotation.Nullable;
import java.util.Map;
public final class CustomDomainContext extends CommandInputContext<InvalidDomainFormatException> {
private CustomDomainContext(Actor sender, String input, Map<String, Object> values) {
super(sender, input, values);
}
public static CustomDomainContext.CustomDomainContextBuilder create() {
return new CustomDomainContext.CustomDomainContextBuilder();
}
/**
* Create a copy of this CustomDomainContext, with optional substitutions for values
*
* <p>If any supplied variable is null, it will be ignored.
* If a map is supplied, it will override this CustomDomainContext's values of the same key,
* but unprovided keys will not be overriden and will be returned as shallow copies.</p>
*
* @param commandSender CommandSender for the new CustomDomainContext to run under
* @param s String of the user input for the new CustomDomainContext
* @param values map of values to override from the current CustomDomainContext
* @return a copy of this CustomDomainContext
*/
public CustomDomainContext copyWith(@Nullable Actor commandSender, @Nullable String s, @Nullable Map<String, Object> values) {
Map<String, Object> map = Maps.newHashMap();
map.putAll(context);
if (values != null) {
map.putAll(values);
}
return new CustomDomainContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map);
}
@Override
protected InvalidDomainFormatException createException(String str) {
return new InvalidDomainFormatException(str);
}
public static class CustomDomainContextBuilder {
private Actor sender;
private String input;
private Map<String, Object> map = Maps.newHashMap();
public CustomDomainContextBuilder setSender(Actor sender) {
this.sender = sender;
return this;
}
public CustomDomainContextBuilder setInput(String input) {
this.input = input;
return this;
}
public CustomDomainContextBuilder setObject(String key, Object value) {
this.map.put(key, value);
return this;
}
public boolean tryAddToMap(String key, Object value) {
if (map.containsKey(key)) return false;
this.map.put(key, value);
return true;
}
public CustomDomainContext build() {
return new CustomDomainContext(sender, input, map);
}
}
}
@@ -0,0 +1,26 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
public class DomainConflictException extends RuntimeException {
public DomainConflictException(String message) {
super(message);
}
}
@@ -0,0 +1,28 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
@FunctionalInterface
public interface DomainFactory<T extends CustomDomain> {
T create(String name);
}
@@ -0,0 +1,94 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
public interface DomainRegistry extends Iterable<DomainFactory<?>> {
/**
* Register a new Domain
*
* <p>There may be an appropiate time to register domains. if domains are
* registered outside this time, then an exception may be thrown.</p>
*
* @param domain The domain
* @throws DomainConflictException Thrown when already an existing domain exists with the same name
* @throws IllegalStateException If it is not the right time to register new domains
*/
void register(String name, DomainFactory<?> domain) throws DomainConflictException;
/**
* Register a collection of domains.
*
* <p>There may be an appropriate time to register domains. If domains are
* registered outside this time, then an exception may be thrown.</p>
*
* <p>If there is a domain conflict, then an error will be logged but
* no exception will be thrown.</p>
*
* @param domains a collection of domain factories
* @throws IllegalStateException If it is not the right time to register new domains
*/
void registerAll(Map<String, DomainFactory<?>> domains);
/**
* Get the domain by its name.
*
* @param name The name
* @return The domain, if it has been registered
*/
@Nullable
DomainFactory<?> get(String name);
/**
* Try to get a domain by its name
*/
@Nullable
CustomDomain createDomain(String name);
/**
* Get all domains keyed by the registered name
*
* @return All domains
*/
Map<String, DomainFactory<?>> getAll();
/**
* Unmarshal a raw map of values into a list of domains with their
* unmarshalled values.
*
* @param rawValues The raw values map
* @param createUnknown Whether "just in time" domains should be created for unknown domains
* @return The unmarshalled domain list
*/
Map<String, CustomDomain> unmarshal(Map<String, Object> rawValues, boolean createUnknown);
/**
* Get the number of registered domains.
*
* @return The number of registered domains
*/
int size();
}
@@ -0,0 +1,28 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
public class InvalidDomainFormatException extends Exception {
private static final long serialVersionUID = 8101615074524004172L;
public InvalidDomainFormatException(String msg) {
super(msg);
}
}
@@ -0,0 +1,166 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.sk89q.worldguard.domains.CustomDomain;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
public class SimpleDomainRegistry implements DomainRegistry {
private static final Logger log = Logger.getLogger(SimpleDomainRegistry.class.getCanonicalName());
private final Object lock = new Object();
private final ConcurrentMap<String, DomainFactory<?>> domains = Maps.newConcurrentMap();
private boolean initialized = false;
public boolean isInitialized() {
return initialized;
}
public void setInitialized(boolean initialized) {
this.initialized = initialized;
}
@Override
public void register(String name, DomainFactory<?> domain) throws DomainConflictException {
synchronized (lock) {
if (initialized) {
throw new IllegalStateException("New domains cannot be registered at this time");
}
forceRegister(name, domain);
}
}
@Override
public void registerAll(Map<String, DomainFactory<?>> domains) {
synchronized (lock) {
for (Map.Entry<String, DomainFactory<?>> entry : domains.entrySet()) {
try {
register(entry.getKey(), entry.getValue());
} catch (DomainConflictException e) {
log.log(Level.WARNING, e.getMessage());
}
}
}
}
private <T extends DomainFactory<?>> T forceRegister(String name, T domain) throws DomainConflictException {
checkNotNull(domain, "domain");
checkNotNull(name, "name");
if (!CustomDomain.isValidName(name)) {
throw new IllegalArgumentException("Invalid Domain name used.");
}
synchronized (lock) {
if (domains.containsKey(name)) {
throw new DomainConflictException("A domain already exists by the name " + name);
}
domains.put(name, domain);
}
return domain;
}
@Nullable
@Override
public DomainFactory<?> get(String name) {
checkNotNull(name, "name");
return domains.get(name.toLowerCase());
}
@Nullable
@Override
public CustomDomain createDomain(String name) {
DomainFactory<?> factory = get(name);
if (factory == null) return null;
return factory.create(name);
}
@Override
public Map<String, DomainFactory<?>> getAll() {
return ImmutableMap.copyOf(domains);
}
private CustomDomain getOrCreate(String name, Object value, boolean createUnknown) {
CustomDomain customDomain = createDomain(name);
if (customDomain != null) {
customDomain.unmarshal(value);
return customDomain;
}
synchronized (lock) {
customDomain = createDomain(name); // Load again because the previous load was not synchronized
if (customDomain != null) {
customDomain.unmarshal(value);
return customDomain;
}
if (createUnknown) {
DomainFactory<UnknownDomain> unknownFactory = forceRegister(name, UnknownDomain.FACTORY);
if (unknownFactory != null) {
customDomain = unknownFactory.create(name);
if (customDomain != null) customDomain.unmarshal(value);
return customDomain;
}
}
}
return null;
}
public Map<String, CustomDomain> unmarshal(Map<String, Object> rawValues, boolean createUnknown) {
checkNotNull(rawValues, "rawValues");
Map<String, CustomDomain> domains = new HashMap<>();
for (Map.Entry<String, Object> entry : rawValues.entrySet()) {
try {
CustomDomain domain = getOrCreate(entry.getKey(), entry.getValue(), createUnknown);
domains.put(domain.getName(), domain);
} catch (Throwable e) {
log.log(Level.WARNING, "Failed to unmarshal domain for " + entry.getKey(), e);
}
}
return domains;
}
@Override
public int size() {
return domains.size();
}
@Override
public Iterator<DomainFactory<?>> iterator() {
return Iterators.unmodifiableIterator(domains.values().iterator());
}
}
@@ -0,0 +1,88 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.domains.registry;
import com.sk89q.worldguard.domains.CustomDomain;
import java.util.UUID;
public class UnknownDomain extends CustomDomain {
public static DomainFactory<UnknownDomain> FACTORY = UnknownDomain::new;
private boolean isDirty = false;
private Object o;
public UnknownDomain(String name) {
super(name);
}
@Override
public void parseInput(CustomDomainContext context) throws InvalidDomainFormatException {
throw new InvalidDomainFormatException("The plugin that registered this domain is not currently installed");
}
@Override
public void unmarshal(Object o) {
this.o = o;
}
@Override
public Object marshal() {
return o;
}
@Override
public boolean contains(UUID uniqueId) {
return false;
}
@Override
public boolean contains(String playerName) {
return false;
}
@Override
public int size() {
return 0;
}
@Override
public void clear() {
isDirty = true;
o = null;
}
@Override
public void setDirty(boolean dirty) {
isDirty = dirty;
}
@Override
public boolean isDirty() {
return isDirty;
}
@Override
public String toString() {
return "UnknownDomain{" +
"o=" + o +
'}';
}
}
@@ -63,7 +63,11 @@ public class RegionPermissionModel extends AbstractPermissionModel {
public boolean mayMigrateRegionNames() {
return hasPluginPermission("region.migrateuuid");
}
public boolean mayMigrateRegionHeights() {
return hasPluginPermission("region.migrateheights");
}
public boolean mayDefine() {
return hasPluginPermission("region.define");
}
@@ -106,6 +110,10 @@ public class RegionPermissionModel extends AbstractPermissionModel {
return hasPatternPermission("teleport", region);
}
public boolean mayTeleportToCenter(ProtectedRegion region) {
return hasPatternPermission("teleportcenter", region);
}
public boolean mayOverrideLocationFlagBounds(ProtectedRegion region) {
return hasPatternPermission("locationoverride", region);
}
@@ -125,7 +133,7 @@ public class RegionPermissionModel extends AbstractPermissionModel {
return mayList();
}
}
public boolean maySetFlag(ProtectedRegion region) {
return hasPatternPermission("flag.regions", region);
}
@@ -168,13 +176,14 @@ public class RegionPermissionModel extends AbstractPermissionModel {
public boolean mayRemoveOwners(ProtectedRegion region) {
return hasPatternPermission("removeowner", region);
}
/**
* Checks to see if the given sender has permission to modify the given region
* using the region permission pattern.
*
* @param perm the name of the node
* @param region the region
* @return whether the actor has the permission
*/
private boolean hasPatternPermission(String perm, ProtectedRegion region) {
if (!(getSender() instanceof Player)) {
@@ -195,5 +204,4 @@ public class RegionPermissionModel extends AbstractPermissionModel {
return hasPluginPermission(effectivePerm);
}
}
@@ -33,7 +33,7 @@ public class BooleanFlag extends Flag<Boolean> {
}
@Override
public Boolean parseInput(FlagContext context) throws InvalidFlagFormat {
public Boolean parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
if (input.equalsIgnoreCase("true") || input.equalsIgnoreCase("yes")
@@ -45,7 +45,7 @@ public class BooleanFlag extends Flag<Boolean> {
|| input.equalsIgnoreCase("0")) {
return false;
} else {
throw new InvalidFlagFormat("Not a yes/no value: " + input);
throw new InvalidFlagFormatException("Not a yes/no value: " + input);
}
}
@@ -33,7 +33,7 @@ public class CommandStringFlag extends Flag<String> {
}
@Override
public String parseInput(FlagContext context) throws InvalidFlagFormat {
public String parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
if (!input.startsWith("/")) {
@@ -33,7 +33,7 @@ public class DoubleFlag extends NumberFlag<Double> {
}
@Override
public Double parseInput(FlagContext context) throws InvalidFlagFormat {
public Double parseInput(FlagContext context) throws InvalidFlagFormatException {
return context.getUserInputAsDouble();
}
@@ -40,12 +40,12 @@ public class EntityTypeFlag extends Flag<EntityType> {
}
@Override
public EntityType parseInput(FlagContext context) throws InvalidFlagFormat {
public EntityType parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
input = input.trim();
EntityType entityType = unmarshal(input);
if (entityType == null) {
throw new InvalidFlagFormat("Unknown entity type: " + input);
throw new InvalidFlagFormatException("Unknown entity type: " + input);
}
return entityType;
}
@@ -57,6 +57,6 @@ public class EntityTypeFlag extends Flag<EntityType> {
@Override
public Object marshal(EntityType o) {
return o.getId();
return o.id();
}
}
@@ -74,12 +74,12 @@ public class EnumFlag<T extends Enum<T>> extends Flag<T> {
}
@Override
public T parseInput(FlagContext context) throws InvalidFlagFormat {
public T parseInput(FlagContext context) throws InvalidFlagFormatException {
String input = context.getUserInput();
try {
return findValue(input);
} catch (IllegalArgumentException e) {
throw new InvalidFlagFormat("Unknown value '" + input + "' in "
throw new InvalidFlagFormatException("Unknown value '" + input + "' in "
+ enumClass.getName());
}
}
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff. Show more