Compare commits

...
100 Commits
Author SHA1 Message Date
wizjany 014277fb2f Release 7.0.4. 2020-09-26 12:55:18 -04:00
wizjany f7ff984c34 Update changelog for release. 2020-09-26 12:46:20 -04:00
Pisich d4b2060766 Removed extra ";" 2020-09-26 12:06:06 -04:00
JOO200 0e73b50d6f Moved default bypass options to global configuration section 2020-09-16 13:34:56 -04:00
JOO200 136ec31f38 Add configurable announcement for current bypass status 2020-09-16 13:34:56 -04:00
JOO200andwizjany ad000ab051 Rename config option for default bypass option
Co-authored-by: wizjany <wizjany@gmail.com>
2020-09-16 13:34:56 -04:00
JOO200 af67f1dd6a Add config option to deny region bypass by default 2020-09-16 13:34:56 -04:00
wizjany 8dee2ad3b8 Don't check ride for unsaddled striders. 2020-09-11 20:44:47 -04:00
wizjany c860fce299 Document ProtectedRegion's comparable behavior.
ProtectedRegion's compareTo is inconsistent with equals when comparing regions across managers.
2020-09-09 15:16:15 -04:00
wizjany 0cb84927a3 Don't fire xp spawn events for fishing where xp was already 0.
Dedicated to @mikroskeem who let me forget about this.
2020-08-30 13:25:36 -04:00
wizjany 2ed60eba02 Add deprecation warnings for names in Domains. 2020-08-21 15:51:33 -04:00
wizjany 91a1494634 Add piglin brutes. 2020-08-16 18:03:05 -04:00
Matthew Miller 5b8c3e7f70 Use a lower level exception in BukkitWorldConfiguration to get a printout when more severe YAML issues occur 2020-08-16 16:55:19 +10:00
Matthew Miller c1ff4fc3d3 s/WorlGuard/WorldGuard 2020-08-16 14:44:57 +10:00
JOO200andwizjany 691325c8f0 Update worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java
fixed typo

Co-authored-by: wizjany <wizjany@gmail.com>
2020-08-14 14:01:58 -04:00
JOO200 3da19a7ff0 Added world option to block turtle egg trampling 2020-08-14 14:01:58 -04:00
wizjany f677af566f Don't try dropping items from falling blocks that won't drop one.
To quote myself from the adjacent commit almost exactly one year ago,
"some plugins do weird things with falling blocks."

Fixes #1624.
2020-08-07 13:59:22 -04:00
wizjany 58eaf31879 Merge pull request #1618 from JOO200/piston
Implement new alternative association mode to limit piston movement
2020-08-03 10:53:31 -04:00
wizjany 6708b21016 Abstract RegionOverlapAssociation, deprecate/fix packaging. 2020-08-03 10:46:40 -04:00
wizjany ed4287ace7 Cleanup use-max-prio algorithm, add tests. 2020-08-03 10:21:35 -04:00
wizjany 03f05d3a4e Simplify and remove duplicate code. 2020-08-03 07:21:56 -04:00
JOO200 c8bde17994 Fixed "null" output for invalid worldedit selections 2020-08-01 16:55:37 +02:00
JOO200 449145ba1f Renamed option to use-max-priority-association, Code cleanup 2020-08-01 13:54:27 +02:00
JOO200 85c5f53d29 only detect max priority once 2020-07-30 20:37:49 +02:00
JOO200 5162ce3dbd Implement new alternative association mode to limit piston movement 2020-07-30 20:24:18 +02:00
wizjany efe1e48bd4 Merge pull request #1615 from JOO200/toRegionSelector
Add Helper to convert WorldGuard's ProtectedRegion to WorldEdit's Region and RegionSelector
2020-07-29 23:42:00 -04:00
wizjany 1710c07623 Check non-waterloggable waterlogged blocks for liquid flow.
Fixes #1616.
2020-07-29 23:39:04 -04:00
JOO200 6f9ed5d10f Private ctor to match checkstyle. 2020-07-27 17:55:11 +02:00
JOO200 f0ec54af49 Added missing license to WorldEditRegionConverter 2020-07-27 17:17:20 +02:00
JOO200 e9e1885f2e Moved toRegion and toRegionSelector in a helper class 2020-07-27 17:03:50 +02:00
wizjany f8e2d8d6b7 Redstone wire is toggled between dot and cross on interact now. 2020-07-19 16:47:30 -04:00
wizjany 2c0b592b19 Declare some recently hidden dependencies. 2020-07-17 01:11:12 -04:00
wizjany 46e230e625 Missed import. 2020-07-16 21:41:08 -04:00
wizjany fe24668c6a Re-add pom-switcheroo to expose spigot as a dep instead of paper.
Makes it easier for downstream projects that don't have paper-repo.
2020-07-15 19:23:44 -04:00
wizjany 23efd5fec2 Fireworks are now projectiles.
Only use paper-api for fallback.
2020-07-15 19:23:01 -04:00
JOO200 e54235a65e Removed unnecessary relevant flag as it's checked by the UseBlockEvent listener 2020-07-15 18:43:25 -04:00
JOO200 5ec3ed6092 Changed handling von PlayerTakeLecternBookEvent to match the chest-access flag 2020-07-15 18:43:25 -04:00
TheMolkaPL 1652c9bfc0 Allocate WorldPlayerTuple only when using cache 2020-07-03 20:26:56 -04:00
TheMolkaPL a97db0ede9 Add an option to disable bypass permission cache 2020-07-03 20:26:56 -04:00
wizjany 36e42eefd0 Update gradle wrapper, more buildscript fixes. 2020-07-03 17:06:31 -04:00
wizjany 5b8eef92b8 Build script cleanup/updates. 2020-07-02 19:09:09 -04:00
wizjany d73dc6d719 Cleanup issue template a bit. 2020-07-02 18:55:08 -04:00
wizjany 74d8a4f0e7 Typo. 2020-06-27 19:55:34 -04:00
JOO200 613406aab4 Add Weeping Vines and Twisting Vines to vine-growth flag 2020-06-27 18:19:11 -04:00
wizjany 66fd84ba2f Add GitHub Sponsors link. 2020-06-27 00:24:46 -04:00
wizjany 53abb6c4ad Back to snapshot. 2020-06-26 02:09:36 -04:00
wizjany 923369e28c Release 7.0.4-beta1. 2020-06-26 02:02:48 -04:00
wizjany bc551da903 Update buildscript and WE dep. 2020-06-26 01:21:30 -04:00
wizjany bffe5e76f2 Additional 1.16 material defs. 2020-06-26 00:52:29 -04:00
JOO200 8722322cd8 Added new flag respawn-anchors similar to block respawn anchor usage 2020-06-26 00:02:50 -04:00
JOO200 0fa92d4836 Removed unnecessary if branch 2020-06-26 00:02:49 -04:00
JOO200 e52875bd0b Removed duplicate pressure plates check 2020-06-26 00:02:49 -04:00
JOO200 dbad328d0d Update to Minecraft 1 16, PaperLib to 1 0 4 2020-06-26 00:02:49 -04:00
wizjany 5407315799 Release 7.0.3 for MC 1.14/1.15.
Last release before switching to 1.16.
2020-06-25 23:40:40 -04:00
wizjany b769469f5b Changelog for 7.0.3. 2020-06-25 23:11:51 -04:00
wizjany 3a9b1b1525 Add deprecation warnings to StringFlags. 2020-06-25 22:57:28 -04:00
wizjany ff5f933879 Typo. 2020-06-24 10:42:12 -04:00
wizjany 0492fafe30 Color 3rd party flags and unregistered flags in /rg info. 2020-06-21 17:25:38 -04:00
wizjany 36d95ad090 More inventory holder snapshot use. 2020-06-21 16:57:58 -04:00
wizjany c1ec708050 Use Inventory#getHolder(boolean useSnapshot) where available.
Dedicated to @phoenix616
2020-06-21 16:39:28 -04:00
wizjany f4a3e8a936 Allow setting passthrough on global via /rg flags.
Closes #1584.
2020-06-11 14:57:22 -04:00
wizjany 6c5380ba0b Prioritize tamed owners over entity targets.
Fixes #1587.
2020-06-08 13:14:04 -04:00
wizjany 868089b44f Actually read TargetMatchers from world configs.
Previously only read from global.
2020-06-01 15:52:16 -04:00
wizjany 9905d22ddf Add dyes as tools for interact handling. 2020-05-19 14:50:46 -04:00
UltraFaceguy 4eaa376e2c Providing a solution for tools being unable to interact with usable blocks 2020-05-12 20:56:41 -04:00
JOO200 37ae70f35d Add coral-fade flag and world configuration to disable coral fading
Closes #1532
2020-05-10 03:12:20 -04:00
wizjany 1a69250d9b Allow droppers to drop items without using them.
Fixes #1570.
2020-05-10 03:12:18 -04:00
wizjany b2d2d0815b Silence EntityChangeBlock for redstone ore.
We already silence this for Action.PHYSICAL PlayerInteractEvents.
Unfortunately Bukkit throws another event at us without the extra info
about interaction type, which gets fired if the interact flag is allow.
So silence that too.

Closes #1573.
2020-05-10 03:12:17 -04:00
wizjany 47cd96a3af Add tests to validate behavior of non-player causes in multiple regions. 2020-05-02 10:41:51 -04:00
wizjany 0a735e0146 Don't warn about small global regions.
Closes #1567.
2020-05-01 19:39:59 -04:00
stonar96 60590acfe3 Remove unnecessary checks and add comments 2020-04-29 15:15:07 -04:00
stonar96 6030bea13e Improve default teleport-message and remove null check 2020-04-29 15:15:07 -04:00
stonar96 20f89ea2ae Add teleport-message flag 2020-04-29 15:15:07 -04:00
wizjany 4c351fb0e3 Workaround for CraftBukkit's move event throttling. 2020-04-28 16:19:18 -04:00
wizjany 5e7829c3fe Allow FML2 in forge host keys.
Closes #1542.
2020-04-24 11:43:22 -04:00
wizjany 37e66dae7d Track BlockProjectileSource causes. 2020-04-24 10:06:16 -04:00
wizjany 662ae2bc84 Add issue templates. 2020-04-16 09:02:01 -04:00
wizjany fa60582afe Sand/gravel tick now, even if physics is cancelled. 2020-04-09 18:47:01 -04:00
wizjany 17c1647163 Move profile cache updating to join event.
Adding it to onEnable might back up the executor on /reloads.
2020-04-07 11:25:56 -04:00
wizjany 1fcda13469 Check waterlogged blocks for water-flow flag.
Also remove some terribly outdated obsidian generator protection.

Fixes #1546.
2020-03-29 20:16:50 -04:00
wizjany 570b7f7b77 Allow passthrough allow on global to override added members/owners. 2020-03-29 19:48:13 -04:00
wizjany aca0d843f6 Allow WorldEdit's //world override to affect region commands.
Priority is `-w` flag > //world override > player world > error.
Also makes regions selectable from console.
2020-03-23 21:32:25 -04:00
wizjany 1172ebd419 More spawn protection warnings.
Can't have enough of these apparently.
2020-03-23 16:40:12 -04:00
wizjany a09ccc5b45 Fire block breaks for piston extends, not just places. 2020-03-21 11:25:46 -04:00
wizjany e6bdf8abb5 Fix cauldron NPE.
Closes #1541.
2020-03-19 22:34:39 -04:00
wizjany df2ae6a666 Tweak some region info output, fix teleport location. 2020-03-19 13:34:20 -04:00
wizjany e4481f9337 Protect cauldron level change.
Closes #1262.
2020-03-12 15:26:22 -04:00
wizjany 2169aa218e Add option to always use default MC times for sending titles.
Alleviates issues with other plugins setting extremely short/long times.
2020-02-15 16:04:47 -05:00
wizjany 523e45188d Default nether-portal-protection to true.
Pre 1.14, this was false by default as one could repeatedly force portal
searches by entering a portal which would lead into a protected area.

Since 1.14, the event we have access too happens independently of the
portal search, so the player will get teleported regardless of whether
a portal is present or if the creation gets cancelled.
2020-02-15 13:31:38 -05:00
wizjany d95c6af1be Remove metadata when the entity is done.
Apparently Bukkit doesn't actually do this.
Fixes WORLDGUARD-4169.
2020-02-13 23:20:04 -05:00
wizjany 0d860bfca7 Change bypass cache to expireAfterWrite.
This hasn't caused issues for the past 5 years but I guess ¯\_(ツ)_/¯
2020-02-06 18:16:55 -05:00
wizjany 6f6125fe00 Treat farmland and turtle egg PIE as EntityChangeBlock.
Note that as in d37f015f this decouples the event from interact flag,
meaning that block-trampling must be explicitly set to allow to maintain
previous behavior. It also means that setting interact to allow won't
by default allow players to trample turtle eggs (but this wasn't the case
for farmland, since that was already handled by ECB - thanks Bukkit).

Fixes WORLDGUARD-4163.
2020-02-01 11:39:20 -05:00
wizjany 0332929531 Bump bStats to 1.7, adding plugin id. 2020-01-31 11:18:50 -05:00
Wyatt Childers 637665f52d Add a scripts folder to gitignore for dev scripts 2020-01-14 22:51:13 -05:00
wizjany db3838ccfe Add flag to prevent natural health regen and hunger drain. 2020-01-09 20:41:57 -05:00
wizjany 789405d116 Ignore session reset if player doesn't move a block.
So technically we do this block check in Session#testMoveTo, but the
/wg flushstates command can force a session re-initialization even if
the player hasn't moved a full block yet.
The amount of logic going on between the event call and the point where
we test that force boolean is rather lengthy though, so ignoring it for
the time being may be worth it.
TL;DR: Don't want WG in timings for PlayerMoveEvent needlessly.
2020-01-07 17:24:43 -05:00
wizjany d37f015f0c De-couple chest-access from interact. READ BELOW.
This is possibly a breaking change, in that WG will be overprotective
in regions which previously had interact set to allow but didn't change
the chest-access flag. If you previously had regions like this where you
would like to have non-members access chests, you will need to set the
chest-access flag to allow.

This change was made to alleviate some confusion that became more
evident recently with lecterns, since interacting with lecterns allowed
one to read a book, but the chest-access flag controlled taking the book.
This required setting interact to allow and chest-access to deny (at
least for nonmembers) to allow guests to read books but not take them.

This is a tentative change and may be reverted if it is too unpopular.
Thanks for testing dev builds :^)
2020-01-05 22:52:23 -05:00
wizjany 239eda3f96 Bump to snapshot. This will likely become 7.1 soon anyway. 2020-01-05 22:43:00 -05:00
wizjany 0715cbe216 Release 7.0.2. 2020-01-05 22:42:15 -05:00
wizjany 738b24bfc1 Changelog for 7.0.2.
Small one.
2020-01-05 22:35:05 -05:00
56 changed files with 1344 additions and 397 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
github: enginehub
+34
View File
@@ -0,0 +1,34 @@
---
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. -->
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: EngineHub Discord
url: https://discord.gg/EngineHub
about: Please ask and answer questions here.
+20
View File
@@ -0,0 +1,20 @@
---
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. -->
+2
View File
@@ -15,3 +15,5 @@ dependency-reduced-pom.xml
.gradle/
**/build/
out/
scripts/
+54
View File
@@ -1,5 +1,59 @@
# Changelog
## 7.0.4 (including beta1)
* Add support for MC 1.16. Dropped support for previous versions.
* Add respawn-anchors flag mirroring the sleep flag (e.g. to prevent using respawn anchors to cause explosions in the overworld)
* Add nether vines to vine-growth flag.
* Add config option to disable the bypass permission cache.
* Fix water-flow flags not checking waterlogged blocks.
* Add config option to consider non-player causes (e.g. pistons, flowing water) to only be members of the highest priority region. This should be enabled for plots-within-city-like setups to prevent things in plots from modifying the city.
* Fix items dropping from falling blocks that were suppressed by other plugins.
* Add config option to block turtle egg trampling.
* Fix ride flag being checked on striders that didn't have saddles.
* Add config option to have /rg bypass toggled off on login.
* Developer changes: Methods taking names in Domains are now explicitly deprecated (was previously just a javadoc comment.); These will eventually be removed: there is no reason to use names over UUIDs. Offline players and NPCs alike have stable UUIDs.
## 7.0.3
* This is the last release supporting MC 1.14 and 1.15.
* Decouple chest-access flag from interact flag. IMPORTANT: If you relied on allowing players to access chests via setting
the interact flag to allow, you will now need to set the chest-access flag to allow instead (or as well). This does not
affect any setups where users were *not* supposed to be able to access chests and other inventories.
* Add natural-health-regen and natural-hunger-drain flags. Unlike the heal/feed flags, these can not restore or deplete health/hunger.
* Fix the interact flag allowing breaking of turtle eggs (now tied directly to block-trampling flag).
* Fix a memory leak that could occur with many many explosives.
* Add regions.titles-always-use-default-times config option. Set this to true if you use greeting/farewell titles and another plugin
makes the titles disappear too quickly.
* Add protection for cauldrons water level changing.
* Improve diagnostic hints and information, such as spawn protection warnings, flag colors in region info, etc.
* Fix waterlogged blocks bypassing water-flow flag.
* Workaround for a CraftBukkit change that made no-physics-sand/gravel non-functional.
* Workaround for CraftBukkit throttling move events.
* Track projectiles shot by dispensers.
* Allowed setting passthrough allow on global to unprotect it if members/owners are added.
* Add support for newer forge clients (FML2) in host keys.
* Allow using WorldEdit's `//world <worldname>` command to select a world for region commands. This removes the need to
use `-w <worldname>` in every command when running commands from console.
* Add a teleport-message flag, shown when using `/rg tp`.
* Add coral-fade flag, which prevents corals from drying when out of water.
* Fix spammy deny-message when walking over redstone ore with certain flag setups.
* Improve handling of interacting with various tools in hand that didn't modify blocks. (eg opening a chest with an axe in hand)
* Fix allow-all-interact option not being read from per-world configs.
* Fix misattribution of pets (eg wolves) in PvP.
* Improve performance of hopper checks when on recent builds of Paper.
* Add event-handling.break-hoppers-on-denied-move config option to prevent hoppers from being broken (but items still won't be moved).
* Note to developers using the WorldGuard API: If you specifically relied on flags such as greeting/farewell, deny-message, etc being
StringFlags, be warned that this will change in a future version to support JSON text components. Please plan accordingly.
## 7.0.2
* Update to MC 1.15. Still compatible with 1.14, and incompatible with 1.13, as before.
* Add an informational message when defining a region that overlaps vanilla spawn protection.
* Protect against pushing a piston with another piston on a region border.
* Protect against buckets in dispensers on region borders.
## 7.0.1
* Add `/rg toggle-bypass` command which temporarily turns off region bypassing until used again.
* More improvements to `/rg flag` and `/rg flags` commands.
+10 -10
View File
@@ -2,16 +2,16 @@
WorldGuard lets you and players guard areas of land against griefers and undesirables, as well as tweak and disable various gameplay features of Minecraft.
* Block creeper and wither block damage, falling damage, etc.;
* Disable fire spread, lava fire spread, ice formation, Endermen picking up blocks, etc.;
* Blacklist certain items and blocks so they can't be used;
* Warn moderators when certain items and blocks are used;
* Protect areas of your world so only certain people can build in them;
* Set areas where PVP, TNT, mob damage, and other features are disabled;
* Protect your server from various 'exploits' like magical obsidian creation machines;
* Disable, or enable, various Minecraft features, like sponges from classic;
* Add useful commands like an immediate "STOP ALL FIRE SPREAD" command.
* Enable only features you want! Everything is off by default.
* Block creeper and wither block damage, falling damage, etc.
* Disable fire spread, lava fire spread, ice formation, Endermen picking up blocks, etc.
* Blacklist certain items and blocks so they can't be used
* Warn moderators when certain items and blocks are used
* Protect areas of your world so only certain people can build in them
* Set areas where PVP, TNT, mob damage, and other features are disabled
* Protect your server from various 'exploits' like magical obsidian creation machines
* Disable, or enable, various Minecraft features, like sponges from classic
* Add useful commands like an immediate "STOP ALL FIRE SPREAD" command
* Enable only features you want! Everything is off by default
WorldGuard is open source and is available under the GNU Lesser
General Public License v3.
+1 -1
View File
@@ -21,6 +21,6 @@ if (!project.hasProperty("gitCommitHash")) {
} catch (e: Exception) {
logger.warn("Error getting commit hash", e)
"no_git_id"
"no.git.id"
}
}
@@ -34,7 +34,7 @@ fun Project.applyRootArtifactoryConfig() {
}
fun Project.applyCommonArtifactoryConfig() {
val named = tasks.named<ArtifactoryTask>("artifactoryPublish") {
tasks.named<ArtifactoryTask>("artifactoryPublish") {
publishConfigs("archives")
}
}
}
+2 -2
View File
@@ -7,12 +7,12 @@ fun Project.applyCommonConfiguration() {
repositories {
mavenCentral()
maven { url = uri("https://maven.sk89q.com/repo/") }
maven { url = uri("https://maven.enginehub.org/repo/") }
maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") }
}
configurations.all {
resolutionStrategy {
cacheChangingModulesFor(5, "minutes")
cacheChangingModulesFor(5, "MINUTES")
}
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ fun Project.applyPlatformAndCoreConfiguration() {
apply(plugin = "com.jfrog.artifactory")
apply(plugin = "net.minecrell.licenser")
ext["internalVersion"] = "$version;${rootProject.ext["gitCommitHash"]}"
ext["internalVersion"] = "$version+${rootProject.ext["gitCommitHash"]}"
configure<JavaPluginConvention> {
sourceCompatibility = JavaVersion.VERSION_1_8
+2 -1
View File
@@ -1,7 +1,8 @@
object Versions {
// const val PISTON = "0.4.3"
// const val AUTO_VALUE = "1.6.5"
const val WORLDEDIT = "7.1.0-SNAPSHOT"
const val WORLDEDIT = "7.2.0-SNAPSHOT"
const val JUNIT = "4.11"
const val SQUIRRELID = "0.2.0"
const val GUAVA = "21.0"
}
+1 -1
View File
@@ -1,2 +1,2 @@
group=com.sk89q.worldguard
version=7.0.2-SNAPSHOT
version=7.0.4
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+17 -1
View File
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ 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"'
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
Vendored
+17 -1
View File
@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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"
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
+9 -8
View File
@@ -24,11 +24,12 @@ repositories {
dependencies {
"compile"(project(":worldguard-core"))
//"compile"(project(":worldguard-libs:bukkit"))
"api"("com.destroystokyo.paper:paper-api:1.15-R0.1-SNAPSHOT")
"implementation"("io.papermc:paperlib:1.0.2")
"api"("com.destroystokyo.paper:paper-api:1.16.2-R0.1-SNAPSHOT")
"implementation"("io.papermc:paperlib:1.0.4")
"api"("com.sk89q.worldedit:worldedit-bukkit:${Versions.WORLDEDIT}") { isTransitive = false }
"implementation"("com.google.guava:guava:${Versions.GUAVA}")
"implementation"("com.sk89q:commandbook:2.3") { isTransitive = false }
"implementation"("org.bstats:bstats-bukkit:1.5")
"implementation"("org.bstats:bstats-bukkit:1.7")
}
tasks.named<Upload>("install") {
@@ -39,8 +40,8 @@ tasks.named<Upload>("install") {
getProperty("groupId") == "com.destroystokyo.paper" && getProperty("artifactId") == "paper-api"
}
}?.withGroovyBuilder {
setProperty("groupId", "org.bukkit")
setProperty("artifactId", "bukkit")
setProperty("groupId", "org.spigotmc")
setProperty("artifactId", "spigot-api")
}
}
}
@@ -61,14 +62,14 @@ tasks.named<Jar>("jar") {
tasks.named<ShadowJar>("shadowJar") {
dependencies {
relocate("org.bstats", "com.sk89q.worldguard.bukkit.bstats") {
include(dependency("org.bstats:bstats-bukkit:1.5"))
include(dependency("org.bstats:bstats-bukkit:1.7"))
}
relocate ("io.papermc.lib", "com.sk89q.worldguard.bukkit.paperlib") {
include(dependency("io.papermc:paperlib:1.0.2"))
include(dependency("io.papermc:paperlib:1.0.4"))
}
}
}
tasks.named("assemble").configure {
dependsOn("shadowJar")
}
}
@@ -24,6 +24,8 @@ import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.weather.WeatherType;
import com.sk89q.worldedit.world.weather.WeatherTypes;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.util.MessagingUtil;
import io.papermc.lib.PaperLib;
import org.bukkit.BanList.Type;
import org.bukkit.Bukkit;
@@ -172,7 +174,11 @@ public class BukkitPlayer extends com.sk89q.worldedit.bukkit.BukkitPlayer implem
@Override
public void sendTitle(String title, String subtitle) {
getPlayer().sendTitle(title, subtitle, -1, -1, -1);
if (WorldGuard.getInstance().getPlatform().getGlobalStateManager().get(getWorld()).forceDefaultTitleTimes) {
getPlayer().sendTitle(title, subtitle, 10, 70, 20);
} else {
getPlayer().sendTitle(title, subtitle, -1, -1, -1);
}
}
@Override
@@ -185,7 +191,10 @@ public class BukkitPlayer extends com.sk89q.worldedit.bukkit.BukkitPlayer implem
PaperLib.teleportAsync(getPlayer(), BukkitAdapter.adapt(location))
.thenApply(success -> {
if (success) {
print(successMessage);
// The success message can be cleared via flag
if (!successMessage.isEmpty()) {
MessagingUtil.sendStringToChat(this, successMessage);
}
} else {
printError(failMessage);
}
@@ -40,7 +40,7 @@ import com.sk89q.worldguard.chest.ChestProtection;
import com.sk89q.worldguard.commands.CommandUtils;
import com.sk89q.worldguard.config.YamlWorldConfiguration;
import org.bukkit.potion.PotionEffectType;
import org.yaml.snakeyaml.parser.ParserException;
import org.yaml.snakeyaml.error.YAMLException;
import java.io.File;
import java.io.FileNotFoundException;
@@ -105,6 +105,13 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
if (inputs == null || inputs.isEmpty()) {
parentConfig.setProperty(node, new ArrayList<String>());
}
if (config.getProperty(node) != null) {
inputs = config.getStringList(node, null);
}
if (inputs == null || inputs.isEmpty()) {
return set;
}
@@ -128,7 +135,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
config.load();
} catch (IOException e) {
log.log(Level.SEVERE, "Error reading configuration for world " + worldName + ": ", e);
} catch (ParserException e) {
} catch (YAMLException e) {
log.severe("Error parsing configuration for world " + worldName + ". ");
throw e;
}
@@ -144,6 +151,7 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
allowAllInteract = getTargetMatchers("event-handling.interaction-whitelist");
blockUseAtFeet = getTargetMatchers("event-handling.emit-block-use-at-feet");
ignoreHopperMoveEvents = getBoolean("event-handling.ignore-hopper-item-move-events", false);
breakDeniedHoppers = getBoolean("event-handling.break-hoppers-on-denied-move", true);
usePaperEntityOrigin = getBoolean("regions.use-paper-entity-origin", false);
@@ -152,6 +160,8 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableExpDrops = getBoolean("protection.disable-xp-orb-drops", false);
disableObsidianGenerators = getBoolean("protection.disable-obsidian-generators", false);
useMaxPriorityAssociation = getBoolean("protection.use-max-priority-association", false);
blockPotions = new HashSet<>();
for (String potionName : getStringList("gameplay.block-potions", null)) {
PotionEffectType effect = PotionEffectType.getByName(potionName);
@@ -230,6 +240,9 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
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);
disallowedLightningBlocks = new HashSet<>(convertLegacyBlocks(getStringList("weather.prevent-lightning-strike-blocks", null)));
preventLightningFire = getBoolean("weather.disable-lightning-strike-fire", false);
disableThunder = getBoolean("weather.disable-thunderstorm", false);
@@ -251,12 +264,14 @@ public class BukkitWorldConfiguration extends YamlWorldConfiguration {
disableVineGrowth = getBoolean("dynamics.disable-vine-growth", false);
disableCropGrowth = getBoolean("dynamics.disable-crop-growth", false);
disableSoilDehydration = getBoolean("dynamics.disable-soil-dehydration", false);
disableCoralBlockFade = getBoolean("dynamics.disable-coral-block-fade", false);
allowedSnowFallOver = new HashSet<>(convertLegacyBlocks(getStringList("dynamics.snow-fall-blocks", null)));
useRegions = getBoolean("regions.enable", true);
regionInvinciblityRemovesMobs = getBoolean("regions.invincibility-removes-mobs", false);
regionCancelEmptyChatEvents = getBoolean("regions.cancel-chat-without-recipients", true);
regionNetherPortalProtection = getBoolean("regions.nether-portal-protection", false);
regionNetherPortalProtection = getBoolean("regions.nether-portal-protection", true);
forceDefaultTitleTimes = config.getBoolean("regions.titles-always-use-default-times", true); // note: technically not region-specific, but we only use it for the title flags
fakePlayerBuildOverride = getBoolean("regions.fake-player-build-override", true);
explosionFlagCancellation = getBoolean("regions.explosion-flags-block-entity-damage", true);
highFreqFlags = getBoolean("regions.high-frequency-flags", false);
@@ -20,7 +20,6 @@
package com.sk89q.worldguard.bukkit;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import com.sk89q.bukkit.util.CommandsManagerRegistration;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
@@ -93,9 +92,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
/**
* The main class for WorldGuard as a Bukkit plugin.
@@ -214,7 +212,7 @@ public class WorldGuardPlugin extends JavaPlugin {
((SimpleFlagRegistry) WorldGuard.getInstance().getFlagRegistry()).setInitialized(true);
// Enable metrics
final Metrics metrics = new Metrics(this);
final Metrics metrics = new Metrics(this, 3283); // bStats plugin id
if (metrics.isEnabled() && platform.getGlobalStateManager().extraStats) {
setupCustomCharts(metrics);
}
@@ -488,44 +486,25 @@ public class WorldGuardPlugin extends JavaPlugin {
return;
}
InputStream input = null;
try {
JarFile file = new JarFile(getFile());
ZipEntry copy = file.getEntry("defaults/" + defaultName);
if (copy == null) throw new FileNotFoundException();
input = file.getInputStream(copy);
try (InputStream stream = getResource("defaults/" + defaultName)){
if (stream == null) throw new FileNotFoundException();
copyDefaultConfig(stream, actual, defaultName);
} catch (IOException e) {
WorldGuard.logger.severe("Unable to read default configuration: " + defaultName);
getLogger().severe("Unable to read default configuration: " + defaultName);
}
if (input != null) {
FileOutputStream output = null;
}
try {
output = new FileOutputStream(actual);
byte[] buf = new byte[8192];
int length = 0;
while ((length = input.read(buf)) > 0) {
output.write(buf, 0, length);
}
WorldGuard.logger.info("Default configuration file written: "
+ actual.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
input.close();
} catch (IOException ignore) {
}
try {
if (output != null) {
output.close();
}
} catch (IOException ignore) {
}
private void copyDefaultConfig(InputStream input, File actual, String name) {
try (FileOutputStream output = new FileOutputStream(actual)) {
byte[] buf = new byte[8192];
int length;
while ((length = input.read(buf)) > 0) {
output.write(buf, 0, length);
}
getLogger().info("Default configuration file written: " + name);
} catch (IOException e) {
getLogger().log(Level.WARNING, "Failed to write default config file", e);
}
}
@@ -36,6 +36,8 @@ import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Vehicle;
import org.bukkit.metadata.Metadatable;
import org.bukkit.projectiles.BlockProjectileSource;
import org.bukkit.projectiles.ProjectileSource;
import javax.annotation.Nullable;
import java.util.ArrayList;
@@ -236,6 +238,15 @@ public final class Cause {
WGMetadata.put(target, CAUSE_KEY, parent);
}
/**
* Remove a parent cause from a {@code Metadatable} object.
*
* @param target the target
*/
public static void untrackParentCause(Metadatable target) {
WGMetadata.remove(target, CAUSE_KEY);
}
/**
* Builds causes.
*/
@@ -260,13 +271,15 @@ public final class Cause {
if (o instanceof TNTPrimed) {
addAll(((TNTPrimed) o).getSource());
} else if (o instanceof Projectile) {
addAll(((Projectile) o).getShooter());
} else if (o instanceof Firework && PaperLib.isPaper()) {
UUID spawningUUID = ((Firework) o).getSpawningEntity();
if (spawningUUID != null) {
Entity spawningEntity = Bukkit.getEntity(spawningUUID);
if (spawningEntity != null) {
addAll(spawningEntity);
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) {
@@ -274,12 +287,14 @@ public final class Cause {
} else if (o instanceof AreaEffectCloud) {
indirect = true;
addAll(((AreaEffectCloud) o).getSource());
} else if (o instanceof Creature && ((Creature) o).getTarget() != null) {
indirect = true;
addAll(((Creature) o).getTarget());
} 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
@@ -75,4 +75,13 @@ public final class WGMetadata {
return null;
}
/**
* Removes metadata from the target.
*
* @param target the target
* @param key the key
*/
public static void remove(Metadatable target, String key) {
target.removeMetadata(key, WorldGuardPlugin.inst());
}
}
@@ -31,7 +31,7 @@ import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.config.ConfigurationManager;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.DelayedRegionOverlapAssociation;
import com.sk89q.worldguard.protection.association.DelayedRegionOverlapAssociation;
import com.sk89q.worldguard.protection.association.Associables;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.regions.RegionQuery;
@@ -127,9 +127,10 @@ class AbstractListener implements Listener {
} else if (rootCause instanceof Entity) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
final Entity entity = (Entity) rootCause;
BukkitWorldConfiguration config =
(BukkitWorldConfiguration) getWorldConfig(BukkitAdapter.adapt(entity.getWorld()));
Location loc;
if (PaperLib.isPaper()
&& ((BukkitWorldConfiguration) getWorldConfig(BukkitAdapter.adapt(entity.getWorld()))).usePaperEntityOrigin) {
if (PaperLib.isPaper() && config.usePaperEntityOrigin) {
loc = entity.getOrigin();
if (loc == null) {
loc = entity.getLocation();
@@ -137,10 +138,13 @@ class AbstractListener implements Listener {
} else {
loc = entity.getLocation();
}
return new DelayedRegionOverlapAssociation(query, BukkitAdapter.adapt(loc));
return new DelayedRegionOverlapAssociation(query, BukkitAdapter.adapt(loc),
config.useMaxPriorityAssociation);
} else if (rootCause instanceof Block) {
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
return new DelayedRegionOverlapAssociation(query, BukkitAdapter.adapt(((Block) rootCause).getLocation()));
Location loc = ((Block) rootCause).getLocation();
return new DelayedRegionOverlapAssociation(query, BukkitAdapter.adapt(loc),
getWorldConfig(BukkitAdapter.adapt(loc.getWorld())).useMaxPriorityAssociation);
} else {
return Associables.constant(Association.NON_MEMBER);
}
@@ -61,6 +61,7 @@ import org.bukkit.block.Chest;
import org.bukkit.block.DoubleChest;
import org.bukkit.block.Hopper;
import org.bukkit.block.PistonMoveReaction;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Dispenser;
import org.bukkit.entity.AreaEffectCloud;
@@ -72,8 +73,10 @@ import org.bukkit.entity.Firework;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.minecart.HopperMinecart;
import org.bukkit.event.Cancellable;
@@ -94,6 +97,7 @@ import org.bukkit.event.block.BlockMultiPlaceEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.CauldronLevelChangeEvent;
import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.entity.AreaEffectCloudApplyEvent;
@@ -135,6 +139,7 @@ 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.projectiles.ProjectileSource;
@@ -154,6 +159,17 @@ 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.
*
@@ -228,7 +244,7 @@ public class EventAbstractionListener extends AbstractListener {
boolean allowed = false;
for (Block source : adjacent) {
if (source.getType() == Material.FIRE) {
if (Materials.isFire(source.getType())) {
found++;
if (Events.fireAndTestCancel(new BreakBlockEvent(event, create(source), target))) {
source.setType(Material.AIR);
@@ -270,14 +286,24 @@ public class EventAbstractionListener extends AbstractListener {
boolean trample = fromType == Material.FARMLAND && toType == Material.DIRT;
BreakBlockEvent breakDelagate = new BreakBlockEvent(event, cause, block);
if (trample) {
breakDelagate.setSilent(true);
breakDelagate.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
} else if (fromType == Material.REDSTONE_ORE) {
breakDelagate.setSilent(true);
}
if (!Events.fireToCancel(event, breakDelagate)) {
boolean denied;
if (!(denied = Events.fireToCancel(event, breakDelagate))) {
PlaceBlockEvent placeDelegate = new PlaceBlockEvent(event, cause, block.getLocation(), toType);
if (trample) {
placeDelegate.setSilent(true);
placeDelegate.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
} else if (fromType == Material.REDSTONE_ORE) {
placeDelegate.setSilent(true);
}
Events.fireToCancel(event, placeDelegate);
denied = Events.fireToCancel(event, placeDelegate);
}
if (denied && entity instanceof Player) {
playDenyEffect((Player) entity, block.getLocation());
}
} else {
if (toType == Material.AIR) {
@@ -296,15 +322,22 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, block.getLocation(), toType));
if (event.isCancelled() && !wasCancelled && entity instanceof FallingBlock) {
FallingBlock fallingBlock = (FallingBlock) entity;
final Material material = fallingBlock.getBlockData().getMaterial();
if (!material.isItem()) return;
ItemStack itemStack = new ItemStack(material, 1);
Item item = block.getWorld().dropItem(fallingBlock.getLocation(), itemStack);
item.setVelocity(new Vector());
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(block, entity), item))) {
item.remove();
if (entity instanceof FallingBlock) {
try {
if (event.isCancelled() && !wasCancelled) {
FallingBlock fallingBlock = (FallingBlock) entity;
if (!fallingBlock.getDropItem()) return;
final Material material = fallingBlock.getBlockData().getMaterial();
if (!material.isItem()) return;
ItemStack itemStack = new ItemStack(material, 1);
Item item = block.getWorld().dropItem(fallingBlock.getLocation(), itemStack);
item.setVelocity(new Vector());
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(block, entity), item))) {
item.remove();
}
}
} finally {
Cause.untrackParentCause(entity);
}
}
}
@@ -315,6 +348,9 @@ public class EventAbstractionListener extends AbstractListener {
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 (entity instanceof Creeper) {
Cause.untrackParentCause(entity);
}
}
@EventHandler(ignoreCancelled = true)
@@ -332,6 +368,7 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, cause, event.getBlock().getWorld(), blocks, Material.AIR));
if (originalSize != blocks.size()) {
event.setCancelled(true);
return;
}
for (Block b : blocks) {
Location loc = b.getRelative(direction).getLocation();
@@ -351,8 +388,14 @@ public class EventAbstractionListener extends AbstractListener {
public void onBlockPistonExtend(BlockPistonExtendEvent event) {
EventDebounce.Entry entry = pistonExtendDebounce.getIfNotPresent(new BlockPistonExtendKey(event), event);
if (entry != null) {
Cause cause = create(event.getBlock());
List<Block> blocks = new ArrayList<>(event.getBlocks());
int originalLength = blocks.size();
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, cause, event.getBlock().getWorld(), blocks, Material.AIR));
if (originalLength != blocks.size()) {
event.setCancelled(true);
return;
}
BlockFace dir = event.getDirection();
for (int i = 0; i < blocks.size(); i++) {
Block existing = blocks.get(i);
@@ -362,7 +405,7 @@ public class EventAbstractionListener extends AbstractListener {
blocks.set(i, existing.getRelative(dir));
}
}
Events.fireBulkEventToCancel(event, new PlaceBlockEvent(event, create(event.getBlock()), event.getBlock().getWorld(), blocks, Material.STONE));
Events.fireBulkEventToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getWorld(), blocks, Material.STONE));
if (blocks.size() != originalLength) {
event.setCancelled(true);
}
@@ -395,23 +438,37 @@ public class EventAbstractionListener extends AbstractListener {
@Nullable ItemStack item = event.getItem();
Block clicked = event.getClickedBlock();
Block placed;
boolean silent = false;
boolean modifiesWorld;
Cause cause = create(player);
switch (event.getAction()) {
case PHYSICAL:
if (event.useInteractedBlock() != Result.DENY) {
if (clicked.getType() == Material.FARMLAND || clicked.getType() == Material.TURTLE_EGG) {
BreakBlockEvent breakDelagate = new BreakBlockEvent(event, cause, clicked);
breakDelagate.setSilent(true);
breakDelagate.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
boolean denied;
if (!(denied = Events.fireToCancel(event, breakDelagate))) {
PlaceBlockEvent placeDelegate = new PlaceBlockEvent(event, cause, clicked.getLocation(),
clicked.getType() == Material.FARMLAND ? Material.DIRT : clicked.getType());
placeDelegate.setSilent(true);
placeDelegate.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
denied = Events.fireToCancel(event, placeDelegate);
}
if (denied) {
playDenyEffect(player, clicked.getLocation());
}
return;
}
DelegateEvent firedEvent = new UseBlockEvent(event, cause, clicked).setAllowed(hasInteractBypass(clicked));
if (clicked.getType() == Material.REDSTONE_ORE) {
silent = true;
firedEvent.setSilent(true);
}
if (clicked.getType() == Material.FARMLAND || clicked.getType() == Material.TURTLE_EGG) {
silent = true;
firedEvent.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
}
firedEvent.setSilent(silent);
interactDebounce.debounce(clicked, event.getPlayer(), event, firedEvent);
if (event.useInteractedBlock() == Result.DENY) {
playDenyEffect(player, clicked.getLocation().add(0, 1, 0));
}
}
break;
@@ -453,7 +510,7 @@ public class EventAbstractionListener extends AbstractListener {
}
// Special handling of putting out fires
if (event.getAction() == Action.LEFT_CLICK_BLOCK && placed.getType() == Material.FIRE) {
if (event.getAction() == Action.LEFT_CLICK_BLOCK && Materials.isFire(placed.getType())) {
if (Events.fireAndTestCancel(new BreakBlockEvent(event, create(event.getPlayer()), placed))) {
event.setUseInteractedBlock(Result.DENY);
break;
@@ -704,7 +761,7 @@ public class EventAbstractionListener extends AbstractListener {
event.setCancelled(true);
}
} else if (event.getState() == PlayerFishEvent.State.CAUGHT_FISH) {
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getPlayer(), event.getHook()), event.getHook().getLocation(), EntityType.EXPERIENCE_ORB))) {
if (event.getExpToDrop() > 0 && Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getPlayer(), event.getHook()), event.getHook().getLocation(), EntityType.EXPERIENCE_ORB))) {
event.setExpToDrop(0);
}
} else if (event.getState() == PlayerFishEvent.State.CAUGHT_ENTITY) {
@@ -793,7 +850,11 @@ public class EventAbstractionListener extends AbstractListener {
} else if (damager instanceof Creeper) {
eventToFire.getRelevantFlags().add(Flags.CREEPER_EXPLOSION);
}
Events.fireToCancel(event, eventToFire);
if (Events.fireToCancel(event, eventToFire)) {
if (damager instanceof Tameable && damager instanceof Mob) {
((Mob) damager).setTarget(null);
}
}
// Item use event with the item in hand
// Older blacklist handler code used this, although it suffers from
@@ -874,21 +935,35 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onInventoryMoveItem(InventoryMoveItemEvent event) {
final InventoryHolder causeHolder = event.getInitiator().getHolder();
InventoryHolder causeHolder;
if (HAS_SNAPSHOT_INVHOLDER) {
causeHolder = event.getInitiator().getHolder(false);
} else {
causeHolder = event.getInitiator().getHolder();
}
WorldConfiguration wcfg = null;
if (causeHolder instanceof Hopper
&& getWorldConfig(BukkitAdapter.adapt((((Hopper) causeHolder).getWorld()))).ignoreHopperMoveEvents) {
&& (wcfg = getWorldConfig(BukkitAdapter.adapt((((Hopper) causeHolder).getWorld())))).ignoreHopperMoveEvents) {
return;
} else if (causeHolder instanceof HopperMinecart
&& getWorldConfig(BukkitAdapter.adapt((((HopperMinecart) causeHolder).getWorld()))).ignoreHopperMoveEvents) {
&& (wcfg = getWorldConfig(BukkitAdapter.adapt((((HopperMinecart) causeHolder).getWorld())))).ignoreHopperMoveEvents) {
return;
}
Entry entry;
if ((entry = moveItemDebounce.tryDebounce(event)) != null) {
InventoryHolder sourceHolder = event.getSource().getHolder();
InventoryHolder targetHolder = event.getDestination().getHolder();
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();
}
Cause cause;
if (causeHolder instanceof Entity) {
@@ -905,7 +980,7 @@ public class EventAbstractionListener extends AbstractListener {
handleInventoryHolderUse(event, cause, targetHolder);
if (event.isCancelled() && causeHolder instanceof Hopper) {
if (event.isCancelled() && causeHolder instanceof Hopper && wcfg.breakDeniedHoppers) {
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(),
() -> ((Hopper) causeHolder).getBlock().breakNaturally());
} else {
@@ -952,15 +1027,18 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onBlockDispense(BlockDispenseEvent event) {
Cause cause = create(event.getBlock());
Block dispenserBlock = event.getBlock();
ItemStack item = event.getItem();
Events.fireToCancel(event, new UseItemEvent(event, cause, dispenserBlock.getWorld(), item));
// Simulate right click event as players have it
if (dispenserBlock.getBlockData() instanceof Dispenser) {
Dispenser dispenser = (Dispenser) dispenserBlock.getBlockData();
if (dispenserBlock.getType() == Material.DISPENSER) {
Cause cause = create(event.getBlock());
ItemStack item = event.getItem();
if (Events.fireToCancel(event, new UseItemEvent(event, cause, dispenserBlock.getWorld(), item))) {
return;
}
BlockData blockData = dispenserBlock.getBlockData();
Dispenser dispenser = (Dispenser) blockData; // if this ClassCastExceptions it's a bukkit bug
Block placed = dispenserBlock.getRelative(dispenser.getFacing());
Block clicked = placed.getRelative(dispenser.getFacing());
handleBlockRightClick(event, cause, item, clicked, placed);
@@ -1010,10 +1088,17 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onTakeLecternBook(PlayerTakeLecternBookEvent event) {
final UseBlockEvent useEvent = new UseBlockEvent(event, create(event.getPlayer()), event.getLectern().getBlock());
useEvent.getRelevantFlags().add(Flags.CHEST_ACCESS);
Events.fireToCancel(event, useEvent);
}
@EventHandler(ignoreCancelled = true)
public void onCauldronLevelChange(CauldronLevelChangeEvent event) {
if (event.getEntity() == null) return;
interactDebounce.debounce(event.getBlock(), event.getEntity(), event,
new UseBlockEvent(event, create(event.getEntity()),
event.getBlock()).setAllowed(hasInteractBypass(event.getBlock())));
}
/**
* Handle the right click of a block while an item is held.
*
@@ -35,6 +35,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
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;
@@ -77,6 +78,14 @@ public class PlayerMoveListener implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerMove(PlayerMoveEvent event) {
Location from = event.getFrom();
Location to = event.getTo();
if (from.getBlockX() == to.getBlockX()
&& from.getBlockY() == to.getBlockY()
&& from.getBlockZ() == to.getBlockZ()) {
return;
}
final Player player = event.getPlayer();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
@@ -89,15 +98,15 @@ public class PlayerMoveListener implements Listener {
} else if (event.getPlayer().getVehicle() != null && event.getPlayer().getVehicle() instanceof Horse) {
moveType = MoveType.RIDE;
}
com.sk89q.worldedit.util.Location weLocation = session.testMoveTo(localPlayer, BukkitAdapter.adapt(event.getTo()), moveType);
com.sk89q.worldedit.util.Location weLocation = session.testMoveTo(localPlayer, BukkitAdapter.adapt(to), moveType);
if (weLocation != null) {
final Location override = BukkitAdapter.adapt(weLocation);
override.setX(override.getBlockX() + 0.5);
override.setY(override.getBlockY());
override.setZ(override.getBlockZ() + 0.5);
override.setPitch(event.getTo().getPitch());
override.setYaw(event.getTo().getYaw());
override.setPitch(to.getPitch());
override.setYaw(to.getYaw());
event.setTo(override.clone());
@@ -124,4 +133,16 @@ public class PlayerMoveListener implements Listener {
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
final Player player = event.getPlayer();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
Session session = WorldGuard.getInstance().getPlatform().getSessionManager().get(localPlayer);
com.sk89q.worldedit.util.Location loc = session.testMoveTo(localPlayer,
BukkitAdapter.adapt(event.getPlayer().getLocation()), MoveType.OTHER_CANCELLABLE); // white lie
if (loc != null) {
player.teleport(BukkitAdapter.adapt(loc));
}
}
}
@@ -41,7 +41,6 @@ import com.sk89q.worldguard.bukkit.util.InteropUtils;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.commands.CommandUtils;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
@@ -59,8 +58,10 @@ import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
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.player.PlayerTakeLecternBookEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
import java.util.ArrayList;
@@ -171,9 +172,9 @@ public class RegionProtectionListener extends AbstractListener {
String what;
/* Flint and steel, fire charge, etc. */
if (type == Material.FIRE) {
if (Materials.isFire(type)) {
Block block = event.getCause().getFirstBlock();
boolean fire = block != null && block.getType() == Material.FIRE;
boolean fire = block != null && Materials.isFire(type);
boolean lava = block != null && Materials.isLava(block.getType());
List<StateFlag> flags = new ArrayList<>();
flags.add(Flags.BLOCK_PLACE);
@@ -259,14 +260,24 @@ public class RegionProtectionListener extends AbstractListener {
/* Inventory */
} else if (Materials.isInventoryBlock(type)) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.INTERACT, Flags.CHEST_ACCESS));
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.CHEST_ACCESS));
what = "open that";
/* Inventory for blocks with the possibility to be only use, e.g. lectern */
} else if (handleAsInventoryUsage(event.getOriginalEvent())) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.CHEST_ACCESS));
what = "take that";
/* Beds */
} else if (Materials.isBed(type)) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.INTERACT, Flags.SLEEP));
what = "sleep";
/* Respawn Anchors */
} else if(type == Material.RESPAWN_ANCHOR) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.INTERACT, Flags.RESPAWN_ANCHORS));
what = "use anchors";
/* TNT */
} else if (type == Material.TNT) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.INTERACT, Flags.TNT));
@@ -329,12 +340,7 @@ public class RegionProtectionListener extends AbstractListener {
/* Everything else */
} else {
canSpawn = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event));
if (event.getEntity() instanceof Item) {
what = "drop items";
} else {
what = "place things";
}
what = "place things";
}
if (!canSpawn) {
@@ -553,4 +559,14 @@ public class RegionProtectionListener extends AbstractListener {
return flags;
}
/**
* Check if that event should be handled as inventory usage, e.g. if a player takes a book from a lectern
*
* @param event the event to handle
* @return whether it should be handled as inventory usage
*/
private static boolean handleAsInventoryUsage(Event event) {
return event instanceof PlayerTakeLecternBookEvent;
}
}
@@ -34,6 +34,7 @@ import com.sk89q.worldguard.util.SpongeUtil;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.entity.Player;
import org.bukkit.entity.Snowman;
import org.bukkit.event.EventHandler;
@@ -131,9 +132,10 @@ public class WorldGuardBlockListener implements Listener {
Block blockFrom = event.getBlock();
Block blockTo = event.getToBlock();
boolean isWater = blockFrom.getType() == Material.WATER;
boolean isLava = blockFrom.getType() == Material.LAVA;
boolean isAir = blockFrom.getType() == Material.AIR;
Material fromType = blockFrom.getType();
boolean isWater = Materials.isWater(fromType);
boolean isLava = fromType == Material.LAVA;
boolean isAir = fromType == Material.AIR;
ConfigurationManager cfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager();
WorldConfiguration wcfg = getWorldConfig(event.getBlock().getWorld());
@@ -194,7 +196,7 @@ public class WorldGuardBlockListener implements Listener {
}
}
if (wcfg.highFreqFlags && isWater
if (wcfg.highFreqFlags && (isWater || blockFrom.getBlockData() instanceof Waterlogged)
&& WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().queryState(BukkitAdapter.adapt(blockFrom.getLocation()), (RegionAssociable) null, Flags.WATER_FLOW) == StateFlag.State.DENY) {
event.setCancelled(true);
return;
@@ -205,13 +207,6 @@ public class WorldGuardBlockListener implements Listener {
event.setCancelled(true);
return;
}
if (wcfg.disableObsidianGenerators && (isAir || isLava)
&& (blockTo.getType() == Material.REDSTONE_WIRE
|| blockTo.getType() == Material.TRIPWIRE)) {
blockTo.setType(Material.AIR);
return;
}
}
/*
@@ -326,7 +321,7 @@ public class WorldGuardBlockListener implements Listener {
if (wcfg.fireSpreadDisableToggle) {
Block block = event.getBlock();
event.setCancelled(true);
checkAndDestroyAround(block.getWorld(), block.getX(), block.getY(), block.getZ(), Material.FIRE);
checkAndDestroyFireAround(block.getWorld(), block.getX(), block.getY(), block.getZ());
return;
}
@@ -335,7 +330,7 @@ public class WorldGuardBlockListener implements Listener {
if (wcfg.disableFireSpreadBlocks.contains(BukkitAdapter.asBlockType(block.getType()).getId())) {
event.setCancelled(true);
checkAndDestroyAround(block.getWorld(), block.getX(), block.getY(), block.getZ(), Material.FIRE);
checkAndDestroyFireAround(block.getWorld(), block.getX(), block.getY(), block.getZ());
return;
}
}
@@ -354,24 +349,24 @@ public class WorldGuardBlockListener implements Listener {
WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(block.getLocation()));
if (!set.testState(null, Flags.FIRE_SPREAD)) {
checkAndDestroyAround(block.getWorld(), x, y, z, Material.FIRE);
checkAndDestroyFireAround(block.getWorld(), x, y, z);
event.setCancelled(true);
}
}
}
private void checkAndDestroyAround(World world, int x, int y, int z, Material required) {
checkAndDestroy(world, x, y, z + 1, required);
checkAndDestroy(world, x, y, z - 1, required);
checkAndDestroy(world, x, y + 1, z, required);
checkAndDestroy(world, x, y - 1, z, required);
checkAndDestroy(world, x + 1, y, z, required);
checkAndDestroy(world, x - 1, y, z, required);
private void checkAndDestroyFireAround(World world, int x, int y, int z) {
checkAndDestroyFire(world, x, y, z + 1);
checkAndDestroyFire(world, x, y, z - 1);
checkAndDestroyFire(world, x, y + 1, z);
checkAndDestroyFire(world, x, y - 1, z);
checkAndDestroyFire(world, x + 1, y, z);
checkAndDestroyFire(world, x - 1, y, z);
}
private void checkAndDestroy(World world, int x, int y, int z, Material required) {
if (world.getBlockAt(x, y, z).getType() == required) {
private void checkAndDestroyFire(World world, int x, int y, int z) {
if (Materials.isFire(world.getBlockAt(x, y, z).getType())) {
world.getBlockAt(x, y, z).setType(Material.AIR);
}
}
@@ -603,7 +598,7 @@ public class WorldGuardBlockListener implements Listener {
}
}
if (newType == Material.VINE || newType == Material.KELP) {
if (Materials.isVine(newType)) {
if (wcfg.disableVineGrowth) {
event.setCancelled(true);
return;
@@ -682,6 +677,16 @@ public class WorldGuardBlockListener implements Listener {
event.setCancelled(true);
return;
}
} else if (Materials.isCoral(event.getBlock().getType())) {
if (wcfg.disableCoralBlockFade) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && !StateFlag.test(WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery()
.queryState(BukkitAdapter.adapt(event.getBlock().getLocation()), (RegionAssociable) null, Flags.CORAL_FADE))) {
event.setCancelled(true);
return;
}
}
}
@@ -47,7 +47,9 @@ import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@@ -74,8 +76,10 @@ import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityInteractEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.entity.EntityTransformEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.entity.PigZapEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.world.PortalCreateEvent;
@@ -117,11 +121,13 @@ public class WorldGuardEntityListener implements Listener {
ConfigurationManager cfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(BukkitAdapter.adapt(entity.getWorld()));
if (block.getType() == Material.FARMLAND) {
if (/* entity instanceof Creature && // catch for any entity (not thrown for players) */
wcfg.disableCreatureCropTrampling) {
event.setCancelled(true);
}
if (block.getType() == Material.FARMLAND && wcfg.disableCreatureCropTrampling) {
event.setCancelled(true);
return;
}
if (block.getType() == Material.TURTLE_EGG && wcfg.disableCreatureTurtleEggTrampling) {
event.setCancelled(true);
return;
}
}
@@ -748,6 +754,10 @@ public class WorldGuardEntityListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityRegainHealth(EntityRegainHealthEvent event) {
RegainReason regainReason = event.getRegainReason();
if (regainReason != RegainReason.REGEN && regainReason != RegainReason.SATIATED) {
return;
}
Entity ent = event.getEntity();
World world = ent.getWorld();
@@ -759,6 +769,31 @@ public class WorldGuardEntityListener implements Listener {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && ent instanceof Player
&& !WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().testState(
BukkitAdapter.adapt(ent.getLocation()),
WorldGuardPlugin.inst().wrapPlayer((Player) ent),
Flags.HEALTH_REGEN)) {
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onFoodChange(FoodLevelChangeEvent event) {
if (event.getItem() != null) return;
HumanEntity ent = event.getEntity();
if (!(ent instanceof Player)) return;
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer((Player) ent);
if (event.getFoodLevel() > player.getFoodLevel()) return;
ConfigurationManager cfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
if (wcfg.useRegions
&& !WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery().testState(
player.getLocation(), player, Flags.HUNGER_DRAIN)) {
event.setCancelled(true);
}
}
/**
@@ -774,7 +809,19 @@ public class WorldGuardEntityListener implements Listener {
ConfigurationManager cfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(BukkitAdapter.adapt(ent.getWorld()));
if (ent instanceof Enderman) {
if (ent instanceof FallingBlock) {
Material id = event.getBlock().getType();
if (id == Material.GRAVEL && wcfg.noPhysicsGravel) {
event.setCancelled(true);
return;
}
if (id == Material.SAND && wcfg.noPhysicsSand) {
event.setCancelled(true);
return;
}
} else if (ent instanceof Enderman) {
if (wcfg.disableEndermanGriefing) {
event.setCancelled(true);
return;
@@ -38,6 +38,7 @@ import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.GameModeFlag;
import com.sk89q.worldguard.util.Entities;
import com.sk89q.worldguard.util.command.CommandFilter;
import com.sk89q.worldguard.util.profile.Profile;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
@@ -147,6 +148,8 @@ public class WorldGuardPlayerListener implements Listener {
}
Events.fire(new ProcessPlayerEvent(player));
WorldGuard.getInstance().getExecutorService().submit(() ->
WorldGuard.getInstance().getProfileCache().put(new Profile(player.getUniqueId(), player.getName())));
}
@EventHandler(ignoreCancelled = true)
@@ -199,7 +202,8 @@ public class WorldGuardPlayerListener implements Listener {
}
if (!hostname.equals(hostKey)
&& !(cfg.hostKeysAllowFMLClients && hostname.equals(hostKey + "\u0000FML\u0000"))) {
&& !(cfg.hostKeysAllowFMLClients &&
(hostname.equals(hostKey + "\u0000FML\u0000") || hostname.equals(hostKey + "\u0000FML2\u0000")))) {
event.disallow(PlayerLoginEvent.Result.KICK_OTHER,
"You did not join with the valid host key!");
log.warning("WorldGuard host key check: " +
@@ -310,13 +314,17 @@ public class WorldGuardPlayerListener implements Listener {
Player player = event.getPlayer();
Block block = event.getClickedBlock(); //not actually clicked but whatever
//int type = block.getTypeId();
Material type = block.getType();
World world = player.getWorld();
ConfigurationManager cfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(BukkitAdapter.adapt(world));
if (block.getType() == Material.FARMLAND && wcfg.disablePlayerCropTrampling) {
if (type == Material.FARMLAND && wcfg.disablePlayerCropTrampling) {
event.setCancelled(true);
return;
}
if (type == Material.TURTLE_EGG && wcfg.disablePlayerTurtleEggTrampling) {
event.setCancelled(true);
return;
}
@@ -27,7 +27,6 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
import com.sk89q.worldguard.session.AbstractSessionManager;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.util.profile.Profile;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -62,8 +61,6 @@ public class BukkitSessionManager extends AbstractSessionManager implements Runn
// Pre-load a session
LocalPlayer player = WorldGuardPlugin.inst().wrapPlayer(event.getPlayer());
get(player).initialize(player);
WorldGuard.getInstance().getExecutorService().submit(() ->
WorldGuard.getInstance().getProfileCache().put(new Profile(player.getUniqueId(), player.getName())));
}
@Override
@@ -33,12 +33,12 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Monster;
import org.bukkit.entity.NPC;
import org.bukkit.entity.Pig;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Shulker;
import org.bukkit.entity.Slime;
import org.bukkit.entity.SpectralArrow;
import org.bukkit.entity.Steerable;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Vehicle;
@@ -91,7 +91,7 @@ public final class Entities {
* @return true if the entity can be ridden
*/
public static boolean isRiddenOnUse(Entity entity) {
return entity instanceof Pig ? ((Pig) entity).hasSaddle() : entity instanceof Vehicle;
return entity instanceof Steerable ? ((Steerable) entity).hasSaddle() : entity instanceof Vehicle;
}
/**
@@ -140,7 +140,7 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.FIRE, 0);
MATERIAL_FLAGS.put(Material.SPAWNER, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CHEST, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REDSTONE_WIRE, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_WIRE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DIAMOND_ORE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_BLOCK, 0);
MATERIAL_FLAGS.put(Material.CRAFTING_TABLE, 0);
@@ -161,7 +161,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.CACTUS, 0);
MATERIAL_FLAGS.put(Material.CLAY, 0);
MATERIAL_FLAGS.put(Material.JUKEBOX, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.OAK_FENCE, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN, 0);
MATERIAL_FLAGS.put(Material.NETHERRACK, 0);
MATERIAL_FLAGS.put(Material.SOUL_SAND, 0);
@@ -195,17 +194,10 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.PUMPKIN_STEM, 0);
MATERIAL_FLAGS.put(Material.MELON_STEM, 0);
MATERIAL_FLAGS.put(Material.VINE, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.ACACIA_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BIRCH_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DARK_OAK_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.JUNGLE_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.OAK_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BRICK_STAIRS, 0);
MATERIAL_FLAGS.put(Material.MYCELIUM, 0);
MATERIAL_FLAGS.put(Material.LILY_PAD, 0);
MATERIAL_FLAGS.put(Material.NETHER_BRICK, 0);
MATERIAL_FLAGS.put(Material.NETHER_BRICK_FENCE, 0);
MATERIAL_FLAGS.put(Material.NETHER_BRICK_STAIRS, 0);
MATERIAL_FLAGS.put(Material.ENCHANTING_TABLE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BREWING_STAND, MODIFIED_ON_RIGHT);
@@ -257,11 +249,6 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.IRON_TRAPDOOR, 0);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE, 0);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE_STAIRS, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_FENCE, 0);
MATERIAL_FLAGS.put(Material.BIRCH_FENCE, 0);
MATERIAL_FLAGS.put(Material.JUNGLE_FENCE, 0);
MATERIAL_FLAGS.put(Material.DARK_OAK_FENCE, 0);
MATERIAL_FLAGS.put(Material.ACACIA_FENCE, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BIRCH_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.JUNGLE_DOOR, MODIFIED_ON_RIGHT);
@@ -454,9 +441,9 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.STONECUTTER, 0);
MATERIAL_FLAGS.put(Material.SWEET_BERRY_BUSH, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.IRON_SHOVEL, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.IRON_SHOVEL, 0);
MATERIAL_FLAGS.put(Material.IRON_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.IRON_AXE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.IRON_AXE, 0);
MATERIAL_FLAGS.put(Material.FLINT_AND_STEEL, 0);
MATERIAL_FLAGS.put(Material.APPLE, 0);
MATERIAL_FLAGS.put(Material.BOW, 0);
@@ -467,32 +454,32 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.GOLD_INGOT, 0);
MATERIAL_FLAGS.put(Material.IRON_SWORD, 0);
MATERIAL_FLAGS.put(Material.WOODEN_SWORD, 0);
MATERIAL_FLAGS.put(Material.WOODEN_SHOVEL, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.WOODEN_SHOVEL, 0);
MATERIAL_FLAGS.put(Material.WOODEN_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.WOODEN_AXE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.WOODEN_AXE, 0);
MATERIAL_FLAGS.put(Material.STONE_SWORD, 0);
MATERIAL_FLAGS.put(Material.STONE_SHOVEL, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.STONE_SHOVEL, 0);
MATERIAL_FLAGS.put(Material.STONE_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.STONE_AXE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.STONE_AXE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_SWORD, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_SHOVEL, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.DIAMOND_SHOVEL, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_AXE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.DIAMOND_AXE, 0);
MATERIAL_FLAGS.put(Material.STICK, 0);
MATERIAL_FLAGS.put(Material.BOWL, 0);
MATERIAL_FLAGS.put(Material.MUSHROOM_STEW, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_SWORD, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_SHOVEL, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.GOLDEN_SHOVEL, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_AXE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.GOLDEN_AXE, 0);
MATERIAL_FLAGS.put(Material.STRING, 0);
MATERIAL_FLAGS.put(Material.FEATHER, 0);
MATERIAL_FLAGS.put(Material.GUNPOWDER, 0);
MATERIAL_FLAGS.put(Material.WOODEN_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.STONE_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.IRON_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.DIAMOND_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.GOLDEN_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.WOODEN_HOE, 0);
MATERIAL_FLAGS.put(Material.STONE_HOE, 0);
MATERIAL_FLAGS.put(Material.IRON_HOE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_HOE, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_HOE, 0);
MATERIAL_FLAGS.put(Material.WHEAT_SEEDS, 0);
MATERIAL_FLAGS.put(Material.BREAD, 0);
MATERIAL_FLAGS.put(Material.LEATHER_HELMET, 0);
@@ -547,29 +534,29 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.COD, 0);
MATERIAL_FLAGS.put(Material.COOKED_COD, 0);
MATERIAL_FLAGS.put(Material.INK_SAC, 0);
MATERIAL_FLAGS.put(Material.BLACK_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.BLUE_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.BROWN_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.CYAN_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.GRAY_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.GREEN_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.LIME_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.MAGENTA_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.ORANGE_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.PINK_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.PURPLE_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.RED_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.WHITE_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.YELLOW_DYE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.BLACK_DYE, 0);
MATERIAL_FLAGS.put(Material.BLUE_DYE, 0);
MATERIAL_FLAGS.put(Material.BROWN_DYE, 0);
MATERIAL_FLAGS.put(Material.CYAN_DYE, 0);
MATERIAL_FLAGS.put(Material.GRAY_DYE, 0);
MATERIAL_FLAGS.put(Material.GREEN_DYE, 0);
MATERIAL_FLAGS.put(Material.LIGHT_BLUE_DYE, 0);
MATERIAL_FLAGS.put(Material.LIGHT_GRAY_DYE, 0);
MATERIAL_FLAGS.put(Material.LIME_DYE, 0);
MATERIAL_FLAGS.put(Material.MAGENTA_DYE, 0);
MATERIAL_FLAGS.put(Material.ORANGE_DYE, 0);
MATERIAL_FLAGS.put(Material.PINK_DYE, 0);
MATERIAL_FLAGS.put(Material.PURPLE_DYE, 0);
MATERIAL_FLAGS.put(Material.RED_DYE, 0);
MATERIAL_FLAGS.put(Material.WHITE_DYE, 0);
MATERIAL_FLAGS.put(Material.YELLOW_DYE, 0);
MATERIAL_FLAGS.put(Material.COCOA_BEANS, 0);
MATERIAL_FLAGS.put(Material.BONE_MEAL, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.BONE, 0);
MATERIAL_FLAGS.put(Material.SUGAR, 0);
MATERIAL_FLAGS.put(Material.COOKIE, 0);
MATERIAL_FLAGS.put(Material.MAP, 0);
MATERIAL_FLAGS.put(Material.SHEARS, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.SHEARS, 0);
MATERIAL_FLAGS.put(Material.MELON_SLICE, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN_SEEDS, 0);
MATERIAL_FLAGS.put(Material.MELON_SEEDS, 0);
@@ -693,15 +680,72 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.SWEET_BERRIES, 0);
// 1.15
try {
MATERIAL_FLAGS.put(Material.BEEHIVE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BEE_NEST, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.HONEY_BLOCK, 0);
MATERIAL_FLAGS.put(Material.HONEYCOMB_BLOCK, 0);
MATERIAL_FLAGS.put(Material.HONEY_BOTTLE, 0);
MATERIAL_FLAGS.put(Material.HONEYCOMB, 0);
} catch (NoSuchFieldError ignored) {
}
MATERIAL_FLAGS.put(Material.BEEHIVE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BEE_NEST, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.HONEY_BLOCK, 0);
MATERIAL_FLAGS.put(Material.HONEYCOMB_BLOCK, 0);
MATERIAL_FLAGS.put(Material.HONEY_BOTTLE, 0);
MATERIAL_FLAGS.put(Material.HONEYCOMB, 0);
// 1.16
MATERIAL_FLAGS.put(Material.ANCIENT_DEBRIS, 0);
MATERIAL_FLAGS.put(Material.BASALT, 0);
MATERIAL_FLAGS.put(Material.BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.CHAIN, 0);
MATERIAL_FLAGS.put(Material.CHISELED_NETHER_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CHISELED_POLISHED_BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.CRACKED_NETHER_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CRACKED_POLISHED_BLACKSTONE_BRICKS, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_FUNGUS, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_NYLIUM, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_ROOTS, 0);
MATERIAL_FLAGS.put(Material.CRIMSON_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CRYING_OBSIDIAN, 0);
MATERIAL_FLAGS.put(Material.GILDED_BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.LODESTONE, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_AXE, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_BLOCK, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_BOOTS, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_CHESTPLATE, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_HELMET, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_HOE, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_INGOT, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_LEGGINGS, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_SCRAP, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_SHOVEL, 0);
MATERIAL_FLAGS.put(Material.NETHERITE_SWORD, 0);
MATERIAL_FLAGS.put(Material.NETHER_GOLD_ORE, 0);
MATERIAL_FLAGS.put(Material.NETHER_SPROUTS, 0);
MATERIAL_FLAGS.put(Material.PIGLIN_BANNER_PATTERN, 0);
MATERIAL_FLAGS.put(Material.POLISHED_BASALT, 0);
MATERIAL_FLAGS.put(Material.POLISHED_BLACKSTONE, 0);
MATERIAL_FLAGS.put(Material.POLISHED_BLACKSTONE_BRICKS, 0);
MATERIAL_FLAGS.put(Material.POLISHED_BLACKSTONE_PRESSURE_PLATE, 0);
MATERIAL_FLAGS.put(Material.QUARTZ_BRICKS, 0);
MATERIAL_FLAGS.put(Material.RESPAWN_ANCHOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SHROOMLIGHT, 0);
MATERIAL_FLAGS.put(Material.SOUL_CAMPFIRE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SOUL_FIRE, 0);
MATERIAL_FLAGS.put(Material.SOUL_LANTERN, 0);
MATERIAL_FLAGS.put(Material.SOUL_SOIL, 0);
MATERIAL_FLAGS.put(Material.SOUL_TORCH, 0);
MATERIAL_FLAGS.put(Material.SOUL_WALL_TORCH, 0);
MATERIAL_FLAGS.put(Material.TARGET, 0);
MATERIAL_FLAGS.put(Material.TWISTING_VINES, 0);
MATERIAL_FLAGS.put(Material.TWISTING_VINES_PLANT, 0);
MATERIAL_FLAGS.put(Material.WARPED_FUNGUS, 0);
MATERIAL_FLAGS.put(Material.WARPED_FUNGUS_ON_A_STICK, 0);
MATERIAL_FLAGS.put(Material.WARPED_NYLIUM, 0);
MATERIAL_FLAGS.put(Material.WARPED_ROOTS, 0);
MATERIAL_FLAGS.put(Material.WARPED_TRAPDOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.WARPED_WART_BLOCK, 0);
MATERIAL_FLAGS.put(Material.WEEPING_VINES, 0);
MATERIAL_FLAGS.put(Material.WEEPING_VINES_PLANT, 0);
// Fake tags
for (Material m : shulkerBoxes) {
@@ -769,6 +813,12 @@ public final class Materials {
for (Material bannerPat : Tag.ITEMS_BANNERS.getValues()) {
MATERIAL_FLAGS.put(bannerPat, 0);
}
for (Material fenceGate : Tag.FENCE_GATES.getValues()) {
MATERIAL_FLAGS.put(fenceGate, MODIFIED_ON_RIGHT);
}
for (Material fence : Tag.FENCES.getValues()) {
MATERIAL_FLAGS.put(fence, 0);
}
Stream.concat(Stream.concat(
Tag.CORAL_BLOCKS.getValues().stream(),
Tag.CORALS.getValues().stream()),
@@ -912,7 +962,8 @@ public final class Materials {
* @return true if a water block
*/
public static boolean isWater(Material material) {
return material == Material.WATER || material == Material.BUBBLE_COLUMN;
return material == Material.WATER || material == Material.BUBBLE_COLUMN
|| material == Material.KELP_PLANT || material == Material.SEAGRASS || material == Material.TALL_SEAGRASS;
}
/**
@@ -1026,6 +1077,7 @@ public final class Materials {
case FOX_SPAWN_EGG:
case GHAST_SPAWN_EGG:
case GUARDIAN_SPAWN_EGG:
case HOGLIN_SPAWN_EGG:
case HORSE_SPAWN_EGG:
case HUSK_SPAWN_EGG:
case LLAMA_SPAWN_EGG:
@@ -1036,6 +1088,8 @@ public final class Materials {
case PANDA_SPAWN_EGG:
case PARROT_SPAWN_EGG:
case PHANTOM_SPAWN_EGG:
case PIGLIN_BRUTE_SPAWN_EGG:
case PIGLIN_SPAWN_EGG:
case PIG_SPAWN_EGG:
case PILLAGER_SPAWN_EGG:
case POLAR_BEAR_SPAWN_EGG:
@@ -1051,6 +1105,7 @@ public final class Materials {
case SLIME_SPAWN_EGG:
case SQUID_SPAWN_EGG:
case STRAY_SPAWN_EGG:
case STRIDER_SPAWN_EGG:
case TRADER_LLAMA_SPAWN_EGG:
case TROPICAL_FISH_SPAWN_EGG:
case TURTLE_SPAWN_EGG:
@@ -1061,8 +1116,9 @@ public final class Materials {
case WITCH_SPAWN_EGG:
case WITHER_SKELETON_SPAWN_EGG:
case WOLF_SPAWN_EGG:
case ZOGLIN_SPAWN_EGG:
case ZOMBIE_HORSE_SPAWN_EGG:
case ZOMBIE_PIGMAN_SPAWN_EGG:
case ZOMBIFIED_PIGLIN_SPAWN_EGG:
case ZOMBIE_SPAWN_EGG:
case ZOMBIE_VILLAGER_SPAWN_EGG:
return true;
@@ -1113,6 +1169,8 @@ public final class Materials {
return EntityType.GHAST;
case GUARDIAN_SPAWN_EGG:
return EntityType.GUARDIAN;
case HOGLIN_SPAWN_EGG:
return EntityType.HOGLIN;
case HORSE_SPAWN_EGG:
return EntityType.HORSE;
case HUSK_SPAWN_EGG:
@@ -1133,6 +1191,10 @@ public final class Materials {
return EntityType.PARROT;
case PHANTOM_SPAWN_EGG:
return EntityType.PHANTOM;
case PIGLIN_BRUTE_SPAWN_EGG:
return EntityType.PIGLIN_BRUTE;
case PIGLIN_SPAWN_EGG:
return EntityType.PIGLIN;
case PILLAGER_SPAWN_EGG:
return EntityType.PILLAGER;
case POLAR_BEAR_SPAWN_EGG:
@@ -1161,6 +1223,8 @@ public final class Materials {
return EntityType.SQUID;
case STRAY_SPAWN_EGG:
return EntityType.STRAY;
case STRIDER_SPAWN_EGG:
return EntityType.STRIDER;
case TRADER_LLAMA_SPAWN_EGG:
return EntityType.TRADER_LLAMA;
case TROPICAL_FISH_SPAWN_EGG:
@@ -1183,8 +1247,8 @@ public final class Materials {
return EntityType.WOLF;
case ZOMBIE_HORSE_SPAWN_EGG:
return EntityType.ZOMBIE_HORSE;
case ZOMBIE_PIGMAN_SPAWN_EGG:
return EntityType.PIG_ZOMBIE;
case ZOMBIFIED_PIGLIN_SPAWN_EGG:
return EntityType.ZOMBIFIED_PIGLIN;
case ZOMBIE_SPAWN_EGG:
return EntityType.ZOMBIE;
case ZOMBIE_VILLAGER_SPAWN_EGG:
@@ -1199,6 +1263,13 @@ public final class Materials {
return Tag.BEDS.isTagged(material);
}
public static boolean isCoral(Material material) {
return Tag.CORAL_BLOCKS.isTagged(material) ||
Tag.CORAL_PLANTS.isTagged(material) ||
Tag.CORALS.isTagged(material) ||
Tag.WALL_CORALS.isTagged(material);
}
/**
* Test whether the material is a crop.
* @param type the material
@@ -1219,6 +1290,19 @@ public final class Materials {
|| type == Material.BAMBOO_SAPLING;
}
/**
* Test whether the material should be handled as vine. Used by the vine-growth flag
* @param newType the material
* @return true if the material should be handled as vine
*/
public static boolean isVine(Material newType) {
return newType == Material.VINE ||
newType == Material.KELP ||
newType == Material.TWISTING_VINES ||
newType == Material.WEEPING_VINES;
}
/**
* Test whether the given material is affected by
* {@link Flags#USE}.
@@ -1232,25 +1316,15 @@ public final class Materials {
public static boolean isUseFlagApplicable(Material material) {
if (Tag.BUTTONS.isTagged(material)
|| Tag.DOORS.isTagged(material)
|| Tag.WOODEN_PRESSURE_PLATES.isTagged(material)
|| Tag.WOODEN_TRAPDOORS.isTagged(material)) {
|| Tag.WOODEN_TRAPDOORS.isTagged(material)
|| Tag.FENCE_GATES.isTagged(material)
|| Tag.PRESSURE_PLATES.isTagged(material)
|| Tag.ANVIL.isTagged(material)) {
return true;
}
switch (material) {
case LEVER:
case LECTERN:
case ACACIA_FENCE_GATE:
case DARK_OAK_FENCE_GATE:
case JUNGLE_FENCE_GATE:
case BIRCH_FENCE_GATE:
case SPRUCE_FENCE_GATE:
case OAK_FENCE_GATE:
case LIGHT_WEIGHTED_PRESSURE_PLATE:
case HEAVY_WEIGHTED_PRESSURE_PLATE:
case STONE_PRESSURE_PLATE:
case ANVIL:
case DAMAGED_ANVIL:
case CHIPPED_ANVIL:
case ENCHANTING_TABLE:
case BELL:
case LOOM:
@@ -1292,7 +1366,7 @@ public final class Materials {
*/
public static boolean isItemAppliedToBlock(Material item, Material block) {
Integer flags = MATERIAL_FLAGS.get(item);
return flags == null || (flags & MODIFIES_BLOCKS) == MODIFIES_BLOCKS;
return flags == null || (flags & MODIFIES_BLOCKS) == MODIFIES_BLOCKS || isToolApplicable(item, block);
}
/**
@@ -1356,6 +1430,10 @@ public final class Materials {
case GOLDEN_CHESTPLATE:
case GOLDEN_LEGGINGS:
case GOLDEN_BOOTS:
case NETHERITE_HELMET:
case NETHERITE_CHESTPLATE:
case NETHERITE_LEGGINGS:
case NETHERITE_BOOTS:
case TURTLE_HELMET:
case ELYTRA:
return true;
@@ -1364,4 +1442,102 @@ public final class Materials {
}
}
/**
* Check if the material is usable via right-click on the target
* material. Returns false if the target material cannot be modified
* by the provided tool, or of the provided tool material isn't
* a tool material.
*
* @param toolMaterial the tool material being used
* @param targetMaterial the target material to check
* @return true if tool has an interact function with this material
*/
public static boolean isToolApplicable(Material toolMaterial, Material targetMaterial) {
switch (toolMaterial) {
case WOODEN_HOE:
case STONE_HOE:
case IRON_HOE:
case GOLDEN_HOE:
case DIAMOND_HOE:
case NETHERITE_HOE:
switch (targetMaterial) {
case GRASS_BLOCK:
case DIRT:
case GRASS_PATH:
// case COARSE_DIRT: // already handled by the server...
return true;
}
return false;
case WOODEN_AXE:
case STONE_AXE:
case IRON_AXE:
case GOLDEN_AXE:
case DIAMOND_AXE:
case NETHERITE_AXE:
switch (targetMaterial) {
case OAK_LOG:
case DARK_OAK_LOG:
case ACACIA_LOG:
case BIRCH_LOG:
case SPRUCE_LOG:
case JUNGLE_LOG:
case OAK_WOOD:
case DARK_OAK_WOOD:
case ACACIA_WOOD:
case BIRCH_WOOD:
case SPRUCE_WOOD:
case JUNGLE_WOOD:
case CRIMSON_STEM:
case WARPED_STEM:
case CRIMSON_HYPHAE:
case WARPED_HYPHAE:
return true;
}
return false;
case WOODEN_SHOVEL:
case STONE_SHOVEL:
case IRON_SHOVEL:
case GOLDEN_SHOVEL:
case DIAMOND_SHOVEL:
case NETHERITE_SHOVEL:
switch (targetMaterial) {
case GRASS_BLOCK:
case CAMPFIRE:
case SOUL_CAMPFIRE:
return true;
}
return false;
case SHEARS:
switch (targetMaterial) {
case PUMPKIN:
case BEE_NEST:
case BEEHIVE:
return true;
}
return false;
case BLACK_DYE:
case BLUE_DYE:
case BROWN_DYE:
case CYAN_DYE:
case GRAY_DYE:
case GREEN_DYE:
case LIGHT_BLUE_DYE:
case LIGHT_GRAY_DYE:
case LIME_DYE:
case MAGENTA_DYE:
case ORANGE_DYE:
case PINK_DYE:
case PURPLE_DYE:
case RED_DYE:
case WHITE_DYE:
case YELLOW_DYE:
return Tag.SIGNS.isTagged(targetMaterial);
default:
return false;
}
}
public static boolean isFire(Material type) {
return type == Material.FIRE || type == Material.SOUL_FIRE;
}
}
@@ -3,4 +3,4 @@ main: com.sk89q.worldguard.bukkit.WorldGuardPlugin
version: "${internalVersion}"
depend: [WorldEdit]
softdepend: [CommandBook]
api-version: 1.13
api-version: 1.16
+4 -2
View File
@@ -7,9 +7,11 @@ plugins {
applyPlatformAndCoreConfiguration()
dependencies {
"compile"(project(":worldguard-libs:core"))
"compile"("com.sk89q.worldedit:worldedit-core:${Versions.WORLDEDIT}")
"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.9")
"implementation"("com.google.guava:guava:${Versions.GUAVA}")
"compileOnly"("com.google.code.findbugs:jsr305:1.3.9")
"testImplementation"("org.hamcrest:hamcrest-library:1.2.1")
@@ -75,7 +75,7 @@ class FlagHelperBox extends PaginationBox {
.collect(Collectors.toList());
private static final int SIZE = FLAGS.size() == Flags.INBUILT_FLAGS.size() ? FLAGS.size() : FLAGS.size() + 1;
private static final int PAD_PX_SIZE = 180;
private static final Set<Flag<?>> DANGER_ZONE = ImmutableSet.of(Flags.BUILD, Flags.PASSTHROUGH, Flags.BLOCK_PLACE, Flags.BLOCK_BREAK);
static final Set<Flag<?>> DANGER_ZONE = ImmutableSet.of(Flags.BUILD, Flags.PASSTHROUGH, Flags.BLOCK_PLACE, Flags.BLOCK_BREAK);
private final World world;
private final ProtectedRegion region;
@@ -199,7 +199,7 @@ class FlagHelperBox extends PaginationBox {
if (maySet) {
if (isExplicitSet) {
hoverTexts.add(TextComponent.of("Click to unset", TextColor.GOLD));
} else if (DANGER_ZONE.contains(flag)) {
} else if (DANGER_ZONE.contains(flag) && !(ProtectedRegion.GLOBAL_REGION.equals(region.getId()) && flag == Flags.PASSTHROUGH)) {
hoverTexts.add(TextComponent.of("Setting this flag may have unintended consequences.", TextColor.RED)
.append(TextComponent.newline())
.append(TextComponent.of("Please read the documentation and set this flag manually if you really intend to.")
@@ -44,7 +44,6 @@ 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;
import com.sk89q.worldguard.commands.CommandUtils;
import com.sk89q.worldguard.commands.task.RegionAdder;
import com.sk89q.worldguard.commands.task.RegionLister;
import com.sk89q.worldguard.commands.task.RegionManagerLoader;
@@ -129,22 +128,21 @@ public final class RegionCommands extends RegionCommandsBase {
* @throws CommandException any error
*/
@Command(aliases = {"define", "def", "d", "create"},
usage = "<id> [<owner1> [<owner2> [<owners...>]]]",
flags = "ng",
usage = "[-w <world>] <id> [<owner1> [<owner2> [<owners...>]]]",
flags = "ngw:",
desc = "Defines a region",
min = 1)
public void define(CommandContext args, Actor sender) throws CommandException {
warnAboutSaveFailures(sender);
LocalPlayer player = worldGuard.checkPlayer(sender);
// Check permissions
if (!getPermissionModel(player).mayDefine()) {
if (!getPermissionModel(sender).mayDefine()) {
throw new CommandPermissionsException();
}
String id = checkRegionId(args.getString(0), false);
World world = player.getWorld();
World world = checkWorld(args, sender, 'w');
RegionManager manager = checkRegionManager(world);
checkRegionDoesNotExist(manager, id, true);
@@ -154,7 +152,7 @@ public final class RegionCommands extends RegionCommandsBase {
if (args.hasFlag('g')) {
region = new GlobalProtectedRegion(id);
} else {
region = checkRegionFromSelection(player, id);
region = checkRegionFromSelection(sender, id);
}
RegionAdder task = new RegionAdder(manager, region);
@@ -182,24 +180,22 @@ public final class RegionCommands extends RegionCommandsBase {
* @throws CommandException any error
*/
@Command(aliases = {"redefine", "update", "move"},
usage = "<id>",
usage = "[-w <world>] <id>",
desc = "Re-defines the shape of a region",
flags = "g",
flags = "gw:",
min = 1, max = 1)
public void redefine(CommandContext args, Actor sender) throws CommandException {
warnAboutSaveFailures(sender);
LocalPlayer player = worldGuard.checkPlayer(sender);
String id = checkRegionId(args.getString(0), false);
World world = player.getWorld();
World world = checkWorld(args, sender, 'w');
RegionManager manager = checkRegionManager(world);
ProtectedRegion existing = checkExistingRegion(manager, id, false);
// Check permissions
if (!getPermissionModel(player).mayRedefine(existing)) {
if (!getPermissionModel(sender).mayRedefine(existing)) {
throw new CommandPermissionsException();
}
@@ -208,7 +204,7 @@ public final class RegionCommands extends RegionCommandsBase {
if (args.hasFlag('g')) {
region = new GlobalProtectedRegion(id);
} else {
region = checkRegionFromSelection(player, id);
region = checkRegionFromSelection(sender, id);
}
region.copyFrom(existing);
@@ -221,9 +217,9 @@ public final class RegionCommands extends RegionCommandsBase {
.sendMessageAfterDelay("(Please wait... " + description + ")")
.onSuccess((Component) null,
t -> {
player.print(String.format("Region '%s' has been updated with a new area.", region.getId()));
warnAboutDimensions(player, region);
informNewUser(player, manager, region);
sender.print(String.format("Region '%s' has been updated with a new area.", region.getId()));
warnAboutDimensions(sender, region);
informNewUser(sender, manager, region);
checkSpawnOverlap(sender, world, region);
})
.onFailure(String.format("Failed to update the region '%s'", region.getId()), worldGuard.getExceptionConverter())
@@ -338,28 +334,34 @@ public final class RegionCommands extends RegionCommandsBase {
* @throws CommandException any error
*/
@Command(aliases = {"select", "sel", "s"},
usage = "[id]",
usage = "[-w <world>] [id]",
desc = "Load a region as a WorldEdit selection",
min = 0, max = 1)
min = 0, max = 1,
flags = "w:")
public void select(CommandContext args, Actor sender) throws CommandException {
LocalPlayer player = worldGuard.checkPlayer(sender);
RegionManager manager = checkRegionManager(player.getWorld());
World world = checkWorld(args, sender, 'w');
RegionManager manager = checkRegionManager(world);
ProtectedRegion existing;
// If no arguments were given, get the region that the player is inside
if (args.argsLength() == 0) {
existing = checkRegionStandingIn(manager, player, "/rg select %id%");
LocalPlayer player = worldGuard.checkPlayer(sender);
if (!player.getWorld().equals(world)) { // confusing to get current location regions in another world
throw new CommandException("Please specify a region name."); // just don't allow that
}
world = player.getWorld();
existing = checkRegionStandingIn(manager, player, "/rg select -w \"" + world.getName() + "\" %id%");
} else {
existing = checkExistingRegion(manager, args.getString(0), false);
}
// Check permissions
if (!getPermissionModel(player).maySelect(existing)) {
if (!getPermissionModel(sender).maySelect(existing)) {
throw new CommandPermissionsException();
}
// Select
setPlayerSelection(player, existing);
setPlayerSelection(sender, existing, world);
}
/**
@@ -407,7 +409,7 @@ public final class RegionCommands extends RegionCommandsBase {
throw new CommandPermissionsException();
}
setPlayerSelection(worldGuard.checkPlayer(sender), existing);
setPlayerSelection(worldGuard.checkPlayer(sender), existing, world);
}
// Print region information
@@ -417,7 +419,10 @@ public final class RegionCommands extends RegionCommandsBase {
AsyncCommandBuilder.wrap(printout, sender)
.registerWithSupervisor(WorldGuard.getInstance().getSupervisor(), "Fetching region info")
.sendMessageAfterDelay("(Please wait... fetching region information...)")
.onSuccess((Component) null, sender::print)
.onSuccess((Component) null, component -> {
sender.print(component);
checkSpawnOverlap(sender, world, existing);
})
.onFailure("Failed to fetch region information", WorldGuard.getInstance().getExceptionConverter())
.buildAndExec(WorldGuard.getInstance().getExecutorService());
}
@@ -622,6 +627,7 @@ public final class RegionCommands extends RegionCommandsBase {
printout.appendFlagsList(false);
printout.append(SubtleFormat.wrap(")"));
printout.send(sender);
checkSpawnOverlap(sender, world, existing);
}
}
@@ -638,7 +644,7 @@ public final class RegionCommands extends RegionCommandsBase {
ProtectedRegion region;
if (args.argsLength() == 0) { // Get region from where the player is
if (!(sender instanceof LocalPlayer)) {
throw new CommandException("Please specify the region with /region info -w world_name region_name.");
throw new CommandException("Please specify the region with /region flags -w world_name region_name.");
}
region = checkRegionStandingIn(manager, (LocalPlayer) sender, true,
@@ -662,7 +668,12 @@ public final class RegionCommands extends RegionCommandsBase {
if (!sender.isPlayer()) {
flagHelperBox.tryMonoSpacing();
}
AsyncCommandBuilder.wrap(() -> flagHelperBox.create(page), sender)
AsyncCommandBuilder.wrap(() -> {
if (checkSpawnOverlap(sender, world, region)) {
flagHelperBox.setComponentsPerPage(15);
}
return flagHelperBox.create(page);
}, sender)
.onSuccess((Component) null, sender::print)
.onFailure("Failed to get region flags", WorldGuard.getInstance().getExceptionConverter())
.buildAndExec(WorldGuard.getInstance().getExecutorService());
@@ -698,6 +709,7 @@ public final class RegionCommands extends RegionCommandsBase {
existing.setPriority(priority);
sender.print("Priority of '" + existing.getId() + "' set to " + priority + " (higher numbers override).");
checkSpawnOverlap(sender, world, existing);
}
/**
@@ -1098,8 +1110,16 @@ public final class RegionCommands extends RegionCommandsBase {
}
}
String message = existing.getFlag(Flags.TELE_MESSAGE);
// If the flag isn't set, use the default message
// If message.isEmpty(), no message is sent by LocalPlayer#teleport(...)
if (message == null) {
message = Flags.TELE_MESSAGE.getDefault();
}
player.teleport(teleportLocation,
"Teleported you to the region '" + existing.getId() + "'.",
message.replace("%id%", existing.getId()),
"Unable to teleport to region '" + existing.getId() + "'.");
}
@@ -31,6 +31,7 @@ import com.sk89q.worldedit.math.BlockVector3;
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;
@@ -54,6 +55,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.util.WorldEditRegionConverter;
import java.util.Set;
import java.util.stream.Collectors;
@@ -84,9 +86,25 @@ class RegionCommandsBase {
* @throws CommandException on error
*/
protected static World checkWorld(CommandContext args, Actor sender, char flag) throws CommandException {
return checkWorld(args, sender, flag, true);
}
protected static World checkWorld(CommandContext args, Actor sender, char flag, boolean allowWorldEditOverride) throws CommandException {
if (args.hasFlag(flag)) {
return WorldGuard.getInstance().getPlatform().getMatcher().matchWorld(sender, args.getFlag(flag));
} else {
if (allowWorldEditOverride) {
try {
World override = WorldEdit.getInstance().getSessionManager().get(sender).getWorldOverride();
if (override != null) {
if (sender instanceof LocalPlayer && !override.equals(((LocalPlayer) sender).getWorld())) {
sender.printDebug(TextComponent.of("Using //world override for region command: " + override.getName()));
}
return override;
}
} catch (NoSuchMethodError ignored) {
}
}
if (sender instanceof LocalPlayer) {
return ((LocalPlayer) sender).getWorld();
} else {
@@ -219,21 +237,24 @@ class RegionCommandsBase {
}
/**
* Get a WorldEdit selection for a player, or emit an exception if there is none
* Get a WorldEdit selection for an actor, or emit an exception if there is none
* available.
*
* @param player the player
* @param actor the actor
* @return the selection
* @throws CommandException thrown on an error
*/
protected static Region checkSelection(LocalPlayer player) throws CommandException {
protected static Region checkSelection(Actor actor) throws CommandException {
LocalSession localSession = WorldEdit.getInstance().getSessionManager().get(actor);
try {
return WorldEdit.getInstance().getSessionManager().get(player).getRegionSelector(player.getWorld()).getRegion();
if (localSession == null || localSession.getSelectionWorld() == null) {
throw new IncompleteRegionException();
}
return localSession.getRegionSelector(localSession.getSelectionWorld()).getRegion();
} catch (IncompleteRegionException e) {
throw new CommandException(
"Please select an area first. " +
"Use WorldEdit to make a selection! " +
"(see: https://worldedit.enginehub.org/en/latest/usage/regions/selections/).");
throw new CommandException("Please select an area first. " +
"Use WorldEdit to make a selection! " +
"(see: https://worldedit.enginehub.org/en/latest/usage/regions/selections/).");
}
}
@@ -273,15 +294,15 @@ class RegionCommandsBase {
}
/**
* Create a {@link ProtectedRegion} from the player's selection.
* Create a {@link ProtectedRegion} from the actor's selection.
*
* @param player the player
* @param actor the actor
* @param id the ID of the new region
* @return a new region
* @throws CommandException thrown on an error
*/
protected static ProtectedRegion checkRegionFromSelection(LocalPlayer player, String id) throws CommandException {
Region selection = checkSelection(player);
protected static ProtectedRegion checkRegionFromSelection(Actor actor, String id) throws CommandException {
Region selection = checkSelection(actor);
// Detect the type of region from WorldEdit
if (selection instanceof Polygonal2DRegion) {
@@ -323,6 +344,9 @@ class RegionCommandsBase {
* @param region the region
*/
protected static void warnAboutDimensions(Actor sender, ProtectedRegion region) {
if (region instanceof GlobalProtectedRegion) {
return;
}
int height = region.getMaximumPoint().getBlockY() - region.getMinimumPoint().getBlockY();
if (height <= 2) {
sender.printDebug("(Warning: The height of the region was " + (height + 1) + " block(s).)");
@@ -351,56 +375,38 @@ class RegionCommandsBase {
* @param world the world the region is in
* @param region the region
*/
protected static void checkSpawnOverlap(Actor sender, World world, ProtectedRegion region) {
protected static boolean checkSpawnOverlap(Actor sender, World world, ProtectedRegion region) {
ProtectedRegion spawn = WorldGuard.getInstance().getPlatform().getSpawnProtection(world);
if (spawn != null) {
if (!spawn.getIntersectingRegions(ImmutableList.of(region)).isEmpty()) {
sender.print(ErrorFormat.wrap("Warning!")
.append(TextComponent.of(" This region overlaps vanilla's spawn protection. WorldGuard cannot " +
"override this, and only server operators will be able to interact with this area.")));
"override this, and only server operators will be able to interact with this area.", TextColor.WHITE)));
return true;
}
}
return false;
}
/**
* Set a player's selection to a given region.
* Set an actor's selection to a given region.
*
* @param player the player
* @param actor the actor
* @param region the region
* @throws CommandException thrown on a command error
*/
protected static void setPlayerSelection(LocalPlayer player, ProtectedRegion region) throws CommandException {
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
// Set selection
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
BlockVector3 pt1 = cuboid.getMinimumPoint();
BlockVector3 pt2 = cuboid.getMaximumPoint();
CuboidRegionSelector selector = new CuboidRegionSelector(player.getWorld(), pt1, pt2);
session.setRegionSelector(player.getWorld(), selector);
selector.explainRegionAdjust(player, session);
player.print("Region selected as a cuboid.");
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly2d = (ProtectedPolygonalRegion) region;
Polygonal2DRegionSelector selector = new Polygonal2DRegionSelector(
player.getWorld(), poly2d.getPoints(),
poly2d.getMinimumPoint().getBlockY(),
poly2d.getMaximumPoint().getBlockY());
session.setRegionSelector(player.getWorld(), selector);
selector.explainRegionAdjust(player, session);
player.print("Region selected as a polygon.");
} else if (region instanceof GlobalProtectedRegion) {
throw new CommandException(
"Can't select global regions! " +
"That would cover the entire world.");
protected static void setPlayerSelection(Actor actor, ProtectedRegion region, World world) throws CommandException {
LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor);
RegionSelector selector = WorldEditRegionConverter.convertToSelector(region);
if (selector != null) {
selector.setWorld(world);
session.setRegionSelector(world, selector);
selector.explainRegionAdjust(actor, session);
actor.print("Region selected as " + region.getType().getName());
} else {
throw new CommandException("Unknown region type: " +
region.getClass().getCanonicalName());
throw new CommandException("Can't select that region! " +
"The region type '" + region.getType().getName() + "' can't be selected.");
}
}
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.commands.region;
import com.sk89q.worldguard.protection.flags.registry.UnknownFlag;
import com.sk89q.worldguard.util.profile.cache.ProfileCache;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.math.BlockVector3;
@@ -143,8 +144,22 @@ public class RegionPrintoutBuilder implements Callable<TextComponent> {
flagString = flag.getName() + " -g " + group + ": ";
}
TextComponent flagText = TextComponent.of(flagString, useColors ? TextColor.GOLD : TextColor.WHITE)
.append(TextComponent.of(String.valueOf(val), useColors? TextColor.YELLOW : TextColor.WHITE));
TextColor flagColor = TextColor.WHITE;
if (useColors) {
// passthrough is ok on global
if (FlagHelperBox.DANGER_ZONE.contains(flag)
&& !(region.getId().equals(ProtectedRegion.GLOBAL_REGION) && flag == Flags.PASSTHROUGH)) {
flagColor = TextColor.DARK_RED;
} else if (Flags.INBUILT_FLAGS.contains(flag.getName())) {
flagColor = TextColor.GOLD;
} else if (flag instanceof UnknownFlag) {
flagColor = TextColor.GRAY;
} else {
flagColor = TextColor.LIGHT_PURPLE;
}
}
TextComponent flagText = TextComponent.of(flagString, flagColor)
.append(TextComponent.of(String.valueOf(val), useColors ? TextColor.YELLOW : TextColor.WHITE));
if (perms != null && perms.maySetFlag(region, flag)) {
flagText = flagText.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to set flag")))
.clickEvent(ClickEvent.of(ClickEvent.Action.SUGGEST_COMMAND,
@@ -305,7 +320,7 @@ public class RegionPrintoutBuilder implements Callable<TextComponent> {
builder.append(TextComponent.space().append(TextComponent.of("[Teleport]", TextColor.GRAY)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT,
TextComponent.of("Click to teleport").append(TextComponent.newline()).append(
TextComponent.of(teleFlag.getBlockY() + ", "
TextComponent.of(teleFlag.getBlockX() + ", "
+ teleFlag.getBlockY() + ", "
+ teleFlag.getBlockZ()))))
.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND,
@@ -76,6 +76,9 @@ public abstract class ConfigurationManager {
public boolean migrateRegionsToUuid;
public boolean keepUnresolvedNames;
public boolean particleEffects;
public boolean disablePermissionCache;
public boolean disableDefaultBypass;
public boolean announceBypassStatus;
@Unreported public Map<String, String> hostKeys = new HashMap<>();
public boolean hostKeysAllowFMLClients;
@@ -135,6 +135,8 @@ public abstract class WorldConfiguration {
public boolean removeInfiniteStacks;
public boolean disableCreatureCropTrampling;
public boolean disablePlayerCropTrampling;
public boolean disableCreatureTurtleEggTrampling;
public boolean disablePlayerTurtleEggTrampling;
public boolean preventLightningFire;
public Set<String> disallowedLightningBlocks;
public boolean disableThunder;
@@ -158,16 +160,20 @@ public abstract class WorldConfiguration {
public boolean disableEndermanGriefing;
public boolean disableSnowmanTrails;
public boolean disableSoilDehydration;
public boolean disableCoralBlockFade;
public Set<String> allowedSnowFallOver;
public boolean regionInvinciblityRemovesMobs;
public boolean regionCancelEmptyChatEvents;
public boolean regionNetherPortalProtection;
public boolean forceDefaultTitleTimes;
public boolean fakePlayerBuildOverride;
public boolean explosionFlagCancellation;
public boolean disableDeathMessages;
public boolean disableObsidianGenerators;
public boolean strictEntitySpawn;
public boolean ignoreHopperMoveEvents;
public boolean breakDeniedHoppers;
public boolean useMaxPriorityAssociation;
protected Map<String, Integer> maxRegionCounts;
/**
@@ -56,6 +56,9 @@ public abstract class YamlConfigurationManager extends ConfigurationManager {
migrateRegionsToUuid = config.getBoolean("regions.uuid-migration.perform-on-next-start", true);
keepUnresolvedNames = config.getBoolean("regions.uuid-migration.keep-names-that-lack-uuids", true);
useRegionsCreatureSpawnEvent = config.getBoolean("regions.use-creature-spawn-event", true);
disableDefaultBypass = config.getBoolean("regions.disable-bypass-by-default", false);
announceBypassStatus = config.getBoolean("regions.announce-bypass-status", false);
useGodPermission = config.getBoolean("auto-invincible", config.getBoolean("auto-invincible-permission", false));
useGodGroup = config.getBoolean("auto-invincible-group", false);
useAmphibiousGroup = config.getBoolean("auto-no-drowning-group", false);
@@ -63,6 +66,7 @@ public abstract class YamlConfigurationManager extends ConfigurationManager {
usePlayerMove = config.getBoolean("use-player-move-event", true);
usePlayerTeleports = config.getBoolean("use-player-teleports", true);
particleEffects = config.getBoolean("use-particle-effects", true);
disablePermissionCache = config.getBoolean("disable-permission-cache", false);
deopOnJoin = config.getBoolean("security.deop-everyone-on-join", false);
blockInGameOp = config.getBoolean("security.block-in-game-op-command", false);
@@ -311,7 +311,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
public String toGroupsString() {
StringBuilder str = new StringBuilder();
for (Iterator<String> it = groupDomain.getGroups().iterator(); it.hasNext(); ) {
str.append("*");
str.append("g:");
str.append(it.next());
if (it.hasNext()) {
str.append(", ");
@@ -373,7 +373,8 @@ public class DefaultDomain implements Domain, ChangeTracked {
private Component toGroupsComponent() {
final TextComponent.Builder builder = TextComponent.builder("");
for (Iterator<String> it = groupDomain.getGroups().iterator(); it.hasNext(); ) {
builder.append(TextComponent.of(it.next(), TextColor.GOLD));
builder.append(TextComponent.of("g:", TextColor.GRAY))
.append(TextComponent.of(it.next(), TextColor.GOLD));
if (it.hasNext()) {
builder.append(TextComponent.of(", "));
}
@@ -73,7 +73,9 @@ public class PlayerDomain implements Domain, ChangeTracked {
* Add the given player to the domain, identified by the player's name.
*
* @param name the name of the player
* @deprecated names are deprecated in favor of UUIDs in MC 1.7+
*/
@Deprecated
public void addPlayer(String name) {
checkNotNull(name);
if (!name.trim().isEmpty()) {
@@ -111,7 +113,9 @@ public class PlayerDomain implements Domain, ChangeTracked {
* Remove the given player from the domain, identified by the player's name.
*
* @param name the name of the player
* @deprecated names are deprecated in favor of UUIDs in MC 1.7+
*/
@Deprecated
public void removePlayer(String name) {
checkNotNull(name);
setDirty(true);
@@ -152,7 +156,9 @@ public class PlayerDomain implements Domain, ChangeTracked {
* Get the set of player names.
*
* @return the set of player names
* @deprecated names are deprecated in favor of UUIDs in MC 1.7+
*/
@Deprecated
public Set<String> getPlayers() {
return Collections.unmodifiableSet(names);
}
@@ -21,16 +21,8 @@ package com.sk89q.worldguard.protection;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Determines that the association to a region is {@code OWNER} if the input
@@ -38,41 +30,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
*
* <p>This class only performs a spatial query if its
* {@link #getAssociation(List)} method is called.</p>
*
* @deprecated Use {@link com.sk89q.worldguard.protection.association.DelayedRegionOverlapAssociation} instead. This class is mis-packaged.
*/
public class DelayedRegionOverlapAssociation implements RegionAssociable {
private final RegionQuery query;
private final Location location;
@Nullable
private Set<ProtectedRegion> source;
@Deprecated
public class DelayedRegionOverlapAssociation extends com.sk89q.worldguard.protection.association.DelayedRegionOverlapAssociation {
/**
* Create a new instance.
*
* @param query the query
* @param location the location
*/
public DelayedRegionOverlapAssociation(RegionQuery query, Location location) {
checkNotNull(query);
checkNotNull(location);
this.query = query;
this.location = location;
}
@Override
public Association getAssociation(List<ProtectedRegion> regions) {
if (source == null) {
ApplicableRegionSet result = query.getApplicableRegions(location);
source = result.getRegions();
}
for (ProtectedRegion region : regions) {
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) {
return Association.OWNER;
}
}
return Association.NON_MEMBER;
super(query, location, false);
}
}
@@ -361,7 +361,8 @@ public class FlagValueCalculator {
if (flag == Flags.PASSTHROUGH) {
// Has members/owners -> the global region acts like
// a regular region without PASSTHROUGH
if (region.hasMembersOrOwners() || region.getFlag(Flags.PASSTHROUGH) == State.DENY) {
State passthrough = region.getFlag(Flags.PASSTHROUGH);
if (passthrough == State.DENY || passthrough != State.ALLOW && region.hasMembersOrOwners()) {
return null;
} else {
return (V) State.ALLOW;
@@ -0,0 +1,77 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.protection.association;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
public abstract class AbstractRegionOverlapAssociation implements RegionAssociable {
@Nullable
protected Set<ProtectedRegion> source;
private boolean useMaxPriorityAssociation;
private int maxPriority;
protected AbstractRegionOverlapAssociation(@Nullable Set<ProtectedRegion> source, boolean useMaxPriorityAssociation) {
this.source = source;
this.useMaxPriorityAssociation = useMaxPriorityAssociation;
}
protected void calcMaxPriority() {
checkNotNull(source);
int best = 0;
for (ProtectedRegion region : source) {
int priority = region.getPriority();
if (priority > best) {
best = priority;
}
}
this.maxPriority = best;
}
@Override
public Association getAssociation(List<ProtectedRegion> regions) {
checkNotNull(source);
for (ProtectedRegion region : regions) {
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty())) {
return Association.OWNER;
}
if (source.contains(region)) {
if (useMaxPriorityAssociation) {
int priority = region.getPriority();
if (priority == maxPriority) {
return Association.OWNER;
}
} else {
return Association.OWNER;
}
}
}
return Association.NON_MEMBER;
}
}
@@ -0,0 +1,78 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.protection.association;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import java.util.List;
/**
* Determines that the association to a region is {@code OWNER} if the input
* region is in a set of source regions.
*
* <p>This class only performs a spatial query if its
* {@link #getAssociation(List)} method is called.</p>
*/
public class DelayedRegionOverlapAssociation extends AbstractRegionOverlapAssociation {
private final RegionQuery query;
private final Location location;
/**
* Create a new instance.
* @param query the query
* @param location the location
*/
public DelayedRegionOverlapAssociation(RegionQuery query, Location location) {
this(query, location, false);
}
/**
* Create a new instance.
* @param query the query
* @param location the location
* @param useMaxPriorityAssociation whether to use the max priority from regions to determine association
*/
public DelayedRegionOverlapAssociation(RegionQuery query, Location location, boolean useMaxPriorityAssociation) {
super(null, useMaxPriorityAssociation);
checkNotNull(query);
checkNotNull(location);
this.query = query;
this.location = location;
}
@Override
public Association getAssociation(List<ProtectedRegion> regions) {
if (source == null) {
ApplicableRegionSet result = query.getApplicableRegions(location);
source = result.getRegions();
calcMaxPriority();
}
return super.getAssociation(regions);
}
}
@@ -19,41 +19,35 @@
package com.sk89q.worldguard.protection.association;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.List;
import javax.annotation.Nonnull;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Determines that the association to a region is {@code OWNER} if the input
* region is in a set of source regions.
*/
public class RegionOverlapAssociation implements RegionAssociable {
private final Set<ProtectedRegion> source;
public class RegionOverlapAssociation extends AbstractRegionOverlapAssociation {
/**
* Create a new instance.
*
* @param source set of regions that input regions must be contained within
*/
public RegionOverlapAssociation(Set<ProtectedRegion> source) {
checkNotNull(source);
this.source = source;
public RegionOverlapAssociation(@Nonnull Set<ProtectedRegion> source) {
this(source, false);
}
@Override
public Association getAssociation(List<ProtectedRegion> regions) {
for (ProtectedRegion region : regions) {
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) {
return Association.OWNER;
}
}
return Association.NON_MEMBER;
/**
* Create a new instance.
*
* @param source set of regions that input regions must be contained within
* @param useMaxPriorityAssociation whether to use the max priority from regions to determine association
*/
public RegionOverlapAssociation(@Nonnull Set<ProtectedRegion> source, boolean useMaxPriorityAssociation) {
super(source, useMaxPriorityAssociation);
calcMaxPriority();
}
}
@@ -60,6 +60,7 @@ public final class Flags {
public static final StateFlag DAMAGE_ANIMALS = register(new StateFlag("damage-animals", false));
public static final StateFlag PVP = register(new StateFlag("pvp", false));
public static final StateFlag SLEEP = register(new StateFlag("sleep", false));
public static final StateFlag RESPAWN_ANCHORS = register(new StateFlag("respawn-anchors", false));
public static final StateFlag TNT = register(new StateFlag("tnt", false));
public static final StateFlag CHEST_ACCESS = register(new StateFlag("chest-access", false));
public static final StateFlag PLACE_VEHICLE = register(new StateFlag("vehicle-place", false));
@@ -118,6 +119,7 @@ public final class Flags {
public static final StateFlag VINE_GROWTH = register(new StateFlag("vine-growth", true));
public static final StateFlag CROP_GROWTH = register(new StateFlag("crop-growth", true));
public static final StateFlag SOIL_DRY = register(new StateFlag("soil-dry", true));
public static final StateFlag CORAL_FADE = register(new StateFlag("coral-fade", true));
public static final StateFlag WATER_FLOW = register(new StateFlag("water-flow", true));
public static final StateFlag LAVA_FLOW = register(new StateFlag("lava-flow", true));
@@ -134,9 +136,20 @@ public final class Flags {
public static final LocationFlag TELE_LOC = register(new LocationFlag("teleport", RegionGroup.MEMBERS));
public static final LocationFlag SPAWN_LOC = register(new LocationFlag("spawn", RegionGroup.MEMBERS));
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag TELE_MESSAGE = register(new StringFlag("teleport-message",
LegacyComponentSerializer.INSTANCE.serialize(TextComponent.of("").append(TextComponent.of(
"Teleported you to the region '%id%'.", TextColor.LIGHT_PURPLE)))));
// idk?
public static final StateFlag INVINCIBILITY = register(new StateFlag("invincible", false));
public static final StateFlag FALL_DAMAGE = register(new StateFlag("fall-damage", true));
public static final StateFlag HEALTH_REGEN = register(new StateFlag("natural-health-regen", true));
public static final StateFlag HUNGER_DRAIN = register(new StateFlag("natural-hunger-drain", true));
// session and movement based flags
public static final StateFlag ENTRY = register(new StateFlag("entry", true, RegionGroup.NON_MEMBERS));
@@ -147,9 +160,29 @@ public final class Flags {
public static final StateFlag ENDERPEARL = register(new StateFlag("enderpearl", true));
public static final StateFlag CHORUS_TELEPORT = register(new StateFlag("chorus-fruit-teleport", true));
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag GREET_MESSAGE = register(new StringFlag("greeting"));
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag FAREWELL_MESSAGE = register(new StringFlag("farewell"));
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag GREET_TITLE = register(new StringFlag("greeting-title"));
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag FAREWELL_TITLE = register(new StringFlag("farewell-title"));
public static final BooleanFlag NOTIFY_ENTER = register(new BooleanFlag("notify-enter"));
@@ -173,14 +206,29 @@ public final class Flags {
public static final IntegerFlag MAX_FOOD = register(new IntegerFlag("feed-max-hunger"), f -> f.setSuggestedValues(VITALS_MAXS));
// deny messages
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag DENY_MESSAGE = register(new StringFlag("deny-message",
LegacyComponentSerializer.INSTANCE.serialize(TextComponent.of("").append(TextComponent.of("Hey!",
TextColor.RED, Sets.newHashSet(TextDecoration.BOLD)))
.append(TextComponent.of(" Sorry, but you can't %what% here.", TextColor.GRAY)))));
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag ENTRY_DENY_MESSAGE = register(new StringFlag("entry-deny-message",
LegacyComponentSerializer.INSTANCE.serialize(TextComponent.of("").append(TextComponent.of("Hey!",
TextColor.RED, Sets.newHashSet(TextDecoration.BOLD)))
.append(TextComponent.of(" You are not permitted to enter this area.", TextColor.GRAY)))));
/**
* @deprecated The type of this flag will change from a StringFlag to a ComponentFlag to support JSON text
* in a future release. If you depend on the type of this flag, take proper precaution for future breakage.
*/
@Deprecated
public static final StringFlag EXIT_DENY_MESSAGE = register(new StringFlag("exit-deny-message",
LegacyComponentSerializer.INSTANCE.serialize(TextComponent.of("").append(TextComponent.of("Hey!",
TextColor.RED, Sets.newHashSet(TextDecoration.BOLD)))
@@ -21,6 +21,8 @@ package com.sk89q.worldguard.protection.flags;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
/**
* Stores an Number.
*/
@@ -37,10 +39,20 @@ public abstract class NumberFlag<T extends Number> extends Flag<T> {
super(name);
}
/**
* Not recommended for public use. Will likely be moved when migrating to piston for commands.
* @param values suggested values
*/
@Beta
public void setSuggestedValues(Number[] values) {
this.suggestions = checkNotNull(values);
}
/**
* Not recommended for public use. Will likely be moved when migrating to piston for commands.
* @return suggested values
*/
@Beta
public Number[] getSuggestedValues() {
return suggestions;
}
@@ -46,6 +46,10 @@ import javax.annotation.Nullable;
* against it.
*
* <p>Instances can be modified and access from several threads at a time.</p>
*
* Note: this class has a natural ordering that is inconsistent with equals.
* Regions with identical ids (and also the same priority) may exist in different managers (or no manager at all),
* so care should be taken when comparing regions that have not been obtained from a single manager.
*/
public abstract class ProtectedRegion implements ChangeTracked, Comparable<ProtectedRegion> {
@@ -0,0 +1,75 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.protection.util;
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.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
/**
* A helper class to convert regions from WorldGuard to WorldEdit
*/
public final class WorldEditRegionConverter {
private WorldEditRegionConverter() {
}
/**
* Converts a ProtectedRegion to a WorldEdit Region, otherwise null if
* the ProtectedRegion can't be converted to a RegionSelector.
*
* @param region the WorldGuard region
* @return the WorldEdit Region
*/
public static Region convertToRegion(ProtectedRegion region) {
if (region instanceof ProtectedCuboidRegion) {
return new CuboidRegion(null, region.getMinimumPoint(), region.getMaximumPoint());
}
if (region instanceof ProtectedPolygonalRegion) {
return new Polygonal2DRegion(null, region.getPoints(),
region.getMinimumPoint().getY(), region.getMaximumPoint().getY());
}
return null;
}
/**
* Converts a ProtectedRegion to a WorldEdit RegionSelector, otherwise null if
* the ProtectedRegion can't be converted to a RegionSelector.
*
* @param region the WorldGuard region
* @return the WorldEdit Region
*/
public static RegionSelector convertToSelector(ProtectedRegion region) {
if (region instanceof ProtectedCuboidRegion) {
return new CuboidRegionSelector(null, region.getMinimumPoint(), region.getMaximumPoint());
}
if (region instanceof ProtectedPolygonalRegion) {
return new Polygonal2DRegionSelector(null, region.getPoints(),
region.getMinimumPoint().getY(), region.getMaximumPoint().getY());
}
return null;
}
}
@@ -48,6 +48,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.BiPredicate;
import java.util.logging.Level;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -57,11 +58,14 @@ public abstract class AbstractSessionManager implements SessionManager {
public static final int RUN_DELAY = 20;
public static final long SESSION_LIFETIME = 10;
private static final BiPredicate<World, LocalPlayer> BYPASS_PERMISSION_TEST = (world, player) -> {
return player.hasPermission("worldguard.region.bypass." + world.getName());
};
private final LoadingCache<WorldPlayerTuple, Boolean> bypassCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(2, TimeUnit.SECONDS)
.build(CacheLoader.from(tuple ->
tuple.getPlayer().hasPermission("worldguard.region.bypass." + tuple.getWorld().getName())));
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(CacheLoader.from(tuple -> BYPASS_PERMISSION_TEST.test(tuple.getWorld(), tuple.getPlayer())));
private final LoadingCache<CacheKey, Session> sessions = CacheBuilder.newBuilder()
.expireAfterAccess(SESSION_LIFETIME, TimeUnit.MINUTES)
@@ -134,8 +138,15 @@ public abstract class AbstractSessionManager implements SessionManager {
@Override
public boolean hasBypass(LocalPlayer player, World world) {
Session sess = getIfPresent(player);
return sess != null && !sess.hasBypassDisabled()
&& bypassCache.getUnchecked(new WorldPlayerTuple(world, player));
if (sess == null || sess.hasBypassDisabled()) {
return false;
}
if (WorldGuard.getInstance().getPlatform().getGlobalStateManager().disablePermissionCache) {
return BYPASS_PERMISSION_TEST.test(world, player);
}
return bypassCache.getUnchecked(new WorldPlayerTuple(world, player));
}
@Override
@@ -22,8 +22,11 @@ package com.sk89q.worldguard.session;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.config.ConfigurationManager;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
@@ -103,6 +106,14 @@ public class Session {
lastValid = location;
lastRegionSet = set.getRegions();
ConfigurationManager cfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager();
disableBypass = cfg.disableDefaultBypass;
if (cfg.announceBypassStatus && player.hasPermission("worldguard.region.toggle-bypass")) {
player.printInfo(TextComponent.of(
"You are " + (disableBypass ? "not" : "") + " bypassing region protection. " +
"You can toggle this with /rg bypass", TextColor.DARK_PURPLE));
}
for (Handler handler : handlers.values()) {
handler.initialize(player, location, set);
@@ -27,6 +27,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.TestPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.association.RegionOverlapAssociation;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
@@ -37,10 +38,14 @@ import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@RunWith(Parameterized.class)
public abstract class RegionOverlapTest {
static String COURTYARD_ID = "courtyard";
static String FOUNTAIN_ID = "fountain";
@@ -59,6 +64,14 @@ public abstract class RegionOverlapTest {
TestPlayer player1;
TestPlayer player2;
@Parameterized.Parameters(name = "{index}: useMaxPrio = {0}")
public static Iterable<Object[]> params() {
return Arrays.asList(new Object[][]{{true}, {false}});
}
@Parameterized.Parameter
public boolean useMaxPriorityAssociation;
protected FlagRegistry getFlagRegistry() {
return WorldGuard.getInstance().getFlagRegistry();
}
@@ -104,6 +117,7 @@ public abstract class RegionOverlapTest {
ProtectedRegion region = new ProtectedPolygonalRegion(COURTYARD_ID, points, 0, 10);
region.setOwners(domain);
region.setPriority(5);
manager.addRegion(region);
courtyard = region;
@@ -116,6 +130,7 @@ public abstract class RegionOverlapTest {
ProtectedRegion region = new ProtectedCuboidRegion(FOUNTAIN_ID,
BlockVector3.ZERO, BlockVector3.at(5, 5, 5));
region.setMembers(domain);
region.setPriority(10);
manager.addRegion(region);
fountain = region;
@@ -168,10 +183,6 @@ public abstract class RegionOverlapTest {
public void testPlayer2BuildAccess() {
ApplicableRegionSet appl;
HashSet<ProtectedRegion> test = new HashSet<>();
test.add(courtyard);
test.add(fountain);
// Outside
appl = manager.getApplicableRegions(outside);
assertTrue(appl.testState(player2, Flags.BUILD));
@@ -182,4 +193,61 @@ public abstract class RegionOverlapTest {
appl = manager.getApplicableRegions(inFountain);
assertTrue(appl.testState(player2, Flags.BUILD));
}
@Test
public void testNonPlayerBuildAccessInOneRegion() {
ApplicableRegionSet appl;
HashSet<ProtectedRegion> source = new HashSet<>();
source.add(courtyard);
RegionOverlapAssociation assoc = new RegionOverlapAssociation(source, useMaxPriorityAssociation);
// Outside
appl = manager.getApplicableRegions(outside);
assertTrue(appl.testState(assoc, Flags.BUILD));
// Inside courtyard
appl = manager.getApplicableRegions(inCourtyard);
assertTrue(appl.testState(assoc, Flags.BUILD));
// Inside fountain
appl = manager.getApplicableRegions(inFountain);
assertFalse(appl.testState(assoc, Flags.BUILD));
}
@Test
public void testNonPlayerBuildAccessInBothRegions() {
ApplicableRegionSet appl;
HashSet<ProtectedRegion> source = new HashSet<>();
source.add(fountain);
source.add(courtyard);
RegionOverlapAssociation assoc = new RegionOverlapAssociation(source, useMaxPriorityAssociation);
// Outside
appl = manager.getApplicableRegions(outside);
assertTrue(appl.testState(assoc, Flags.BUILD));
// Inside courtyard
appl = manager.getApplicableRegions(inCourtyard);
assertTrue(useMaxPriorityAssociation ^ appl.testState(assoc, Flags.BUILD));
// Inside fountain
appl = manager.getApplicableRegions(inFountain);
assertTrue(appl.testState(assoc, Flags.BUILD));
}
@Test
public void testNonPlayerBuildAccessInNoRegions() {
ApplicableRegionSet appl;
HashSet<ProtectedRegion> source = new HashSet<>();
RegionOverlapAssociation assoc = new RegionOverlapAssociation(source, useMaxPriorityAssociation);
// Outside
appl = manager.getApplicableRegions(outside);
assertTrue(appl.testState(assoc, Flags.BUILD));
// Inside courtyard
appl = manager.getApplicableRegions(inCourtyard);
assertFalse(appl.testState(assoc, Flags.BUILD));
// Inside fountain
appl = manager.getApplicableRegions(inFountain);
assertFalse(appl.testState(assoc, Flags.BUILD));
}
}