Compare commits

...
163 Commits
Author SHA1 Message Date
sk89q 9cf85caf3c Set version to 6.1. 2015-06-08 15:04:59 -07:00
sk89q 2f1343f408 Updated changelog for v6.1. 2015-06-08 15:04:52 -07:00
wizjany 3cb6c4e46f Check both attacker and defender locations for PvP.
Fixes WORLDGUARD-3494.
2015-06-08 14:37:32 -07:00
sk89q 7f9b850288 Always generate Javadocs and sources .jar. 2015-06-08 14:37:32 -07:00
sk89q e8d4f2fd84 Turn off doclint. 2015-06-08 14:37:32 -07:00
sk89q f3891aaaf9 Add a workaround for incorrect piston retract information. 2015-06-03 23:46:24 -07:00
wizjany ea75549a29 Clean up Heal and Feed flags.
Allow the flags to increase values for players who are invincible (or in creative mode),
but not decrease them.
Fixes WORLDGUARD-3492.
2015-06-04 02:02:53 -04:00
wizjany fbd8206038 Check for connected chests.
Fixes WORLDGUARD-3021.
2015-05-29 03:56:14 -04:00
wizjany 522ac459db Fix weather lock flag.
Probably. Maybe.
Fixes WORLDGUARD-3452.
2015-05-29 02:26:32 -04:00
wizjany 255dd2d41a Add support for Spigot's BlockExplodeEvent.
Also update Bukkit dependency and guava version quirks.
Fixes WORLDGUARD-3484.
2015-05-29 01:49:20 -04:00
wizjany cf1716ff37 Separate vehicles and animals from INTERACT flag.
Destroying vehicles now checks only the vehicle-destroy flag.
Damaging animals checks the new damage-animals flag.
These are both allowed for members by default, like other build-dependent flags.

Fixes WORLDGUARD-3427 and WORLDGUARD-3358.
2015-05-28 17:21:58 -04:00
sk89q a277e69e9c Get the session during the gamemode event lazily. 2015-05-28 11:28:02 -07:00
sk89q ec5bb32510 Add -s to show stack traces with the event debugging command. 2015-05-27 22:18:30 -07:00
Wizjany 8ddb7d4b99 Don't add a period for custom blacklist messages.
Fixes WORLDGUARD-3472
2015-05-02 22:38:42 -04:00
Wizjany 3258bff2d1 Fix CommandFilter matching emoticons etc.
Fixes WORLDGUARD-3461.
2015-04-18 12:01:21 -04:00
Wizjany 8d7d32a2d2 Check event cancellation before playing deny effect for bucket events. 2015-04-05 15:44:43 -04:00
Wizjany a907eb2348 Move repeaters/comparators from use to build.
This should mirror the protection given in WG 5.9.
2015-03-13 23:34:22 -04:00
wizjany 32132b5b0a Protect against spawn egg usage.
Fixes WORLDGUARD-3347.
2015-03-11 01:46:55 -04:00
wizjany c0c7c3215e Mark Player/Group Domains as dirty in a few missing places.
Fixes WORLDGUARD-3404.
2015-03-11 00:44:41 -04:00
Wizjany ddf0f41061 Actually register WorldRulesListener for events.
Fixes WORLDGUARD-3406.
2015-03-03 13:09:50 -05:00
Wizjany d3ecbcb18a Protect switching inverted daylight detectors too. 2015-02-28 18:39:54 -05:00
wizjany b7f4262978 Add comparators to USE too for consistency. 2015-02-19 21:21:17 -05:00
wizjany 60e6f92c64 Have repeaters be covered by the USE flag. 2015-02-19 21:17:45 -05:00
wizjany 98af7966cd Added weather-lock flag.
Valid values are clear or downfall. Unset to restore to normal world weather.
2015-02-18 02:24:31 -05:00
wizjany 99d042d260 Added time-lock flag.
Valid values are 0 to 24000 for absolute time, or +- any number for relative time.
Closes WORLDGUARD-3379.
2015-02-18 01:59:30 -05:00
wizjany c9d6166fcb Check for null task fields.
Fixes WORLDGUARD-3372.
2015-02-17 16:51:02 -05:00
sk89q 752ccec150 Don't call initialize() on non-cancellable movements.
Fixes WORLDGUARD-3362.
2015-02-11 17:12:10 -08:00
sk89q 91ccb95672 Add classloader override to the build POM. 2015-02-11 17:09:10 -08:00
wizjany 4caff457d3 Add Citizens NPCs to NPC detection for region whitelisting.
Fixes WORLDGUARD-3356.
2015-02-04 17:03:01 -05:00
wizjany a1a6ee7107 Fixed blocks (e.g. sugar canes) adjacent to physics blocks (e.g. sand) not updating.
Fixes WORLDGUARD-3367. This change MAY have breaking unintended consequences,
but the physics configs seem to still be working.
2015-02-04 03:33:37 -05:00
sk89q af157b88bd Handle empty sets in SetFlag. 2015-01-30 00:03:25 -08:00
sk89q ea4f4c088b Have enderchests be covered by the USE flag.
Fixes WORLDGUARD-3336.
2015-01-28 01:36:07 -08:00
sk89q 6559ed5c1a Have tripwire be covered by the USE flag.
Fixes WORLDGUARD-3351.
2015-01-28 01:35:17 -08:00
sk89q deddcf8dd2 Handle null block attacker.
Fixes WORLDGUARD-3350.
2015-01-28 01:26:50 -08:00
sk89q dfe536a2d2 Fix issues with MC 1.7 compatibility. 2015-01-28 01:11:36 -08:00
sk89q 5bfb348354 Add a fall-damage flag.
Closes WORLDGUARD-2279.
2015-01-28 01:01:43 -08:00
sk89q afcf93b7b1 Reset handler caches when a move type is non-cancellable. 2015-01-27 15:21:56 -08:00
sk89q e1843624bb Add exit-via-teleport flag (default allow). 2015-01-27 15:01:01 -08:00
wizjany 0f4e7b5061 Creeper explosions with a player target cause should no longer be ignored.
Also fixed primed tnt being checked twice for tnt flags. TNT Minecarts are not included, as was prior behavior.
Fixes WORLDGUARD-3344
2015-01-24 23:00:19 -05:00
wizjany 869ead63bc Fix armor stands to behave more like item frames.
Placing and modifying them respects permissions, and  they are no longer blocked by mob-spawning deny.
2015-01-24 17:02:55 -05:00
sk89q 6a6de7802b Fix missing material data for 1.8 items.
Fixes WORLDGUARD-3306.
2015-01-22 21:42:53 -08:00
sk89q b50302d9d0 Set version back to 6.0.0-SNAPSHOT. 2015-01-20 19:28:22 -08:00
sk89q c841d74aaf Set version to 6.0.0-beta-05. 2015-01-20 19:26:39 -08:00
sk89q 09cce39aff Update changelog for 6.0 beta 5. 2015-01-20 19:25:34 -08:00
sk89q e5b76a571b Always call boundary crossing handlers. 2015-01-20 19:24:55 -08:00
sk89q 7c58fa4be6 Add BukkitUtil.toRegion(Chunk).
Closes WORLDGUARD-3292.
2015-01-19 23:19:44 -08:00
sk89q f150a41d72 Ensure that region properties are immutable. 2015-01-19 23:11:28 -08:00
sk89q bca1c2bdb3 Fix region intersection tests involving polygons.
Fixes WORLDGUARD-3216.
2015-01-19 22:56:16 -08:00
sk89q 47a8bcc442 Floor components in getApplicableRegions(Location).
Fixes WORLDGUARD-3288.
2015-01-19 19:22:15 -08:00
sk89q 83cad75916 Fix /wg flushstates not doing anything. 2015-01-19 19:04:49 -08:00
sk89q 6b5a12105e Group together invincibility listeners.
Fixes WORLDGUARD-3315.
2015-01-19 19:03:54 -08:00
sk89q 451b679323 Track cause through targets.
Fixes WORLDGUARD-3314.
2015-01-19 18:28:41 -08:00
sk89q 66a8bfd5b1 Fix typo in region gamemode change log message. 2015-01-19 14:12:04 -08:00
sk89q 2a2b2f6f64 Limit the cause chain to 40 items. 2015-01-19 14:08:53 -08:00
sk89q 73dea11de2 Restore game mode flag logic to pre-refactor version.
Fixes WORLDGUARD-3320.
2015-01-19 13:23:23 -08:00
wizjany 9998a6c930 Restore Java 6 compatibility. 2015-01-19 15:01:43 -05:00
wizjany 5111d40aaf Add colorification to entry and exit messages as well. 2015-01-19 14:23:04 -05:00
sk89q 972ccaed7e Rename InteropUtil -> InteropUtils. 2015-01-19 11:20:53 -08:00
sk89q f7d36bc1f3 Protect enderchests as well. 2015-01-19 11:20:23 -08:00
sk89q 8073945af0 Fix color codes in greeting/farewell messages.
Fixes WORLDGUARD-3319.
2015-01-19 11:17:06 -08:00
sk89q 91353d6b01 Improve fake player detection. 2015-01-19 03:23:52 -08:00
sk89q bfbcc8dcf8 Fix a typo in the class source warning message. 2015-01-19 01:55:56 -08:00
sk89q 8f65798141 Check when plugins shade WorldGuard inappropriately. 2015-01-19 01:54:23 -08:00
sk89q fdddb17d2f TypeToken is not available on old Guava. 2015-01-17 19:26:33 -08:00
sk89q 520f9e3fcf Check movement with vehicle enter. 2015-01-17 19:25:15 -08:00
sk89q a3d2a1b127 Don't call boundary crossing handlers unless a boundary was crossed. 2015-01-17 19:17:17 -08:00
sk89q 7ecf73165b Handle entry flag only on boundary crossing. 2015-01-17 19:17:02 -08:00
sk89q e90a7ed075 Add new exit-override flag instead of fiddling with default exit flag values. 2015-01-17 19:13:25 -08:00
sk89q aae521b727 Rewrite session and movement flag code.
Also adds entry-deny-message and exit-deny-message.

Fixes WORLDGUARD-3086, WORLDGUARD-2542, WORLDGUARD-2731.
2015-01-17 18:54:10 -08:00
sk89q 643345b459 Add Locations.isDifferentBlock(). 2015-01-17 15:04:42 -08:00
sk89q a62d9f5617 Reuse set in RegionResultSet for getRegions(). 2015-01-17 14:29:14 -08:00
sk89q 2f3f76c8cf Funnel pre-allowed events too.
Fixes WORLDGUARD-3308.
2015-01-16 15:43:13 -08:00
sk89q a03aaa45b1 Revert "Have the PvP flag apply to self-attack."
This reverts commit d8dd86dfe8.

Fixes WORLDGUARD-3312.
2015-01-16 14:22:46 -08:00
sk89q 372155b5c3 Don't check player inventories for protection.
Fixes WORLDGUARD-3309, WORLDGUARD-3310.
2015-01-16 14:20:01 -08:00
sk89q 159de771bf Fix build perms item use event not working correctly. 2015-01-15 18:42:26 -08:00
sk89q 41d922cb27 Add special case for global regions in RegionOverlapAssociation too. 2015-01-15 16:49:07 -08:00
sk89q 6a4fac63e8 Change version back to 6.0.0-SNAPSHOT. 2015-01-13 12:44:17 -08:00
sk89q 3daf8db113 Bump to 6.0.0 beta 04. 2015-01-13 12:42:11 -08:00
sk89q 9c62a35e07 Update CHANGELOG for 6.0 beta 4. 2015-01-13 12:29:43 -08:00
sk89q 931f438b14 Add material flags for MC 1.8.
Fixes WORLDGUARD-3306.
2015-01-13 12:19:53 -08:00
sk89q 3109612c1b Expand the USE flag to cover 1.8 doors and gates.
Fixes WORLDGUARD-3304.
2015-01-13 12:12:12 -08:00
sk89q e4d63ffbcc Permit org.json.simple package usage. 2015-01-13 03:24:00 -08:00
sk89q 866a554d30 Shade JSON simple. 2015-01-13 03:23:49 -08:00
sk89q ab2811ed2d Remove boot class / library path report values. 2015-01-13 03:19:47 -08:00
sk89q 8cc7bcc849 Improve report output. 2015-01-13 02:44:58 -08:00
sk89q 547e89b85d Add CPU profiling with WarmRoast "lite." 2015-01-13 01:49:59 -08:00
sk89q 477f1188df Use EH pastebin and remove debug code. 2015-01-12 22:19:49 -08:00
sk89q d9e4b27cd2 Handle PlayerInteractAtEntityEvent again.
Fixes WORLDGUARD-3291.
2015-01-11 02:34:12 -08:00
sk89q 37f39eaf66 Use a less coarse can-interact-on-click check.
Fixes WORLDGUARD-3303.
2015-01-11 02:05:31 -08:00
sk89q 223d22e79f Fire UseEntityEvent for InventoryOpenEvent for entities. 2015-01-11 00:10:52 -08:00
sk89q 04214a96eb Ignore unknown cause entity damage.
Fixes WORLDGUARD-3293.
2015-01-11 00:08:41 -08:00
sk89q f40cb69f38 Ignore unknown cause hanging breaks.
Fixes WORLDGUARD-3301.
2015-01-11 00:05:07 -08:00
sk89q 6c1489d434 Make NormativeOrders non-instantiable. 2015-01-10 23:44:31 -08:00
sk89q 6fe63838f5 testState(relevant flags) == DENY on whitelist cases.
Fixes WORLDGUARD-3294.
2015-01-10 23:31:24 -08:00
sk89q d883c22d64 Document flag classes and make BUILD slightly less magic. 2015-01-10 23:15:32 -08:00
sk89q 3bd1c869f1 Sort applicable regions by inheritance too. 2015-01-10 22:45:15 -08:00
sk89q e7273aaf6f ALLOW on a child region should override DENY on a parent. 2015-01-10 18:37:28 -08:00
zml 6e02f80f6c Pass Player objects during WEPIF permission checks 2015-01-10 16:14:17 -08:00
sk89q 01276dfc62 Fix incorrect region group inheritance and broken flag override in children. 2015-01-09 13:21:17 -08:00
sk89q f516fd5e54 Have on-acquire also check inventory transfers.
Fixes WORLDGUARD-2752.
2015-01-08 15:43:02 -08:00
sk89q 79612915a7 Fix NPE caused by flag value permissions. 2015-01-08 14:29:06 -08:00
sk89q f04f9093bc Add &r as a reset color code.
Closes WORLDGUARD-3286.
2015-01-08 13:40:57 -08:00
sk89q 9dac950faf Fix a little typo in the UPGRADE document. 2015-01-08 11:58:20 -08:00
sk89q f2a8ff3f64 Add missing wood plate to USE flag. 2015-01-08 11:25:19 -08:00
sk89q b78317dd42 Add color code support to the blacklist.
Fixes WORLDGUARD-3284.
2015-01-08 11:24:22 -08:00
sk89q 048dd25099 Remove outdated information in the upgrade document. 2015-01-08 01:14:12 -08:00
sk89q 0900289437 Add permissions for individual flag values.
Closes WORLDGUARD-3103.
2015-01-08 01:04:36 -08:00
sk89q d8dd86dfe8 Have the PvP flag apply to self-attack.
Closes WORLDGUARD-3278.
2015-01-08 00:35:30 -08:00
sk89q 9a569d7ed8 Don't throw internal DamageEntityEvents for unknown cause entity combusts.
Fixes WORLDGUARD-3277.
2015-01-08 00:32:57 -08:00
sk89q 53132ce83a Add support for slightly older versions of Bukkit 1.7.9. 2015-01-08 00:25:07 -08:00
sk89q c3bdc33215 Set version to 6.0.0-SNAPSHOT. 2015-01-07 18:51:07 -08:00
sk89q c6bf8ceb5c Bump version to 6.0.0-beta-03. 2015-01-07 18:49:34 -08:00
sk89q 792d041078 Update CHANGELOG. 2015-01-07 18:48:58 -08:00
sk89q cb965c9bf9 Update the UPGRADE document. 2015-01-07 18:42:57 -08:00
sk89q f33889b88f Support both MC 1.7.10 and 1.8. 2015-01-07 18:07:30 -08:00
sk89q e747e3a3fa Bump Bukkit dependency to 1.7.9-R0.3-SNAPSHOT. 2015-01-07 16:28:26 -08:00
sk89q fd460337f4 Don't apply the region override permission to PvP. 2015-01-06 15:14:30 -08:00
sk89q 38c9479385 Fix incorrect detection of hostile and ambient creatures. 2015-01-06 15:01:07 -08:00
sk89q da032cb04e Fix the splash potion flag not working with the other flags.
Fixes WORLDGUARD-3274.
2015-01-06 15:00:54 -08:00
sk89q 37a80338f5 Adjust USE flag material filter to include the proper items. 2015-01-05 13:31:14 -08:00
sk89q 8a5f233e84 Use an interact event for non-damaging splash potions.
Fixes WORLDGUARD-3184.
2015-01-04 19:54:34 -08:00
sk89q e3a9131929 Fix potion blocking.
Fixes WORLDGUARD-3207
2015-01-04 19:43:55 -08:00
sk89q bab98d5463 Fix broken recursive dump in DataReport. 2015-01-04 19:19:53 -08:00
sk89q 4333b39377 Consider enchantment table + workbench MODIFIED_ON_CLICK. 2015-01-04 19:13:07 -08:00
sk89q 8bd427a6ab Make PASSTHROUGH=DENY useful on __global__. 2015-01-04 18:58:00 -08:00
sk89q d3493a3361 Fix missing __global__ constant. 2015-01-04 18:51:32 -08:00
sk89q 51982cda28 Do a better check of the global region. 2015-01-04 18:51:18 -08:00
sk89q a2e14bc76a Fix issues caused by adding members to __global__.
Fixes WORLDGUARD-3195.
2015-01-04 18:44:57 -08:00
sk89q c050d274f5 Make the EXP_DROPS flag a build-compat flag and set its deny message.
Fixes WORLDGUARD-3231.
2015-01-04 18:26:11 -08:00
sk89q bdff22cbac Give the player back his/her XP bottle if it was blocked. 2015-01-04 18:20:33 -08:00
sk89q 7da10198e3 Expand interaction whitelist to "physical" events.
Closes WORLDGUARD-3238.
2015-01-04 18:05:50 -08:00
sk89q b11e2b3d11 Catch command prefixes in the filter.
Fixes WORLDGUARD-3196.
2015-01-04 17:56:00 -08:00
sk89q c95b619974 Add a RIDE flag for vehicles. 2015-01-04 17:52:32 -08:00
sk89q e61b2e18c1 Also permit hoppers. 2015-01-04 16:09:57 -08:00
sk89q e9d64dbf03 Check for names in addition to UUIDs with /rg list. 2015-01-04 14:25:04 -08:00
sk89q 3c8121d088 Whitelist hoppers and let them cross regions regardless of permissions. 2015-01-04 13:57:03 -08:00
sk89q 93ced5ca7a Revert USE flag's functionality to 5.x, add new INTERACT flag. 2015-01-04 13:50:48 -08:00
sk89q 7580583fbf Fix spawn egg blocking.
Closes WORLDGUARD-3254.
2014-12-31 02:30:58 -08:00
sk89q 41c68664d7 Fix failed detection of incorrect blacklist names. 2014-12-31 02:30:31 -08:00
sk89q c8393cdcec Fix bypass with the block op configuration. 2014-12-31 02:13:35 -08:00
sk89q 42d12e4fa8 Reorganize some packages. 2014-12-31 02:05:47 -08:00
sk89q bed9bd77a6 Merge pull request #336 from ST-DDT/configLoadExceptions
Show more details in error log which world the error belongs to.
2014-12-31 01:59:57 -08:00
sk89q f3c2390fbb Attempt to clean up the move listener. 2014-12-31 01:41:41 -08:00
sk89q 83a7ed58a5 Cache bypass permission checks in the move listener.
Some permission plugins are slow.
2014-12-31 01:39:11 -08:00
sk89q ddc1f77825 Move move listener to a new class. 2014-12-31 01:31:30 -08:00
sk89q 88169236cb Rewrite and update report generation. 2014-12-31 01:18:23 -08:00
sk89q 0cb36b3b8b Remove ArrayReader and FatalConfigurationLoadingException. 2014-12-30 22:37:54 -08:00
sk89q ce169461a3 Add event cancellation debug commands. 2014-12-30 20:05:42 -08:00
sk89q 18ec3db1bb Modernize pastebin code. 2014-12-30 17:41:56 -08:00
sk89q 53fdff1d9b Add hack to make Location flags work with unloaded worlds. 2014-12-29 16:35:22 -08:00
ST-DDT 9a91336958 Show more details in error log which world the error belongs to. 2014-12-19 13:55:18 +01:00
sk89q 7bd69bebf4 Add missing color codes when parsing input. 2014-11-14 12:57:38 -08:00
sk89q 57b6f04b79 Let players use NPCs always.
Fixes WORLDGUARD-3190.
2014-11-11 00:32:42 -08:00
sk89q c7442c2a9e Fix [WorldGuard] in log messages stacking on reloads.
Fixes WORLDGUARD-3192.
2014-11-11 00:29:25 -08:00
sk89q df985013eb Handle null EntityTypes from SpawnEggs.
Fixes WORLDGUARD-3179.
2014-11-11 00:02:54 -08:00
sk89q 41f520845a Better handle empty group / player names due to bad region data.
Fixes WORLDGUARD-3182.
2014-11-10 23:59:57 -08:00
sk89q dac09c64c8 Fix players being invincible with BUILD = deny.
Fixes WORLDGUARD-3201.
2014-11-10 23:56:11 -08:00
sk89q a2defe5971 Fix certain entities not being damaged in protected regions. 2014-11-10 23:52:53 -08:00
sk89q ba4e5d6ea9 Improve entity detection in Entities utility class, add Entities.isNonPlayerCreature(). 2014-11-10 23:52:53 -08:00
sk89q 25f12e9733 Remove CraftBukkit runtime dependency in pom.xml. 2014-09-18 20:32:59 -07:00
sk89q ca37dc0fc6 Merge pull request #328 from zreed/master
Add missing SQL table prefix in statement selecting world names.
2014-09-02 23:30:26 -07:00
zreed 7d41835794 Add missing SQL table prefix in statement selecting world names. 2014-09-02 17:05:28 -04:00
sk89q b37014463f Reset version back to 6.0.0-SNAPSHOT. 2014-08-31 20:04:04 -07:00
152 changed files with 7959 additions and 2728 deletions

No files matched your search

+118
View File
@@ -1,5 +1,123 @@
# Changelog
## 6.1
* Added `exit-via-teleport` flag (default allow) to control exiting an exit=deny region via teleportation.
* Added a `fall-damage` flag to control player damage caused by falling.
* Added a `time-lock` flag to lock players' time of day. Valid values are from 0 to 24000 for absolute time, or +- any number for relative time.
* Added a `weather-lock` flag to lock players' weather. Valid values are "clear" or "downfall". Unset to restore to normal world weather.
* Added `-s` to the event debugging commands to show a stack trace rather than attempt to detect the causing plugin.
* Added support for using the `-e` argument (sets an empty value for the flag) in the flag set command when the type of flag is of the 'set' type.
* Added NPCs from the Citizens plugin to a whitelist so they are not protected.
* Added support for Spigot's BlockExplodeEvent.
* Changed tripwire to fall under the `use` flag.
* Changed enderchests to fall under the `use` flag.
* Changed vehicles and animals so they are not included in the `interact` flag.
* Changed the display of custom blacklist messages to no longer include a period at the end.
* Changed protection logic to consider connected chests.
* Changed the heal and feed flags to increase values for players who are invincible (or in creative mode) but not decrease them.
* Changed PvP protection to consider both attacker and defender locations.
* Fixed missing protection data for some 1.8-added blocks.
* Fixed compatibility issues with MC 1.7.
* Fixed inverted daylight detectors not being protected.
* Fixed spawn eggs not being included in protection.
* Fixed piston blocking not working due to a bug in Spigot.
* Fixed the blocking of certain invalid entity damage events.
* Fixed creeper explosions not being blocked in certain situations with explosion related flags set.
* Fixed "stickiness" with some position-related flags, sometimes resulting in rubber banding in the exit flags.
* Fixed armor stands so that they are treated more like item frames than mobs.
* Fixed blocks (e.g. sugar canes) adjacent to physics blocks (e.g. sand) not updating.
* Fixed a NullPointerException that occurred sometimes when generating the scheduler section of the report function (`/wg report`).
* Fixed the "no XP drops" configuration not functioning following a previous release.
* Fixed changes to region ownership sometimes not triggering a region database save.
* Fixed bucket protection displaying the "deny effect" even if bucket use was not prevented.
* Fixed CommandFilter matching emoticons and other unwanted characters.
* Fixed an exception occurring sometimes during game mode changes.
* Fixed primed TNT being checked twice for TNT flags.
## 6.0 beta 5
MC 1.7.9, 1.7.10 and 1.8 (Spigot only) are supported.
* Added a feature to detect when another plugin (incorrectly) includes WorldGuard's files, causing errors.
* Added a new `exit-override` flag that can be used on an entry=allow region that players can walk into from an entry=deny region.
* Added a new `entry-deny-message` to change the "entry denied" message.
* Added a new `exit-deny-message` to change the "exit denied" message.
* Changed entry/exit blocking to disembark players from their vehicles.
* Changed the PvP flag to no longer apply to self-attack.
* Fixed [#3220](http://youtrack.sk89q.com/issue/WORLDGUARD-3220): Polygon regions sharing points
* Fixed [#3216](http://youtrack.sk89q.com/issue/WORLDGUARD-3216): Polygon regions 'disappearing' or not working correctly
* Fixed [#3315](http://youtrack.sk89q.com/issue/WORLDGUARD-3315): Invincibility flag and mode not blocking knockback from snowballs, etc.
* Fixed [#3314](http://youtrack.sk89q.com/issue/WORLDGUARD-3314): Protection bypassable by getting a skeleton or creeper to target a player
* Fixed [#3326](http://youtrack.sk89q.com/issue/WORLDGUARD-3326): Enderchests cannot be protected with the use flag
* Fixed [#3327](http://youtrack.sk89q.com/issue/WORLDGUARD-3327): Fake players from some Forge mods are not being detected properly
* Fixed [#3328](http://youtrack.sk89q.com/issue/WORLDGUARD-3328): TypeToken error with CraftBukkit 1.7 in `/wg report`
* Fixed [#3086](http://youtrack.sk89q.com/issue/WORLDGUARD-3086): Region entry / exit messages overlap between seprate worlds
* Fixed [#2542](http://youtrack.sk89q.com/issue/WORLDGUARD-2542): Exit deny regions don't handle respawn / logout consistently
* Fixed [#2731](http://youtrack.sk89q.com/issue/WORLDGUARD-2731): Greeting / farewell messages don't understand region inheritance
* Fixed [#3308](http://youtrack.sk89q.com/issue/WORLDGUARD-3308): Enderchest interaction block not functioning with blacklist.txt
* Fixed [#3312](http://youtrack.sk89q.com/issue/WORLDGUARD-3312): PVP flag blocking enderpearl teleport fall damage
* Fixed [#3309](http://youtrack.sk89q.com/issue/WORLDGUARD-3309): Inventory view commands being blocked in protected regions
* Fixed [#3310](http://youtrack.sk89q.com/issue/WORLDGUARD-3310): USE flag is not allowing workbench usage
* Fixed [#3330](http://youtrack.sk89q.com/issue/WORLDGUARD-3330): Build permissions preventing block placement
* API: Added `BukkitUtil.toRegion(Chunk)`
## 6.0 beta 4
MC 1.7.9, 1.7.10 and 1.8 (Spigot only) are supported.
* Added better support for MC 1.8 blocks (regarding the use flag, etc.).
* Added an an experimental "lite" version of WarmRoast to CPU profile your server (try it: `/wg profile -p`)
* Added permissions for individual flag values (i.e. `worldguard.region.flag.flags.use.allow`).
* Added support for slightly older versions of Bukkit 1.7.9.
* Improved `/wg report`'s output (try it: `/wg report -p`)
* Fixed armor stands not being protected properly.
* Fixed lack of wood plate support with the `USE` flag.
* Fixed left click also being blocked when only right click needed to be blocked.
* Fixed items and paintings/item frames not decaying under some versions of Spigot.
* Fixed parent-child inheritance so the child will always inherit the parent.
* Fixed inheritance issues with a flag is set with a region group on a parent region.
* Fixed high CPU usage when Citizens is also installed.
* Fixed `on-acquire` in the blacklist so it also handles item transfers between inventories.
* Fixed the blacklist not supporting color codes.
* Changed the PvP flag so it applies to self-attack like in WG 5 (this change *may* be reverted).
## 6.0 beta 3
MC 1.7.10 and 1.8 (Spigot only) are supported.
* Support both MC 1.7.10 and 1.8.
* Don't apply the region override permission to PvP.
* Fix incorrect detection of hostile and ambient creatures when protecting against PvE.
* Fix the splash potion flag not working with the other flags.
* Fix potion blocking.
* Fix inability to blacklist the enchantment table and the workbench.
* Make PASSTHROUGH=DENY useful on ``__global__``.
* Fix issues (pistons broken, etc.) caused by adding members to ``__global__``.
* Make the EXP_DROPS flag a build-compat flag and set its deny message.
* Give the player back his/her XP bottle if it was blocked.
* Expand the interaction whitelist configuration to "physical" events.
* Catch command prefixes in the command flags.
* Add a RIDE flag for vehicles.
* Check for names in addition to UUIDs with /rg list.
* Whitelist hoppers and let them cross regions regardless of region protection.
* Revert USE flag's functionality to 5.x, add new INTERACT flag.
* Fix spawn egg blocking.
* Fix failed detection of incorrect blacklist block and item names.
* Fix command prefix bypass with the op command blocking configuration.
* Rewrite and update report generation (wg report).
* Add event cancellation debug commands.
* Fix location flags causing NullPointerExceptions.
* Show more details in error log which world the error belongs to.
* Add missing color codes when parsing input.
* Let players use NPCs always.
* Fix [WorldGuard] in log messages stacking on reloads.
* Better handle empty group / player names due to bad region data.
* Fix players being invincible with BUILD=deny.
* Fix certain entities not being damaged in protected regions.
* Improve entity detection in Entities utility class, add Entities.isNonPlayerCreature().
* Add missing SQL table prefix in statement selecting world names.
## 6.0 beta 2
* Added an `-e` parameter to `/rg flag` that sets the flag to an empty value. You can use this to, for example, make it so the `deny-message` flag is empty, meaning that players won't get a message at all.
+33 -121
View File
@@ -1,143 +1,55 @@
# Upgrading to WorldGuard 6
Version 6 is a __MAJOR UPGRADE__ to WorldGuard so we recommend:
This is a **major upgrade**. However, it is relatively well-tested because many people have *accidentally* updated to version 6 when the Spigot team updated WorldGuard for 1.8 but did not update v5.9.
* Making backups of your worlds
* Making backups of your WorldGuard configuration
The version that you downloaded supports Minecraft 1.7.10 and 1.8.
(Periodical backups are recommended anyway.)
**NEW DOCUMENTATION:** There is [new work-in-progress documentation](http://docs.enginehub.org/manual/worldguard/latest/). However, refer to the [older wiki](http://wiki.sk89q.com/wiki/WorldGuard) for missing pages.
You can upgrade from any version of WorldGuard 5.
## Downgrading to 5.9
It is __NOT POSSIBLE TO DOWNGRADE__ after upgrading to WorldGuard 6 without loss of data due to the conversion to UUIDs. Do NOT downgrade WorldGuard once you have installed version 6.
When updating to v6, your region data will be updated to use player UUIDs rather than their names. That means that you **cannot downgrade** to WG 5.9 because it does not understand UUIDs and will remove all ownership data. However, you can use [Six2Five](https://github.com/sk89q/Six2Five/releases/tag/release-1.0) to downgrade region data stored as YAML.
If downgrading becomes necessary, please file a ticket on our issue tracker.
Remember to make backups.
If this is a __BETA BUILD__ or __SNAPSHOT BUILD__, then you should re-read this document every new release until after you have upgraded to a final release. Breaking changes may be added until the final release.
If you do not use region protection, then downgrading requires no extra steps.
You have downloaded version ${project.version}.
## What's Changed?
## Reporting problems
There have been many changes, but the most important (and breaking ones) are listed below.
You can report bugs that you encounter on our [issue tracker](http://youtrack.sk89q.com) and [ask questions on our forum](http://forum.sk89q.com).
### Region Protection
## Breaking changes
The region protection has been optimized and aggressive caching has been added. That means that the impact of region protection when hundreds or thousands of regions exist has been minimized.
Be aware of these breaking changes:
* UUID support was added. On first server start, your region data will be converted to use UUIDs. Names that lack a UUID (i.e. they refer to accounts that don't exist) will remain, but can be removed by re-running the conversion (see the config) after changing the configuration to remove unconverted names.
* Build protection for regions is now much more complete, and WorldGuard protects against entities and blocks making changes as if they were players. For example, TNT cannot be flung into a protected region and piston machines cannot push into a protected region. Liquid flow (lava and water) can also be checked, although this is disabled by default.
* Setting the `build` flag to `deny` will break pistons and Redstone. When you set the `build` flag to `deny`, you are essentially saying that *no one* can build at all. Now that blocks and entities are considered the same as players, they get blocked in that case. What's the solution? First of all, you probably do **not** want to set the build flag: remember, when you create a region, only members can build in it, so there's no need to change the `build` flag.
* If you want to deny building "in the wilderness," use `/rg flag __global__ passthrough deny`. Unset the `build` flag if you had set it to `deny`. As you may know, when you create a region, protection is automatically turned on (only members can build). If you don't want that, you can set a region's `passthrough` flag to `allow`. In the case of the global region, it *defaults* to `allow`, so you have to set it to `deny` to turn that off.
* Earlier versions of WorldGuard 6 changed the ``use`` flag to be much more encompassing, but this is **no longer the case**. The ``use`` flag now works like it did before in 5.x, only applying to things like doors, pressure plates, and levers. A new ``interact`` flag was added instead that controls all right clicks of blocks and entities.
* By default, the ``use`` flag is now set so only members of a region can use levers and doors within a region. If you want to disable this type of protection in all protected regions, use `/rg flag __global__ use allow`.
* Region groups for flags now work properly. You can set a certain flag to apply to only a certain group (owners, members, nonmembers, nonowners, all). Before, it only worked correctly for some flags. Region groups can be set like this: `/rg flag spawn pvp -g nonmembers deny`.
* In WG 5.9, some flags had a default region group of "non-members." That means that if you did `/rg flag spawn chest-access deny`, only non-members would be unable to open chests. In WG 6, you have to explicitly specify this: `/rg flag spawn chest-access -g nonmembers deny`.
* It is now possible to change the message that users get when they are prevented from interacting with blocks or entities. This message is defined as a region flag, so you can set it on the `__global__` region or override it in a specific region. In addition, the tone and color of the default message has been softened, but you are free to change it entirely.
* The MySQL code was substantially rewritten to be faster and more efficient. Some changes are needed to the table structure, but WorldGuard is now capable of performing those automatically. However, those who use table prefixes *may* run into trouble.
### Blacklist
* Children regions now inherit from their parent even if there is no overlap.
* MySQL support now features the ability to migrate tables. If you are using tables without a prefix, then the new migration code should be able to handle your table. However, if you are using a table prefix, you may encounter trouble with migration.
* Protection is now a lot more exhaustive so it is no longer, for example, possible to fling sand into a region, grow trees into a region, and so on.build
* The `USE` flag is now much more encompassing so you may find that it blocks things like CraftBook gates (for users of CraftBook). To fix that, you can do `/rg flag REGION_NAME use allow`, but be aware that that will also allow the opening of inventories. To block inventories specifically, use `/rg flag REGION_NAME chest-access deny -g nonmembers`. The `-g nonmembers` makes it so only non-members of the region are unable to use chests, but this is optional.
* If you want to blacklist only water and lava blocks and not buckets, you can no longer apply `on-place` to water or lava blocks because it will also deny the use of buckets. If you wish to deny the use of just the liquid blocks, use `on-use`. This is because WorldGuard now considers the use of a bucket also the placement of a liquid block.
* In the rare situation that you are user of the "auto-invincibility" and "auto-no-drowning" groups (`wg-invincible` and `wg-amphibious`), you now have to enable these features in the config (`auto-invincible-group: true` and `auto-no-drowning-group: true`). This is because some permission plugins have been causing severe hang ups whenever it is queried for a player's groups, which, in this case, happens to include when the player joins.
* Plugins that utilize WorldGuard's API may not work anymore. They may crash with errors.
## Incompatibility issues
### Miscellaneous
* In the rare situation that you are user of the "auto-invincibility" and "auto-no-drowning" groups (`wg-invincible` and `wg-amphibious`), you now have to enable these features in the config (`auto-invincible-group: true` and `auto-no-drowning-group: true`). This is because some permission plugins have been causing severe hang ups whenever it is queried for a player's groups, which, in this case, happens to include when the player joins.
## Known Incompatibilities
Plugins that utilize WorldGuard's API may not work anymore. They may crash with errors. The API has changed somewhat.
* Spigot:
* `settings.global-api-cache`, if enabled, will crash WG UUID lookups (fixed in Spigot build #1625)
* EchoPet
* Can't spawn pets ([issue #393](https://github.com/DSH105/EchoPet/issues/393))
* CraftBook
* Unable to use mechanics unless the `USE` flag is explicitly set to `ALLOW` ([CRAFTBOOK-3057](http://youtrack.sk89q.com/issue/CRAFTBOOK-3057))
## Major features
## Other Changes
### UUID support
The rest of the changes can be found in the CHANGELOG file.
Regions now fully support the use of UUIDs rather than names for storing the owners and members of a region. Commands still accept names, but they are translated into UUIDs in the background. For users who already have existing region data, names will be automatically converted to UUIDs on the first run of WorldGuard.
It is still possible to specify names rather than a UUID by using the `-n` flag with the region membership commands.
### 'Deny by default'
Previously, a pre-determined list of blocks and entities was used to determine whether an action by the player should be blocked. However, this has been reversed so that every action on a block or entity is denied (in a protected region) unless it has been deemed safe (such as, for example, right clicking with steak). Mods are now supported as a result.
The `USE` flag has been repurposed as a general "interaction" flag and covers every left click or right click of a block or entity. It also covers interaction that falls outside clicking.
### Exhaustive protection
More events are now handled in the protection code. For example,
* It is no longer possible to drop sand or gravel into a protected region from outside.
* It is no longer possible to grief a region by growing a tree into it.
* The entry and exit flags now handle players sitting on vehicles properly.
* Piston-moved blocks cannot be pushed into a different protected region.
* Owners of tamable animals are now considered in protection code.
Even water and lava flow can also be checked, although this requires that it be explicitly enabled in the configuration (flow events are very frequent, so they incur extra CPU cost).
The goal is to provide extremely exhaustive protection.
### Large performance boost for spatial queries
The performance of spatial queries for regions has been substantially increased at least an order of magnitude. Spatial queries are a necessity for the region code to query the list of regions that apply to a location in the world. There should be a negligible difference between 4, 40, and 4000 regions as long as too many regions are not overlapping.
### Background region operations
Region commands are now executed in the background. Notably, saves and loads will not lock up your server while they complete. Additionally, changes to regions are now saved periodically rather than immediately after every change.
### Updated MySQL region support
MySQL support has been completely overhauled. It should now be faster, no longer crash on foreign key index errors, use transactions, and support automatic creation and migration of tables (including support for table prefixes).
### Partial region data saving
For users of MySQL, WorldGuard now only saves changed and deleted regions when saving region data. No longer does WorldGuard have to rewrite the entire region database on each save.
### Improved handling of related flags
Multiple flags that apply to an event are now evaluated together if they are similar. For example, if a player right clicks a bed to sleep in it, both the `USE` and `SLEEP` flag are checked since they are both interaction-related. If one of them is `DENY`, then sleeping is denied (remember, `DENY` overrides `ALLOW`). If one of them is `ALLOW` and the other is not `DENY`, then sleeping is permitted.
### Flag groups now work properly
While you could always set a group to a flag's value, the functionality was incomplete and did not work most of the time.
Now that groups are supported, you can change a flag so it only applies to a certain group of players. For example, `/rg flag example sleep deny -g members` would deny sleeping for only members of the `example` region.
### Inheritance now works as expected
Previously, a region only inherited flags and other details from its parents if the parent and the child overlapped at the location queried. This is no longer the case and inheritance is now always applied.
In addition, a new `-g` flag for `/rg define` lets you create a region with no physical area so that you can assign flags and use this region as a "template region."
### Settable deny message
It is now possible to change the message that users get when they are prevented from interacting with blocks or entities. This message is defined as a region flag, so you can set it on the `__global__` region or override it in a specific region. In addition, the tone and color of the default message has been softened, but you are free to change it entirely.
### Blacklist support for data values (and later, variants)
The blacklist was rewritten to support more than just block and item IDs. The immediate result is that you can now use data values, but as those are in the process of being deprecated by Mojang, it also allows support for Minecraft's new block variants in the future.
### Debounced events
Events that tend to reoccur very frequently (such as the ones that occur when you stand on a pressure plate continuously) have been "debounced" to reduce the number of checks that WorldGuard has to perform, reducing the amount of wasted CPU. In addition, the "you don't have permission" message is rate limited so players are not flooded with the message.
### New block place and break flags
A long requested feature was the availability of block place and break flags. These newly added flags work in tandem with the `BUILD` flag but can override `BUILD`. At the moment, it is not possible to allow explicit types of blocks to be placed or broken yet.
### Build permission nodes
A new optional (disabled by default in the configuration) feature is the checking of build permission nodes. For every block, entity, and item, the following permission nodes are checked:
* Block place: `worldguard.build.block.place.<material>`
* Block break: `worldguard.build.block.remove.<material>`
* Block interact: `worldguard.build.block.interact.<material>`
* Entity spawn: `worldguard.build.entity.place.<type>`
* Entity destroy: `worldguard.build.entity.remove.<type>`
* Entity interact: `worldguard.build.entity.interact.<type>`
* Entity damage: `worldguard.build.entity.damage.<type>`
* Item use: `worldguard.build.item.use.<material>`
In addition, the permissions are also checked in the style of `worldguard.build.block.<material>.<action>`, so `worldguard.build.block.<material>.place` would work too.
The list of usable material names comes from the [Material enumeration in Bukkit](http://jd.bukkit.org/rb/apidocs/org/bukkit/Material.html). For example, the permission for placing the bed block would be `worldguard.build.build.place.bed_block`. Be aware that _Material_ contains both item and block names.
For entity names, see [EntityType](http://jd.bukkit.org/rb/apidocs/org/bukkit/entity/EntityType.html).
# Other changes
The rest of the changes can be found in the CHANGELOG file.
In addition, there is [new work-in-progress documentation](http://docs.enginehub.org/manual/worldguard/latest/) that describes some of the new features.
+1
View File
@@ -37,4 +37,5 @@
<allow pkg="com.google.common"/>
<allow pkg="com.jolbox.bonecp"/>
<allow pkg="org.flywaydb.core"/>
<allow pkg="org.json.simple"/>
</import-control>
+59 -62
View File
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.sk89q</groupId>
<artifactId>worldguard</artifactId>
<version>6.0.0-beta-02</version>
<version>6.1</version>
<packaging>jar</packaging>
<!-- Project information -->
@@ -66,8 +66,8 @@
<url>http://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>bukkit-repo</id>
<url>http://repo.bukkit.org/content/groups/public</url>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
</repositories>
@@ -90,30 +90,17 @@
</exclusions>
</dependency>
<!-- Used for running CraftBukkit from within your IDE
These are runtime-only dependencies -->
<dependency>
<groupId>org.sk89q.bukkit</groupId>
<groupId>com.sk89q.spigot</groupId>
<artifactId>bukkit-classloader-check</artifactId>
<version>1.7.9-R0.2</version>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>runtime</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.9-R0.2</version>
<scope>runtime</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<!-- End runtime only -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.7.9-R0.2</version>
<version>1.8.6-R0.1-SNAPSHOT</version>
<scope>compile</scope>
<type>jar</type>
</dependency>
@@ -150,10 +137,12 @@
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>10.0.1</version> <!-- Bukkit only bundles 10.0.1 -->
<scope>compile</scope> <!-- required runtime dependency -->
<!-- Contains parts of Guava that are not compatible
between Bukkit 10.0.1 and 17+ -->
<groupId>com.sk89q</groupId>
<artifactId>guavabackport</artifactId>
<version>1.1</version>
<scope>compile</scope>
<type>jar</type>
</dependency>
@@ -164,6 +153,12 @@
<scope>compile</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.khelekore</groupId>
@@ -391,9 +386,15 @@
<include>org.khelekore:prtree</include>
<include>org.flywaydb:flyway-core</include>
<include>com.sk89q:squirrelid</include>
<include>com.sk89q:guavabackport</include>
<include>com.googlecode.json-simple:json-simple</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>com.sk89q.guavabackport</pattern>
<shadedPattern>com.sk89q.worldguard.internal.guava</shadedPattern>
</relocation>
<relocation>
<pattern>org.flywaydb</pattern>
<shadedPattern>com.sk89q.worldguard.internal.flywaydb</shadedPattern>
@@ -402,6 +403,10 @@
<pattern>com.sk89q.squirrelid</pattern>
<shadedPattern>com.sk89q.worldguard.util.profile</shadedPattern>
</relocation>
<relocation>
<pattern>org.json.simple</pattern>
<shadedPattern>com.sk89q.worldguard.util.jsonsimple</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
@@ -455,6 +460,37 @@
<tagNameFormat>@{project.version}</tagNameFormat>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8.1</version>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -486,43 +522,4 @@
</plugin>
</plugins>
</build>
<profiles>
<!-- Attach javadocs and source .jars -->
<profile>
<id>attach-docs</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
@@ -24,6 +24,7 @@ import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.List;
import java.util.UUID;
public abstract class LocalPlayer implements RegionAssociable {
@@ -94,14 +95,18 @@ public abstract class LocalPlayer implements RegionAssociable {
public abstract boolean hasPermission(String perm);
@Override
public Association getAssociation(ProtectedRegion region) {
if (region.isOwner(this)) {
return Association.OWNER;
} else if (region.isMember(this)) {
return Association.MEMBER;
} else {
return Association.NON_MEMBER;
public Association getAssociation(List<ProtectedRegion> regions) {
boolean member = false;
for (ProtectedRegion region : regions) {
if (region.isOwner(this)) {
return Association.OWNER;
} else if (!member && region.isMember(this)) {
member = true;
}
}
return member ? Association.MEMBER : Association.NON_MEMBER;
}
@Override
@@ -19,9 +19,6 @@
package com.sk89q.worldguard.blacklist;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.sk89q.worldguard.blacklist.action.Action;
import com.sk89q.worldguard.blacklist.action.ActionType;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
@@ -29,6 +26,10 @@ import com.sk89q.worldguard.blacklist.event.EventType;
import com.sk89q.worldguard.blacklist.target.TargetMatcher;
import com.sk89q.worldguard.blacklist.target.TargetMatcherParseException;
import com.sk89q.worldguard.blacklist.target.TargetMatcherParser;
import com.sk89q.guavabackport.cache.CacheBuilder;
import com.sk89q.guavabackport.cache.CacheLoader;
import com.sk89q.guavabackport.cache.LoadingCache;
import com.sk89q.worldguard.bukkit.commands.CommandUtils;
import org.bukkit.ChatColor;
import java.io.BufferedReader;
@@ -49,7 +50,7 @@ public abstract class Blacklist {
private final BlacklistLoggerHandler blacklistLogger = new BlacklistLoggerHandler();
private BlacklistEvent lastEvent;
private boolean useAsWhitelist;
private Cache<String, TrackedEvent> repeatingEventCache = CacheBuilder.newBuilder()
private LoadingCache<String, TrackedEvent> repeatingEventCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(new CacheLoader<String, TrackedEvent>() {
@@ -184,10 +185,10 @@ public abstract class Blacklist {
entry.setIgnorePermissions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("message")) {
entry.setMessage(parts[1].trim());
entry.setMessage(CommandUtils.replaceColorMacros(parts[1].trim()));
} else if (parts[0].equalsIgnoreCase("comment")) {
entry.setComment(parts[1].trim());
entry.setComment(CommandUtils.replaceColorMacros(parts[1].trim()));
} else {
boolean found = false;
@@ -284,7 +285,7 @@ public abstract class Blacklist {
*/
public abstract void broadcastNotification(String msg);
public Cache<String, TrackedEvent> getRepeatingEventCache() {
public LoadingCache<String, TrackedEvent> getRepeatingEventCache() {
return repeatingEventCache;
}
@@ -19,20 +19,14 @@
package com.sk89q.worldguard.blacklist;
import com.google.common.cache.Cache;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.action.Action;
import com.sk89q.worldguard.blacklist.action.ActionResult;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
import com.sk89q.guavabackport.cache.LoadingCache;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
public class BlacklistEntry {
@@ -178,7 +172,7 @@ public class BlacklistEntry {
boolean repeating = false;
String eventCacheKey = event.getCauseName();
Cache<String, TrackedEvent> repeatingEventCache = blacklist.getRepeatingEventCache();
LoadingCache<String, TrackedEvent> repeatingEventCache = blacklist.getRepeatingEventCache();
// Check to see whether this event is being repeated
TrackedEvent tracked = repeatingEventCache.getUnchecked(eventCacheKey);
@@ -44,7 +44,7 @@ public class TellAction extends RepeatGuardedAction {
if (event.getPlayer() != null) {
if (message != null) {
event.getPlayer().printRaw(ChatColor.YELLOW + String.format(message, event.getTarget().getFriendlyName()) + ".");
event.getPlayer().printRaw(ChatColor.YELLOW + String.format(message, event.getTarget().getFriendlyName()));
} else {
event.getPlayer().printRaw(ChatColor.YELLOW + "You're not allowed to " + event.getDescription() + " " +
event.getTarget().getFriendlyName() + ".");
@@ -21,7 +21,7 @@ package com.sk89q.worldguard.blacklist.target;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Ranges;
import com.sk89q.guavabackport.collect.Range;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldguard.util.Enums;
import org.bukkit.Material;
@@ -54,7 +54,7 @@ public class TargetMatcherParser {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
int id = getItemID(input);
if (id != 0) {
if (id > 0) {
return id;
}
@@ -84,22 +84,22 @@ public class TargetMatcherParser {
matcher = LESS_THAN_PATTERN.matcher(input);
if (matcher.matches()) {
return Ranges.atMost(Short.parseShort(matcher.group(1)));
return Range.atMost(Short.parseShort(matcher.group(1)));
}
matcher = GREATER_THAN_PATTERN.matcher(input);
if (matcher.matches()) {
return Ranges.atLeast(Short.parseShort(matcher.group(1)));
return Range.atLeast(Short.parseShort(matcher.group(1)));
}
matcher = RANGE_PATTERN.matcher(input);
if (matcher.matches()) {
return Ranges.closed(Short.parseShort(matcher.group(1)), Short.parseShort(matcher.group(2)));
return Range.closed(Short.parseShort(matcher.group(1)), Short.parseShort(matcher.group(2)));
}
try {
short s = Short.parseShort(input);
return Ranges.closed(s, s);
return Range.closed(s, s);
} catch (NumberFormatException e) {
throw new TargetMatcherParseException("Unknown data value range: " + input);
}
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.bukkit;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BlockID;
@@ -26,28 +27,23 @@ import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.blocks.ItemID;
import com.sk89q.worldguard.blacklist.target.MaterialTarget;
import com.sk89q.worldguard.blacklist.target.Target;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.*;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
public class BukkitUtil {
private static Method ONLINE_PLAYERS_METHOD;
private BukkitUtil() {
}
@@ -93,6 +89,20 @@ public class BukkitUtil {
return new Location(world, vec.getX(), vec.getY(), vec.getZ());
}
/**
* Create a dummy region that encompasses the size of a chunk.
*
* @param chunk The chunk
* @return The dummy region
*/
public static ProtectedRegion toRegion(Chunk chunk) {
World world = chunk.getWorld();
int minX = chunk.getX() << 4;
int minZ = chunk.getZ() << 4;
return new ProtectedCuboidRegion("_", new BlockVector(minX, 0, minZ), new BlockVector(minX + 15, world.getMaxHeight(), minZ + 15));
}
/**
* Matches one player based on name.
*
@@ -350,4 +360,42 @@ public class BukkitUtil {
return new MaterialTarget(material.getId(), (short) 0);
}
/**
* Get a collection of the currently online players.
*
* @return The online players
*/
@SuppressWarnings("unchecked")
public static Collection<? extends Player> getOnlinePlayers() {
try {
return Bukkit.getServer().getOnlinePlayers();
} catch (NoSuchMethodError ignored) {
}
try {
if (ONLINE_PLAYERS_METHOD == null) {
ONLINE_PLAYERS_METHOD = getOnlinePlayersMethod();
}
Object result = ONLINE_PLAYERS_METHOD.invoke(Bukkit.getServer());
if (result instanceof Player[]) {
return ImmutableList.copyOf((Player[]) result);
} else if (result instanceof Collection<?>) {
return (Collection<? extends Player>) result;
} else {
throw new RuntimeException("Result of getOnlinePlayers() call was not a known data type");
}
} catch (Exception e) {
throw new RuntimeException("WorldGuard is not compatible with this version of Bukkit", e);
}
}
private static Method getOnlinePlayersMethod() throws NoSuchMethodException {
try {
return Server.class.getMethod("getOnlinePlayers");
} catch (NoSuchMethodException e1) {
return Server.class.getMethod("_INVALID_getOnlinePlayers");
}
}
}
@@ -20,15 +20,14 @@
package com.sk89q.worldguard.bukkit;
import com.google.common.collect.ImmutableMap;
import com.sk89q.commandbook.CommandBook;
import com.sk89q.commandbook.GodComponent;
import com.sk89q.util.yaml.YAMLFormat;
import com.sk89q.util.yaml.YAMLProcessor;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver;
import com.sk89q.worldguard.protection.managers.storage.DriverType;
import com.sk89q.worldguard.protection.managers.storage.RegionDriver;
import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver;
import com.sk89q.worldguard.protection.managers.storage.sql.SQLDriver;
import com.sk89q.worldguard.session.handler.WaterBreathing;
import com.sk89q.worldguard.util.report.Unreported;
import com.sk89q.worldguard.util.sql.DataSourceConfig;
import org.bukkit.World;
import org.bukkit.entity.Player;
@@ -36,9 +35,7 @@ import org.bukkit.entity.Player;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
@@ -75,16 +72,12 @@ public class ConfigurationManager {
"# - Lines starting with # are comments and so they are ignored.\r\n" +
"#\r\n";
private WorldGuardPlugin plugin;
private ConcurrentMap<String, WorldConfiguration> worlds;
private YAMLProcessor config;
@Deprecated
private Set<String> hasGodMode = new HashSet<String>();
private Set<String> hasAmphibious = new HashSet<String>();
@Unreported private WorldGuardPlugin plugin;
@Unreported private ConcurrentMap<String, WorldConfiguration> worlds;
@Unreported private YAMLProcessor config;
private boolean hasCommandBookGodMode = false;
public boolean useRegionsScheduler;
public boolean useRegionsCreatureSpawnEvent;
public boolean activityHaltToggle = false;
public boolean useGodPermission;
@@ -96,13 +89,14 @@ public class ConfigurationManager {
public boolean blockInGameOp;
public boolean migrateRegionsToUuid;
public boolean keepUnresolvedNames;
public Map<String, String> hostKeys = new HashMap<String, String>();
@Unreported public Map<String, String> hostKeys = new HashMap<String, String>();
/**
* Region Storage Configuration method, and config values
*/
public RegionDriver selectedRegionStoreDriver;
public Map<DriverType, RegionDriver> regionStoreDriverMap;
@Unreported public RegionDriver selectedRegionStoreDriver;
@Unreported public Map<DriverType, RegionDriver> regionStoreDriverMap;
/**
* Construct the object.
@@ -151,7 +145,6 @@ public class ConfigurationManager {
}
config.removeProperty("suppress-tick-sync-warnings");
useRegionsScheduler = config.getBoolean("regions.use-scheduler", true);
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);
@@ -241,37 +234,6 @@ public class ConfigurationManager {
return config;
}
/**
* Forget a player.
*
* @param player The player to forget about
*/
public void forgetPlayer(LocalPlayer player) {
hasGodMode.remove(player.getName());
hasAmphibious.remove(player.getName());
}
/**
* Enable god mode for a player.
*
* @param player The player to enable god mode for.
*/
@Deprecated
public void enableGodMode(Player player) {
hasGodMode.add(player.getName());
}
/**
* Disable god mode for a player.
*
* @param player The player to disable godmode for
*/
@Deprecated
public void disableGodMode(Player player) {
hasGodMode.remove(player.getName());
}
/**
* Check to see if god mode is enabled for a player.
*
@@ -279,13 +241,7 @@ public class ConfigurationManager {
* @return Whether the player has godmode through WorldGuard or CommandBook
*/
public boolean hasGodMode(Player player) {
if (hasCommandBookGodMode) {
GodComponent god = CommandBook.inst().getComponentManager().getComponent(GodComponent.class);
if (god != null) {
return god.hasGodMode(player);
}
}
return hasGodMode.contains(player.getName());
return plugin.getSessionManager().get(player).isInvincible(player);
}
/**
@@ -294,7 +250,10 @@ public class ConfigurationManager {
* @param player The player to enable amphibious mode for
*/
public void enableAmphibiousMode(Player player) {
hasAmphibious.add(player.getName());
WaterBreathing handler = plugin.getSessionManager().get(player).getHandler(WaterBreathing.class);
if (handler != null) {
handler.setWaterBreathing(true);
}
}
/**
@@ -303,7 +262,10 @@ public class ConfigurationManager {
* @param player The player to disable amphibious mode for
*/
public void disableAmphibiousMode(Player player) {
hasAmphibious.remove(player.getName());
WaterBreathing handler = plugin.getSessionManager().get(player).getHandler(WaterBreathing.class);
if (handler != null) {
handler.setWaterBreathing(false);
}
}
/**
@@ -313,7 +275,8 @@ public class ConfigurationManager {
* @return Whether {@code player} has amphibious mode
*/
public boolean hasAmphibiousMode(Player player) {
return hasAmphibious.contains(player.getName());
WaterBreathing handler = plugin.getSessionManager().get(player).getHandler(WaterBreathing.class);
return handler != null && handler.hasWaterBreathing();
}
public void updateCommandBookGodMode() {
@@ -29,23 +29,21 @@ import com.sk89q.worldguard.blacklist.logger.FileHandler;
import com.sk89q.worldguard.blacklist.target.TargetMatcherParseException;
import com.sk89q.worldguard.blacklist.target.TargetMatcherParser;
import com.sk89q.worldguard.bukkit.commands.CommandUtils;
import com.sk89q.worldguard.bukkit.util.TargetMatcherSet;
import com.sk89q.worldguard.bukkit.internal.BukkitBlacklist;
import com.sk89q.worldguard.bukkit.internal.TargetMatcherSet;
import com.sk89q.worldguard.chest.ChestProtection;
import com.sk89q.worldguard.chest.SignChestProtection;
import com.sk89q.worldguard.util.report.Unreported;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import org.yaml.snakeyaml.parser.ParserException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -71,15 +69,15 @@ public class WorldConfiguration {
"# Remove the {} and add your own entries.\r\n" +
"#\r\n";
private WorldGuardPlugin plugin;
@Unreported private WorldGuardPlugin plugin;
private String worldName;
private YAMLProcessor parentConfig;
private YAMLProcessor config;
@Unreported private String worldName;
@Unreported private YAMLProcessor parentConfig;
@Unreported private YAMLProcessor config;
private File blacklistFile;
private Blacklist blacklist;
private ChestProtection chestProtection = new SignChestProtection();
@Unreported private Blacklist blacklist;
@Unreported private ChestProtection chestProtection = new SignChestProtection();
/* Configuration data start */
public boolean summaryOnStart;
@@ -336,6 +334,9 @@ public class WorldConfiguration {
} catch (IOException e) {
log.severe("Error reading configuration for world " + worldName + ": ");
e.printStackTrace();
} catch (ParserException e) {
log.severe("Error parsing configuration for world " + worldName + ". ");
throw e;
}
summaryOnStart = getBoolean("summary-on-start", true);
@@ -19,25 +19,17 @@
package com.sk89q.worldguard.bukkit;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.bukkit.util.CommandsManagerRegistration;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.minecraft.util.commands.CommandUsageException;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.minecraft.util.commands.MissingNestedCommandException;
import com.sk89q.minecraft.util.commands.SimpleInjector;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import com.sk89q.minecraft.util.commands.*;
import com.sk89q.squirrelid.cache.HashMapCache;
import com.sk89q.squirrelid.cache.ProfileCache;
import com.sk89q.squirrelid.cache.SQLiteCache;
import com.sk89q.squirrelid.resolver.BukkitPlayerService;
import com.sk89q.squirrelid.resolver.CacheForwardingService;
import com.sk89q.squirrelid.resolver.CombinedProfileService;
import com.sk89q.squirrelid.resolver.HttpRepositoryService;
import com.sk89q.squirrelid.resolver.ProfileService;
import com.sk89q.squirrelid.resolver.*;
import com.sk89q.wepif.PermissionsResolverManager;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.LocalPlayer;
@@ -45,32 +37,18 @@ import com.sk89q.worldguard.bukkit.commands.GeneralCommands;
import com.sk89q.worldguard.bukkit.commands.ProtectionCommands;
import com.sk89q.worldguard.bukkit.commands.ToggleCommands;
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
import com.sk89q.worldguard.bukkit.listener.BlacklistListener;
import com.sk89q.worldguard.bukkit.listener.BlockedPotionsListener;
import com.sk89q.worldguard.bukkit.listener.BuildPermissionListener;
import com.sk89q.worldguard.bukkit.listener.ChestProtectionListener;
import com.sk89q.worldguard.bukkit.listener.DebuggingListener;
import com.sk89q.worldguard.bukkit.listener.EventAbstractionListener;
import com.sk89q.worldguard.bukkit.listener.FlagStateManager;
import com.sk89q.worldguard.bukkit.listener.PlayerModesListener;
import com.sk89q.worldguard.bukkit.listener.RegionFlagsListener;
import com.sk89q.worldguard.bukkit.listener.RegionProtectionListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardBlockListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardCommandBookListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardEntityListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardHangingListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardPlayerListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardServerListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardVehicleListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardWeatherListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardWorldListener;
import com.sk89q.worldguard.bukkit.listener.*;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.storage.StorageException;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.util.UnresolvedNamesException;
import com.sk89q.worldguard.util.FatalConfigurationLoadingException;
import com.sk89q.worldguard.session.SessionManager;
import com.sk89q.worldguard.util.concurrent.EvenMoreExecutors;
import com.sk89q.worldguard.util.logging.ClassSourceValidator;
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
import com.sk89q.worldguard.util.task.SimpleSupervisor;
import com.sk89q.worldguard.util.task.Supervisor;
@@ -90,16 +68,8 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import javax.annotation.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.io.*;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
@@ -121,11 +91,12 @@ public class WorldGuardPlugin extends JavaPlugin {
private final ConfigurationManager configuration = new ConfigurationManager(this);
private final RegionContainer regionContainer = new RegionContainer(this);
private final GlobalRegionManager globalRegionManager = new GlobalRegionManager(this, regionContainer);
private FlagStateManager flagStateManager;
private SessionManager sessionManager;
private final Supervisor supervisor = new SimpleSupervisor();
private ListeningExecutorService executorService;
private ProfileService profileService;
private ProfileCache profileCache;
private PlayerMoveListener playerMoveListener;
/**
* Construct objects. Actual loading occurs when the plugin is enabled, so
@@ -161,9 +132,16 @@ public class WorldGuardPlugin extends JavaPlugin {
executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20));
sessionManager = new SessionManager(this);
// Set the proper command injector
commands.setInjector(new SimpleInjector(this));
// Catch bad things being done by naughty plugins that include
// WorldGuard's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
verifier.reportMismatches(ImmutableList.of(WGBukkit.class, ProtectedRegion.class, ProtectedCuboidRegion.class, Flag.class));
// Register command classes
final CommandsManagerRegistration reg = new CommandsManagerRegistration(this, commands);
reg.register(ToggleCommands.class);
@@ -194,36 +172,15 @@ public class WorldGuardPlugin extends JavaPlugin {
profileCache);
PermissionsResolverManager.initialize(this);
try {
// Load the configuration
configuration.load();
} catch (FatalConfigurationLoadingException e) {
log.log(Level.WARNING, "Encountered fatal error while loading configuration", e);
getServer().shutdown();
log.log(Level.WARNING, "\n" +
"******************************************************\n" +
"* Failed to load WorldGuard configuration!\n" +
"* \n" +
"* Shutting down the server just in case...\n" +
"* \n" +
"* The error should be printed above this message. If you can't\n" +
"* figure out the problem, ask us on our forums:\n" +
"* http://forum.enginehub.org\n" +
"******************************************************\n");
}
configuration.load();
log.info("Loading region data...");
regionContainer.initialize();
flagStateManager = new FlagStateManager(this);
if (configuration.useRegionsScheduler) {
getServer().getScheduler().scheduleSyncRepeatingTask(this, flagStateManager,
FlagStateManager.RUN_DELAY, FlagStateManager.RUN_DELAY);
}
getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, SessionManager.RUN_DELAY, SessionManager.RUN_DELAY);
// Register events
getServer().getPluginManager().registerEvents(sessionManager, this);
(new WorldGuardPlayerListener(this)).registerEvents();
(new WorldGuardBlockListener(this)).registerEvents();
(new WorldGuardEntityListener(this)).registerEvents();
@@ -233,14 +190,17 @@ public class WorldGuardPlugin extends JavaPlugin {
(new WorldGuardHangingListener(this)).registerEvents();
// Modules
(playerMoveListener = new PlayerMoveListener(this)).registerEvents();
(new BlacklistListener(this)).registerEvents();
(new ChestProtectionListener(this)).registerEvents();
(new RegionProtectionListener(this)).registerEvents();
(new RegionFlagsListener(this)).registerEvents();
(new WorldRulesListener(this)).registerEvents();
(new BlockedPotionsListener(this)).registerEvents();
(new EventAbstractionListener(this)).registerEvents();
(new PlayerModesListener(this)).registerEvents();
(new BuildPermissionListener(this)).registerEvents();
(new InvincibilityListener(this)).registerEvents();
if ("true".equalsIgnoreCase(System.getProperty("worldguard.debug.listener"))) {
(new DebuggingListener(this, log)).registerEvents();
}
@@ -258,7 +218,7 @@ public class WorldGuardPlugin extends JavaPlugin {
}
worldListener.registerEvents();
for (Player player : getServer().getOnlinePlayers()) {
for (Player player : BukkitUtil.getOnlinePlayers()) {
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
Events.fire(event);
}
@@ -378,8 +338,8 @@ public class WorldGuardPlugin extends JavaPlugin {
*
* @return The flag state manager
*/
public FlagStateManager getFlagStateManager() {
return flagStateManager;
public SessionManager getSessionManager() {
return sessionManager;
}
/**
@@ -513,7 +473,7 @@ public class WorldGuardPlugin extends JavaPlugin {
// Invoke the permissions resolver
if (sender instanceof Player) {
Player player = (Player) sender;
return PermissionsResolverManager.getInstance().hasPermission(player.getWorld().getName(), player.getName(), perm);
return PermissionsResolverManager.getInstance().hasPermission(player.getWorld().getName(), player, perm);
}
return false;
@@ -561,7 +521,7 @@ public class WorldGuardPlugin extends JavaPlugin {
* @return A {@link List} of players who match {@code filter}
*/
public List<Player> matchPlayerNames(String filter) {
Player[] players = getServer().getOnlinePlayers();
Collection<? extends Player> players = BukkitUtil.getOnlinePlayers();
filter = filter.toLowerCase();
@@ -614,7 +574,7 @@ public class WorldGuardPlugin extends JavaPlugin {
* @return {@code players} as an {@link Iterable}
* @throws CommandException If {@code players} is empty
*/
protected Iterable<Player> checkPlayerMatch(List<Player> players)
protected Iterable<? extends Player> checkPlayerMatch(List<? extends Player> players)
throws CommandException {
// Check to see if there were any matches
if (players.size() == 0) {
@@ -639,15 +599,15 @@ public class WorldGuardPlugin extends JavaPlugin {
* @return iterator for players
* @throws CommandException if no matches are found
*/
public Iterable<Player> matchPlayers(CommandSender source, String filter)
public Iterable<? extends Player> matchPlayers(CommandSender source, String filter)
throws CommandException {
if (getServer().getOnlinePlayers().length == 0) {
if (BukkitUtil.getOnlinePlayers().isEmpty()) {
throw new CommandException("No players matched query.");
}
if (filter.equals("*")) {
return checkPlayerMatch(Arrays.asList(getServer().getOnlinePlayers()));
return checkPlayerMatch(Lists.newArrayList(BukkitUtil.getOnlinePlayers()));
}
// Handle special hash tag groups
@@ -659,7 +619,7 @@ public class WorldGuardPlugin extends JavaPlugin {
Player sourcePlayer = checkPlayer(source);
World sourceWorld = sourcePlayer.getWorld();
for (Player player : getServer().getOnlinePlayers()) {
for (Player player : BukkitUtil.getOnlinePlayers()) {
if (player.getWorld().equals(sourceWorld)) {
players.add(player);
}
@@ -675,7 +635,7 @@ public class WorldGuardPlugin extends JavaPlugin {
org.bukkit.util.Vector sourceVector
= sourcePlayer.getLocation().toVector();
for (Player player : getServer().getOnlinePlayers()) {
for (Player player : BukkitUtil.getOnlinePlayers()) {
if (player.getWorld().equals(sourceWorld)
&& player.getLocation().toVector().distanceSquared(
sourceVector) < 900) {
@@ -707,7 +667,7 @@ public class WorldGuardPlugin extends JavaPlugin {
public Player matchSinglePlayer(CommandSender sender, String filter)
throws CommandException {
// This will throw an exception if there are no matches
Iterator<Player> players = matchPlayers(sender, filter).iterator();
Iterator<? extends Player> players = matchPlayers(sender, filter).iterator();
Player match = players.next();
@@ -967,7 +927,7 @@ public class WorldGuardPlugin extends JavaPlugin {
public void broadcastNotification(String msg) {
getServer().broadcast(msg, "worldguard.notify");
Set<Permissible> subs = getServer().getPluginManager().getPermissionSubscriptions("worldguard.notify");
for (Player player : getServer().getOnlinePlayers()) {
for (Player player : BukkitUtil.getOnlinePlayers()) {
if (!(subs.contains(player) && player.hasPermission("worldguard.notify")) &&
hasPermission(player, "worldguard.notify")) { // Make sure the player wasn't already broadcasted to.
player.sendMessage(msg);
@@ -976,15 +936,6 @@ public class WorldGuardPlugin extends JavaPlugin {
log.info(msg);
}
/**
* Forgets a player.
*
* @param player The player to remove state information for
*/
public void forgetPlayer(Player player) {
flagStateManager.forget(player);
}
/**
* Checks to see if a player can build at a location. This will return
* true if region protection is disabled.
@@ -1025,6 +976,10 @@ public class WorldGuardPlugin extends JavaPlugin {
return getGlobalRegionManager().get(world);
}
public PlayerMoveListener getPlayerMoveListener() {
return playerMoveListener;
}
/**
* Replace macros in the text.
*
@@ -1041,11 +996,11 @@ public class WorldGuardPlugin extends JavaPlugin {
* @return The message with macros replaced
*/
public String replaceMacros(CommandSender sender, String message) {
Player[] online = getServer().getOnlinePlayers();
Collection<? extends Player> online = BukkitUtil.getOnlinePlayers();
message = message.replace("%name%", toName(sender));
message = message.replace("%id%", toUniqueName(sender));
message = message.replace("%online%", String.valueOf(online.length));
message = message.replace("%online%", String.valueOf(online.size()));
if (sender instanceof Player) {
Player player = (Player) sender;
@@ -20,21 +20,17 @@
package com.sk89q.worldguard.bukkit.cause;
import com.google.common.base.Joiner;
import com.sk89q.worldguard.bukkit.util.WGMetadata;
import com.google.common.collect.Sets;
import com.sk89q.worldguard.bukkit.internal.WGMetadata;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.*;
import org.bukkit.metadata.Metadatable;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -47,21 +43,36 @@ import static com.google.common.base.Preconditions.checkNotNull;
* is the initiator, while the arrow is merely controlled by the player to
* hit the item frame.</p>
*/
public class Cause {
public final class Cause {
private static final String CAUSE_KEY = "worldguard.cause";
private static final Cause UNKNOWN = new Cause(Collections.emptyList());
private static final Cause UNKNOWN = new Cause(Collections.emptyList(), false);
private final List<Object> causes;
private final boolean indirect;
/**
* Create a new instance.
*
* @param causes a list of causes
* @param indirect whether the cause is indirect
*/
private Cause(List<Object> causes) {
private Cause(List<Object> causes, boolean indirect) {
checkNotNull(causes);
this.causes = causes;
this.indirect = indirect;
}
/**
* Test whether the traced cause is indirect.
*
* <p>If the cause is indirect, then the root cause may not be notified,
* for example.</p>
*
* @return true if the cause is indirect
*/
public boolean isIndirect() {
return indirect;
}
/**
@@ -118,6 +129,17 @@ public class Cause {
return null;
}
@Nullable
public Entity getFirstNonPlayerEntity() {
for (Object object : causes) {
if (object instanceof Entity && !(object instanceof Player)) {
return (Entity) object;
}
}
return null;
}
@Nullable
public Block getFirstBlock() {
for (Object object : causes) {
@@ -155,44 +177,6 @@ public class Cause {
return Joiner.on(" | ").join(causes);
}
/**
* Expand an cause object.
*
* @param list the list to add elements to
* @param element an array of objects
*/
private static void expand(List<Object> list, @Nullable Object ... element) {
if (element != null) {
for (Object o : element) {
if (o == null) {
continue;
}
if (o instanceof TNTPrimed) {
expand(list, ((TNTPrimed) o).getSource());
} else if (o instanceof Projectile) {
expand(list, ((Projectile) o).getShooter());
} else if (o instanceof Vehicle) {
expand(list, ((Vehicle) o).getPassenger());
} else if (o instanceof Tameable) {
expand(list, ((Tameable) o).getOwner());
}
// Add manually tracked parent causes
Object source = o;
int index = list.size();
while (source instanceof Metadatable && !(source instanceof Block)) {
source = WGMetadata.getIfPresent((Metadatable) source, CAUSE_KEY, Object.class);
if (source != null) {
list.add(index, source);
}
}
list.add(o);
}
}
}
/**
* Create a new instance with the given objects as the cause,
* where the first-most object is the initial initiator and those
@@ -201,11 +185,11 @@ public class Cause {
* @param cause an array of causing objects
* @return a cause
*/
public static Cause create(@Nullable Object ... cause) {
public static Cause create(@Nullable Object... cause) {
if (cause != null) {
List<Object> causes = new ArrayList<Object>(cause.length);
expand(causes, cause);
return new Cause(causes);
Builder builder = new Builder(cause.length);
builder.addAll(cause);
return builder.build();
} else {
return UNKNOWN;
}
@@ -240,4 +224,60 @@ public class Cause {
WGMetadata.put(target, CAUSE_KEY, parent);
}
/**
* Builds causes.
*/
private static final class Builder {
private final List<Object> causes;
private final Set<Object> seen = Sets.newHashSet();
private boolean indirect;
private Builder(int expectedSize) {
this.causes = new ArrayList<Object>(expectedSize);
}
private void addAll(@Nullable Object... element) {
if (element != null) {
for (Object o : element) {
if (o == null || seen.contains(o)) {
continue;
}
seen.add(o);
if (o instanceof TNTPrimed) {
addAll(((TNTPrimed) o).getSource());
} else if (o instanceof Projectile) {
addAll(((Projectile) o).getShooter());
} else if (o instanceof Vehicle) {
addAll(((Vehicle) o).getPassenger());
} 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());
}
// Add manually tracked parent causes
Object source = o;
int index = causes.size();
while (source instanceof Metadatable && !(source instanceof Block)) {
source = WGMetadata.getIfPresent((Metadatable) source, CAUSE_KEY, Object.class);
if (source != null) {
causes.add(index, source);
seen.add(source);
}
}
causes.add(o);
}
}
}
public Cause build() {
return new Cause(causes, indirect);
}
}
}
@@ -20,6 +20,11 @@
package com.sk89q.worldguard.bukkit.commands;
import com.google.common.base.Function;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.util.paste.EngineHubPaste;
import org.bukkit.ChatColor;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
@@ -27,12 +32,17 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Command-related utility methods.
*/
public final class CommandUtils {
private static final Logger log = Logger.getLogger(CommandUtils.class.getCanonicalName());
private CommandUtils() {
}
@@ -102,6 +112,16 @@ public final class CommandUtils {
str = str.replace("&7", ChatColor.GRAY.toString());
str = str.replace("&f", ChatColor.WHITE.toString());
str = str.replace("&k", ChatColor.MAGIC.toString());
str = str.replace("&l", ChatColor.BOLD.toString());
str = str.replace("&m", ChatColor.STRIKETHROUGH.toString());
str = str.replace("&n", ChatColor.UNDERLINE.toString());
str = str.replace("&o", ChatColor.ITALIC.toString());
str = str.replace("&x", ChatColor.RESET.toString());
str = str.replace("&r", ChatColor.RESET.toString());
return str;
}
@@ -143,4 +163,34 @@ public final class CommandUtils {
};
}
/**
* Submit data to a pastebin service and inform the sender of
* success or failure.
*
* @param plugin The plugin
* @param sender The sender
* @param content The content
* @param successMessage The message, formatted with {@link String#format(String, Object...)} on success
*/
public static void pastebin(WorldGuardPlugin plugin, final CommandSender sender, String content, final String successMessage) {
ListenableFuture<URL> future = new EngineHubPaste().paste(content);
AsyncCommandHelper.wrap(future, plugin, sender)
.registerWithSupervisor("Submitting content to a pastebin service...")
.sendMessageAfterDelay("(Please wait... sending output to pastebin...)");
Futures.addCallback(future, new FutureCallback<URL>() {
@Override
public void onSuccess(URL url) {
sender.sendMessage(ChatColor.YELLOW + String.format(successMessage, url));
}
@Override
public void onFailure(Throwable throwable) {
log.log(Level.WARNING, "Failed to submit pastebin", throwable);
sender.sendMessage(ChatColor.RED + "Failed to submit to a pastebin. Please see console for the error.");
}
});
}
}
@@ -0,0 +1,220 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands;
import com.sk89q.minecraft.util.commands.*;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.debug.*;
import com.sk89q.worldguard.util.report.CancelReport;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.util.BlockIterator;
import java.util.logging.Logger;
public class DebuggingCommands {
private static final Logger log = Logger.getLogger(DebuggingCommands.class.getCanonicalName());
private static final int MAX_TRACE_DISTANCE = 20;
private final WorldGuardPlugin plugin;
/**
* Create a new instance.
*
* @param plugin The plugin instance
*/
public DebuggingCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
@Command(aliases = {"testbreak"}, usage = "[player]", desc = "Simulate a block break", min = 1, max = 1, flags = "ts")
@CommandPermissions("worldguard.debug.event")
public void fireBreakEvent(CommandContext args, final CommandSender sender) throws CommandException {
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
Block block = traceBlock(sender, target, args.hasFlag('t'));
sender.sendMessage(ChatColor.AQUA + "Testing BLOCK BREAK at " + ChatColor.DARK_AQUA + block);
LoggingBlockBreakEvent event = new LoggingBlockBreakEvent(block, target);
testEvent(sender, target, event, args.hasFlag('s'));
}
@Command(aliases = {"testplace"}, usage = "[player]", desc = "Simulate a block place", min = 1, max = 1, flags = "ts")
@CommandPermissions("worldguard.debug.event")
public void firePlaceEvent(CommandContext args, final CommandSender sender) throws CommandException {
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
Block block = traceBlock(sender, target, args.hasFlag('t'));
sender.sendMessage(ChatColor.AQUA + "Testing BLOCK PLACE at " + ChatColor.DARK_AQUA + block);
LoggingBlockPlaceEvent event = new LoggingBlockPlaceEvent(block, block.getState(), block.getRelative(BlockFace.DOWN), target.getItemInHand(), target, true);
testEvent(sender, target, event, args.hasFlag('s'));
}
@Command(aliases = {"testinteract"}, usage = "[player]", desc = "Simulate a block interact", min = 1, max = 1, flags = "ts")
@CommandPermissions("worldguard.debug.event")
public void fireInteractEvent(CommandContext args, final CommandSender sender) throws CommandException {
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
Block block = traceBlock(sender, target, args.hasFlag('t'));
sender.sendMessage(ChatColor.AQUA + "Testing BLOCK INTERACT at " + ChatColor.DARK_AQUA + block);
LoggingPlayerInteractEvent event = new LoggingPlayerInteractEvent(target, Action.RIGHT_CLICK_BLOCK, target.getItemInHand(), block, BlockFace.SOUTH);
testEvent(sender, target, event, args.hasFlag('s'));
}
@Command(aliases = {"testdamage"}, usage = "[player]", desc = "Simulate an entity damage", min = 1, max = 1, flags = "ts")
@CommandPermissions("worldguard.debug.event")
public void fireDamageEvent(CommandContext args, final CommandSender sender) throws CommandException {
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
Entity entity = traceEntity(sender, target, args.hasFlag('t'));
sender.sendMessage(ChatColor.AQUA + "Testing ENTITY DAMAGE on " + ChatColor.DARK_AQUA + entity);
LoggingEntityDamageByEntityEvent event = new LoggingEntityDamageByEntityEvent(target, entity, DamageCause.ENTITY_ATTACK, 1);
testEvent(sender, target, event, args.hasFlag('s'));
}
/**
* Simulate an event and print its report.
*
* @param receiver The receiver of the messages
* @param target The target
* @param event The event
* @param stacktraceMode Whether stack traces should be generated and posted
* @param <T> The type of event
*/
private <T extends Event & CancelLogging> void testEvent(CommandSender receiver, Player target, T event, boolean stacktraceMode) throws CommandPermissionsException {
boolean isConsole = receiver instanceof ConsoleCommandSender;
if (!receiver.equals(target)) {
if (!isConsole) {
log.info(receiver.getName() + " is simulating an event on " + target.getName());
}
target.sendMessage(
ChatColor.RED + "(Please ignore any messages that may immediately follow.)");
}
Bukkit.getPluginManager().callEvent(event);
int start = new Exception().getStackTrace().length;
CancelReport report = new CancelReport(event, event.getCancels(), start);
report.setDetectingPlugin(!stacktraceMode);
String result = report.toString();
if (stacktraceMode) {
receiver.sendMessage(ChatColor.GRAY + "The report was printed to console.");
log.info("Event report for " + receiver.getName() + ":\n\n" + result);
plugin.checkPermission(receiver, "worldguard.debug.pastebin");
CommandUtils.pastebin(plugin, receiver, result, "Event debugging report: %s.txt");
} else {
receiver.sendMessage(result.replaceAll("(?m)^", ChatColor.AQUA.toString()));
if (result.length() >= 500 && !isConsole) {
receiver.sendMessage(ChatColor.GRAY + "The report was also printed to console.");
log.info("Event report for " + receiver.getName() + ":\n\n" + result);
}
}
}
/**
* Get the source of the test.
*
* @param sender The message sender
* @param target The provided target
* @param fromTarget Whether the source should be the target
* @return The source
* @throws CommandException Thrown if a condition is not met
*/
private Player getSource(CommandSender sender, Player target, boolean fromTarget) throws CommandException {
if (fromTarget) {
return target;
} else {
if (sender instanceof Player) {
return (Player) sender;
} else {
throw new CommandException(
"If this command is not to be used in-game, use -t to run the test from the viewpoint of the given player rather than yourself.");
}
}
}
/**
* Find the first non-air block in a ray trace.
*
* @param sender The sender
* @param target The target
* @param fromTarget Whether the trace should originate from the target
* @return The block found
* @throws CommandException Throw on an incorrect parameter
*/
private Block traceBlock(CommandSender sender, Player target, boolean fromTarget) throws CommandException {
Player source = getSource(sender, target, fromTarget);
BlockIterator it = new BlockIterator(source);
int i = 0;
while (it.hasNext() && i < MAX_TRACE_DISTANCE) {
Block block = it.next();
if (block.getType() != Material.AIR) {
return block;
}
i++;
}
throw new CommandException("Not currently looking at a block that is close enough.");
}
/**
* Find the first nearby entity in a ray trace.
*
* @param sender The sender
* @param target The target
* @param fromTarget Whether the trace should originate from the target
* @return The entity found
* @throws CommandException Throw on an incorrect parameter
*/
private Entity traceEntity(CommandSender sender, Player target, boolean fromTarget) throws CommandException {
Player source = getSource(sender, target, fromTarget);
BlockIterator it = new BlockIterator(source);
int i = 0;
while (it.hasNext() && i < MAX_TRACE_DISTANCE) {
Block block = it.next();
// A very in-accurate and slow search
Entity[] entities = block.getChunk().getEntities();
for (Entity entity : entities) {
if (!entity.equals(target) && entity.getLocation().distanceSquared(block.getLocation()) < 10) {
return entity;
}
}
i++;
}
throw new CommandException("Not currently looking at an entity that is close enough.");
}
}
@@ -19,11 +19,6 @@
package com.sk89q.worldguard.bukkit.commands;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
@@ -31,6 +26,12 @@ import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.GodMode;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class GeneralCommands {
private final WorldGuardPlugin plugin;
@@ -45,7 +46,7 @@ public class GeneralCommands {
public void god(CommandContext args, CommandSender sender) throws CommandException {
ConfigurationManager config = plugin.getGlobalStateManager();
Iterable<Player> targets = null;
Iterable<? extends Player> targets = null;
boolean included = false;
// Detect arguments based on the number of arguments provided
@@ -54,7 +55,7 @@ public class GeneralCommands {
// Check permissions!
plugin.checkPermission(sender, "worldguard.god");
} else if (args.argsLength() == 1) {
} else {
targets = plugin.matchPlayers(sender, args.getString(0));
// Check permissions!
@@ -62,26 +63,29 @@ public class GeneralCommands {
}
for (Player player : targets) {
config.enableGodMode(player);
player.setFireTicks(0);
// Tell the user
if (player.equals(sender)) {
player.sendMessage(ChatColor.YELLOW + "God mode enabled! Use /ungod to disable.");
// Keep track of this
included = true;
} else {
player.sendMessage(ChatColor.YELLOW + "God enabled by "
+ plugin.toName(sender) + ".");
Session session = plugin.getSessionManager().get(player);
if (GodMode.set(player, session, true)) {
player.setFireTicks(0);
// Tell the user
if (player.equals(sender)) {
player.sendMessage(ChatColor.YELLOW + "God mode enabled! Use /ungod to disable.");
// Keep track of this
included = true;
} else {
player.sendMessage(ChatColor.YELLOW + "God enabled by "
+ plugin.toName(sender) + ".");
}
}
}
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
sender.sendMessage(ChatColor.YELLOW.toString() + "Players now have god mode.");
sender.sendMessage(ChatColor.YELLOW + "Players now have god mode.");
}
}
@@ -91,7 +95,7 @@ public class GeneralCommands {
public void ungod(CommandContext args, CommandSender sender) throws CommandException {
ConfigurationManager config = plugin.getGlobalStateManager();
Iterable<Player> targets = null;
Iterable<? extends Player> targets = null;
boolean included = false;
// Detect arguments based on the number of arguments provided
@@ -100,7 +104,7 @@ public class GeneralCommands {
// Check permissions!
plugin.checkPermission(sender, "worldguard.god");
} else if (args.argsLength() == 1) {
} else {
targets = plugin.matchPlayers(sender, args.getString(0));
// Check permissions!
@@ -108,32 +112,34 @@ public class GeneralCommands {
}
for (Player player : targets) {
config.disableGodMode(player);
// Tell the user
if (player.equals(sender)) {
player.sendMessage(ChatColor.YELLOW + "God mode disabled!");
// Keep track of this
included = true;
} else {
player.sendMessage(ChatColor.YELLOW + "God disabled by "
+ plugin.toName(sender) + ".");
Session session = plugin.getSessionManager().get(player);
if (GodMode.set(player, session, false)) {
// Tell the user
if (player.equals(sender)) {
player.sendMessage(ChatColor.YELLOW + "God mode disabled!");
// Keep track of this
included = true;
} else {
player.sendMessage(ChatColor.YELLOW + "God disabled by "
+ plugin.toName(sender) + ".");
}
}
}
// The player didn't receive any items, then we need to send the
// user a message so s/he know that something is indeed working
if (!included && args.hasFlag('s')) {
sender.sendMessage(ChatColor.YELLOW.toString() + "Players no longer have god mode.");
sender.sendMessage(ChatColor.YELLOW + "Players no longer have god mode.");
}
}
@Command(aliases = {"heal"}, usage = "[player]", desc = "Heal a player", flags = "s", max = 1)
public void heal(CommandContext args,CommandSender sender) throws CommandException {
Iterable<Player> targets = null;
Iterable<? extends Player> targets = null;
boolean included = false;
// Detect arguments based on the number of arguments provided
@@ -176,7 +182,7 @@ public class GeneralCommands {
@Command(aliases = {"slay"}, usage = "[player]", desc = "Slay a player", flags = "s", max = 1)
public void slay(CommandContext args, CommandSender sender) throws CommandException {
Iterable<Player> targets = null;
Iterable<? extends Player> targets = null;
boolean included = false;
// Detect arguments based on the number of arguments provided
@@ -19,16 +19,23 @@
package com.sk89q.worldguard.bukkit.commands;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.io.Files;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.minecraft.util.commands.*;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.LoggerToChatHandler;
import com.sk89q.worldguard.bukkit.util.ReportWriter;
import com.sk89q.worldguard.util.PastebinPoster;
import com.sk89q.worldguard.util.PastebinPoster.PasteCallback;
import com.sk89q.worldguard.bukkit.util.logging.LoggerToChatHandler;
import com.sk89q.worldguard.bukkit.util.report.*;
import com.sk89q.worldguard.util.profiler.SamplerBuilder;
import com.sk89q.worldguard.util.profiler.SamplerBuilder.Sampler;
import com.sk89q.worldguard.util.profiler.ThreadIdFilter;
import com.sk89q.worldguard.util.profiler.ThreadNameFilter;
import com.sk89q.worldguard.util.report.ReportList;
import com.sk89q.worldguard.util.report.SystemInfoReport;
import com.sk89q.worldguard.util.task.Task;
import com.sk89q.worldguard.util.task.TaskStateComparator;
import org.bukkit.Bukkit;
@@ -37,15 +44,24 @@ import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.lang.management.ThreadInfo;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WorldGuardCommands {
private static final Logger log = Logger.getLogger(WorldGuardCommands.class.getCanonicalName());
private final WorldGuardPlugin plugin;
@Nullable
private Sampler activeSampler;
public WorldGuardCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
@@ -101,36 +117,132 @@ public class WorldGuardCommands {
@Command(aliases = {"report"}, desc = "Writes a report on WorldGuard", flags = "p", max = 0)
@CommandPermissions({"worldguard.report"})
public void report(CommandContext args, final CommandSender sender) throws CommandException {
File dest = new File(plugin.getDataFolder(), "report.txt");
ReportWriter report = new ReportWriter(plugin);
ReportList report = new ReportList("Report");
report.add(new SystemInfoReport());
report.add(new ServerReport());
report.add(new PluginReport());
report.add(new SchedulerReport());
report.add(new ServicesReport());
report.add(new WorldReport());
report.add(new PerformanceReport());
report.add(new ConfigReport(plugin));
String result = report.toString();
try {
report.write(dest);
sender.sendMessage(ChatColor.YELLOW + "WorldGuard report written to "
+ dest.getAbsolutePath());
File dest = new File(plugin.getDataFolder(), "report.txt");
Files.write(result, dest, Charset.forName("UTF-8"));
sender.sendMessage(ChatColor.YELLOW + "WorldGuard report written to " + dest.getAbsolutePath());
} catch (IOException e) {
throw new CommandException("Failed to write report: " + e.getMessage());
}
if (args.hasFlag('p')) {
plugin.checkPermission(sender, "worldguard.report.pastebin");
sender.sendMessage(ChatColor.YELLOW + "Now uploading to Pastebin...");
PastebinPoster.paste(report.toString(), new PasteCallback() {
public void handleSuccess(String url) {
// Hope we don't have a thread safety issue here
sender.sendMessage(ChatColor.YELLOW + "WorldGuard report (1 hour): " + url);
}
public void handleError(String err) {
// Hope we don't have a thread safety issue here
sender.sendMessage(ChatColor.YELLOW + "WorldGuard report pastebin error: " + err);
}
});
CommandUtils.pastebin(plugin, sender, result, "WorldGuard report: %s.report");
}
}
@Command(aliases = {"profile"}, usage = "[<minutes>]",
desc = "Profile the CPU usage of the server", min = 0, max = 1,
flags = "t:p")
@CommandPermissions("worldguard.profile")
public void profile(final CommandContext args, final CommandSender sender) throws CommandException {
Predicate<ThreadInfo> threadFilter;
String threadName = args.getFlag('t');
final boolean pastebin;
if (args.hasFlag('p')) {
plugin.checkPermission(sender, "worldguard.report.pastebin");
pastebin = true;
} else {
pastebin = false;
}
if (threadName == null) {
threadFilter = new ThreadIdFilter(Thread.currentThread().getId());
} else if (threadName.equals("*")) {
threadFilter = Predicates.alwaysTrue();
} else {
threadFilter = new ThreadNameFilter(threadName);
}
int minutes;
if (args.argsLength() == 0) {
minutes = 5;
} else {
minutes = args.getInteger(0);
if (minutes < 1) {
throw new CommandException("You must run the profile for at least 1 minute.");
} else if (minutes > 10) {
throw new CommandException("You can profile for, at maximum, 10 minutes.");
}
}
Sampler sampler;
synchronized (this) {
if (activeSampler != null) {
throw new CommandException("A profile is currently in progress! Please use /wg stopprofile to stop the current profile.");
}
SamplerBuilder builder = new SamplerBuilder();
builder.setThreadFilter(threadFilter);
builder.setRunTime(minutes, TimeUnit.MINUTES);
sampler = activeSampler = builder.start();
}
AsyncCommandHelper.wrap(sampler.getFuture(), plugin, sender)
.formatUsing(minutes)
.registerWithSupervisor("Running CPU profiler for %d minute(s)...")
.sendMessageAfterDelay("(Please wait... profiling for %d minute(s)...)")
.thenTellErrorsOnly("CPU profiling failed.");
sampler.getFuture().addListener(new Runnable() {
@Override
public void run() {
synchronized (WorldGuardCommands.this) {
activeSampler = null;
}
}
}, MoreExecutors.sameThreadExecutor());
Futures.addCallback(sampler.getFuture(), new FutureCallback<Sampler>() {
@Override
public void onSuccess(Sampler result) {
String output = result.toString();
try {
File dest = new File(plugin.getDataFolder(), "profile.txt");
Files.write(output, dest, Charset.forName("UTF-8"));
sender.sendMessage(ChatColor.YELLOW + "CPU profiling data written to " + dest.getAbsolutePath());
} catch (IOException e) {
sender.sendMessage(ChatColor.RED + "Failed to write CPU profiling data: " + e.getMessage());
}
if (pastebin) {
CommandUtils.pastebin(plugin, sender, output, "Profile result: %s.profile");
}
}
@Override
public void onFailure(Throwable throwable) {
}
});
}
@Command(aliases = {"stopprofile"}, usage = "",desc = "Stop a running profile", min = 0, max = 0)
@CommandPermissions("worldguard.profile")
public void stopProfile(CommandContext args, final CommandSender sender) throws CommandException {
synchronized (this) {
if (activeSampler == null) {
throw new CommandException("No CPU profile is currently running.");
}
activeSampler.cancel();
activeSampler = null;
}
sender.sendMessage("The running CPU profile has been stopped.");
}
@Command(aliases = {"flushstates", "clearstates"},
@@ -138,12 +250,12 @@ public class WorldGuardCommands {
@CommandPermissions("worldguard.flushstates")
public void flushStates(CommandContext args, CommandSender sender) throws CommandException {
if (args.argsLength() == 0) {
plugin.getFlagStateManager().forgetAll();
plugin.getSessionManager().resetAllStates();
sender.sendMessage("Cleared all states.");
} else {
Player player = plugin.getServer().getPlayer(args.getString(0));
if (player != null) {
plugin.getFlagStateManager().forget(player);
plugin.getSessionManager().resetState(player);
sender.sendMessage("Cleared states for player \"" + player.getName() + "\".");
}
}
@@ -177,4 +289,8 @@ public class WorldGuardCommands {
}
}
@Command(aliases = {"debug"}, desc = "Debugging commands")
@NestedCommand({DebuggingCommands.class})
public void debug(CommandContext args, CommandSender sender) {}
}
@@ -42,7 +42,7 @@ import com.sk89q.worldguard.bukkit.commands.task.RegionManagerReloader;
import com.sk89q.worldguard.bukkit.commands.task.RegionManagerSaver;
import com.sk89q.worldguard.bukkit.commands.task.RegionRemover;
import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel;
import com.sk89q.worldguard.bukkit.util.LoggerToChatHandler;
import com.sk89q.worldguard.bukkit.util.logging.LoggerToChatHandler;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
@@ -519,7 +519,7 @@ public final class RegionCommands extends RegionCommandsBase {
// Also make sure that we can use this flag
// This permission is confusing and probably should be replaced, but
// but not here -- in the model
if (!permModel.maySetFlag(existing, foundFlag)) {
if (!permModel.maySetFlag(existing, foundFlag, value)) {
throw new CommandPermissionsException();
}
@@ -116,6 +116,10 @@ public class RegionLister implements Callable<Integer> {
@Override
public boolean isContainedWithin(DefaultDomain domain) throws CommandException {
if (domain.contains(name)) {
return true;
}
if (uniqueId == null) {
Profile profile;
@@ -19,20 +19,21 @@
package com.sk89q.worldguard.bukkit.event;
import org.bukkit.event.Event.Result;
/**
* A bulk event contains several affected objects in a list.
*/
public interface BulkEvent {
/**
* Return whether the event is explicitly cancelled.
* Get the actual result.
*
* <p>By default, bulk events will cancel itself if the number of affected
* objects drops to zero. This method returns the true cancellation
* status.</p>
* <p>By default, bulk events will set the result to DENY if the number of
* affected objects drops to zero. This method returns the true result.</p>
*
* @return true if really cancelled
* @return the explicit result
*/
boolean isExplicitlyCancelled();
Result getExplicitResult();
}
@@ -19,11 +19,14 @@
package com.sk89q.worldguard.bukkit.event;
import com.google.common.collect.Lists;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.protection.flags.StateFlag;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import javax.annotation.Nullable;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -31,12 +34,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
* This event is an internal event. We do not recommend handling or throwing
* this event or its subclasses as the interface is highly subject to change.
*/
public abstract class DelegateEvent extends Event implements Cancellable {
public abstract class DelegateEvent extends Event implements Cancellable, Handleable {
@Nullable
private final Event originalEvent;
private final Cause cause;
private boolean cancelled;
private final List<StateFlag> relevantFlags = Lists.newArrayList();
private Result result = Result.DEFAULT;
private boolean silent;
/**
@@ -70,14 +74,35 @@ public abstract class DelegateEvent extends Event implements Cancellable {
return cause;
}
/**
* Get a list of relevant flags to consider for this event.
*
* @return A list of relevant flags
*/
public List<StateFlag> getRelevantFlags() {
return relevantFlags;
}
@Override
public boolean isCancelled() {
return cancelled;
return getResult() == Result.DENY;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
if (cancel) {
setResult(Result.DENY);
}
}
@Override
public Result getResult() {
return result;
}
@Override
public void setResult(Result result) {
this.result = result;
}
/**
@@ -93,9 +118,25 @@ public abstract class DelegateEvent extends Event implements Cancellable {
* Set whether this should be a silent check.
*
* @param silent true if silent
* @return the same event
*/
void setSilent(boolean silent) {
public DelegateEvent setSilent(boolean silent) {
this.silent = silent;
return this;
}
/**
* Set the event to {@link Result#ALLOW} if {@code allowed} is true.
*
* @param allowed true to set the result
* @return the same event
*/
public DelegateEvent setAllowed(boolean allowed) {
if (allowed) {
setResult(Result.ALLOW);
}
return this;
}
}
@@ -19,6 +19,8 @@
package com.sk89q.worldguard.bukkit.event;
import org.bukkit.event.Event.Result;
/**
* Utility methods for dealing with delegate events.
*/
@@ -52,4 +54,19 @@ public final class DelegateEvents {
return event;
}
/**
* Set an event as handled as {@link Result#ALLOW} if {@code allowed} is
* true, otherwise do nothing.
*
* @param event the event
* @param <T> the type of event
* @return the same event
*/
public static <T extends Handleable> T setAllowed(T event, boolean allowed) {
if (allowed) {
event.setResult(Result.ALLOW);
}
return event;
}
}
@@ -0,0 +1,30 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event;
import org.bukkit.event.Event.Result;
public interface Handleable {
Result getResult();
void setResult(Result result);
}
@@ -70,16 +70,6 @@ abstract class AbstractBlockEvent extends DelegateEvent implements BulkEvent {
return blocks;
}
@Override
public boolean isCancelled() {
return super.isCancelled() || blocks.isEmpty();
}
@Override
public boolean isExplicitlyCancelled() {
return super.isCancelled();
}
/**
* Get the world.
*
@@ -153,4 +143,18 @@ abstract class AbstractBlockEvent extends DelegateEvent implements BulkEvent {
public Material getEffectiveMaterial() {
return effectiveMaterial;
}
@Override
public Result getResult() {
if (blocks.isEmpty()) {
return Result.DENY;
}
return super.getResult();
}
@Override
public Result getExplicitResult() {
return super.getResult();
}
}
@@ -0,0 +1,76 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event.debug;
import org.bukkit.event.Cancellable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents call to {@link Cancellable#setCancelled(boolean)}.
*/
public class CancelAttempt {
private final boolean before;
private final boolean after;
private final StackTraceElement[] stackTrace;
/**
* Create a new instance.
*
* @param before The cancellation flag before the call
* @param after The cancellation flag after the call
* @param stackTrace The stack trace
*/
public CancelAttempt(boolean before, boolean after, StackTraceElement[] stackTrace) {
checkNotNull(stackTrace, "stackTrace");
this.before = before;
this.after = after;
this.stackTrace = stackTrace;
}
/**
* Get the cancellation state before the call.
*
* @return Whether the event was cancelled before
*/
public boolean getBefore() {
return before;
}
/**
* Get the cancellation state after the call.
*
* @return The new cancellation state
*/
public boolean getAfter() {
return after;
}
/**
* Get the stack trace.
*
* @return The stack trace
*/
public StackTraceElement[] getStackTrace() {
return stackTrace;
}
}
@@ -0,0 +1,54 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event.debug;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
/**
* Logs attempts at cancellation.
*/
public class CancelLogger {
private List<CancelAttempt> entries = new ArrayList<CancelAttempt>();
/**
* Log a call.
*
* @param before The cancellation flag before the call
* @param after The cancellation flag after the call
* @param stackTrace The stack trace
*/
public void log(boolean before, boolean after, StackTraceElement[] stackTrace) {
entries.add(new CancelAttempt(before, after, stackTrace));
}
/**
* Get an immutable list of cancels.
*
* @return An immutable list
*/
public List<CancelAttempt> getCancels() {
return ImmutableList.copyOf(entries);
}
}
@@ -0,0 +1,35 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event.debug;
import org.bukkit.event.Cancellable;
import java.util.List;
public interface CancelLogging extends Cancellable {
/**
* Get an immutable list of cancels.
*
* @return An immutable list
*/
List<CancelAttempt> getCancels();
}
@@ -0,0 +1,46 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event.debug;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockBreakEvent;
import java.util.List;
public class LoggingBlockBreakEvent extends BlockBreakEvent implements CancelLogging {
private final CancelLogger logger = new CancelLogger();
public LoggingBlockBreakEvent(Block block, Player player) {
super(block, player);
}
public List<CancelAttempt> getCancels() {
return logger.getCancels();
}
@Override
public void setCancelled(boolean cancel) {
this.logger.log(isCancelled(), cancel, new Exception().getStackTrace());
super.setCancelled(cancel);
}
}
@@ -0,0 +1,48 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event.debug;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class LoggingBlockPlaceEvent extends BlockPlaceEvent implements CancelLogging {
private final CancelLogger logger = new CancelLogger();
public LoggingBlockPlaceEvent(Block placedBlock, BlockState replacedBlockState, Block placedAgainst, ItemStack itemInHand, Player thePlayer, boolean canBuild) {
super(placedBlock, replacedBlockState, placedAgainst, itemInHand, thePlayer, canBuild);
}
public List<CancelAttempt> getCancels() {
return logger.getCancels();
}
@Override
public void setCancelled(boolean cancel) {
this.logger.log(isCancelled(), cancel, new Exception().getStackTrace());
super.setCancelled(cancel);
}
}
@@ -0,0 +1,45 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event.debug;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import java.util.List;
public class LoggingEntityDamageByEntityEvent extends EntityDamageByEntityEvent implements CancelLogging {
private final CancelLogger logger = new CancelLogger();
public LoggingEntityDamageByEntityEvent(Entity damager, Entity damagee, DamageCause cause, double damage) {
super(damager, damagee, cause, damage);
}
public List<CancelAttempt> getCancels() {
return logger.getCancels();
}
@Override
public void setCancelled(boolean cancel) {
this.logger.log(isCancelled(), cancel, new Exception().getStackTrace());
super.setCancelled(cancel);
}
}
@@ -0,0 +1,49 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event.debug;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class LoggingPlayerInteractEvent extends PlayerInteractEvent implements CancelLogging {
private final CancelLogger logger = new CancelLogger();
public LoggingPlayerInteractEvent(Player who, Action action, ItemStack item, Block clickedBlock, BlockFace clickedFace) {
super(who, action, item, clickedBlock, clickedFace);
}
public List<CancelAttempt> getCancels() {
return logger.getCancels();
}
@Override
public void setCancelled(boolean cancel) {
this.logger.log(isCancelled(), cancel, new Exception().getStackTrace());
super.setCancelled(cancel);
}
}
@@ -1,40 +1,39 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import com.sk89q.worldguard.blacklist.Blacklist;
import java.util.logging.Logger;
class BukkitBlacklist extends Blacklist {
private WorldGuardPlugin plugin;
public BukkitBlacklist(Boolean useAsWhitelist, WorldGuardPlugin plugin) {
super(useAsWhitelist);
this.plugin = plugin;
}
@Override
public void broadcastNotification(String msg) {
plugin.broadcastNotification(msg);
}
}
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.internal;
import com.sk89q.worldguard.blacklist.Blacklist;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
public class BukkitBlacklist extends Blacklist {
private WorldGuardPlugin plugin;
public BukkitBlacklist(Boolean useAsWhitelist, WorldGuardPlugin plugin) {
super(useAsWhitelist);
this.plugin = plugin;
}
@Override
public void broadcastNotification(String msg) {
plugin.broadcastNotification(msg);
}
}
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
package com.sk89q.worldguard.bukkit.internal;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
@@ -70,4 +70,9 @@ public class TargetMatcherSet {
return test(new MaterialTarget(itemStack.getTypeId(), itemStack.getDurability()));
}
@Override
public String toString() {
return entries.toString();
}
}
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
package com.sk89q.worldguard.bukkit.internal;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.metadata.FixedMetadataValue;
@@ -21,14 +21,7 @@ package com.sk89q.worldguard.bukkit.listener;
import com.google.common.base.Predicate;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.BlockDispenseBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.BlockInteractBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.BlockPlaceBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemAcquireBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemDestroyWithBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemDropBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.*;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
@@ -42,11 +35,16 @@ import com.sk89q.worldguard.bukkit.util.Materials;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCreativeEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget;
@@ -259,4 +257,64 @@ public class BlacklistListener extends AbstractListener {
}
}
@EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event) {
HumanEntity entity = event.getWhoClicked();
Inventory inventory = event.getInventory();
ItemStack item = event.getCurrentItem();
if (item != null && entity instanceof Player) {
Player player = (Player) entity;
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(entity.getWorld());
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
if (wcfg.getBlacklist() != null && !wcfg.getBlacklist().check(
new ItemAcquireBlacklistEvent(localPlayer, toVector(entity.getLocation()), createTarget(item)), false, false)) {
event.setCancelled(true);
if (inventory.getHolder().equals(player)) {
event.setCurrentItem(null);
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onInventoryCreative(InventoryCreativeEvent event) {
HumanEntity entity = event.getWhoClicked();
ItemStack item = event.getCursor();
if (item != null && entity instanceof Player) {
Player player = (Player) entity;
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(entity.getWorld());
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
if (wcfg.getBlacklist() != null && !wcfg.getBlacklist().check(
new ItemAcquireBlacklistEvent(localPlayer, toVector(entity.getLocation()), createTarget(item)), false, false)) {
event.setCancelled(true);
event.setCursor(null);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
Player player = event.getPlayer();
Inventory inventory = player.getInventory();
ItemStack item = inventory.getItem(event.getNewSlot());
if (item != null) {
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
if (wcfg.getBlacklist() != null && !wcfg.getBlacklist().check(
new ItemAcquireBlacklistEvent(localPlayer, toVector(player.getLocation()), createTarget(item)), false, false)) {
inventory.setItem(event.getNewSlot(), null);
}
}
}
}
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
package com.sk89q.worldguard.bukkit.listener;
import com.google.common.base.Function;
import org.bukkit.block.Block;
@@ -25,7 +25,7 @@ import org.bukkit.block.BlockState;
import javax.annotation.Nullable;
public class BlockStateAsBlockFunction implements Function<BlockState, Block> {
class BlockStateAsBlockFunction implements Function<BlockState, Block> {
@Override
public Block apply(@Nullable BlockState blockState) {
@@ -28,7 +28,6 @@ import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
@@ -49,21 +48,10 @@ public class BlockedPotionsListener extends AbstractListener {
@EventHandler
public void onItemInteract(UseItemEvent event) {
// We only care about player caused events
if (event.getCause().getFirstPlayer() == null) {
return;
}
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
ItemStack item = event.getItemStack();
// Only block potions via PotionSplashEvent if "over reliable potion
// blocking" is enabled
if (!wcfg.blockPotionsAlways && event.getOriginalEvent() instanceof PotionSplashEvent) {
return;
}
// We only care about portions
if (item.getType() != Material.POTION || BukkitUtil.isWaterPotion(item)) {
return;
@@ -193,8 +193,12 @@ public class BuildPermissionListener extends AbstractListener {
Player player = (Player) rootCause;
Material material = event.getItemStack().getType();
if (material.isBlock()) {
return;
}
if (!hasBuildPermission(player, "item." + material.name().toLowerCase() + ".use")
|| hasBuildPermission(player, "item.use." + material.name().toLowerCase())) {
&& !hasBuildPermission(player, "item.use." + material.name().toLowerCase())) {
tellErrorMessage(player, event.getWorld());
event.setCancelled(true);
}
@@ -30,6 +30,7 @@ import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -67,8 +68,8 @@ public class DebuggingListener extends AbstractListener {
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
if (event.getResult() != Result.DEFAULT) {
builder.append(" [").append(event.getResult()).append("]");
}
logger.info(builder.toString());
}
@@ -85,8 +86,8 @@ public class DebuggingListener extends AbstractListener {
builder.append("@").append(toBlockString(event.getBlocks()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
if (event.getResult() != Result.DEFAULT) {
builder.append(" [").append(event.getResult()).append("]");
}
logger.info(builder.toString());
}
@@ -103,8 +104,8 @@ public class DebuggingListener extends AbstractListener {
builder.append("@").append(toBlockString(event.getBlocks()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
if (event.getResult() != Result.DEFAULT) {
builder.append(" [").append(event.getResult()).append("]");
}
logger.info(builder.toString());
}
@@ -121,8 +122,8 @@ public class DebuggingListener extends AbstractListener {
builder.append("@").append(toBlockString(event.getTarget()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
if (event.getResult() != Result.DEFAULT) {
builder.append(" [").append(event.getResult()).append("]");
}
logger.info(builder.toString());
}
@@ -139,8 +140,8 @@ public class DebuggingListener extends AbstractListener {
builder.append("@").append(toBlockString(event.getTarget()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
if (event.getResult() != Result.DEFAULT) {
builder.append(" [").append(event.getResult()).append("]");
}
logger.info(builder.toString());
}
@@ -157,8 +158,8 @@ public class DebuggingListener extends AbstractListener {
builder.append("@").append(toBlockString(event.getTarget()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
if (event.getResult() != Result.DEFAULT) {
builder.append(" [").append(event.getResult()).append("]");
}
logger.info(builder.toString());
}
@@ -175,8 +176,8 @@ public class DebuggingListener extends AbstractListener {
builder.append("@").append(event.getWorld().getName());
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
if (event.getResult() != Result.DEFAULT) {
builder.append(" [").append(event.getResult()).append("]");
}
logger.info(builder.toString());
}
@@ -23,7 +23,7 @@ import com.google.common.collect.Lists;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.DelegateEvents;
import com.sk89q.worldguard.bukkit.event.DelegateEvent;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
@@ -39,80 +39,34 @@ import com.sk89q.worldguard.bukkit.listener.debounce.legacy.AbstractEventDebounc
import com.sk89q.worldguard.bukkit.listener.debounce.legacy.BlockEntityEventDebounce;
import com.sk89q.worldguard.bukkit.listener.debounce.legacy.EntityEntityEventDebounce;
import com.sk89q.worldguard.bukkit.listener.debounce.legacy.InventoryMoveItemEventDebounce;
import com.sk89q.worldguard.bukkit.util.BlockStateAsBlockFunction;
import com.sk89q.worldguard.bukkit.util.Blocks;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import org.bukkit.Bukkit;
import org.bukkit.DyeColor;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.DoubleChest;
import org.bukkit.block.Hopper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.ThrownPotion;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.entity.*;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.block.BlockExpEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityCombustByBlockEvent;
import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityTameEvent;
import org.bukkit.event.entity.EntityUnleashEvent;
import org.bukkit.event.entity.ExpBottleEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.Listener;
import org.bukkit.event.block.*;
import org.bukkit.event.entity.*;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerShearEntityEvent;
import org.bukkit.event.player.PlayerUnleashEntityEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.*;
import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.*;
import org.bukkit.material.Dispenser;
import org.bukkit.material.MaterialData;
import org.bukkit.material.SpawnEgg;
import org.bukkit.projectiles.ProjectileSource;
import org.bukkit.util.Vector;
import javax.annotation.Nullable;
@@ -139,6 +93,16 @@ public class EventAbstractionListener extends AbstractListener {
super(plugin);
}
@Override
public void registerEvents() {
super.registerEvents();
try {
getPlugin().getServer().getPluginManager().registerEvents(new SpigotCompatListener(), getPlugin());
} catch (LinkageError ignored) {
}
}
//-------------------------------------------------------------------------
// Block break / place
//-------------------------------------------------------------------------
@@ -278,18 +242,28 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR));
}
@SuppressWarnings("deprecation")
@EventHandler(ignoreCancelled = true)
public void onBlockPistonRetract(BlockPistonRetractEvent event) {
if (event.isSticky()) {
EventDebounce.Entry entry = pistonRetractDebounce.getIfNotPresent(new BlockPistonRetractKey(event), event);
if (entry != null) {
Cause cause = create(event.getBlock());
Events.fireToCancel(event, new BreakBlockEvent(event, cause, event.getRetractLocation(), Material.AIR));
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getRelative(event.getDirection())));
Block piston = event.getBlock();
Cause cause = create(piston);
// Workaround for incorrect piston events
BlockFace direction = event.getDirection();
if (piston.getType() == Material.PISTON_MOVING_PIECE) {
direction = new PistonExtensionMaterial(Material.PISTON_STICKY_BASE.getId(), piston.getData()).getFacing();
}
Location retractLocation = piston.getRelative(direction, 2).getLocation();
Events.fireToCancel(event, new BreakBlockEvent(event, cause, retractLocation, Material.AIR));
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, piston.getRelative(direction)));
entry.setCancelled(event.isCancelled());
if (event.isCancelled()) {
playDenyEffect(event.getBlock().getLocation().add(0.5, 1, 0.5));
playDenyEffect(piston.getLocation().add(0.5, 1, 0.5));
}
}
}
@@ -338,6 +312,7 @@ public class EventAbstractionListener extends AbstractListener {
Block clicked = event.getClickedBlock();
Block placed;
boolean silent = false;
boolean modifiesWorld;
Cause cause = create(player);
switch (event.getAction()) {
@@ -347,7 +322,8 @@ public class EventAbstractionListener extends AbstractListener {
silent = true;
}
interactDebounce.debounce(clicked, event.getPlayer(), event, DelegateEvents.setSilent(new UseBlockEvent(event, cause, clicked), silent));
interactDebounce.debounce(clicked, event.getPlayer(), event,
new UseBlockEvent(event, cause, clicked).setSilent(silent).setAllowed(hasInteractBypass(clicked)));
break;
case RIGHT_CLICK_BLOCK:
@@ -360,17 +336,17 @@ public class EventAbstractionListener extends AbstractListener {
placed = clicked.getRelative(event.getBlockFace());
// Only fire events for blocks that are modified when right clicked
if (isBlockModifiedOnClick(clicked) || (item != null && isItemAppliedToBlock(item, clicked))) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked))) {
event.setUseInteractedBlock(Result.DENY);
}
modifiesWorld = isBlockModifiedOnClick(clicked, event.getAction() == Action.RIGHT_CLICK_BLOCK) || (item != null && isItemAppliedToBlock(item, clicked));
// Handle connected blocks (i.e. beds, chests)
for (Block connected : Blocks.getConnected(clicked)) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, create(event.getPlayer()), connected))) {
event.setUseInteractedBlock(Result.DENY);
break;
}
if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked).setAllowed(!modifiesWorld))) {
event.setUseInteractedBlock(Result.DENY);
}
// Handle connected blocks (i.e. beds, chests)
for (Block connected : Blocks.getConnected(clicked)) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, create(event.getPlayer()), connected).setAllowed(!modifiesWorld))) {
event.setUseInteractedBlock(Result.DENY);
break;
}
}
@@ -390,6 +366,7 @@ public class EventAbstractionListener extends AbstractListener {
case RIGHT_CLICK_AIR:
if (item != null && !item.getType().isBlock() && Events.fireAndTestCancel(new UseItemEvent(event, cause, player.getWorld(), item))) {
event.setUseItemInHand(Result.DENY);
event.setCancelled(true); // The line above does not appear to work with spawn eggs
}
// Check for items that the administrator has configured to
@@ -408,7 +385,8 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityInteract(org.bukkit.event.entity.EntityInteractEvent event) {
interactDebounce.debounce(event.getBlock(), event.getEntity(), event, new UseBlockEvent(event, create(event.getEntity()), event.getBlock()));
interactDebounce.debounce(event.getBlock(), event.getEntity(), event,
new UseBlockEvent(event, create(event.getEntity()), event.getBlock()).setAllowed(hasInteractBypass(event.getBlock())));
}
@EventHandler(ignoreCancelled = true)
@@ -449,31 +427,41 @@ public class EventAbstractionListener extends AbstractListener {
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
Player player = event.getPlayer();
Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace());
boolean allowed = false;
// Milk buckets can't be emptied as of writing
if (event.getBucket() != Material.MILK_BUCKET) {
ItemStack item = new ItemStack(event.getBucket(), 1);
Material blockMaterial = Materials.getBucketBlockMaterial(event.getBucket());
Events.fireToCancel(event, new PlaceBlockEvent(event, create(player), blockAffected.getLocation(), blockMaterial));
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item));
if (event.getBucket() == Material.MILK_BUCKET) {
allowed = true;
}
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 0.5, 0.5));
ItemStack item = new ItemStack(event.getBucket(), 1);
Material blockMaterial = Materials.getBucketBlockMaterial(event.getBucket());
Events.fireToCancel(event, new PlaceBlockEvent(event, create(player), blockAffected.getLocation(), blockMaterial).setAllowed(allowed));
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item).setAllowed(allowed));
if (event.isCancelled()) {
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 0.5, 0.5));
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerBucketFill(PlayerBucketFillEvent event) {
Player player = event.getPlayer();
Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace());
boolean allowed = false;
// Milk buckets can't be filled by right clicking the ground as of writing
if (event.getBucket() != Material.MILK_BUCKET) {
ItemStack item = new ItemStack(event.getBucket(), 1);
Events.fireToCancel(event, new BreakBlockEvent(event, create(player), blockAffected));
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item));
// Milk buckets can't be emptied as of writing
if (event.getBucket() == Material.MILK_BUCKET) {
allowed = true;
}
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 1, 0.5));
ItemStack item = new ItemStack(event.getBucket(), 1);
Events.fireToCancel(event, new BreakBlockEvent(event, create(player), blockAffected).setAllowed(allowed));
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item).setAllowed(allowed));
if (event.isCancelled()) {
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 0.5, 0.5));
}
}
// TODO: Handle EntityPortalEnterEvent
@@ -577,8 +565,6 @@ public class EventAbstractionListener extends AbstractListener {
if (event.isCancelled() && remover instanceof Player) {
playDenyEffect((Player) remover, event.getEntity().getLocation());
}
} else {
Events.fireToCancel(event, new DestroyEntityEvent(event, Cause.unknown(), event.getEntity()));
}
}
@@ -607,6 +593,15 @@ public class EventAbstractionListener extends AbstractListener {
public void onExpBottle(ExpBottleEvent event) {
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getEntity()), event.getEntity().getLocation(), EntityType.EXPERIENCE_ORB))) {
event.setExperience(0);
// Give the player back his or her XP bottle
ProjectileSource shooter = event.getEntity().getShooter();
if (shooter instanceof Player) {
Player player = (Player) shooter;
if (player.getGameMode() != GameMode.CREATIVE) {
player.getInventory().addItem(new ItemStack(Material.EXP_BOTTLE, 1));
}
}
}
}
@@ -637,7 +632,13 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
if (event instanceof EntityDamageByBlockEvent) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityDamageByBlockEvent) event).getDamager()), event.getEntity()));
@Nullable Block attacker = ((EntityDamageByBlockEvent) event).getDamager();
// The attacker should NOT be null, but sometimes it is
// See WORLDGUARD-3350
if (attacker != null) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(attacker), event.getEntity()));
}
} else if (event instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent entityEvent = (EntityDamageByEntityEvent) event;
@@ -654,9 +655,6 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireToCancel(event, new UseItemEvent(event, create(damager), event.getEntity().getWorld(), item));
}
}
} else {
Events.fireToCancel(event, new DamageEntityEvent(event, Cause.unknown(), event.getEntity()));
}
}
@@ -667,9 +665,6 @@ public class EventAbstractionListener extends AbstractListener {
} else if (event instanceof EntityCombustByEntityEvent) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityCombustByEntityEvent) event).getCombuster()), event.getEntity()));
} else {
Events.fireToCancel(event, new DamageEntityEvent(event, Cause.unknown(), event.getEntity()));
}
}
@@ -707,7 +702,7 @@ public class EventAbstractionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onVehicleDamage(VehicleDamageEvent event) {
Entity attacker = event.getAttacker();
Events.fireToCancel(event, new DestroyEntityEvent(event, create(attacker), event.getVehicle()));
Events.fireToCancel(event, new DamageEntityEvent(event, create(attacker), event.getVehicle()));
}
@EventHandler(ignoreCancelled = true)
@@ -719,6 +714,23 @@ public class EventAbstractionListener extends AbstractListener {
// Composite events
//-------------------------------------------------------------------------
@EventHandler(ignoreCancelled = true)
public void onPlayerItemConsume(PlayerItemConsumeEvent event) {
Events.fireToCancel(event, new UseItemEvent(event, create(event.getPlayer()), event.getPlayer().getWorld(), event.getItem()));
}
@EventHandler(ignoreCancelled = true)
public void onInventoryOpen(InventoryOpenEvent event) {
InventoryHolder holder = event.getInventory().getHolder();
if (holder instanceof BlockState) {
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), ((BlockState) holder).getBlock()));
} else if (holder instanceof Entity) {
if (!(holder instanceof Player)) {
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getPlayer()), (Entity) holder));
}
}
}
@EventHandler(ignoreCancelled = true)
public void onInventoryMoveItem(InventoryMoveItemEvent event) {
final InventoryHolder causeHolder = event.getInitiator().getHolder();
@@ -762,7 +774,7 @@ public class EventAbstractionListener extends AbstractListener {
Entity entity = event.getEntity();
ThrownPotion potion = event.getPotion();
World world = entity.getWorld();
Cause cause = create(potion.getShooter());
Cause cause = create(potion);
// Fire item interaction event
Events.fireToCancel(event, new UseItemEvent(event, cause, world, potion.getItem()));
@@ -770,9 +782,17 @@ public class EventAbstractionListener extends AbstractListener {
// Fire entity interaction event
if (!event.isCancelled()) {
int blocked = 0;
boolean hasDamageEffect = Materials.hasDamageEffect(potion.getEffects());
for (LivingEntity affected : event.getAffectedEntities()) {
if (Events.fireAndTestCancel(new DamageEntityEvent(event, cause, affected))) {
DelegateEvent delegate = hasDamageEffect
? new DamageEntityEvent(event, cause, affected) :
new UseEntityEvent(event, cause, affected);
// Consider the potion splash flag
delegate.getRelevantFlags().add(DefaultFlag.POTION_SPLASH);
if (Events.fireAndTestCancel(delegate)) {
event.setIntensity(affected, 0);
blocked++;
}
@@ -832,11 +852,20 @@ public class EventAbstractionListener extends AbstractListener {
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.BOAT));
}
// Handle created armor stands
if (item != null && item.getType() == Materials.ARMOR_STAND) {
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ARMOR_STAND));
}
// Handle created spawn eggs
if (item != null && item.getType() == Material.MONSTER_EGG) {
MaterialData data = item.getData();
if (data instanceof SpawnEgg) {
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), ((SpawnEgg) data).getSpawnedType()));
@Nullable EntityType type = ((SpawnEgg) data).getSpawnedType();
if (type == null) {
type = EntityType.SHEEP; // Haven't investigated why it's sometimes null
}
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), type));
}
}
@@ -870,14 +899,22 @@ public class EventAbstractionListener extends AbstractListener {
}
}
private boolean isBlockModifiedOnClick(Block block) {
return Materials.isBlockModifiedOnClick(block.getType()) && !getWorldConfig(block.getWorld()).allowAllInteract.test(block);
private boolean hasInteractBypass(Block block) {
return getWorldConfig(block.getWorld()).allowAllInteract.test(block);
}
private boolean hasInteractBypass(World world, ItemStack item) {
return getWorldConfig(world).allowAllInteract.test(item);
}
private boolean isBlockModifiedOnClick(Block block, boolean rightClick) {
return Materials.isBlockModifiedOnClick(block.getType(), rightClick) && !hasInteractBypass(block);
}
private boolean isItemAppliedToBlock(ItemStack item, Block clicked) {
return Materials.isItemAppliedToBlock(item.getType(), clicked.getType())
&& !getWorldConfig(clicked.getWorld()).allowAllInteract.test(clicked)
&& !getWorldConfig(clicked.getWorld()).allowAllInteract.test(item);
&& !hasInteractBypass(clicked)
&& !hasInteractBypass(clicked.getWorld(), item);
}
private void playDenyEffect(Player player, Location location) {
@@ -889,4 +926,17 @@ public class EventAbstractionListener extends AbstractListener {
location.getWorld().playEffect(location, Effect.SMOKE, BlockFace.UP);
}
public class SpigotCompatListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event){
onPlayerInteractEntity(event);
}
@EventHandler(ignoreCancelled = true)
public void onBlockExplode(BlockExplodeEvent event) {
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(event.getBlock()),
event.getBlock().getLocation().getWorld(), event.blockList(), Material.AIR));
}
}
}
@@ -1,250 +0,0 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.RegionQueryUtil;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.GameMode;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
/**
* This processes per-player state information and is also meant to be used
* as a scheduled task.
*
* @author sk89q
*/
public class FlagStateManager implements Runnable {
public static final int RUN_DELAY = 20;
private WorldGuardPlugin plugin;
private Map<String, PlayerFlagState> states;
/**
* Construct the object.
*
* @param plugin The plugin instance
*/
public FlagStateManager(WorldGuardPlugin plugin) {
this.plugin = plugin;
states = new HashMap<String, PlayerFlagState>();
}
/**
* Run the task.
*/
@Override
public void run() {
Player[] players = plugin.getServer().getOnlinePlayers();
ConfigurationManager config = plugin.getGlobalStateManager();
for (Player player : players) {
WorldConfiguration worldConfig = config.get(player.getWorld());
if (!worldConfig.useRegions) {
continue;
}
PlayerFlagState state;
synchronized (this) {
state = states.get(player.getName());
if (state == null) {
state = new PlayerFlagState();
states.put(player.getName(), state);
}
}
ApplicableRegionSet applicable = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation());
if (!RegionQueryUtil.isInvincible(plugin, player, applicable)
&& !plugin.getGlobalStateManager().hasGodMode(player)
&& !(player.getGameMode() == GameMode.CREATIVE)) {
processHeal(applicable, player, state);
processFeed(applicable, player, state);
}
}
}
/**
* Process healing for a player.
*
* @param applicable The set of applicable regions
* @param player The player to process healing flags on
* @param state The player's state
*/
private void processHeal(ApplicableRegionSet applicable, Player player,
PlayerFlagState state) {
if (player.getHealth() <= 0) {
return;
}
long now = System.currentTimeMillis();
Integer healAmount = applicable.getFlag(DefaultFlag.HEAL_AMOUNT);
Integer healDelay = applicable.getFlag(DefaultFlag.HEAL_DELAY);
Double minHealth = applicable.getFlag(DefaultFlag.MIN_HEAL);
Double maxHealth = applicable.getFlag(DefaultFlag.MAX_HEAL);
if (healAmount == null || healDelay == null || healAmount == 0 || healDelay < 0) {
return;
}
if (minHealth == null) {
minHealth = 0.0;
}
if (maxHealth == null) {
maxHealth = player.getMaxHealth();
}
// Apply a cap to prevent possible exceptions
minHealth = Math.min(player.getMaxHealth(), minHealth);
maxHealth = Math.min(player.getMaxHealth(), maxHealth);
if (player.getHealth() >= maxHealth && healAmount > 0) {
return;
}
if (healDelay <= 0) {
player.setHealth(healAmount > 0 ? maxHealth : minHealth); // this will insta-kill if the flag is unset
state.lastHeal = now;
} else if (now - state.lastHeal > healDelay * 1000) {
// clamp health between minimum and maximum
player.setHealth(Math.min(maxHealth, Math.max(minHealth, player.getHealth() + healAmount)));
state.lastHeal = now;
}
}
/**
* Process restoring hunger for a player.
*
* @param applicable The set of applicable regions
* @param player The player to process hunger flags on
* @param state The player's state
*/
private void processFeed(ApplicableRegionSet applicable, Player player,
PlayerFlagState state) {
long now = System.currentTimeMillis();
Integer feedAmount = applicable.getFlag(DefaultFlag.FEED_AMOUNT);
Integer feedDelay = applicable.getFlag(DefaultFlag.FEED_DELAY);
Integer minHunger = applicable.getFlag(DefaultFlag.MIN_FOOD);
Integer maxHunger = applicable.getFlag(DefaultFlag.MAX_FOOD);
if (feedAmount == null || feedDelay == null || feedAmount == 0 || feedDelay < 0) {
return;
}
if (minHunger == null) {
minHunger = 0;
}
if (maxHunger == null) {
maxHunger = 20;
}
// Apply a cap to prevent possible exceptions
minHunger = Math.min(20, minHunger);
maxHunger = Math.min(20, maxHunger);
if (player.getFoodLevel() >= maxHunger && feedAmount > 0) {
return;
}
if (feedDelay <= 0) {
player.setFoodLevel(feedAmount > 0 ? maxHunger : minHunger);
player.setSaturation(player.getFoodLevel());
state.lastFeed = now;
} else if (now - state.lastFeed > feedDelay * 1000) {
// clamp health between minimum and maximum
player.setFoodLevel(Math.min(maxHunger, Math.max(minHunger, player.getFoodLevel() + feedAmount)));
player.setSaturation(player.getFoodLevel());
state.lastFeed = now;
}
}
/**
* Forget a player.
*
* @param player The player to forget
*/
public synchronized void forget(Player player) {
states.remove(player.getName());
}
/**
* Forget all managed players. Use with caution.
*/
public synchronized void forgetAll() {
states.clear();
}
/**
* Get a player's flag state. A new state will be created if there is no existing
* state for the player.
*
* @param player The player to get a state for
* @return The {@code player}'s state
*/
public synchronized PlayerFlagState getState(Player player) {
PlayerFlagState state = states.get(player.getName());
if (state == null) {
state = new PlayerFlagState();
states.put(player.getName(), state);
}
return state;
}
/**
* Keeps state per player.
*/
public static class PlayerFlagState {
public long lastHeal;
public long lastFeed;
public String lastGreeting;
public String lastFarewell;
public Boolean lastExitAllowed = null;
public Boolean notifiedForLeave = false;
public Boolean notifiedForEnter = false;
public GameMode lastGameMode;
public World lastWorld;
public int lastBlockX;
public int lastBlockY;
public int lastBlockZ;
/* Used to cache invincibility status */
public World lastInvincibleWorld;
public int lastInvincibleX;
public int lastInvincibleY;
public int lastInvincibleZ;
public boolean wasInvincible;
}
}
@@ -0,0 +1,105 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
public class InvincibilityListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public InvincibilityListener(WorldGuardPlugin plugin) {
super(plugin);
}
/**
* Test whether a player should be invincible.
*
* @param player The player
* @return True if invincible
*/
private boolean isInvincible(Player player) {
return getPlugin().getSessionManager().get(player).isInvincible(player);
}
@EventHandler(ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
Entity victim = event.getEntity();
WorldConfiguration worldConfig = getPlugin().getGlobalStateManager().get(victim.getWorld());
if (victim instanceof Player) {
Player player = (Player) victim;
if (isInvincible(player)) {
player.setFireTicks(0);
event.setCancelled(true);
if (event instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent byEntityEvent = (EntityDamageByEntityEvent) event;
Entity attacker = byEntityEvent.getDamager();
if (worldConfig.regionInvinciblityRemovesMobs
&& attacker instanceof LivingEntity && !(attacker instanceof Player)
&& !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) {
attacker.remove();
}
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onEntityCombust(EntityCombustEvent event) {
Entity entity = event.getEntity();
if (entity instanceof Player) {
Player player = (Player) entity;
if (isInvincible(player)) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onFoodLevelChange(FoodLevelChangeEvent event) {
if (event.getEntity() instanceof Player) {
Player player = (Player) event.getEntity();
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(player)) {
event.setCancelled(true);
}
}
}
}
@@ -22,6 +22,9 @@ package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.GodMode;
import com.sk89q.worldguard.session.handler.WaterBreathing;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -61,17 +64,18 @@ public class PlayerModesListener extends AbstractListener {
public void onProcessPlayer(ProcessPlayerEvent event) {
ConfigurationManager config = getConfig();
Player player = event.getPlayer();
Session session = getPlugin().getSessionManager().get(player);
if (!config.hasCommandBookGodMode()) {
if (hasGodModeGroup(player) || hasGodModePermission(player)) {
if (hasGodModeGroup(player) || hasGodModePermission(player)) {
if (GodMode.set(player, session, true)) {
log.log(Level.INFO, "Enabled auto-god mode for " + player.getName());
config.enableGodMode(player);
}
}
if (hasAmphibiousGroup(player)) {
log.log(Level.INFO, "Enabled no-drowning mode for " + player.getName() + " (player is in group 'wg-amphibious')");
config.enableAmphibiousMode(player);
if (WaterBreathing.set(player, session, true)) {
log.log(Level.INFO, "Enabled water breathing mode for " + player.getName() + " (player is in group 'wg-amphibious')");
}
}
}
@@ -0,0 +1,118 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector;
public class PlayerMoveListener implements Listener {
private final WorldGuardPlugin plugin;
public PlayerMoveListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
public void registerEvents() {
if (plugin.getGlobalStateManager().usePlayerMove) {
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvents(this, plugin);
}
}
@EventHandler
public void onPlayerRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
Session session = plugin.getSessionManager().get(player);
session.testMoveTo(player, event.getRespawnLocation(), MoveType.RESPAWN, true);
}
@EventHandler
public void onVehicleEnter(VehicleEnterEvent event) {
Entity entity = event.getEntered();
if (entity instanceof Player) {
Player player = (Player) entity;
Session session = plugin.getSessionManager().get(player);
if (null != session.testMoveTo(player, event.getVehicle().getLocation(), MoveType.EMBARK, true)) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerMove(PlayerMoveEvent event) {
final Player player = event.getPlayer();
Session session = plugin.getSessionManager().get(player);
final Location override = session.testMoveTo(player, event.getTo(), MoveType.MOVE);
if (override != null) {
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());
event.setTo(override.clone());
Entity vehicle = player.getVehicle();
if (vehicle != null) {
vehicle.eject();
Entity current = vehicle;
while (current != null) {
current.eject();
vehicle.setVelocity(new Vector());
if (vehicle instanceof LivingEntity) {
vehicle.teleport(override.clone());
} else {
vehicle.teleport(override.clone().add(0, 1, 0));
}
current = current.getVehicle();
}
player.teleport(override.clone().add(0, 1, 0));
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
player.teleport(override.clone().add(0, 1, 0));
}
}, 1);
}
}
}
}
@@ -25,19 +25,21 @@ import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import javax.annotation.Nullable;
@@ -89,7 +91,7 @@ public class RegionFlagsListener extends AbstractListener {
}
Entity entity;
if ((entity = event.getCause().getFirstEntity()) != null) {
if ((entity = event.getCause().getFirstNonPlayerEntity()) != null) {
// ================================================================
// CREEPER_EXPLOSION flag
// ================================================================
@@ -110,17 +112,17 @@ public class RegionFlagsListener extends AbstractListener {
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onSpawnEntity(final SpawnEntityEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
public void onEntityDamage(EntityDamageEvent event) {
Entity entity = event.getEntity();
World world = entity.getWorld();
if (!isRegionSupportEnabled(world)) return; // Region support disabled
RegionQuery query = getPlugin().getRegionContainer().createQuery();
// ================================================================
// EXP_DROPS flag
// ================================================================
if (event.getEffectiveType() == EntityType.EXPERIENCE_ORB) {
event.filter(testState(query, DefaultFlag.EXP_DROPS), false);
if (entity instanceof Player && event.getCause() == DamageCause.FALL) {
if (!query.testState(entity.getLocation(), (Player) entity, DefaultFlag.FALL_DAMAGE)) {
event.setCancelled(true);
}
}
}
@@ -32,33 +32,30 @@ import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.bukkit.internal.WGMetadata;
import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel;
import com.sk89q.worldguard.bukkit.util.DelayedRegionOverlapAssociation;
import com.sk89q.worldguard.bukkit.protection.DelayedRegionOverlapAssociation;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.bukkit.util.WGMetadata;
import com.sk89q.worldguard.bukkit.util.InteropUtils;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.association.Associables;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.events.DisallowedPVPEvent;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.*;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.vehicle.VehicleExitEvent;
import java.util.Arrays;
import java.util.List;
/**
* Handle events that need to be processed by region protection.
*/
@@ -86,7 +83,7 @@ public class RegionProtectionListener extends AbstractListener {
* @param what what was done
*/
private void tellErrorMessage(DelegateEvent event, Cause cause, Location location, String what) {
if (event.isSilent()) {
if (event.isSilent() || cause.isIndirect()) {
return;
}
@@ -112,20 +109,25 @@ public class RegionProtectionListener extends AbstractListener {
* Return whether the given cause is whitelist (should be ignored).
*
* @param cause the cause
* @param world the world
* @param pvp whether the event in question is PvP combat
* @return true if whitelisted
*/
private boolean isWhitelisted(Cause cause, World world) {
private boolean isWhitelisted(Cause cause, World world, boolean pvp) {
Object rootCause = cause.getRootCause();
if (rootCause instanceof Player) {
if (rootCause instanceof Block) {
Material type = ((Block) rootCause).getType();
return type == Material.HOPPER || type == Material.DROPPER;
} else if (rootCause instanceof Player) {
Player player = (Player) rootCause;
WorldConfiguration config = getWorldConfig(world);
if (config.fakePlayerBuildOverride && Entities.isFakePlayer(player)) {
if (config.fakePlayerBuildOverride && InteropUtils.isFakePlayer(player)) {
return true;
}
return new RegionPermissionModel(getPlugin(), player).mayIgnoreRegionProtection(world);
return !pvp && new RegionPermissionModel(getPlugin(), player).mayIgnoreRegionProtection(world);
} else {
return false;
}
@@ -153,8 +155,9 @@ public class RegionProtectionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onPlaceBlock(final PlaceBlockEvent event) {
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
final Material type = event.getEffectiveMaterial();
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
@@ -175,12 +178,12 @@ public class RegionProtectionListener extends AbstractListener {
/* Flint and steel, fire charge, etc. */
if (type == Material.FIRE) {
canPlace = query.testBuild(target, associable, DefaultFlag.BLOCK_PLACE, DefaultFlag.LIGHTER);
canPlace = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_PLACE, DefaultFlag.LIGHTER));
what = "place fire";
/* Everything else */
} else {
canPlace = query.testBuild(target, associable, DefaultFlag.BLOCK_PLACE);
canPlace = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_PLACE));
what = "place that block";
}
@@ -196,8 +199,9 @@ public class RegionProtectionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onBreakBlock(final BreakBlockEvent event) {
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
@@ -211,13 +215,13 @@ public class RegionProtectionListener extends AbstractListener {
String what;
/* TNT */
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.PRIMED_TNT) != null) {
canBreak = query.testBuild(target, associable, DefaultFlag.BLOCK_BREAK, DefaultFlag.TNT);
what = "dynamite blocks";
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.MINECART_TNT) != null) {
canBreak = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_BREAK, DefaultFlag.TNT));
what = "use dynamite";
/* Everything else */
} else {
canBreak = query.testBuild(target, associable, DefaultFlag.BLOCK_BREAK);
canBreak = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_BREAK));
what = "break that block";
}
@@ -234,8 +238,9 @@ public class RegionProtectionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onUseBlock(final UseBlockEvent event) {
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
final Material type = event.getEffectiveMaterial();
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
@@ -249,27 +254,32 @@ public class RegionProtectionListener extends AbstractListener {
/* Saplings, etc. */
if (Materials.isConsideredBuildingIfUsed(type)) {
canUse = query.testBuild(target, associable);
canUse = query.testBuild(target, associable, combine(event));
what = "use that";
/* Inventory */
} else if (Materials.isInventoryBlock(type)) {
canUse = query.testBuild(target, associable, DefaultFlag.USE, DefaultFlag.CHEST_ACCESS);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.CHEST_ACCESS));
what = "open that";
/* Beds */
} else if (type == Material.BED_BLOCK) {
canUse = query.testBuild(target, associable, DefaultFlag.USE, DefaultFlag.SLEEP);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.SLEEP));
what = "sleep";
/* TNT */
} else if (type == Material.TNT) {
canUse = query.testBuild(target, associable, DefaultFlag.TNT);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.TNT));
what = "use explosives";
/* Legacy USE flag */
} else if (Materials.isUseFlagApplicable(type)) {
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.USE));
what = "use that";
/* Everything else */
} else {
canUse = query.testBuild(target, associable, DefaultFlag.USE);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT));
what = "use that";
}
@@ -285,8 +295,9 @@ public class RegionProtectionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onSpawnEntity(SpawnEntityEvent event) {
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
Location target = event.getTarget();
EntityType type = event.getEffectiveType();
@@ -299,17 +310,22 @@ public class RegionProtectionListener extends AbstractListener {
/* Vehicles */
if (Entities.isVehicle(type)) {
canSpawn = query.testBuild(target, associable, DefaultFlag.PLACE_VEHICLE);
canSpawn = query.testBuild(target, associable, combine(event, DefaultFlag.PLACE_VEHICLE));
what = "place vehicles";
/* Item pickup */
} else if (event.getEntity() instanceof Item) {
canSpawn = query.testBuild(target, associable, DefaultFlag.ITEM_DROP);
canSpawn = query.testBuild(target, associable, combine(event, DefaultFlag.ITEM_DROP));
what = "drop items";
/* XP drops */
} else if (event.getEffectiveType() == EntityType.EXPERIENCE_ORB) {
canSpawn = query.testBuild(target, associable, combine(event, DefaultFlag.EXP_DROPS));
what = "drop XP";
/* Everything else */
} else {
canSpawn = query.testBuild(target, associable);
canSpawn = query.testBuild(target, associable, combine(event));
if (event.getEntity() instanceof Item) {
what = "drop items";
@@ -326,8 +342,9 @@ public class RegionProtectionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onDestroyEntity(DestroyEntityEvent event) {
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
Location target = event.getTarget();
EntityType type = event.getEntity().getType();
@@ -339,17 +356,17 @@ public class RegionProtectionListener extends AbstractListener {
/* Vehicles */
if (Entities.isVehicle(type)) {
canDestroy = query.testBuild(target, associable, DefaultFlag.DESTROY_VEHICLE);
canDestroy = query.testBuild(target, associable, combine(event, DefaultFlag.DESTROY_VEHICLE));
what = "break vehicles";
/* Item pickup */
} else if (event.getEntity() instanceof Item || event.getEntity() instanceof ExperienceOrb) {
canDestroy = query.testBuild(target, associable, DefaultFlag.ITEM_PICKUP);
canDestroy = query.testBuild(target, associable, combine(event, DefaultFlag.ITEM_PICKUP));
what = "pick up items";
/* Everything else */
} else {
canDestroy = query.testBuild(target, associable);
canDestroy = query.testBuild(target, associable, combine(event));
what = "break things";
}
@@ -361,8 +378,9 @@ public class RegionProtectionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onUseEntity(UseEntityEvent event) {
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
Location target = event.getTarget();
RegionAssociable associable = createRegionAssociable(event.getCause());
@@ -372,18 +390,24 @@ public class RegionProtectionListener extends AbstractListener {
String what;
/* Hostile / ambient mob override */
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())) {
canUse = true;
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())
|| Entities.isNPC(event.getEntity()) || Entities.isVehicle(event.getEntity().getType())) {
canUse = event.getRelevantFlags().isEmpty() || query.queryState(target, associable, combine(event)) != State.DENY;
what = "use that";
/* Paintings, item frames, etc. */
} else if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
canUse = query.testBuild(target, associable);
canUse = query.testBuild(target, associable, combine(event));
what = "change that";
/* Ridden on use */
} else if (Entities.isRiddenOnUse(event.getEntity())) {
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.RIDE, DefaultFlag.INTERACT));
what = "ride that";
/* Everything else */
} else {
canUse = query.testBuild(target, associable, DefaultFlag.USE);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT));
what = "use that";
}
@@ -395,45 +419,65 @@ public class RegionProtectionListener extends AbstractListener {
@EventHandler(ignoreCancelled = true)
public void onDamageEntity(DamageEntityEvent event) {
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
// Whitelist check is below
Location target = event.getTarget();
RegionAssociable associable = createRegionAssociable(event.getCause());
RegionQuery query = getPlugin().getRegionContainer().createQuery();
Object rootCause = event.getCause().getRootCause();
Player attacker;
Player playerAttacker = event.getCause().getFirstPlayer();
boolean canDamage;
String what;
// Block PvP like normal even if the player has an override permission
// because (1) this is a frequent source of confusion and
// (2) some users want to block PvP even with the bypass permission
boolean pvp = event.getEntity() instanceof Player && playerAttacker != null && !playerAttacker.equals(event.getEntity());
if (isWhitelisted(event.getCause(), event.getWorld(), pvp)) {
return;
}
/* Hostile / ambient mob override */
if (isWhitelistedEntity(event.getEntity()) || (rootCause instanceof Entity && isWhitelistedEntity((Entity) rootCause))) {
canDamage = true;
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())
|| Entities.isVehicle(event.getEntity().getType())) {
canDamage = event.getRelevantFlags().isEmpty() || query.queryState(target, associable, combine(event)) != State.DENY;
what = "hit that";
/* Paintings, item frames, etc. */
} else if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
canDamage = query.testBuild(target, associable);
canDamage = query.testBuild(target, associable, combine(event));
what = "change that";
/* PVP */
} else if (event.getEntity() instanceof Player && (attacker = event.getCause().getFirstPlayer()) != null && !attacker.equals(event.getEntity())) {
} else if (pvp) {
Player defender = (Player) event.getEntity();
canDamage = query.testBuild(target, associable, DefaultFlag.PVP)
&& query.queryState(attacker.getLocation(), attacker, DefaultFlag.PVP) != State.DENY;
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.PVP))
&& query.queryState(playerAttacker.getLocation(), playerAttacker, combine(event, DefaultFlag.PVP)) != State.DENY
&& query.queryState(target, playerAttacker, combine(event, DefaultFlag.PVP)) != State.DENY;
// Fire the disallow PVP event
if (!canDamage && Events.fireAndTestCancel(new DisallowedPVPEvent(attacker, defender, event.getOriginalEvent()))) {
if (!canDamage && Events.fireAndTestCancel(new DisallowedPVPEvent(playerAttacker, defender, event.getOriginalEvent()))) {
canDamage = true;
}
what = "PvP";
/* Player damage not caused by another player */
} else if (event.getEntity() instanceof Player) {
canDamage = event.getRelevantFlags().isEmpty() || query.queryState(target, associable, combine(event)) != State.DENY;
what = "damage that";
/* damage to non-hostile mobs (e.g. animals) */
} else if (Entities.isNonHostile(event.getEntity())) {
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.DAMAGE_ANIMALS));
what = "harm that";
/* Everything else */
} else {
canDamage = query.testBuild(target, associable, DefaultFlag.USE);
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT));
what = "hit that";
}
@@ -450,10 +494,10 @@ public class RegionProtectionListener extends AbstractListener {
if (vehicle instanceof Tameable && exited instanceof Player) {
Player player = (Player) exited;
if (!isWhitelisted(Cause.create(player), vehicle.getWorld())) {
if (!isWhitelisted(Cause.create(player), vehicle.getWorld(), false)) {
RegionQuery query = getPlugin().getRegionContainer().createQuery();
Location location = vehicle.getLocation();
if (!query.testBuild(location, player, DefaultFlag.USE)) {
if (!query.testBuild(location, player, DefaultFlag.RIDE, DefaultFlag.INTERACT)) {
long now = System.currentTimeMillis();
Long lastTime = WGMetadata.getIfPresent(player, DISEMBARK_MESSAGE_KEY, Long.class);
if (lastTime == null || now - lastTime >= LAST_MESSAGE_DELAY) {
@@ -468,7 +512,25 @@ public class RegionProtectionListener extends AbstractListener {
}
private boolean isWhitelistedEntity(Entity entity) {
return Entities.isHostile(entity) || Entities.isAmbient(entity);
return Entities.isNonPlayerCreature(entity);
}
/**
* Combine the flags from a delegate event with an array of flags.
*
* <p>The delegate event's flags appear at the end.</p>
*
* @param event The event
* @param flag An array of flags
* @return An array of flags
*/
private static StateFlag[] combine(DelegateEvent event, StateFlag... flag) {
List<StateFlag> extra = event.getRelevantFlags();
StateFlag[] flags = Arrays.copyOf(flag, flag.length + extra.size());
for (int i = 0; i < extra.size(); i++) {
flags[flag.length + i] = extra.get(i);
}
return flags;
}
}
@@ -380,7 +380,7 @@ public class WorldGuardBlockListener implements Listener {
return;
}
int id = event.getChangedTypeId();
int id = event.getBlock().getTypeId();
if (id == 13 && wcfg.noPhysicsGravel) {
event.setCancelled(true);
@@ -21,59 +21,22 @@ package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.BukkitUtil;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.RegionQuery;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.RegionQueryUtil;
import com.sk89q.worldguard.bukkit.*;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.Wither;
import org.bukkit.entity.WitherSkull;
import org.bukkit.entity.Wolf;
import org.bukkit.entity.*;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.*;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.CreeperPowerEvent;
import org.bukkit.event.entity.EntityBreakDoorEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityCreatePortalEvent;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
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.ExplosionPrimeEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.entity.PigZapEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.projectiles.ProjectileSource;
@@ -144,11 +107,6 @@ public class WorldGuardEntityListener implements Listener {
} else if (defender instanceof Player) {
Player player = (Player) defender;
if (isInvincible(player)) {
event.setCancelled(true);
return;
}
if (wcfg.disableLavaDamage && type == DamageCause.LAVA) {
event.setCancelled(true);
player.setFireTicks(0);
@@ -216,17 +174,6 @@ public class WorldGuardEntityListener implements Listener {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
if (isInvincible(player)) {
if (wcfg.regionInvinciblityRemovesMobs
&& attacker instanceof LivingEntity && !(attacker instanceof Player)
&& !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) {
attacker.remove();
}
event.setCancelled(true);
return;
}
if (wcfg.disableLightningDamage && event.getCause() == DamageCause.LIGHTNING) {
event.setCancelled(true);
return;
@@ -322,12 +269,6 @@ public class WorldGuardEntityListener implements Listener {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
// Check Invincible
if (isInvincible(player)) {
event.setCancelled(true);
return;
}
// Check Mob
if (attacker != null && !(attacker instanceof Player)) {
if (wcfg.disableMobDamage) {
@@ -375,12 +316,6 @@ public class WorldGuardEntityListener implements Listener {
} else if (defender instanceof Player) {
Player player = (Player) defender;
if (isInvincible(player)) {
event.setCancelled(true);
player.setFireTicks(0);
return;
}
if (type == DamageCause.WITHER) {
// wither boss DoT tick
if (wcfg.disableMobDamage) {
@@ -445,23 +380,6 @@ public class WorldGuardEntityListener implements Listener {
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityCombust(EntityCombustEvent event) {
Entity entity = event.getEntity();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(entity.getWorld());
if (entity instanceof Player) {
Player player = (Player) entity;
if (cfg.hasGodMode(player) || (wcfg.useRegions && RegionQueryUtil.isInvincible(plugin, player))) {
event.setCancelled(true);
return;
}
}
}
/*
* Called on entity explode.
*/
@@ -635,6 +553,11 @@ public class WorldGuardEntityListener implements Listener {
return;
}
// armor stands are living entities, but we check them as blocks/non-living entities, so ignore them here
if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
return;
}
if (wcfg.allowTamedSpawns
&& event.getEntity() instanceof Tameable // nullsafe check
&& ((Tameable) event.getEntity()).isTamed()) {
@@ -758,69 +681,6 @@ public class WorldGuardEntityListener implements Listener {
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onFoodLevelChange(FoodLevelChangeEvent event) {
if (event.getEntity() instanceof Player) {
Player player = (Player) event.getEntity();
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(player)) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPotionSplash(PotionSplashEvent event) {
Entity entity = event.getEntity();
ThrownPotion potion = event.getPotion();
World world = entity.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
GlobalRegionManager regionMan = plugin.getGlobalRegionManager();
int blockedEntities = 0;
for (LivingEntity e : event.getAffectedEntities()) {
if (!regionMan.allows(DefaultFlag.POTION_SPLASH, e.getLocation(),
e instanceof Player ? plugin.wrapPlayer((Player) e) : null)) {
event.setIntensity(e, 0);
++blockedEntities;
}
}
if (blockedEntities == event.getAffectedEntities().size()) {
event.setCancelled(true);
}
}
/**
* Check if a player is invincible, via either god mode or region flag. If
* the region denies invincibility, the player must have an extra permission
* to override it. (worldguard.god.override-regions)
*
* @param player The player to check
* @return Whether {@code player} is invincible
*/
private boolean isInvincible(Player player) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
boolean god = cfg.hasGodMode(player);
if (wcfg.useRegions) {
Boolean flag = RegionQueryUtil.isAllowedInvinciblity(plugin, player);
boolean allowed = flag == null || flag;
boolean invincible = RegionQueryUtil.isInvincible(plugin, player);
if (allowed) {
return god || invincible;
} else {
return (god && plugin.hasPermission(player, "worldguard.god.override-regions"))
|| invincible;
}
} else {
return god;
}
}
/**
* Checks regions and config settings to protect items from being knocked
* out of item frames.
@@ -19,7 +19,6 @@
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.BukkitUtil;
@@ -27,12 +26,13 @@ import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
import com.sk89q.worldguard.bukkit.listener.FlagStateManager.PlayerFlagState;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.session.MoveType;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.session.handler.GameModeFlag;
import com.sk89q.worldguard.util.command.CommandFilter;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
@@ -45,17 +45,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.*;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
@@ -71,7 +61,7 @@ import java.util.regex.Pattern;
public class WorldGuardPlayerListener implements Listener {
private static final Logger log = Logger.getLogger(WorldGuardPlayerListener.class.getCanonicalName());
private Pattern opPattern = Pattern.compile("^/op(?:\\s.*)?$", Pattern.CASE_INSENSITIVE);
private static final Pattern opPattern = Pattern.compile("^/(?:bukkit:)?op(?:\\s.*)?$", Pattern.CASE_INSENSITIVE);
private WorldGuardPlugin plugin;
/**
@@ -87,232 +77,23 @@ public class WorldGuardPlayerListener implements Listener {
* Register events.
*/
public void registerEvents() {
final PluginManager pm = plugin.getServer().getPluginManager();
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvents(this, plugin);
if (plugin.getGlobalStateManager().usePlayerMove) {
pm.registerEvents(new PlayerMoveHandler(), plugin);
}
}
// unsure if anyone actually started using this yet, but just in case...
@Deprecated
public static boolean checkMove(WorldGuardPlugin plugin, Player player, World world, Location from, Location to) {
return checkMove(plugin, player, from, to); // drop world since it used to be mishandled
}
/**
* Handles movement related events, including changing gamemode, sending
* greeting/farewell messages, etc.
* A reference to WorldGuardPlugin is required to keep this method static
* although WGBukkit.getPlugin() may be used.
* @return true if the movement should not be allowed
*/
public static boolean checkMove(WorldGuardPlugin plugin, Player player, Location from, Location to) {
PlayerFlagState state = plugin.getFlagStateManager().getState(player);
//Flush states in multiworld scenario
if (state.lastWorld != null && !state.lastWorld.equals(to.getWorld())) {
plugin.getFlagStateManager().forget(player);
state = plugin.getFlagStateManager().getState(player);
}
World world = from.getWorld();
World toWorld = to.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world);
boolean hasRemoteBypass;
if (world.equals(toWorld)) {
hasRemoteBypass = hasBypass;
} else {
hasRemoteBypass = plugin.getGlobalRegionManager().hasBypass(player, toWorld);
}
RegionManager mgr = plugin.getGlobalRegionManager().get(toWorld);
if (mgr == null) {
return false;
}
Vector pt = new Vector(to.getBlockX(), to.getBlockY(), to.getBlockZ());
ApplicableRegionSet set = mgr.getApplicableRegions(pt);
/*
// check if region is full
// get the lowest number of allowed members in any region
boolean regionFull = false;
String maxPlayerMessage = null;
if (!hasBypass) {
for (ProtectedRegion region : set) {
if (region instanceof GlobalProtectedRegion) {
continue; // global region can't have a max
}
// get the max for just this region
Integer maxPlayers = region.getFlag(DefaultFlag.MAX_PLAYERS);
if (maxPlayers == null) {
continue;
}
int occupantCount = 0;
for(Player occupant : world.getPlayers()) {
// each player in this region counts as one toward the max of just this region
// A person with bypass doesn't count as an occupant of the region
if (!occupant.equals(player) && !plugin.getGlobalRegionManager().hasBypass(occupant, world)) {
if (region.contains(BukkitUtil.toVector(occupant.getLocation()))) {
if (++occupantCount >= maxPlayers) {
regionFull = true;
maxPlayerMessage = region.getFlag(DefaultFlag.MAX_PLAYERS_MESSAGE);
// At least one region in the set is full, we are going to use this message because it
// was the first one we detected as full. In reality we should check them all and then
// resolve the message from full regions, but that is probably a lot laggier (and this
// is already pretty laggy. In practice, we can't really control which one we get first
// right here.
break;
}
}
}
}
}
}
*/
boolean entryAllowed = set.allows(DefaultFlag.ENTRY, localPlayer);
if (!hasRemoteBypass && (!entryAllowed /*|| regionFull*/)) {
String message = /*maxPlayerMessage != null ? maxPlayerMessage :*/ "You are not permitted to enter this area.";
player.sendMessage(ChatColor.DARK_RED + message);
return true;
}
// Have to set this state
if (state.lastExitAllowed == null) {
state.lastExitAllowed = plugin.getRegionContainer().createQuery().getApplicableRegions(from)
.allows(DefaultFlag.EXIT, localPlayer);
}
boolean exitAllowed = set.allows(DefaultFlag.EXIT, localPlayer);
if (!hasBypass && exitAllowed && !state.lastExitAllowed) {
player.sendMessage(ChatColor.DARK_RED + "You are not permitted to leave this area.");
return true;
}
// WorldGuardRegionMoveEvent event = new WorldGuardRegionMoveEvent(plugin, player, state, set, from, to);
// Bukkit.getPluginManager().callEvent(event);
String greeting = set.getFlag(DefaultFlag.GREET_MESSAGE);//, localPlayer);
String farewell = set.getFlag(DefaultFlag.FAREWELL_MESSAGE);//, localPlayer);
Boolean notifyEnter = set.getFlag(DefaultFlag.NOTIFY_ENTER);//, localPlayer);
Boolean notifyLeave = set.getFlag(DefaultFlag.NOTIFY_LEAVE);//, localPlayer);
GameMode gameMode = set.getFlag(DefaultFlag.GAME_MODE);
if (state.lastFarewell != null && (farewell == null
|| !state.lastFarewell.equals(farewell))) {
String replacedFarewell = plugin.replaceMacros(
player, BukkitUtil.replaceColorMacros(state.lastFarewell));
player.sendMessage(replacedFarewell.replaceAll("\\\\n", "\n").split("\\n"));
}
if (greeting != null && (state.lastGreeting == null
|| !state.lastGreeting.equals(greeting))) {
String replacedGreeting = plugin.replaceMacros(
player, BukkitUtil.replaceColorMacros(greeting));
player.sendMessage(replacedGreeting.replaceAll("\\\\n", "\n").split("\\n"));
}
if ((notifyLeave == null || !notifyLeave)
&& state.notifiedForLeave != null && state.notifiedForLeave) {
plugin.broadcastNotification(ChatColor.GRAY + "WG: "
+ ChatColor.LIGHT_PURPLE + player.getName()
+ ChatColor.GOLD + " left NOTIFY region");
}
if (notifyEnter != null && notifyEnter && (state.notifiedForEnter == null
|| !state.notifiedForEnter)) {
StringBuilder regionList = new StringBuilder();
for (ProtectedRegion region : set) {
if (regionList.length() != 0) {
regionList.append(", ");
}
regionList.append(region.getId());
}
plugin.broadcastNotification(ChatColor.GRAY + "WG: "
+ ChatColor.LIGHT_PURPLE + player.getName()
+ ChatColor.GOLD + " entered NOTIFY region: "
+ ChatColor.WHITE
+ regionList);
}
if (!hasBypass && gameMode != null) {
if (player.getGameMode() != gameMode) {
state.lastGameMode = player.getGameMode();
player.setGameMode(gameMode);
} else if (state.lastGameMode == null) {
state.lastGameMode = player.getServer().getDefaultGameMode();
}
} else {
if (state.lastGameMode != null) {
GameMode mode = state.lastGameMode;
state.lastGameMode = null;
player.setGameMode(mode);
}
}
state.lastGreeting = greeting;
state.lastFarewell = farewell;
state.notifiedForEnter = notifyEnter;
state.notifiedForLeave = notifyLeave;
state.lastExitAllowed = exitAllowed;
state.lastWorld = to.getWorld();
state.lastBlockX = to.getBlockX();
state.lastBlockY = to.getBlockY();
state.lastBlockZ = to.getBlockZ();
return false;
}
class PlayerMoveHandler implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerMove(PlayerMoveEvent event) {
final Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.useRegions) {
// Did we move a block?
if (event.getFrom().getBlockX() != event.getTo().getBlockX()
|| event.getFrom().getBlockY() != event.getTo().getBlockY()
|| event.getFrom().getBlockZ() != event.getTo().getBlockZ()) {
boolean result = checkMove(plugin, player, event.getFrom(), event.getTo());
if (result) {
final Location newLoc = event.getFrom();
newLoc.setX(newLoc.getBlockX() + 0.5);
newLoc.setY(newLoc.getBlockY());
newLoc.setZ(newLoc.getBlockZ() + 0.5);
event.setTo(newLoc);
final Entity vehicle = player.getVehicle();
if (vehicle != null) {
vehicle.eject();
vehicle.teleport(newLoc);
player.teleport(newLoc);
vehicle.setPassenger(player);
}
}
}
}
}
}
@EventHandler
public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) {
Player player = event.getPlayer();
WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld());
if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, player.getWorld())) {
GameMode gameMode = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation()).getFlag(DefaultFlag.GAME_MODE);
if (plugin.getFlagStateManager().getState(player).lastGameMode != null
&& gameMode != null && event.getNewGameMode() != gameMode) {
event.setCancelled(true);
Session session = plugin.getSessionManager().getIfPresent(player);
if (session != null) {
GameModeFlag handler = session.getHandler(GameModeFlag.class);
if (handler != null && wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, player.getWorld())) {
GameMode expected = handler.getSetGameMode();
if (handler.getOriginalGameMode() != null && expected != null && expected != event.getNewGameMode()) {
log.info("Game mode change on " + player.getName() + " has been blocked due to the region GAMEMODE flag");
event.setCancelled(true);
}
}
}
}
@@ -351,14 +132,7 @@ public class WorldGuardPlayerListener implements Listener {
Events.fire(new ProcessPlayerEvent(player));
if (wcfg.useRegions) {
PlayerFlagState state = plugin.getFlagStateManager().getState(player);
Location loc = player.getLocation();
state.lastWorld = loc.getWorld();
state.lastBlockX = loc.getBlockX();
state.lastBlockY = loc.getBlockY();
state.lastBlockZ = loc.getBlockZ();
}
plugin.getSessionManager().get(player); // Initializes a session
}
@EventHandler(ignoreCancelled = true)
@@ -411,46 +185,6 @@ public class WorldGuardPlayerListener implements Listener {
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// This is to make the enter/exit flags accurate -- move events are not
// sent constantly, so it is possible to move just a little enough to
// not trigger the event and then rejoin so that you are then considered
// outside the border. This should work around that.
if (wcfg.useRegions) {
boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world);
PlayerFlagState state = plugin.getFlagStateManager().getState(player);
if (state.lastWorld != null && !hasBypass) {
LocalPlayer localPlayer = plugin.wrapPlayer(player);
Location loc = player.getLocation();
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(loc);
if (state.lastExitAllowed == null) {
state.lastExitAllowed = set.allows(DefaultFlag.EXIT, localPlayer);
}
if (!state.lastExitAllowed || !set.allows(DefaultFlag.ENTRY, localPlayer)) {
// Only if we have the last location cached
if (state.lastWorld.equals(world)) {
Location newLoc = new Location(world, state.lastBlockX + 0.5,
state.lastBlockY, state.lastBlockZ + 0.5);
player.teleport(newLoc);
}
}
}
}
cfg.forgetPlayer(plugin.wrapPlayer(player));
plugin.forgetPlayer(player);
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
@@ -603,20 +337,20 @@ public class WorldGuardPlayerListener implements Listener {
}
}
@EventHandler(priority= EventPriority.LOW, ignoreCancelled = true)
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
World world = event.getFrom().getWorld();
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.useRegions) {
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(event.getTo());
ApplicableRegionSet setFrom = plugin.getRegionContainer().createQuery().getApplicableRegions(event.getFrom());
LocalPlayer localPlayer = plugin.wrapPlayer(event.getPlayer());
LocalPlayer localPlayer = plugin.wrapPlayer(player);
if (cfg.usePlayerTeleports) {
boolean result = checkMove(plugin, event.getPlayer(), event.getFrom(), event.getTo());
if (result) {
if (null != plugin.getSessionManager().get(player).testMoveTo(player, event.getTo(), MoveType.TELEPORT)) {
event.setCancelled(true);
return;
}
@@ -626,7 +360,7 @@ public class WorldGuardPlayerListener implements Listener {
if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world)
&& !(set.allows(DefaultFlag.ENDERPEARL, localPlayer)
&& setFrom.allows(DefaultFlag.ENDERPEARL, localPlayer))) {
event.getPlayer().sendMessage(ChatColor.DARK_RED + "You're not allowed to go there.");
player.sendMessage(ChatColor.DARK_RED + "You're not allowed to go there.");
event.setCancelled(true);
return;
}
@@ -22,12 +22,15 @@ package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.Locations;
import com.sk89q.worldguard.session.MoveType;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.vehicle.VehicleMoveEvent;
import org.bukkit.util.Vector;
public class WorldGuardVehicleListener implements Listener {
@@ -52,8 +55,7 @@ public class WorldGuardVehicleListener implements Listener {
@EventHandler
public void onVehicleMove(VehicleMoveEvent event) {
Vehicle vehicle = event.getVehicle();
if (vehicle.getPassenger() == null
|| !(vehicle.getPassenger() instanceof Player)) return;
if (vehicle.getPassenger() == null || !(vehicle.getPassenger() instanceof Player)) return;
Player player = (Player) vehicle.getPassenger();
World world = vehicle.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
@@ -61,12 +63,9 @@ public class WorldGuardVehicleListener implements Listener {
if (wcfg.useRegions) {
// Did we move a block?
if (event.getFrom().getBlockX() != event.getTo().getBlockX()
|| event.getFrom().getBlockY() != event.getTo().getBlockY()
|| event.getFrom().getBlockZ() != event.getTo().getBlockZ()) {
boolean result = WorldGuardPlayerListener.checkMove(plugin, player, event.getFrom(), event.getTo());
if (result) {
vehicle.setVelocity(new org.bukkit.util.Vector(0,0,0));
if (Locations.isDifferentBlock(event.getFrom(), event.getTo())) {
if (null != plugin.getSessionManager().get(player).testMoveTo(player, event.getTo(), MoveType.RIDE)) {
vehicle.setVelocity(new Vector(0,0,0));
vehicle.teleport(event.getFrom());
}
}
@@ -19,10 +19,10 @@
package com.sk89q.worldguard.bukkit.listener.debounce;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.guavabackport.cache.CacheBuilder;
import com.sk89q.guavabackport.cache.CacheLoader;
import com.sk89q.guavabackport.cache.LoadingCache;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
@@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit;
public class EventDebounce<K> {
private final Cache<K, Entry> cache;
private final LoadingCache<K, Entry> cache;
public EventDebounce(int debounceTime) {
cache = CacheBuilder.newBuilder()
@@ -19,10 +19,10 @@
package com.sk89q.worldguard.bukkit.listener.debounce.legacy;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.guavabackport.cache.CacheBuilder;
import com.sk89q.guavabackport.cache.CacheLoader;
import com.sk89q.guavabackport.cache.LoadingCache;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
@@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit;
public class AbstractEventDebounce<K> {
private final Cache<K, Entry> cache;
private final LoadingCache<K, Entry> cache;
AbstractEventDebounce(int debounceTime) {
cache = CacheBuilder.newBuilder()
@@ -27,6 +27,8 @@ import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
/**
* Used for querying region-related permissions.
*/
@@ -117,13 +119,30 @@ public class RegionPermissionModel extends AbstractPermissionModel {
public boolean maySetFlag(ProtectedRegion region) {
return hasPatternPermission("flag.regions", region);
}
public boolean maySetFlag(ProtectedRegion region, Flag<?> flag) {
// This is a WTF permission
return hasPatternPermission(
"flag.flags." + flag.getName().toLowerCase(), region);
}
public boolean maySetFlag(ProtectedRegion region, Flag<?> flag, @Nullable String value) {
String sanitizedValue;
if (value != null) {
sanitizedValue = value.trim().toLowerCase().replaceAll("[^a-z0-9]", "");
if (sanitizedValue.length() > 20) {
sanitizedValue = sanitizedValue.substring(0, 20);
}
} else {
sanitizedValue = "unset";
}
// This is a WTF permission
return hasPatternPermission(
"flag.flags." + flag.getName().toLowerCase() + "." + sanitizedValue, region);
}
public boolean mayAddMembers(ProtectedRegion region) {
return hasPatternPermission("addmember", region);
}
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
package com.sk89q.worldguard.bukkit.protection;
import com.sk89q.worldguard.bukkit.RegionQuery;
import com.sk89q.worldguard.domains.Association;
@@ -27,6 +27,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.Location;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -36,7 +37,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* region is in a set of source regions.
*
* <p>This class only performs a spatial query if its
* {@link #getAssociation(ProtectedRegion)} method is called.</p>
* {@link #getAssociation(List)} method is called.</p>
*/
public class DelayedRegionOverlapAssociation implements RegionAssociable {
@@ -59,17 +60,19 @@ public class DelayedRegionOverlapAssociation implements RegionAssociable {
}
@Override
public Association getAssociation(ProtectedRegion region) {
public Association getAssociation(List<ProtectedRegion> regions) {
if (source == null) {
ApplicableRegionSet result = query.getApplicableRegions(location);
source = result.getRegions();
}
if (source.contains(region)) {
return Association.OWNER;
} else {
return Association.NON_MEMBER;
for (ProtectedRegion region : regions) {
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) {
return Association.OWNER;
}
}
return Association.NON_MEMBER;
}
}
@@ -20,9 +20,13 @@
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.material.Bed;
import org.bukkit.material.Chest;
import org.bukkit.material.MaterialData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -43,7 +47,8 @@ public final class Blocks {
* @return a list of connected blocks, not including the given block
*/
public static List<Block> getConnected(Block block) {
MaterialData data = block.getState().getData();
BlockState state = block.getState();
MaterialData data = state.getData();
if (data instanceof Bed) {
Bed bed = (Bed) data;
@@ -52,6 +57,28 @@ public final class Blocks {
} else {
return Arrays.asList(block.getRelative(bed.getFacing()));
}
} else if (data instanceof Chest) {
BlockFace facing = ((Chest) data).getFacing();
ArrayList<Block> chests = new ArrayList<Block>();
if (facing == BlockFace.NORTH || facing == BlockFace.SOUTH) {
if (block.getRelative(BlockFace.EAST).getState().getData() instanceof Chest) {
chests.add(block.getRelative(BlockFace.EAST));
}
if (block.getRelative(BlockFace.WEST).getState().getData() instanceof Chest) {
chests.add(block.getRelative(BlockFace.WEST));
}
} else if (facing == BlockFace.EAST || facing == BlockFace.WEST) {
if (block.getRelative(BlockFace.NORTH).getState().getData() instanceof Chest) {
chests.add(block.getRelative(BlockFace.NORTH));
}
if (block.getRelative(BlockFace.SOUTH).getState().getData() instanceof Chest) {
chests.add(block.getRelative(BlockFace.SOUTH));
}
} else {
// don't know how to handle diagonal chests
return Collections.emptyList();
}
return chests;
} else {
return Collections.emptyList();
}
@@ -19,16 +19,8 @@
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.entity.Ambient;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Slime;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Tameable;
import com.sk89q.worldguard.util.Enums;
import org.bukkit.entity.*;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.projectiles.ProjectileSource;
@@ -70,6 +62,16 @@ public final class Entities {
return type == EntityType.FIREBALL || type == EntityType.SMALL_FIREBALL;
}
/**
* Test whether the given entity can be ridden if it is right clicked.
*
* @param entity the entity
* @return true if the entity can be ridden
*/
public static boolean isRiddenOnUse(Entity entity) {
return entity instanceof Vehicle;
}
/**
* Test whether the given entity type is a vehicle type.
*
@@ -118,18 +120,6 @@ public final class Entities {
return entity;
}
/**
* Return whether the given player is a fake player using the typical
* fake player convention of [Mod].
*
* @param player the player
* @return true if a fake player
*/
public static boolean isFakePlayer(Player player) {
String name = player.getName();
return name.length() >= 3 && name.charAt(0) == '[' && name.charAt(name.length() - 1) == ']';
}
/**
* Test whether an entity is hostile.
*
@@ -137,7 +127,21 @@ public final class Entities {
* @return true if hostile
*/
public static boolean isHostile(Entity entity) {
return entity instanceof Monster || entity instanceof Slime;
return entity instanceof Monster
|| entity instanceof Slime
|| entity instanceof Flying
|| entity instanceof EnderDragon;
}
/**
* Test whether an entity is a non-hostile creature.
*
* @param entity
* @return true if non-hostile
*/
public static boolean isNonHostile(Entity entity) {
return !isHostile(entity)
&& (entity instanceof Creature || entity instanceof WaterMob);
}
/**
@@ -150,6 +154,30 @@ public final class Entities {
return entity instanceof Ambient;
}
/**
* Test whether an entity is an NPC.
*
* @param entity the entity
* @return true if an NPC
*/
public static boolean isNPC(Entity entity) {
return entity instanceof NPC || entity.hasMetadata("NPC");
}
/**
* Test whether an entity is a creature (a living thing) that is
* not a player.
*
* @param entity the entity
* @return true if a non-player creature
*/
public static boolean isNonPlayerCreature(Entity entity) {
return entity instanceof LivingEntity && !(entity instanceof Player);
}
private static final org.bukkit.entity.EntityType armorStandType =
Enums.findByValue(org.bukkit.entity.EntityType.class, "ARMOR_STAND");
/**
* Test whether using the given entity should be considered "building"
* rather than merely using an entity.
@@ -158,7 +186,8 @@ public final class Entities {
* @return true if considered building
*/
public static boolean isConsideredBuildingIfUsed(Entity entity) {
return entity instanceof Hanging;
return entity instanceof Hanging
|| entity.getType() == armorStandType;
}
}
@@ -1,77 +0,0 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
/**
* Utility methods to deal with event-related enums in Bukkit.
*/
public final class EventEnums {
private EventEnums() {
}
/**
* Return whether the given damage cause is fire-reltaed.
*
* @param cause the cause
* @return true if fire related
*/
public static boolean isFireCause(DamageCause cause) {
return cause == DamageCause.FIRE || cause == DamageCause.FIRE_TICK;
}
/**
* Return whether the given cause is an explosion.
*
* @param cause the cause
* @return true if it is an explosion cuase
*/
public static boolean isExplosionCause(DamageCause cause) {
return cause == DamageCause.BLOCK_EXPLOSION || cause == DamageCause.ENTITY_EXPLOSION;
}
/**
* Restore the statistic associated with the given cause. For example,
* for the {@link DamageCause#DROWNING} cause, the entity would have its
* air level set to its maximum.
*
* @param entity the entity
* @param cause the cuase
*/
public static void restoreStatistic(Entity entity, DamageCause cause) {
if (cause == DamageCause.DROWNING && entity instanceof LivingEntity) {
LivingEntity living = (LivingEntity) entity;
living.setRemainingAir(living.getMaximumAir());
}
if (isFireCause(cause)) {
entity.setFireTicks(0);
}
if (cause == DamageCause.LAVA) {
entity.setFireTicks(0);
}
}
}
@@ -21,9 +21,12 @@ package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.bukkit.event.BulkEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Result;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.player.PlayerInteractEvent;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -107,7 +110,7 @@ public final class Events {
*/
public static <T extends Event & Cancellable & BulkEvent> boolean fireBulkEventToCancel(Cancellable original, T eventToFire) {
Bukkit.getServer().getPluginManager().callEvent(eventToFire);
if (eventToFire.isExplicitlyCancelled()) {
if (eventToFire.getExplicitResult() == Result.DENY) {
original.setCancelled(true);
return true;
}
@@ -115,4 +118,46 @@ public final class Events {
return false;
}
/**
* Return whether the given damage cause is fire-reltaed.
*
* @param cause the cause
* @return true if fire related
*/
public static boolean isFireCause(DamageCause cause) {
return cause == DamageCause.FIRE || cause == DamageCause.FIRE_TICK;
}
/**
* Return whether the given cause is an explosion.
*
* @param cause the cause
* @return true if it is an explosion cuase
*/
public static boolean isExplosionCause(DamageCause cause) {
return cause == DamageCause.BLOCK_EXPLOSION || cause == DamageCause.ENTITY_EXPLOSION;
}
/**
* Restore the statistic associated with the given cause. For example,
* for the {@link DamageCause#DROWNING} cause, the entity would have its
* air level set to its maximum.
*
* @param entity the entity
* @param cause the cuase
*/
public static void restoreStatistic(Entity entity, DamageCause cause) {
if (cause == DamageCause.DROWNING && entity instanceof LivingEntity) {
LivingEntity living = (LivingEntity) entity;
living.setRemainingAir(living.getMaximumAir());
}
if (isFireCause(cause)) {
entity.setFireTicks(0);
}
if (cause == DamageCause.LAVA) {
entity.setFireTicks(0);
}
}
}
@@ -0,0 +1,87 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.google.common.collect.Lists;
import org.bukkit.event.Event;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredListener;
import javax.annotation.Nullable;
import java.util.List;
/**
* Traces the owner of a handler.
*/
public class HandlerTracer {
private final List<Handler> handlers;
public HandlerTracer(Event event) {
this.handlers = getHandlers(event);
}
/**
* Attempt to detect the cause of an event that was fired.
*
* @param elements The stack trace
* @return The plugin, if found
*/
@Nullable
public Plugin detectPlugin(StackTraceElement[] elements) {
for (int i = elements.length - 1; i >= 0; i--) {
StackTraceElement element = elements[i];
for (Handler handler : handlers) {
if (element.getClassName().equals(handler.className)) {
return handler.plugin;
}
}
}
return null;
}
/**
* Build a cache of listeners registered for an event.
*
* @param event The event
* @return A list of handlers
*/
private static List<Handler> getHandlers(Event event) {
List<Handler> handlers = Lists.newArrayList();
for (RegisteredListener listener : event.getHandlers().getRegisteredListeners()) {
handlers.add(new Handler(listener.getListener().getClass().getName(), listener.getPlugin()));
}
return handlers;
}
private static class Handler {
private final String className;
private final Plugin plugin;
private Handler(String className, Plugin plugin) {
this.className = className;
this.plugin = plugin;
}
}
}
@@ -0,0 +1,116 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.google.common.base.Function;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class InteropUtils {
@Nullable
private static final Class<?> forgeFakePlayerClass;
// This UUID is from Minecraft Forge (see FakePlayerFactory)
private static final UUID forgeFakePlayerUuid = UUID.fromString("41c82c87-7afb-4024-ba57-13d2c99cae77");
private static final PlayerHandleFunction playerHandleFunction;
static {
forgeFakePlayerClass = findClass("net.minecraftforge.common.util.FakePlayer");
PlayerHandleFunction function;
try {
function = new PlayerHandleFunction();
} catch (Exception e) {
function = null;
}
playerHandleFunction = function;
}
@Nullable
private static Class<?> findClass(String name) {
try {
return Class.forName(name);
} catch (Throwable ignored) {
return null;
}
}
private InteropUtils() {
}
/**
* Return whether the given player is a fake player.
*
* @param player the player
* @return true if a fake player
*/
public static boolean isFakePlayer(Player player) {
UUID uuid = player.getUniqueId();
String name = player.getName();
if (uuid.equals(forgeFakePlayerUuid)) {
return true;
}
if (forgeFakePlayerClass != null && playerHandleFunction != null) {
Object handle = playerHandleFunction.apply(player);
if (handle != null) {
if (forgeFakePlayerClass.isAssignableFrom(handle.getClass())) {
return true;
}
}
}
if (name.length() >= 3 && name.charAt(0) == '[' && name.charAt(name.length() - 1) == ']') {
return true;
}
return false;
}
private static final class PlayerHandleFunction implements Function<Object, Object> {
private final Class<?> craftPlayerClass;
private final Method getHandleMethod;
private PlayerHandleFunction() throws NoSuchMethodException, ClassNotFoundException {
craftPlayerClass = Class.forName(Bukkit.getServer().getClass().getCanonicalName().replaceAll("CraftServer$", "entity.CraftPlayer"));
getHandleMethod = craftPlayerClass.getMethod("getHandle");
}
@Nullable
@Override
public Object apply(Object o) {
if (craftPlayerClass.isAssignableFrom(o.getClass())) {
try {
return getHandleMethod.invoke(o);
} catch (Throwable ignored) {
}
}
return null;
}
}
}
@@ -0,0 +1,40 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.Location;
public final class Locations {
private Locations() {
}
/**
* Tests whether two different locations are in two different blocks.
*
* @param a The first location
* @param b The second location
* @return Whether the two locations are two different blocks
*/
public static boolean isDifferentBlock(Location a, Location b) {
return a.getBlockX() != b.getBlockX() || a.getBlockY() != b.getBlockY() || a.getBlockZ() != b.getBlockZ();
}
}
@@ -21,28 +21,40 @@ package com.sk89q.worldguard.bukkit.util;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.material.Dye;
import org.bukkit.material.MaterialData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* Material utility class.
*/
public final class Materials {
private static final int MODIFIED_ON_CLICK = 1;
private static final int MODIFIES_BLOCKS = 2;
private static final int MODIFIED_ON_RIGHT = 1;
private static final int MODIFIED_ON_LEFT = 2;
private static final int MODIFIES_BLOCKS = 4;
private static final BiMap<EntityType, Material> ENTITY_ITEMS = HashBiMap.create();
private static final Map<Material, Integer> MATERIAL_FLAGS = new HashMap<Material, Integer>();
private static final Set<PotionEffectType> DAMAGE_EFFECTS = new HashSet<PotionEffectType>();
public static Material ARMOR_STAND;
static {
try {
ARMOR_STAND = Material.ARMOR_STAND;
} catch (NoSuchFieldError ignored) {
ARMOR_STAND = null;
}
ENTITY_ITEMS.put(EntityType.PAINTING, Material.PAINTING);
ENTITY_ITEMS.put(EntityType.ARROW, Material.ARROW);
ENTITY_ITEMS.put(EntityType.SNOWBALL, Material.SNOW_BALL);
@@ -62,6 +74,9 @@ public final class Materials {
ENTITY_ITEMS.put(EntityType.MINECART_HOPPER, Material.HOPPER_MINECART);
ENTITY_ITEMS.put(EntityType.SPLASH_POTION, Material.POTION);
ENTITY_ITEMS.put(EntityType.EGG, Material.EGG);
try {
ENTITY_ITEMS.put(EntityType.ARMOR_STAND, Material.ARMOR_STAND);
} catch (NoSuchFieldError ignored) {}
MATERIAL_FLAGS.put(Material.AIR, 0);
MATERIAL_FLAGS.put(Material.STONE, 0);
@@ -86,10 +101,10 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.GLASS, 0);
MATERIAL_FLAGS.put(Material.LAPIS_ORE, 0);
MATERIAL_FLAGS.put(Material.LAPIS_BLOCK, 0);
MATERIAL_FLAGS.put(Material.DISPENSER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DISPENSER, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SANDSTONE, 0);
MATERIAL_FLAGS.put(Material.NOTE_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BED_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.NOTE_BLOCK, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BED_BLOCK, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.POWERED_RAIL, 0);
MATERIAL_FLAGS.put(Material.DETECTOR_RAIL, 0);
MATERIAL_FLAGS.put(Material.PISTON_STICKY_BASE, 0);
@@ -109,7 +124,7 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.DOUBLE_STEP, 0);
MATERIAL_FLAGS.put(Material.STEP, 0);
MATERIAL_FLAGS.put(Material.BRICK, 0);
MATERIAL_FLAGS.put(Material.TNT, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.TNT, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BOOKSHELF, 0);
MATERIAL_FLAGS.put(Material.MOSSY_COBBLESTONE, 0);
MATERIAL_FLAGS.put(Material.OBSIDIAN, 0);
@@ -117,37 +132,37 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.FIRE, 0);
MATERIAL_FLAGS.put(Material.MOB_SPAWNER, 0);
MATERIAL_FLAGS.put(Material.WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.CHEST, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.CHEST, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REDSTONE_WIRE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_ORE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_BLOCK, 0);
MATERIAL_FLAGS.put(Material.WORKBENCH, 0);
MATERIAL_FLAGS.put(Material.WORKBENCH, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CROPS, 0);
MATERIAL_FLAGS.put(Material.SOIL, 0);
MATERIAL_FLAGS.put(Material.FURNACE, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BURNING_FURNACE, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.FURNACE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BURNING_FURNACE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SIGN_POST, 0);
MATERIAL_FLAGS.put(Material.WOODEN_DOOR, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.WOODEN_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.LADDER, 0);
MATERIAL_FLAGS.put(Material.RAILS, 0);
MATERIAL_FLAGS.put(Material.COBBLESTONE_STAIRS, 0);
MATERIAL_FLAGS.put(Material.WALL_SIGN, 0);
MATERIAL_FLAGS.put(Material.LEVER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.LEVER, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.STONE_PLATE, 0);
MATERIAL_FLAGS.put(Material.IRON_DOOR_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.IRON_DOOR_BLOCK, 0);
MATERIAL_FLAGS.put(Material.WOOD_PLATE, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_ORE, 0);
MATERIAL_FLAGS.put(Material.GLOWING_REDSTONE_ORE, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_OFF, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_ON, 0);
MATERIAL_FLAGS.put(Material.STONE_BUTTON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.STONE_BUTTON, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SNOW, 0);
MATERIAL_FLAGS.put(Material.ICE, 0);
MATERIAL_FLAGS.put(Material.SNOW_BLOCK, 0);
MATERIAL_FLAGS.put(Material.CACTUS, 0);
MATERIAL_FLAGS.put(Material.CLAY, 0);
MATERIAL_FLAGS.put(Material.SUGAR_CANE_BLOCK, 0);
MATERIAL_FLAGS.put(Material.JUKEBOX, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.JUKEBOX, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.FENCE, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN, 0);
MATERIAL_FLAGS.put(Material.NETHERRACK, 0);
@@ -155,11 +170,11 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.GLOWSTONE, 0);
MATERIAL_FLAGS.put(Material.PORTAL, 0);
MATERIAL_FLAGS.put(Material.JACK_O_LANTERN, 0);
MATERIAL_FLAGS.put(Material.CAKE_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_OFF, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_ON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.CAKE_BLOCK, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_OFF, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_ON, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.STAINED_GLASS, 0);
MATERIAL_FLAGS.put(Material.TRAP_DOOR, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.TRAP_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.MONSTER_EGGS, 0);
MATERIAL_FLAGS.put(Material.SMOOTH_BRICK, 0);
MATERIAL_FLAGS.put(Material.HUGE_MUSHROOM_1, 0);
@@ -170,7 +185,7 @@ 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.FENCE_GATE, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BRICK_STAIRS, 0);
MATERIAL_FLAGS.put(Material.SMOOTH_STAIRS, 0);
MATERIAL_FLAGS.put(Material.MYCEL, 0);
@@ -179,13 +194,13 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.NETHER_FENCE, 0);
MATERIAL_FLAGS.put(Material.NETHER_BRICK_STAIRS, 0);
MATERIAL_FLAGS.put(Material.NETHER_WARTS, 0);
MATERIAL_FLAGS.put(Material.ENCHANTMENT_TABLE, 0);
MATERIAL_FLAGS.put(Material.BREWING_STAND, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.CAULDRON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.ENCHANTMENT_TABLE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BREWING_STAND, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CAULDRON, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.ENDER_PORTAL, 0);
MATERIAL_FLAGS.put(Material.ENDER_PORTAL_FRAME, 0);
MATERIAL_FLAGS.put(Material.ENDER_STONE, 0);
MATERIAL_FLAGS.put(Material.DRAGON_EGG, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DRAGON_EGG, MODIFIED_ON_LEFT | MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_OFF, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_ON, 0);
MATERIAL_FLAGS.put(Material.WOOD_DOUBLE_STEP, 0);
@@ -193,35 +208,35 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.COCOA, 0);
MATERIAL_FLAGS.put(Material.SANDSTONE_STAIRS, 0);
MATERIAL_FLAGS.put(Material.EMERALD_ORE, 0);
MATERIAL_FLAGS.put(Material.ENDER_CHEST, 0);
MATERIAL_FLAGS.put(Material.ENDER_CHEST, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.TRIPWIRE_HOOK, 0);
MATERIAL_FLAGS.put(Material.TRIPWIRE, 0);
MATERIAL_FLAGS.put(Material.EMERALD_BLOCK, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.BIRCH_WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.JUNGLE_WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.COMMAND, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BEACON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.COMMAND, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BEACON, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.COBBLE_WALL, 0);
MATERIAL_FLAGS.put(Material.FLOWER_POT, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.FLOWER_POT, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.CARROT, 0);
MATERIAL_FLAGS.put(Material.POTATO, 0);
MATERIAL_FLAGS.put(Material.WOOD_BUTTON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.WOOD_BUTTON, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.SKULL, 0);
MATERIAL_FLAGS.put(Material.ANVIL, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.TRAPPED_CHEST, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.ANVIL, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.TRAPPED_CHEST, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.GOLD_PLATE, 0);
MATERIAL_FLAGS.put(Material.IRON_PLATE, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_OFF, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_ON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_OFF, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_ON, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.REDSTONE_BLOCK, 0);
MATERIAL_FLAGS.put(Material.QUARTZ_ORE, 0);
MATERIAL_FLAGS.put(Material.HOPPER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.HOPPER, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.QUARTZ_BLOCK, 0);
MATERIAL_FLAGS.put(Material.QUARTZ_STAIRS, 0);
MATERIAL_FLAGS.put(Material.ACTIVATOR_RAIL, 0);
MATERIAL_FLAGS.put(Material.DROPPER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DROPPER, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.STAINED_CLAY, 0);
MATERIAL_FLAGS.put(Material.STAINED_GLASS_PANE, 0);
MATERIAL_FLAGS.put(Material.LEAVES_2, 0);
@@ -234,6 +249,31 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.COAL_BLOCK, 0);
MATERIAL_FLAGS.put(Material.PACKED_ICE, 0);
MATERIAL_FLAGS.put(Material.DOUBLE_PLANT, 0);
try {
MATERIAL_FLAGS.put(Material.STANDING_BANNER, 0);
MATERIAL_FLAGS.put(Material.WALL_BANNER, 0);
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR_INVERTED, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE, 0);
MATERIAL_FLAGS.put(Material.RED_SANDSTONE_STAIRS, 0);
MATERIAL_FLAGS.put(Material.DOUBLE_STONE_SLAB2, 0);
MATERIAL_FLAGS.put(Material.STONE_SLAB2, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.BIRCH_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.JUNGLE_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DARK_OAK_FENCE_GATE, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.ACACIA_FENCE_GATE, MODIFIED_ON_RIGHT);
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);
MATERIAL_FLAGS.put(Material.ACACIA_DOOR, MODIFIED_ON_RIGHT);
MATERIAL_FLAGS.put(Material.DARK_OAK_DOOR, MODIFIED_ON_RIGHT);
} catch (NoSuchFieldError ignored) {
}
MATERIAL_FLAGS.put(Material.IRON_SPADE, 0);
MATERIAL_FLAGS.put(Material.IRON_PICKAXE, 0);
@@ -362,7 +402,7 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.CAULDRON_ITEM, 0);
MATERIAL_FLAGS.put(Material.EYE_OF_ENDER, 0);
MATERIAL_FLAGS.put(Material.SPECKLED_MELON, 0);
MATERIAL_FLAGS.put(Material.MONSTER_EGG, 0);
MATERIAL_FLAGS.put(Material.MONSTER_EGG, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.EXP_BOTTLE, 0);
MATERIAL_FLAGS.put(Material.FIREBALL, 0);
MATERIAL_FLAGS.put(Material.BOOK_AND_QUILL, 0);
@@ -394,6 +434,28 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.LEASH, 0);
MATERIAL_FLAGS.put(Material.NAME_TAG, 0);
MATERIAL_FLAGS.put(Material.COMMAND_MINECART, 0);
try {
MATERIAL_FLAGS.put(Material.PRISMARINE_SHARD, 0);
MATERIAL_FLAGS.put(Material.PRISMARINE_CRYSTALS, 0);
MATERIAL_FLAGS.put(Material.RABBIT, 0);
MATERIAL_FLAGS.put(Material.COOKED_RABBIT, 0);
MATERIAL_FLAGS.put(Material.RABBIT_STEW, 0);
MATERIAL_FLAGS.put(Material.RABBIT_FOOT, 0);
MATERIAL_FLAGS.put(Material.RABBIT_HIDE, 0);
MATERIAL_FLAGS.put(Material.ARMOR_STAND, 0);
MATERIAL_FLAGS.put(Material.IRON_BARDING, 0);
MATERIAL_FLAGS.put(Material.GOLD_BARDING, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_BARDING, 0);;
MATERIAL_FLAGS.put(Material.MUTTON, 0);
MATERIAL_FLAGS.put(Material.COOKED_MUTTON, 0);
MATERIAL_FLAGS.put(Material.BANNER, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_DOOR_ITEM, 0);
MATERIAL_FLAGS.put(Material.BIRCH_DOOR_ITEM, 0);
MATERIAL_FLAGS.put(Material.JUNGLE_DOOR_ITEM, 0);
MATERIAL_FLAGS.put(Material.ACACIA_DOOR_ITEM, 0);
MATERIAL_FLAGS.put(Material.DARK_OAK_DOOR_ITEM, 0);
} catch (NoSuchFieldError ignored) {
}
MATERIAL_FLAGS.put(Material.GOLD_RECORD, 0);
MATERIAL_FLAGS.put(Material.GREEN_RECORD, 0);
MATERIAL_FLAGS.put(Material.RECORD_3, 0);
@@ -406,6 +468,30 @@ public final class Materials {
MATERIAL_FLAGS.put(Material.RECORD_10, 0);
MATERIAL_FLAGS.put(Material.RECORD_11, 0);
MATERIAL_FLAGS.put(Material.RECORD_12, 0);
//DAMAGE_EFFECTS.add(PotionEffectType.ABSORPTION);
DAMAGE_EFFECTS.add(PotionEffectType.BLINDNESS);
DAMAGE_EFFECTS.add(PotionEffectType.CONFUSION);
//DAMAGE_EFFECTS.add(PotionEffectType.DAMAGE_RESISTANCE);
//DAMAGE_EFFECTS.add(PotionEffectType.FAST_DIGGING);
//DAMAGE_EFFECTS.add(PotionEffectType.FIRE_RESISTANCE);
DAMAGE_EFFECTS.add(PotionEffectType.HARM);
//DAMAGE_EFFECTS.add(PotionEffectType.HEAL);
//DAMAGE_EFFECTS.add(PotionEffectType.HEALTH_BOOST);
DAMAGE_EFFECTS.add(PotionEffectType.HUNGER);
//DAMAGE_EFFECTS.add(PotionEffectType.INCREASE_DAMAGE);
//DAMAGE_EFFECTS.add(PotionEffectType.INVISIBILITY);
//DAMAGE_EFFECTS.add(PotionEffectType.JUMP);
//DAMAGE_EFFECTS.add(PotionEffectType.NIGHT_VISION);
DAMAGE_EFFECTS.add(PotionEffectType.POISON);
//DAMAGE_EFFECTS.add(PotionEffectType.REGENERATION);
//DAMAGE_EFFECTS.add(PotionEffectType.SATURATION);
DAMAGE_EFFECTS.add(PotionEffectType.SLOW);
DAMAGE_EFFECTS.add(PotionEffectType.SLOW_DIGGING);
//DAMAGE_EFFECTS.add(PotionEffectType.SPEED);
//DAMAGE_EFFECTS.add(PotionEffectType.WATER_BREATHING);
DAMAGE_EFFECTS.add(PotionEffectType.WEAKNESS);
DAMAGE_EFFECTS.add(PotionEffectType.WITHER);
}
private Materials() {
@@ -576,6 +662,48 @@ public final class Materials {
|| material == Material.DROPPER;
}
/**
* Test whether the given material is affected by
* {@link DefaultFlag#USE}.
*
* <p>Generally, materials that are considered by this method are those
* that are not inventories but can be used.</p>
*
* @param material the material
* @return true if covered by the use flag
*/
public static boolean isUseFlagApplicable(Material material) {
switch (material) {
case LEVER: return true;
case STONE_BUTTON: return true;
case WOOD_BUTTON: return true;
case TRIPWIRE: return true;
case WOODEN_DOOR: return true;
case TRAP_DOOR: return true;
case FENCE_GATE: return true;
case WORKBENCH: return true;
case ENCHANTMENT_TABLE: return true;
case ENDER_CHEST: return true;
case BEACON: return true;
case ANVIL: return true;
case WOOD_PLATE: return true;
case STONE_PLATE: return true;
case IRON_PLATE: return true;
case GOLD_PLATE: return true;
case SPRUCE_FENCE_GATE: return true;
case BIRCH_FENCE_GATE: return true;
case JUNGLE_FENCE_GATE: return true;
case DARK_OAK_FENCE_GATE: return true;
case ACACIA_FENCE_GATE: return true;
case SPRUCE_DOOR: return true;
case BIRCH_DOOR: return true;
case JUNGLE_DOOR: return true;
case ACACIA_DOOR: return true;
case DARK_OAK_DOOR: return true;
default: return false;
}
}
/**
* Test whether the given type is Redstone ore.
*
@@ -594,11 +722,14 @@ public final class Materials {
* aware of.</p>
*
* @param material the material
* @param rightClick whether it is a right click
* @return true if the block is modified
*/
public static boolean isBlockModifiedOnClick(Material material) {
public static boolean isBlockModifiedOnClick(Material material, boolean rightClick) {
Integer flags = MATERIAL_FLAGS.get(material);
return flags == null || (flags & MODIFIED_ON_CLICK) == MODIFIED_ON_CLICK;
return flags == null
|| (rightClick && (flags & MODIFIED_ON_RIGHT) == MODIFIED_ON_RIGHT)
|| (!rightClick && (flags & MODIFIED_ON_LEFT) == MODIFIED_ON_LEFT);
}
/**
@@ -624,7 +755,28 @@ public final class Materials {
* @return true to be considered as used
*/
public static boolean isConsideredBuildingIfUsed(Material type) {
return type == Material.SAPLING;
return type == Material.SAPLING
|| type == Material.DIODE_BLOCK_OFF
|| type == Material.DIODE_BLOCK_ON
|| type == Material.REDSTONE_COMPARATOR_OFF
|| type == Material.REDSTONE_COMPARATOR_ON;
}
/**
* Test whether a list of potion effects contains one or more potion
* effects used for doing damage.
*
* @param effects A collection of effects
* @return True if at least one damage effect exists
*/
public static boolean hasDamageEffect(Collection<PotionEffect> effects) {
for (PotionEffect effect : effects) {
if (DAMAGE_EFFECTS.contains(effect.getType())) {
return true;
}
}
return false;
}
}
@@ -1,88 +0,0 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.listener.FlagStateManager;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
public final class RegionQueryUtil {
private RegionQueryUtil() {
}
public static boolean isInvincible(WorldGuardPlugin plugin, Player player) {
return isInvincible(plugin, player, null);
}
public static boolean isInvincible(WorldGuardPlugin plugin, Player player,
ApplicableRegionSet set) {
Location loc = player.getLocation();
World world = player.getWorld();
FlagStateManager.PlayerFlagState state = plugin.getFlagStateManager().getState(player);
if (state.lastInvincibleWorld == null ||
!state.lastInvincibleWorld.equals(world) ||
state.lastInvincibleX != loc.getBlockX() ||
state.lastInvincibleY != loc.getBlockY() ||
state.lastInvincibleZ != loc.getBlockZ()) {
state.lastInvincibleX = loc.getBlockX();
state.lastInvincibleY = loc.getBlockY();
state.lastInvincibleZ = loc.getBlockZ();
state.lastInvincibleWorld = world;
if (set == null) {
Vector vec = new Vector(state.lastInvincibleX,
state.lastInvincibleY, state.lastInvincibleZ);
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
set = mgr.getApplicableRegions(vec);
}
state.wasInvincible = set.allows(DefaultFlag.INVINCIBILITY, plugin.wrapPlayer(player));
}
return state.wasInvincible;
}
public static Boolean isAllowedInvinciblity(WorldGuardPlugin plugin, Player player) {
World world = player.getWorld();
FlagStateManager.PlayerFlagState state = plugin.getFlagStateManager().getState(player);
Vector vec = new Vector(state.lastInvincibleX, state.lastInvincibleY, state.lastInvincibleZ);
StateFlag.State regionState = plugin.getGlobalRegionManager().get(world).
getApplicableRegions(vec).getFlag(DefaultFlag.INVINCIBILITY, plugin.wrapPlayer(player));
if (regionState == StateFlag.State.ALLOW) {
return Boolean.TRUE;
} else if (regionState == StateFlag.State.DENY) {
return Boolean.FALSE;
} else {
return null;
}
}
}
@@ -1,346 +0,0 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.LogListBlock;
public class ReportWriter {
private static final SimpleDateFormat dateFmt =
new SimpleDateFormat("yyyy-MM-dd kk:mm Z");
private Date date = new Date();
private StringBuilder output = new StringBuilder();
public ReportWriter(WorldGuardPlugin plugin) {
appendReportHeader(plugin);
appendServerInformation(plugin.getServer());
appendPluginInformation(plugin.getServer().getPluginManager().getPlugins());
appendWorldInformation(plugin.getServer().getWorlds());
appendGlobalConfiguration(plugin.getGlobalStateManager());
appendWorldConfigurations(plugin, plugin.getServer().getWorlds(),
plugin.getGlobalRegionManager(), plugin.getGlobalStateManager());
appendln("-------------");
appendln("END OF REPORT");
appendln();
}
protected static String repeat(String str, int n) {
if(str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(str);
}
return sb.toString();
}
protected void appendln(String text) {
output.append(text);
output.append("\r\n");
}
protected void appendln(String text, Object ... args) {
output.append(String.format(text, args));
output.append("\r\n");
}
protected void append(LogListBlock log) {
output.append(log.toString());
}
protected void appendln() {
output.append("\r\n");
}
protected void appendHeader(String text) {
String rule = repeat("-", text.length());
output.append(rule);
output.append("\r\n");
appendln(text);
output.append(rule);
output.append("\r\n");
appendln();
}
private void appendReportHeader(WorldGuardPlugin plugin) {
appendln("WorldGuard Configuration Report");
appendln("Generated " + dateFmt.format(date));
appendln();
appendln("Version: " + plugin.getDescription().getVersion());
appendln();
}
private void appendGlobalConfiguration(ConfigurationManager config) {
appendHeader("Global Configuration");
LogListBlock log = new LogListBlock();
LogListBlock configLog = log.putChild("Configuration");
Class<? extends ConfigurationManager> cls = config.getClass();
for (Field field : cls.getFields()) {
try {
String name = field.getName();
// store these elsewhere maybe?
if (name.equals("CONFIG_HEADER")
|| name.equals("hostKeys")
|| name.equals("sqlPassword")) {
continue;
}
Object val = field.get(config);
configLog.put(name, val);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException ignore) {
}
}
append(log);
appendln();
}
private void appendServerInformation(Server server) {
appendHeader("Server Information");
LogListBlock log = new LogListBlock();
Runtime runtime = Runtime.getRuntime();
log.put("Java", "%s %s (%s)",
System.getProperty("java.vendor"),
System.getProperty("java.version"),
System.getProperty("java.vendor.url"));
log.put("Operating system", "%s %s (%s)",
System.getProperty("os.name"),
System.getProperty("os.version"),
System.getProperty("os.arch"));
log.put("Available processors", runtime.availableProcessors());
log.put("Free memory", runtime.freeMemory() / 1024 / 1024 + " MB");
log.put("Max memory", runtime.maxMemory() / 1024 / 1024 + " MB");
log.put("Total memory", runtime.totalMemory() / 1024 / 1024 + " MB");
log.put("Server ID", server.getServerId());
log.put("Server name", server.getServerName());
log.put("Implementation", server.getVersion());
//log.put("Address", server.getIp(), server.getPort());
log.put("Player count", "%d/%d",
server.getOnlinePlayers().length, server.getMaxPlayers());
append(log);
appendln();
}
private void appendPluginInformation(Plugin[] plugins) {
appendHeader("Plugins (" + plugins.length + ")");
LogListBlock log = new LogListBlock();
for (Plugin plugin : plugins) {
log.put(plugin.getDescription().getName(), plugin.getDescription().getVersion());
}
append(log);
appendln();
/*appendHeader("Plugin Information");
log = new LogListBlock();
for (Plugin plugin : plugins) {
log.putChild(plugin.getDescription().getName())
.put("Data folder", plugin.getDataFolder())
.put("Website", plugin.getDescription().getWebsite())
.put("Entry point", plugin.getDescription().getMain());
}
append(log);
appendln();*/
}
private void appendWorldInformation(List<World> worlds) {
appendHeader("Worlds");
LogListBlock log = new LogListBlock();
int i = 0;
for (World world : worlds) {
int loadedChunkCount = world.getLoadedChunks().length;
LogListBlock worldLog = log.putChild(world.getName() + " (" + i + ")");
LogListBlock infoLog = worldLog.putChild("Information");
LogListBlock entitiesLog = worldLog.putChild("Entities");
infoLog.put("Seed", world.getSeed());
infoLog.put("Environment", world.getEnvironment().toString());
infoLog.put("Player count", world.getPlayers().size());
infoLog.put("Entity count", world.getEntities().size());
infoLog.put("Loaded chunk count", loadedChunkCount);
infoLog.put("Spawn location", world.getSpawnLocation());
infoLog.put("Raw time", world.getFullTime());
Map<Class<? extends Entity>, Integer> entityCounts =
new HashMap<Class<? extends Entity>, Integer>();
// Collect entities
for (Entity entity : world.getEntities()) {
Class<? extends Entity> cls = entity.getClass();
if (entityCounts.containsKey(cls)) {
entityCounts.put(cls, entityCounts.get(cls) + 1);
} else {
entityCounts.put(cls, 1);
}
}
// Print entities
for (Map.Entry<Class<? extends Entity>, Integer> entry
: entityCounts.entrySet()) {
entitiesLog.put(entry.getKey().getSimpleName(),
"%d [%f/chunk]",
entry.getValue(),
(float) (entry.getValue() / (double) loadedChunkCount));
}
i++;
}
append(log);
appendln();
}
private void appendWorldConfigurations(WorldGuardPlugin plugin, List<World> worlds,
GlobalRegionManager regionMgr, ConfigurationManager mgr) {
appendHeader("World Configurations");
LogListBlock log = new LogListBlock();
int i = 0;
for (World world : worlds) {
LogListBlock worldLog = log.putChild(world.getName() + " (" + i + ")");
LogListBlock infoLog = worldLog.putChild("Information");
LogListBlock configLog = worldLog.putChild("Configuration");
LogListBlock blacklistLog = worldLog.putChild("Blacklist");
LogListBlock regionsLog = worldLog.putChild("Region manager");
infoLog.put("Configuration file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/config.yml")).getAbsoluteFile());
infoLog.put("Blacklist file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/blacklist.txt")).getAbsoluteFile());
infoLog.put("Regions file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/regions.yml")).getAbsoluteFile());
WorldConfiguration config = mgr.get(world);
Class<? extends WorldConfiguration> cls = config.getClass();
for (Field field : cls.getFields()) {
try {
Object val = field.get(config);
configLog.put(field.getName(), String.valueOf(val));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException ignore) {
}
}
if (config.getBlacklist() == null) {
blacklistLog.put("State", "DISABLED");
} else {
blacklistLog.put("State", "Enabled");
blacklistLog.put("Number of items",
config.getBlacklist().getItemCount());
blacklistLog.put("Is whitelist",
config.getBlacklist().isWhitelist());
}
RegionManager worldRegions = regionMgr.get(world);
regionsLog.put("Type", worldRegions.getClass().getCanonicalName());
regionsLog.put("Number of regions", worldRegions.getRegions().size());
LogListBlock globalRegionLog = regionsLog.putChild("Global region");
ProtectedRegion globalRegion = worldRegions.matchRegion("__global__");
if (globalRegion == null) {
globalRegionLog.put("Status", "UNDEFINED");
} else {
for (Flag<?> flag : DefaultFlag.getFlags()) {
if (flag instanceof StateFlag) {
globalRegionLog.put(flag.getName(),
globalRegion.getFlag(flag));
}
}
}
}
append(log);
appendln();
}
public void write(File file) throws IOException {
FileWriter writer = null;
BufferedWriter out;
try {
writer = new FileWriter(file);
out = new BufferedWriter(writer);
out.write(output.toString());
out.close();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ignore) {
}
}
}
}
@Override
public String toString() {
return output.toString();
}
}
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
package com.sk89q.worldguard.bukkit.util.logging;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -27,8 +27,6 @@ import java.util.logging.LogRecord;
/**
* Sends all logger messages to a player.
*
* @author sk89q
*/
public class LoggerToChatHandler extends Handler {
/**
@@ -0,0 +1,82 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util.report;
import com.sk89q.worldguard.blacklist.Blacklist;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.report.DataReport;
import com.sk89q.worldguard.util.report.RegionReport;
import com.sk89q.worldguard.util.report.ShallowObjectReport;
import org.bukkit.Bukkit;
import org.bukkit.World;
import java.util.List;
public class ConfigReport extends DataReport {
public ConfigReport(WorldGuardPlugin plugin) {
super("WorldGuard Configuration");
List<World> worlds = Bukkit.getServer().getWorlds();
append("Configuration", new ShallowObjectReport("Configuration", plugin.getGlobalStateManager()));
for (World world : worlds) {
WorldConfiguration config = plugin.getGlobalStateManager().get(world);
DataReport report = new DataReport("World: " + world.getName());
report.append("UUID", world.getUID());
report.append("Configuration", new ShallowObjectReport("Configuration", config));
Blacklist blacklist = config.getBlacklist();
if (blacklist != null) {
DataReport section = new DataReport("Blacklist");
section.append("Rule Count", blacklist.getItemCount());
section.append("Whitelist Mode?", blacklist.isWhitelist());
report.append(section.getTitle(), section);
} else {
report.append("Blacklist", "<Disabled>");
}
RegionManager regions = plugin.getRegionContainer().get(world);
if (regions != null) {
DataReport section = new DataReport("Regions");
section.append("Region Count", regions.size());
ProtectedRegion global = regions.getRegion("__global__");
if (global != null) {
section.append("__global__", new RegionReport(global));
} else {
section.append("__global__", "<Undefined>");
}
report.append(section.getTitle(), section);
} else {
report.append("Regions", "<Disabled>");
}
append(report.getTitle(), report);
}
}
}
@@ -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.bukkit.util.report;
import com.google.common.collect.Maps;
import com.sk89q.worldguard.util.report.DataReport;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import java.util.List;
import java.util.Map;
public class PerformanceReport extends DataReport {
public PerformanceReport() {
super("Performance");
List<World> worlds = Bukkit.getServer().getWorlds();
append("World Count", worlds.size());
for (World world : worlds) {
int loadedChunkCount = world.getLoadedChunks().length;
DataReport report = new DataReport("World: " + world.getName());
report.append("Keep in Memory?", world.getKeepSpawnInMemory());
report.append("Entity Count", world.getEntities().size());
report.append("Chunk Count", loadedChunkCount);
Map<Class<? extends Entity>, Integer> entityCounts = Maps.newHashMap();
// Collect entities
for (Entity entity : world.getEntities()) {
Class<? extends Entity> cls = entity.getClass();
if (entityCounts.containsKey(cls)) {
entityCounts.put(cls, entityCounts.get(cls) + 1);
} else {
entityCounts.put(cls, 1);
}
}
// Print entities
DataReport entities = new DataReport("Entity Distribution");
for (Map.Entry<Class<? extends Entity>, Integer> entry : entityCounts.entrySet()) {
entities.append(entry.getKey().getSimpleName(), "%d [%f/chunk]",
entry.getValue(),
(float) (entry.getValue() / (double) loadedChunkCount));
}
report.append(entities.getTitle(), entities);
append(report.getTitle(), report);
}
}
}
@@ -0,0 +1,54 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util.report;
import com.sk89q.worldguard.util.report.DataReport;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
public class PluginReport extends DataReport {
public PluginReport() {
super("Plugins");
Plugin[] plugins = Bukkit.getServer().getPluginManager().getPlugins();
append("Plugin Count", plugins.length);
for (Plugin plugin : plugins) {
DataReport report = new DataReport("Plugin: " + plugin.getName());
report.append("Enabled?", plugin.isEnabled());
report.append("Full Name", plugin.getDescription().getFullName());
report.append("Version", plugin.getDescription().getVersion());
report.append("Website", plugin.getDescription().getWebsite());
report.append("Description", plugin.getDescription().getDescription());
report.append("Authors", plugin.getDescription().getAuthors());
report.append("Load Before", plugin.getDescription().getLoadBefore());
report.append("Dependencies", plugin.getDescription().getDepend());
report.append("Soft Dependencies", plugin.getDescription().getSoftDepend());
report.append("Folder", plugin.getDataFolder().getAbsoluteFile());
report.append("Entry Point", plugin.getDescription().getMain());
report.append("Class", plugin.getClass().getName());
report.append("Class Source", plugin.getClass().getProtectionDomain().getCodeSource().getLocation());
append(report.getTitle(), report);
}
}
}
@@ -0,0 +1,90 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util.report;
import com.google.common.base.Optional;
import com.google.common.reflect.TypeToken;
import com.sk89q.guavabackport.cache.CacheBuilder;
import com.sk89q.guavabackport.cache.CacheLoader;
import com.sk89q.guavabackport.cache.LoadingCache;
import com.sk89q.worldguard.util.report.DataReport;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
public class SchedulerReport extends DataReport {
private LoadingCache<Class<?>, Optional<Field>> taskFieldCache = CacheBuilder.newBuilder()
.build(new CacheLoader<Class<?>, Optional<Field>>() {
@Override
public Optional<Field> load(Class<?> clazz) throws Exception {
try {
Field field = clazz.getDeclaredField("task");
field.setAccessible(true);
return Optional.fromNullable(field);
} catch (NoSuchFieldException ignored) {
return Optional.absent();
}
}
});
public SchedulerReport() {
super("Scheduler");
List<BukkitTask> tasks = Bukkit.getServer().getScheduler().getPendingTasks();
append("Pending Task Count", tasks.size());
for (BukkitTask task : tasks) {
Class<?> taskClass = getTaskClass(task);
DataReport report = new DataReport("Task: #" + task.getTaskId());
report.append("Owner", task.getOwner().getName());
report.append("Runnable", taskClass != null ? taskClass.getName() : "<Unknown>");
report.append("Synchronous?", task.isSync());
append(report.getTitle(), report);
}
}
@SuppressWarnings("unchecked")
@Nullable
private Class<?> getTaskClass(BukkitTask task) {
try {
Class<?> clazz = task.getClass();
Set<Class<?>> classes = (Set) TypeToken.of(clazz).getTypes().rawTypes();
for (Class<?> type : classes) {
Optional<Field> field = taskFieldCache.getUnchecked(type);
if (field.isPresent()) {
Object res = field.get().get(task);
return res == null ? null : res.getClass();
}
}
} catch (IllegalAccessException ignored) {
} catch (NoClassDefFoundError ignored) {
}
return null;
}
}
@@ -0,0 +1,68 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util.report;
import com.sk89q.worldguard.bukkit.BukkitUtil;
import com.sk89q.worldguard.util.report.DataReport;
import org.bukkit.Bukkit;
import org.bukkit.Server;
public class ServerReport extends DataReport {
public ServerReport() {
super("Server Information");
Server server = Bukkit.getServer();
append("Server ID", server.getServerId());
append("Server Name", server.getServerName());
append("Bukkit Version", server.getBukkitVersion());
append("Implementation", server.getVersion());
append("Player Count", "%d/%d", BukkitUtil.getOnlinePlayers().size(), server.getMaxPlayers());
append("Server Class Source", server.getClass().getProtectionDomain().getCodeSource().getLocation());
DataReport spawning = new DataReport("Spawning");
spawning.append("Ambient Spawn Limit", server.getAmbientSpawnLimit());
spawning.append("Animal Spawn Limit", server.getAnimalSpawnLimit());
spawning.append("Monster Spawn Limit", server.getMonsterSpawnLimit());
spawning.append("Ticks per Animal Spawn", server.getTicksPerAnimalSpawns());
spawning.append("Ticks per Monster Spawn", server.getTicksPerMonsterSpawns());
append(spawning.getTitle(), spawning);
DataReport config = new DataReport("Configuration");
config.append("Nether Enabled?", server.getAllowNether());
config.append("The End Enabled?", server.getAllowEnd());
config.append("Generate Structures?", server.getGenerateStructures());
config.append("Flight Allowed?", server.getAllowFlight());
config.append("Connection Throttle", server.getConnectionThrottle());
config.append("Idle Timeout", server.getIdleTimeout());
config.append("Shutdown Message", server.getShutdownMessage());
config.append("Default Game Mode", server.getDefaultGameMode());
config.append("Main World Type", server.getWorldType());
config.append("View Distance", server.getViewDistance());
append(config.getTitle(), config);
DataReport protection = new DataReport("Protection");
protection.append("Spawn Radius", server.getSpawnRadius());
append(protection.getTitle(), protection);
}
}
@@ -0,0 +1,46 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util.report;
import com.sk89q.worldguard.util.report.DataReport;
import org.bukkit.Bukkit;
import org.bukkit.plugin.ServicesManager;
import org.bukkit.scheduler.BukkitTask;
import java.util.Collection;
import java.util.List;
public class ServicesReport extends DataReport {
public ServicesReport() {
super("Services");
ServicesManager manager = Bukkit.getServer().getServicesManager();
Collection<Class<?>> services = manager.getKnownServices();
for (Class<?> service : services) {
Object provider = manager.load(service);
if (provider != null) {
append(service.getName(), provider);
}
}
}
}
@@ -0,0 +1,76 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util.report;
import com.sk89q.worldguard.util.report.DataReport;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.generator.ChunkGenerator;
import java.util.List;
public class WorldReport extends DataReport {
public WorldReport() {
super("Worlds");
List<World> worlds = Bukkit.getServer().getWorlds();
append("World Count", worlds.size());
for (World world : worlds) {
DataReport report = new DataReport("World: " + world.getName());
report.append("UUID", world.getUID());
report.append("World Type", world.getWorldType());
report.append("Environment", world.getEnvironment());
ChunkGenerator generator = world.getGenerator();
report.append("Chunk Generator", generator != null ? generator.getClass().getName() : "<Default>");
DataReport spawning = new DataReport("Spawning");
spawning.append("Animals?", world.getAllowAnimals());
spawning.append("Monsters?", world.getAllowMonsters());
spawning.append("Ambient Spawn Limit", world.getAmbientSpawnLimit());
spawning.append("Animal Spawn Limit", world.getAnimalSpawnLimit());
spawning.append("Monster Spawn Limit", world.getMonsterSpawnLimit());
spawning.append("Water Creature Spawn Limit", world.getWaterAnimalSpawnLimit());
report.append(spawning.getTitle(), spawning);
DataReport config = new DataReport("Configuration");
config.append("Difficulty", world.getDifficulty());
config.append("Max Height", world.getMaxHeight());
config.append("Sea Level", world.getSeaLevel());
report.append(config.getTitle(), config);
DataReport state = new DataReport("State");
state.append("Spawn Location", world.getSpawnLocation());
state.append("Full Time", world.getFullTime());
state.append("Weather Duration", world.getWeatherDuration());
state.append("Thunder Duration", world.getThunderDuration());
report.append(state.getTitle(), state);
DataReport protection = new DataReport("Protection");
protection.append("PVP?", world.getPVP());
protection.append("Game Rules", world.getGameRules());
report.append(protection.getTitle(), protection);
append(report.getTitle(), report);
}
}
}
@@ -43,6 +43,22 @@ public class DefaultDomain implements Domain, ChangeTracked {
private PlayerDomain playerDomain = new PlayerDomain();
private GroupDomain groupDomain = new GroupDomain();
/**
* Create a new domain.
*/
public DefaultDomain() {
}
/**
* Create a new domain from an existing one, making a copy of all values.
*
* @param existing the other domain to copy values from
*/
public DefaultDomain(DefaultDomain existing) {
setPlayerDomain(existing.getPlayerDomain());
setGroupDomain(existing.getGroupDomain());
}
/**
* Get the domain that holds the players.
*
@@ -59,7 +75,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
*/
public void setPlayerDomain(PlayerDomain playerDomain) {
checkNotNull(playerDomain);
this.playerDomain = playerDomain;
this.playerDomain = new PlayerDomain(playerDomain);
}
/**
@@ -78,7 +94,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
*/
public void setGroupDomain(GroupDomain groupDomain) {
checkNotNull(groupDomain);
this.groupDomain = groupDomain;
this.groupDomain = new GroupDomain(groupDomain);
}
/**
@@ -344,4 +360,12 @@ public class DefaultDomain implements Domain, ChangeTracked {
playerDomain.setDirty(dirty);
groupDomain.setDirty(dirty);
}
@Override
public String toString() {
return "{players=" + playerDomain +
", groups=" + groupDomain +
'}';
}
}
@@ -27,7 +27,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -44,6 +43,16 @@ public class GroupDomain implements Domain, ChangeTracked {
public GroupDomain() {
}
/**
* Create a new instance with copies from another domain.
*
* @param domain the domain to copy values from
*/
public GroupDomain(GroupDomain domain) {
checkNotNull(domain, "domain");
groups.addAll(domain.getGroups());
}
/**
* Create a new instance.
*
@@ -63,9 +72,10 @@ public class GroupDomain implements Domain, ChangeTracked {
*/
public void addGroup(String name) {
checkNotNull(name);
checkArgument(!name.trim().isEmpty(), "Can't add empty group name");
setDirty(true);
groups.add(name.trim().toLowerCase());
if (!name.trim().isEmpty()) {
setDirty(true);
groups.add(name.trim().toLowerCase());
}
}
/**
@@ -117,6 +127,7 @@ public class GroupDomain implements Domain, ChangeTracked {
@Override
public void clear() {
setDirty(true);
groups.clear();
}
@@ -130,4 +141,11 @@ public class GroupDomain implements Domain, ChangeTracked {
this.dirty = dirty;
}
@Override
public String toString() {
return "{" +
"names=" + groups +
'}';
}
}
@@ -27,7 +27,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -45,6 +44,18 @@ public class PlayerDomain implements Domain, ChangeTracked {
public PlayerDomain() {
}
/**
* Create a new instance.
*
* @param domain the domain to copy values from
*/
public PlayerDomain(PlayerDomain domain) {
checkNotNull(domain, "domain");
uniqueIds.addAll(domain.getUniqueIds());
names.addAll(domain.getPlayers());
dirty = true;
}
/**
* Create a new instance with the given names.
*
@@ -65,12 +76,13 @@ public class PlayerDomain implements Domain, ChangeTracked {
*/
public void addPlayer(String name) {
checkNotNull(name);
checkArgument(!name.trim().isEmpty(), "Can't add empty player name");
setDirty(true);
names.add(name.trim().toLowerCase());
// Trim because some names contain spaces (previously valid Minecraft
// names) and we cannot store these correctly in the SQL storage
// implementations
if (!name.trim().isEmpty()) {
setDirty(true);
names.add(name.trim().toLowerCase());
// Trim because some names contain spaces (previously valid Minecraft
// names) and we cannot store these correctly in the SQL storage
// implementations
}
}
/**
@@ -113,6 +125,7 @@ public class PlayerDomain implements Domain, ChangeTracked {
*/
public void removePlayer(UUID uuid) {
checkNotNull(uuid);
setDirty(true);
uniqueIds.remove(uuid);
}
@@ -124,6 +137,7 @@ public class PlayerDomain implements Domain, ChangeTracked {
*/
public void removePlayer(LocalPlayer player) {
checkNotNull(player);
setDirty(true);
removePlayer(player.getName());
removePlayer(player.getUniqueId());
}
@@ -171,6 +185,7 @@ public class PlayerDomain implements Domain, ChangeTracked {
@Override
public void clear() {
setDirty(true);
uniqueIds.clear();
names.clear();
}
@@ -185,4 +200,11 @@ public class PlayerDomain implements Domain, ChangeTracked {
this.dirty = dirty;
}
@Override
public String toString() {
return "{" +
"uuids=" + uniqueIds +
", names=" + names +
'}';
}
}
@@ -21,6 +21,7 @@ package com.sk89q.worldguard.protection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
@@ -29,15 +30,10 @@ import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.util.NormativeOrders;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -61,7 +57,7 @@ public class FlagValueCalculator {
/**
* Create a new instance.
*
* @param regions a list of applicable regions that <strong>must be sorted by priority descending</strong>
* @param regions a list of applicable regions that must be sorted according to {@link NormativeOrders}
* @param globalRegion an optional global region (null to not use one)
*/
public FlagValueCalculator(List<ProtectedRegion> regions, @Nullable ProtectedRegion globalRegion) {
@@ -108,36 +104,9 @@ public class FlagValueCalculator {
checkNotNull(subject);
int minimumPriority = Integer.MIN_VALUE;
boolean foundApplicableRegion = false;
Result result = Result.NO_REGIONS;
// Say there are two regions in one location: CHILD and PARENT (CHILD
// is a child of PARENT). If there are two overlapping regions in WG, a
// subject has to be a member of /both/ (or flags permit) in order to
// build in that location. However, inheritance is supposed
// to allow building if the subject is a member of just CHILD. That
// presents a problem.
//
// To rectify this, we keep two sets. When we iterate over the list of
// regions, there are two scenarios that we may encounter:
//
// 1) PARENT first, CHILD later:
// a) When the loop reaches PARENT, PARENT is added to needsClear.
// b) When the loop reaches CHILD, parents of CHILD (which includes
// PARENT) are removed from needsClear.
// c) needsClear is empty again.
//
// 2) CHILD first, PARENT later:
// a) When the loop reaches CHILD, CHILD's parents (i.e. PARENT) are
// added to hasCleared.
// b) When the loop reaches PARENT, since PARENT is already in
// hasCleared, it does not add PARENT to needsClear.
// c) needsClear stays empty.
//
// As long as the process ends with needsClear being empty, then
// we have satisfied all membership requirements.
Set<ProtectedRegion> needsClear = new HashSet<ProtectedRegion>();
Set<ProtectedRegion> hasCleared = new HashSet<ProtectedRegion>();
Set<ProtectedRegion> ignoredRegions = Sets.newHashSet();
for (ProtectedRegion region : getApplicable()) {
// Don't consider lower priorities below minimumPriority
@@ -153,24 +122,23 @@ public class FlagValueCalculator {
continue;
}
minimumPriority = getPriority(region);
foundApplicableRegion = true;
if (ignoredRegions.contains(region)) {
continue;
}
if (!hasCleared.contains(region)) {
if (!RegionGroup.MEMBERS.contains(subject.getAssociation(region))) {
needsClear.add(region);
} else {
// Need to clear all parents
removeParents(needsClear, hasCleared, region);
}
minimumPriority = getPriority(region);
boolean member = RegionGroup.MEMBERS.contains(subject.getAssociation(Arrays.asList(region)));
if (member) {
result = Result.SUCCESS;
addParents(ignoredRegions, region);
} else {
return Result.FAIL;
}
}
if (foundApplicableRegion) {
return needsClear.isEmpty() ? Result.SUCCESS : Result.FAIL;
} else {
return Result.NO_REGIONS;
}
return result;
}
@@ -249,7 +217,7 @@ public class FlagValueCalculator {
*/
@Nullable
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
Collection<V> values = queryAllValues(subject, flag);
Collection<V> values = queryAllValues(subject, flag, true);
return flag.chooseValue(values);
}
@@ -270,85 +238,80 @@ public class FlagValueCalculator {
* @param flag the flag
* @return a collection of values
*/
@SuppressWarnings("unchecked")
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
return queryAllValues(subject, flag, false);
}
/**
* Get the effective values for a flag, returning a collection of all
* values. It is up to the caller to determine which value, if any,
* from the collection will be used.
*
* <p>A subject can be provided that is used to determine whether the value
* of a flag on a particular region should be used. For example, if a
* flag's region group is set to {@link RegionGroup#MEMBERS} and the given
* subject is not a member, then the region would be skipped when
* querying that flag. If {@code null} is provided for the subject, then
* only flags that use {@link RegionGroup#ALL},
* {@link RegionGroup#NON_MEMBERS}, etc. will apply.</p>
*
* @param subject an optional subject, which would be used to determine the region group to apply
* @param flag the flag
* @param acceptOne if possible, return only one value if it doesn't matter
* @return a collection of values
*/
@SuppressWarnings("unchecked")
private <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
checkNotNull(flag);
// Can't use this optimization with flags that have a conflict resolution strategy
if (acceptOne && flag.hasConflictStrategy()) {
acceptOne = false;
}
// Check to see whether we have a subject if this is BUILD
if (flag == DefaultFlag.BUILD && subject == null) {
throw new NullPointerException("The BUILD flag is handled in a special fashion and requires a non-null subject parameter");
if (flag.requiresSubject() && subject == null) {
throw new NullPointerException("The " + flag.getName() + " flag is handled in a special fashion and requires a non-null subject parameter");
}
int minimumPriority = Integer.MIN_VALUE;
// Say there are two regions in one location: CHILD and PARENT (CHILD
// is a child of PARENT). If the two are overlapping regions in WG,
// both with values set, then we have a problem. Due to inheritance,
// only the CHILD's value for the flag should be used because it
// overrides its parent's value, but default behavior is to collect
// all the values into a list.
//
// To rectify this, we keep a map of consideredValues (region -> value)
// and an ignoredRegions set. When we iterate over the list of
// regions, there are two scenarios that we may encounter:
//
// 1) PARENT first, CHILD later:
// a) When the loop reaches PARENT, PARENT's value is added to
// consideredValues
// b) When the loop reaches CHILD, parents of CHILD (which includes
// PARENT) are removed from consideredValues (so we no longer
// consider those values). The CHILD's value is then added to
// consideredValues.
// c) In the end, only CHILD's value exists in consideredValues.
//
// 2) CHILD first, PARENT later:
// a) When the loop reaches CHILD, CHILD's value is added to
// consideredValues. In addition, the CHILD's parents (which
// includes PARENT) are added to ignoredRegions.
// b) When the loop reaches PARENT, since PARENT is in
// ignoredRegions, the parent is skipped over.
// c) In the end, only CHILD's value exists in consideredValues.
Map<ProtectedRegion, V> consideredValues = new HashMap<ProtectedRegion, V>();
Set<ProtectedRegion> ignoredRegions = new HashSet<ProtectedRegion>();
Set<ProtectedRegion> ignoredParents = new HashSet<ProtectedRegion>();
for (ProtectedRegion region : getApplicable()) {
// Don't consider lower priorities below minimumPriority
// (which starts at Integer.MIN_VALUE). A region that "counts"
// (has the flag set) will raise minimumPriority to its own
// priority.
if (getPriority(region) < minimumPriority) {
break;
}
if (ignoredParents.contains(region)) {
continue;
}
V value = getEffectiveFlag(region, flag, subject);
int priority = getPriority(region);
if (value != null) {
if (!ignoredRegions.contains(region)) {
minimumPriority = priority;
minimumPriority = priority;
ignoreValuesOfParents(consideredValues, ignoredRegions, region);
if (acceptOne) {
return Arrays.asList(value);
} else {
consideredValues.put(region, value);
if (value == State.DENY) {
// Since DENY overrides all other values, there
// is no need to consider any further regions
break;
}
}
}
// The BUILD flag (of lower priorities) can be overridden if
// this region has members... this check is here due to legacy
// reasons
if (priority != minimumPriority && flag == DefaultFlag.BUILD
addParents(ignoredParents, region);
// The BUILD flag is implicitly set on every region where
// PASSTHROUGH is not set to ALLOW
if (priority != minimumPriority && flag.implicitlySetWithMembership()
&& getEffectiveFlag(region, DefaultFlag.PASSTHROUGH, subject) != State.ALLOW) {
minimumPriority = getPriority(region);
}
}
if (flag == DefaultFlag.BUILD && consideredValues.isEmpty()) {
if (flag.usesMembershipAsDefault() && consideredValues.isEmpty()) {
switch (getMembership(subject)) {
case FAIL:
return ImmutableList.of();
@@ -395,23 +358,27 @@ public class FlagValueCalculator {
if (flag == DefaultFlag.PASSTHROUGH) {
// Has members/owners -> the global region acts like
// a regular region without PASSTHROUGH
if (region.hasMembersOrOwners()) {
if (region.hasMembersOrOwners() || region.getFlag(DefaultFlag.PASSTHROUGH) == State.DENY) {
return null;
} else {
return (V) State.ALLOW;
}
} else if (flag == DefaultFlag.BUILD) {
} else if (flag instanceof StateFlag && ((StateFlag) flag).preventsAllowOnGlobal()) {
// Legacy behavior -> we can't let people change BUILD on
// the global region
State value = region.getFlag(DefaultFlag.BUILD);
State value = region.getFlag((StateFlag) flag);
return value != State.ALLOW ? (V) value : null;
}
}
ProtectedRegion current = region;
List<ProtectedRegion> seen = new ArrayList<ProtectedRegion>();
while (current != null) {
seen.add(current);
V value = current.getFlag(flag);
if (value != null) {
@@ -427,7 +394,7 @@ public class FlagValueCalculator {
use = false;
} else if (subject == null) {
use = group.contains(Association.NON_MEMBER);
} else if (!group.contains(subject.getAssociation(region))) {
} else if (!group.contains(subject.getAssociation(seen))) {
use = false;
}
}
@@ -443,40 +410,17 @@ public class FlagValueCalculator {
return null;
}
/**
* Clear a region's parents for isFlagAllowed().
*
* @param needsClear the regions that should be cleared
* @param hasCleared the regions already cleared
* @param region the region to start from
*/
private void removeParents(Set<ProtectedRegion> needsClear, Set<ProtectedRegion> hasCleared, ProtectedRegion region) {
ProtectedRegion parent = region.getParent();
while (parent != null) {
if (!needsClear.remove(parent)) {
hasCleared.add(parent);
}
parent = parent.getParent();
}
}
/**
* Clear a region's parents for getFlag().
*
* @param needsClear The regions that should be cleared
* @param hasCleared The regions already cleared
* @param ignored The regions to ignore
* @param region The region to start from
*/
private void ignoreValuesOfParents(Map<ProtectedRegion, ?> needsClear, Set<ProtectedRegion> hasCleared, ProtectedRegion region) {
private void addParents(Set<ProtectedRegion> ignored, ProtectedRegion region) {
ProtectedRegion parent = region.getParent();
while (parent != null) {
if (needsClear.remove(parent) == null) {
hasCleared.add(parent);
}
ignored.add(parent);
parent = parent.getParent();
}
}
@@ -25,14 +25,10 @@ import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.util.NormativeOrders;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.*;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -47,9 +43,10 @@ public class RegionResultSet extends AbstractRegionSet {
private Set<ProtectedRegion> regionSet;
/**
* Construct the object.
* Create a new region result set.
*
* <p>A sorted set will be created to include the collection of regions.</p>
* <p>The given list must not contain duplicates or the behavior of
* this instance will be undefined.</p>
*
* @param applicable the regions contained in this set
* @param globalRegion the global region, set aside for special handling.
@@ -59,16 +56,31 @@ public class RegionResultSet extends AbstractRegionSet {
}
/**
* Construct the object.
* Create a new region result set.
*
* @param applicable the regions contained in this set
* @param globalRegion the global region, set aside for special handling.
*/
public RegionResultSet(Set<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion) {
this(NormativeOrders.fromSet(applicable), globalRegion, true);
this.regionSet = applicable;
}
/**
* Create a new region result set.
*
* <p>The list of regions may be first sorted with
* {@link NormativeOrders}. If that is the case, {@code sorted} should be
* {@code true}. Otherwise, the list will be sorted in-place.</p>
*
* @param applicable the regions contained in this set
* @param globalRegion the global region, set aside for special handling.
* @param sorted true if the list is already sorted
* @param sorted true if the list is already sorted with {@link NormativeOrders}
*/
private RegionResultSet(List<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion, boolean sorted) {
public RegionResultSet(List<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion, boolean sorted) {
checkNotNull(applicable);
if (!sorted) {
Collections.sort(applicable);
NormativeOrders.sort(applicable);
}
this.applicable = applicable;
this.flagValueCalculator = new FlagValueCalculator(applicable, globalRegion);
@@ -22,6 +22,8 @@ package com.sk89q.worldguard.protection.association;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.List;
class ConstantAssociation implements RegionAssociable {
private final Association association;
@@ -31,7 +33,7 @@ class ConstantAssociation implements RegionAssociable {
}
@Override
public Association getAssociation(ProtectedRegion region) {
public Association getAssociation(List<ProtectedRegion> regions) {
return association;
}
@@ -22,17 +22,19 @@ package com.sk89q.worldguard.protection.association;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.List;
/**
* An object that can have membership in a region.
*/
public interface RegionAssociable {
/**
* Get the most specific association level for the input region.
* Get the highest association level for the input regions.
*
* @param region the input region
* @return the most specific membership level
* @param regions a list of regions
* @return the highest membership level
*/
Association getAssociation(ProtectedRegion region);
Association getAssociation(List<ProtectedRegion> regions);
}
@@ -22,6 +22,7 @@ package com.sk89q.worldguard.protection.association;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -45,12 +46,14 @@ public class RegionOverlapAssociation implements RegionAssociable {
}
@Override
public Association getAssociation(ProtectedRegion region) {
if (source.contains(region)) {
return Association.OWNER;
} else {
return Association.NON_MEMBER;
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;
}
}
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
/**
*
* @author sk89q
* A boolean flag.
*/
public class BooleanFlag extends Flag<Boolean> {
@@ -38,8 +37,7 @@ public class BooleanFlag extends Flag<Boolean> {
}
@Override
public Boolean parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
public Boolean parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
input = input.trim();
if (input.equalsIgnoreCase("true") || input.equalsIgnoreCase("yes")
@@ -0,0 +1,52 @@
/*
* 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.flags;
/**
* A special implementation of the {@link StateFlag} for
* {@link DefaultFlag#BUILD}.
*/
class BuildFlag extends StateFlag {
public BuildFlag(String name, boolean def) {
super(name, def);
}
@Override
public boolean implicitlySetWithMembership() {
return true;
}
@Override
public boolean usesMembershipAsDefault() {
return true;
}
@Override
public boolean preventsAllowOnGlobal() {
return true;
}
@Override
public boolean requiresSubject() {
return true;
}
}
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
/**
*
* @author sk89q
* Stores a command/
*/
public class CommandStringFlag extends Flag<String> {
@@ -38,8 +37,7 @@ public class CommandStringFlag extends Flag<String> {
}
@Override
public String parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
public String parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
input = input.trim();
if (!input.startsWith("/")) {
input = "/" + input;
@@ -21,6 +21,7 @@ package com.sk89q.worldguard.protection.flags;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.WeatherType;
import org.bukkit.entity.EntityType;
/**
@@ -39,7 +40,7 @@ public final class DefaultFlag {
public static final RegionGroupFlag CONSTRUCT = new RegionGroupFlag("construct", RegionGroup.MEMBERS);
// This flag is unlike the others. It forces the checking of region membership
public static final StateFlag BUILD = new StateFlag("build", true);
public static final StateFlag BUILD = new BuildFlag("build", true);
// These flags are used in tandem with the BUILD flag - if the player can
// build, then the following flags do not need to be checked (although they
@@ -47,6 +48,8 @@ public final class DefaultFlag {
public static final StateFlag BLOCK_BREAK = new StateFlag("block-break", false);
public static final StateFlag BLOCK_PLACE = new StateFlag("block-place", false);
public static final StateFlag USE = new StateFlag("use", false);
public static final StateFlag INTERACT = new StateFlag("interact", false);
public static final StateFlag DAMAGE_ANIMALS = new StateFlag("damage-animals", false);
public static final StateFlag PVP = new StateFlag("pvp", false);
public static final StateFlag SLEEP = new StateFlag("sleep", false);
public static final StateFlag TNT = new StateFlag("tnt", false);
@@ -54,6 +57,8 @@ public final class DefaultFlag {
public static final StateFlag PLACE_VEHICLE = new StateFlag("vehicle-place", false);
public static final StateFlag DESTROY_VEHICLE = new StateFlag("vehicle-destroy", false);
public static final StateFlag LIGHTER = new StateFlag("lighter", false);
public static final StateFlag RIDE = new StateFlag("ride", false);
public static final StateFlag POTION_SPLASH = new StateFlag("potion-splash", false);
// These flags are similar to the ones above (used in tandem with BUILD),
// but their defaults are set to TRUE because it is more user friendly.
@@ -62,6 +67,7 @@ public final class DefaultFlag {
// BUILD flag. In the future, StateFlags will need a DISALLOW state.
public static final StateFlag ITEM_PICKUP = new StateFlag("item-pickup", true); // Intentionally true
public static final StateFlag ITEM_DROP = new StateFlag("item-drop", true); // Intentionally true
public static final StateFlag EXP_DROPS = new StateFlag("exp-drops", true); // Intentionally true
// These flags adjust behavior and are not checked in tandem with the
// BUILD flag so they need to be TRUE for their defaults.
@@ -89,7 +95,6 @@ public final class DefaultFlag {
public static final StateFlag SOIL_DRY = new StateFlag("soil-dry", true);
public static final StateFlag ENDER_BUILD = new StateFlag("enderman-grief", true);
public static final StateFlag INVINCIBILITY = new StateFlag("invincible", false);
public static final StateFlag EXP_DROPS = new StateFlag("exp-drops", true);
public static final StateFlag SEND_CHAT = new StateFlag("send-chat", true);
public static final StateFlag RECEIVE_CHAT = new StateFlag("receive-chat", true);
public static final StateFlag ENTRY = new StateFlag("entry", true, RegionGroup.NON_MEMBERS);
@@ -97,17 +102,25 @@ public final class DefaultFlag {
public static final StateFlag ENDERPEARL = new StateFlag("enderpearl", true);
public static final StateFlag ENTITY_PAINTING_DESTROY = new StateFlag("entity-painting-destroy", true);
public static final StateFlag ENTITY_ITEM_FRAME_DESTROY = new StateFlag("entity-item-frame-destroy", true);
public static final StateFlag POTION_SPLASH = new StateFlag("potion-splash", true);
public static final StateFlag FALL_DAMAGE = new StateFlag("fall-damage", true);
// Flags that adjust behaviors that aren't state flags
public static final StringFlag DENY_MESSAGE = new StringFlag("deny-message",
"" + ChatColor.RED + ChatColor.BOLD + "Hey!" + ChatColor.GRAY + " Sorry, but you can't %what% here.");
public static final StringFlag ENTRY_DENY_MESSAGE = new StringFlag("entry-deny-message",
"" + ChatColor.RED + ChatColor.BOLD + "Hey!" + ChatColor.GRAY + " You are not permitted to enter this area.");
public static final StringFlag EXIT_DENY_MESSAGE = new StringFlag("exit-deny-message",
"" + ChatColor.RED + ChatColor.BOLD + "Hey!" + ChatColor.GRAY + " You are not permitted to leave this area.");
public static final BooleanFlag EXIT_OVERRIDE = new BooleanFlag("exit-override");
public static final StateFlag EXIT_VIA_TELEPORT = new StateFlag("exit-via-teleport", true);
public static final StringFlag GREET_MESSAGE = new StringFlag("greeting");
public static final StringFlag FAREWELL_MESSAGE = new StringFlag("farewell");
public static final BooleanFlag NOTIFY_ENTER = new BooleanFlag("notify-enter");
public static final BooleanFlag NOTIFY_LEAVE = new BooleanFlag("notify-leave");
public static final SetFlag<EntityType> DENY_SPAWN = new SetFlag<EntityType>("deny-spawn", new EntityTypeFlag(null));
public static final EnumFlag<GameMode> GAME_MODE = new EnumFlag<GameMode>("game-mode", GameMode.class);
public static final StringFlag TIME_LOCK = new StringFlag("time-lock");
public static final EnumFlag<WeatherType> WEATHER_LOCK = new EnumFlag<WeatherType>("weather-lock", WeatherType.class);
public static final IntegerFlag HEAL_DELAY = new IntegerFlag("heal-delay");
public static final IntegerFlag HEAL_AMOUNT = new IntegerFlag("heal-amount");
public static final DoubleFlag MIN_HEAL = new DoubleFlag("heal-min-health");
@@ -128,18 +141,19 @@ public final class DefaultFlag {
public static final Flag<?>[] flagsList = new Flag<?>[] {
PASSTHROUGH, BUILD, CONSTRUCT, BLOCK_BREAK, BLOCK_PLACE, PVP, CHEST_ACCESS, PISTONS,
TNT, LIGHTER, USE, PLACE_VEHICLE, DESTROY_VEHICLE, SLEEP,
TNT, LIGHTER, RIDE, USE, INTERACT, PLACE_VEHICLE, DESTROY_VEHICLE, DAMAGE_ANIMALS, SLEEP,
MOB_DAMAGE, MOB_SPAWNING, DENY_SPAWN, INVINCIBILITY, EXP_DROPS,
CREEPER_EXPLOSION, OTHER_EXPLOSION, ENDERDRAGON_BLOCK_DAMAGE, GHAST_FIREBALL, ENDER_BUILD,
DENY_MESSAGE, GREET_MESSAGE, FAREWELL_MESSAGE, NOTIFY_ENTER, NOTIFY_LEAVE,
DENY_MESSAGE, ENTRY_DENY_MESSAGE, EXIT_DENY_MESSAGE, EXIT_OVERRIDE, EXIT_VIA_TELEPORT,
GREET_MESSAGE, FAREWELL_MESSAGE, NOTIFY_ENTER, NOTIFY_LEAVE,
EXIT, ENTRY, LIGHTNING, ENTITY_PAINTING_DESTROY, ENDERPEARL,
ENTITY_ITEM_FRAME_DESTROY, ITEM_PICKUP, ITEM_DROP, /*MAX_PLAYERS, MAX_PLAYERS_MESSAGE,*/
ENTITY_ITEM_FRAME_DESTROY, FALL_DAMAGE, ITEM_PICKUP, ITEM_DROP, /*MAX_PLAYERS, MAX_PLAYERS_MESSAGE,*/
HEAL_AMOUNT, HEAL_DELAY, MIN_HEAL, MAX_HEAL,
FEED_DELAY, FEED_AMOUNT, MIN_FOOD, MAX_FOOD,
SNOW_FALL, SNOW_MELT, ICE_FORM, ICE_MELT, SOIL_DRY, GAME_MODE,
MUSHROOMS, LEAF_DECAY, GRASS_SPREAD, MYCELIUM_SPREAD, VINE_GROWTH,
SEND_CHAT, RECEIVE_CHAT, FIRE_SPREAD, LAVA_FIRE, LAVA_FLOW, WATER_FLOW,
TELE_LOC, SPAWN_LOC, POTION_SPLASH,
TELE_LOC, SPAWN_LOC, POTION_SPLASH, TIME_LOCK, WEATHER_LOCK,
BLOCKED_CMDS, ALLOWED_CMDS, PRICE, BUYABLE, ENABLE_SHOP
};
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
/**
*
* @author sk89q
* Stores doubles.
*/
public class DoubleFlag extends Flag<Double> {
@@ -38,8 +37,7 @@ public class DoubleFlag extends Flag<Double> {
}
@Override
public Double parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
public Double parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
input = input.trim();
try {
@@ -22,9 +22,7 @@ package com.sk89q.worldguard.protection.flags;
import org.bukkit.entity.EntityType;
/**
* Represents an entity type.
*
* @author sk89q
* Stores an entity type.
*/
public class EntityTypeFlag extends EnumFlag<EntityType> {
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
/**
*
* @author sk89q
* Stores an enum value.
*/
public class EnumFlag<T extends Enum<T>> extends Flag<T> {
@@ -79,8 +78,7 @@ public class EnumFlag<T extends Enum<T>> extends Flag<T> {
}
@Override
public T parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
public T parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
try {
return findValue(input);
} catch (IllegalArgumentException e) {
@@ -20,33 +20,45 @@
package com.sk89q.worldguard.protection.flags;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.FlagValueCalculator;
import org.bukkit.command.CommandSender;
import javax.annotation.Nullable;
import java.util.Collection;
/**
*
* @author sk89q
* @param <T>
* A flag carries extra data on a region.
*/
public abstract class Flag<T> {
private String name;
private RegionGroupFlag regionGroup;
public Flag(String name, RegionGroup defaultGroup) {
this.name = name;
private final String name;
private final RegionGroupFlag regionGroup;
if (defaultGroup != null) {
this.regionGroup = new RegionGroupFlag(name + "-group", defaultGroup);
}
/**
* Create a new flag.
*
* @param name The name of the flag
* @param defaultGroup The default group
*/
public Flag(String name, @Nullable RegionGroup defaultGroup) {
this.name = name;
this.regionGroup = defaultGroup != null ? new RegionGroupFlag(name + "-group", defaultGroup) : null;
}
/**
* Create a new flag with {@link RegionGroup#ALL} as the default group.
*
* @param name The name of the flag
*/
public Flag(String name) {
this(name, RegionGroup.ALL);
}
/**
* Get the name of the flag.
*
* @return The name of the flag
*/
public String getName() {
return name;
}
@@ -54,7 +66,7 @@ public abstract class Flag<T> {
/**
* Get the default value.
*
* @return the default value, if one exists, otherwise {@code null} may be returned
* @return The default value, if one exists, otherwise {@code null} may be returned
*/
@Nullable
public T getDefault() {
@@ -69,20 +81,106 @@ public abstract class Flag<T> {
return null;
}
}
/**
* Whether the flag can take a list of values and choose a "best one."
*
* <p>This is the case with the {@link StateFlag} where {@code DENY}
* overrides {@code ALLOW}, but most flags just return the
* first result from a list.</p>
*
* <p>This flag is primarily used to optimize flag lookup in
* {@link FlagValueCalculator}.</p>
*
* @return Whether a best value can be chosen
*/
public boolean hasConflictStrategy() {
return false;
}
/**
* Whether the flag implicitly has a value set as long as
* {@link DefaultFlag#PASSTHROUGH} is not set.
*
* <p>This value is only changed, at least in WorldGuard, for the
* {@link DefaultFlag#BUILD} flag.</p>
*
* @return Whether the flag is ignored
*/
public boolean implicitlySetWithMembership() {
return false;
}
/**
* Whether, if the flag is not set at all, the value should be derived
* from membership.
*
* <p>This value is only changed, at least in WorldGuard, for the
* {@link DefaultFlag#BUILD} flag.</p>
*
* @return Whether membership is used
*/
public boolean usesMembershipAsDefault() {
return false;
}
/**
* Whether the flag requires that a subject is specified in
* {@link FlagValueCalculator}.
*
* <p>This value is only changed, at least in WorldGuard, for the
* {@link DefaultFlag#BUILD} flag.</p>
*
* @return Whether a subject is required
*/
public boolean requiresSubject() {
return false;
}
/**
* Get the region group flag.
*
* <p>Every group has a region group flag except for region group flags
* themselves.</p>
*
* @return The region group flag
*/
public RegionGroupFlag getRegionGroupFlag() {
return regionGroup;
}
/**
* Parse a given input to coerce it to a type compatible with the flag.
*
* @param plugin The plugin
* @param sender The sender
* @param input THe input
* @return The coerced type
* @throws InvalidFlagFormat Raised if the input is invalid
*/
public abstract T parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat;
/**
* Convert a raw type that was loaded (from a YAML file, for example)
* into the type that this flag uses.
*
* @param o The object
* @return The unmarshalled type
*/
public abstract T unmarshal(@Nullable Object o);
/**
* Convert the value stored for this flag into a type that can be
* serialized into YAML.
*
* @param o The object
* @return The marshalled type
*/
public abstract Object marshal(T o);
@Override
public String toString() {
return getClass().getName() + "{" +
return getClass().getSimpleName() + "{" +
"name='" + name + '\'' +
'}';
}
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
/**
*
* @author sk89q
* Stores an integer.
*/
public class IntegerFlag extends Flag<Integer> {
@@ -38,8 +37,7 @@ public class IntegerFlag extends Flag<Integer> {
}
@Override
public Integer parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
public Integer parseInput(WorldGuardPlugin plugin, CommandSender sender,String input) throws InvalidFlagFormat {
input = input.trim();
try {
@@ -0,0 +1,72 @@
/*
* 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.flags;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Location;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bukkit.BukkitUtil;
import org.bukkit.Bukkit;
import javax.annotation.Nullable;
/**
* A location that stores the name of the world in case the world is unloaded.
*/
class LazyLocation extends Location {
private final String worldName;
@Nullable
private static LocalWorld findWorld(String worldName) {
return BukkitUtil.getLocalWorld(Bukkit.getServer().getWorld(worldName));
}
public LazyLocation(String worldName, Vector position, float yaw, float pitch) {
super(findWorld(worldName), position, yaw, pitch);
this.worldName = worldName;
}
public LazyLocation(String worldName, Vector position) {
super(findWorld(worldName), position);
this.worldName = worldName;
}
public String getWorldName() {
return worldName;
}
public LazyLocation setAngles(float yaw, float pitch) {
return new LazyLocation(worldName, getPosition(), yaw, pitch);
}
public LazyLocation setPosition(Vector position) {
return new LazyLocation(worldName, position, getYaw(), getPitch());
}
public LazyLocation add(Vector other) {
return this.setPosition(getPosition().add(other));
}
public LazyLocation add(double x, double y, double z) {
return this.setPosition(getPosition().add(x, y, z));
}
}
@@ -19,25 +19,18 @@
package com.sk89q.worldguard.protection.flags;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Location;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bukkit.BukkitUtil;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author sk89q
*/
public class LocationFlag extends Flag<Location> {
public LocationFlag(String name, RegionGroup defaultGroup) {
@@ -60,7 +53,7 @@ public class LocationFlag extends Flag<Location> {
}
if ("here".equalsIgnoreCase(input)) {
return BukkitUtil.toLocation(player.getLocation());
return toLazyLocation(player.getLocation());
} else if ("none".equalsIgnoreCase(input)) {
return null;
} else {
@@ -74,15 +67,7 @@ public class LocationFlag extends Flag<Location> {
final float yaw = split.length < 4 ? 0 : Float.parseFloat(split[3]);
final float pitch = split.length < 5 ? 0 : Float.parseFloat(split[4]);
return new Location(
BukkitUtil.getLocalWorld(world),
new Vector(
x,
y,
z
),
yaw, pitch
);
return new LazyLocation(world.getName(), new Vector(x, y, z), yaw, pitch);
} catch (NumberFormatException ignored) {
}
}
@@ -91,10 +76,14 @@ public class LocationFlag extends Flag<Location> {
}
}
private Location toLazyLocation(org.bukkit.Location location) {
return new LazyLocation(location.getWorld().getName(), BukkitUtil.toVector(location), location.getYaw(), location.getPitch());
}
@Override
public Location unmarshal(Object o) {
if (o instanceof Map<?, ?>) {
Map<?, ?> map = (Map<?, ?>) o;
Map<?, ?> map = (Map<?, ?>) o;
Object rawWorld = map.get("world");
if (rawWorld == null) return null;
@@ -114,13 +103,11 @@ public class LocationFlag extends Flag<Location> {
Object rawPitch = map.get("pitch");
if (rawPitch == null) return null;
World bukkitWorld = Bukkit.getServer().getWorld((String) rawWorld);
LocalWorld world = BukkitUtil.getLocalWorld(bukkitWorld);
Vector position = new Vector(toNumber(rawX), toNumber(rawY), toNumber(rawZ));
float yaw = (float) toNumber(rawYaw);
float pitch = (float) toNumber(rawPitch);
return new Location(world, position, yaw, pitch);
return new LazyLocation(String.valueOf(rawWorld), position, yaw, pitch);
}
return null;
@@ -130,7 +117,15 @@ public class LocationFlag extends Flag<Location> {
public Object marshal(Location o) {
Vector position = o.getPosition();
Map<String, Object> vec = new HashMap<String, Object>();
vec.put("world", o.getWorld().getName());
if (o instanceof LazyLocation) {
vec.put("world", ((LazyLocation) o).getWorldName());
} else {
try {
vec.put("world", o.getWorld().getName());
} catch (NullPointerException e) {
return null;
}
}
vec.put("x", position.getX());
vec.put("y", position.getY());
vec.put("z", position.getZ());
@@ -26,8 +26,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import javax.annotation.Nullable;
/**
*
* @author sk89q
* Stores a region group.
*/
public class RegionGroupFlag extends EnumFlag<RegionGroup> {
@@ -19,6 +19,7 @@
package com.sk89q.worldguard.protection.flags;
import com.google.common.collect.Sets;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.command.CommandSender;
@@ -29,9 +30,7 @@ import java.util.List;
import java.util.Set;
/**
* Represents a flag that consists of a set.
*
* @author sk89q
* Stores a set of types.
*/
public class SetFlag<T> extends Flag<Set<T>> {
@@ -57,15 +56,18 @@ public class SetFlag<T> extends Flag<Set<T>> {
}
@Override
public Set<T> parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
Set<T> items = new HashSet<T>();
public Set<T> parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
if (input.isEmpty()) {
return Sets.newHashSet();
} else {
Set<T> items = Sets.newHashSet();
for (String str : input.split(",")) {
items.add(subFlag.parseInput(plugin, sender, str.trim()));
for (String str : input.split(",")) {
items.add(subFlag.parseInput(plugin, sender, str.trim()));
}
return items;
}
return new HashSet<T>(items);
}
@Override
@@ -26,8 +26,7 @@ import javax.annotation.Nullable;
import java.util.Collection;
/**
*
* @author sk89q
* Stores a bi-state value.
*/
public class StateFlag extends Flag<StateFlag.State> {
@@ -53,6 +52,11 @@ public class StateFlag extends Flag<StateFlag.State> {
return def ? State.ALLOW : null;
}
@Override
public boolean hasConflictStrategy() {
return true;
}
@Override
@Nullable
public State chooseValue(Collection<State> values) {
@@ -63,9 +67,21 @@ public class StateFlag extends Flag<StateFlag.State> {
}
}
/**
* Whether setting this flag to {@link State#ALLOW} is prevented on
* the global region.
*
* <p>This value is only changed, at least in WorldGuard, for the
* {@link DefaultFlag#BUILD} flag.</p>
*
* @return Whether {@code ALLOW} is prevented
*/
public boolean preventsAllowOnGlobal() {
return false;
}
@Override
public State parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
public State parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
input = input.trim();
if (input.equalsIgnoreCase("allow")) {
@@ -26,8 +26,7 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import javax.annotation.Nullable;
/**
*
* @author sk89q
* Stores a string.
*/
public class StringFlag extends Flag<String> {
@@ -60,8 +59,7 @@ public class StringFlag extends Flag<String> {
}
@Override
public String parseInput(WorldGuardPlugin plugin, CommandSender sender,
String input) throws InvalidFlagFormat {
public String parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
return input.replaceAll("(?!\\\\)\\\\n", "\n").replaceAll("\\\\\\\\n", "\\n");
}
@@ -19,19 +19,17 @@
package com.sk89q.worldguard.protection.flags;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.command.CommandSender;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.bukkit.BukkitUtil;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.command.CommandSender;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author sk89q
* Stores a vector.
*/
public class VectorFlag extends Flag<Vector> {
@@ -21,6 +21,7 @@ package com.sk89q.worldguard.protection.managers;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Sets;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldguard.LocalPlayer;
@@ -317,7 +318,7 @@ public final class RegionManager {
public ApplicableRegionSet getApplicableRegions(Vector position) {
checkNotNull(position);
List<ProtectedRegion> regions = new ArrayList<ProtectedRegion>();
Set<ProtectedRegion> regions = Sets.newHashSet();
index.applyContaining(position, new RegionCollectionConsumer(regions, true));
return new RegionResultSet(regions, index.get("__global__"));
}
@@ -332,7 +333,7 @@ public final class RegionManager {
public ApplicableRegionSet getApplicableRegions(ProtectedRegion region) {
checkNotNull(region);
List<ProtectedRegion> regions = new ArrayList<ProtectedRegion>();
Set<ProtectedRegion> regions = Sets.newHashSet();
index.applyIntersecting(region, new RegionCollectionConsumer(regions, true));
return new RegionResultSet(regions, index.get("__global__"));
}
@@ -441,7 +442,7 @@ public final class RegionManager {
* @return an {@code ApplicableRegionSet}
*/
public ApplicableRegionSet getApplicableRegions(org.bukkit.Location loc) {
return getApplicableRegions(com.sk89q.worldedit.bukkit.BukkitUtil.toVector(loc));
return getApplicableRegions(com.sk89q.worldedit.bukkit.BukkitUtil.toVector(loc).floor());
}
}
@@ -85,7 +85,7 @@ public class SQLDriver implements RegionDriver {
List<RegionDatabase> stores = new ArrayList<RegionDatabase>();
Connection connection = closer.register(getConnection());
Statement stmt = connection.createStatement();
ResultSet rs = closer.register(stmt.executeQuery("SELECT name FROM world"));
ResultSet rs = closer.register(stmt.executeQuery("SELECT name FROM " + config.getTablePrefix() + "world"));
while (rs.next()) {
stores.add(get(rs.getString(1)));
}
@@ -23,8 +23,10 @@ import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.Vector;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -47,6 +49,11 @@ public class GlobalProtectedRegion extends ProtectedRegion {
max = new BlockVector(0, 0, 0);
}
@Override
public boolean isPhysicalArea() {
return false;
}
@Override
public List<BlockVector2D> getPoints() {
// This doesn't make sense
@@ -74,7 +81,12 @@ public class GlobalProtectedRegion extends ProtectedRegion {
@Override
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
// Global regions are handled separately so it must not contain any positions
return new ArrayList<ProtectedRegion>();
return Collections.emptyList();
}
@Override
Area toArea() {
return null;
}
}
Loaded 100 of 152 files, more files were not shown because too many files have changed in this diff. Show more